3
$\begingroup$

I am generating a basic terrain using 3 for loops. It currently results in a large block of cubes composed of columns of cubes all of the same height, height meaning how many cubes high each column is. I want to change the top of every column to make an overall terrain look. I hope to use perlin noise to take the columns XY (horizontal) location and use it as a seed to get the height of that column of cubes.

I also hope to use an initial seed that changes the effect of each horizontal seed value as well and the ability to reproduce the final results by being able to enter the seed at start up, but it is not top priority right now, but I would appreciate if you would include that, if you know how.

I want to be using the horizontal position to be the seed to generate the height position with the perlin noise to determine how many cubes high each column should be. Please include full code or at least a good functioning chunk of code. Thank you for reading and your time.

$\endgroup$
  • 1
    $\begingroup$ Is your question: How to define a seed for random generation? $\endgroup$ – Monster Jul 23 '15 at 11:59
  • $\begingroup$ @Monster shortly, yes.my question is how to use an XY position in space to get a somewhat random Y position, through a perlin noise like seed to have smooth results for the terrain. I want to get the same result every time for a position in space. $\endgroup$ – The Blue Racoon Jul 24 '15 at 20:55
  • 1
    $\begingroup$ Why not just use a ready-made Python module like github.com/caseman/noise? $\endgroup$ – Mike Pan Jul 28 '15 at 5:26
1
$\begingroup$

Blender comes with the mathutils module, which has a whole host of functions for just this kind of thing:

enter image description here

Here's the script for the above demo. It's a little boilerplate-y, really the gist of it is just the section in the middle (iterate over each vertex, get value from 2D location of vertex, set Z location of vertex)

from bge import logic
from mathutils import noise

# a list of various noise functions with some default values
noise_functions = [
    lambda p: noise.cell(p),
    lambda p: noise.fractal(p, 1.0, 2.0, 8),
    lambda p: noise.hetero_terrain(p, 1.0, 2.0, 8, 0),
    lambda p: noise.hybrid_multi_fractal(p, 1.0, 2.0, 8, 0, 1),
    lambda p: noise.multi_fractal(p, .5, 2.0, 8),
    lambda p: noise.noise(p),
    lambda p: noise.ridged_multi_fractal(p, .5, 2.0, 8, 1, 0),
    lambda p: noise.turbulence(p, 8, True),
    lambda p: noise.variable_lacunarity(p, 1),

    #lambda p: noise.voronoi(p),
]

verts_per_tic = 100 # number of verts to move every logic tic
zoffset = 1 # sort of useable as a "seed" when distorting a 2D plane on the Z axis like this
scale = .5

def move_verts(cont):
    own = cont.owner

    for m_index in range(len(own.meshes[0].materials)):
        v_range = own.meshes[0].getVertexArrayLength(m_index)

        cvert = own.get("current_vert", v_range)
        noise_scale = own.get("noise_scale", 1)

        if cvert < v_range:
            # iterate over verts in the current material of the current object
            for v in range(cvert, min(cvert + verts_per_tic, v_range)):
                vertex = own.meshes[0].getVertex(m_index, cvert)

                # get the XY position of the current vertex and scale it
                sample_pos = vertex.XYZ.copy().xy * scale

                # turn the 2D XY vector into a 3D vector
                sample_pos.resize(3)

                # set the Z component to a pre-defined constant
                sample_pos.z = zoffset

                # feed it to the current noise function
                height = own["noise_generator"](sample_pos)

                # set the vertex position
                vertex.z = height


                cvert += 1

            own["current_vert"] = cvert    
        else:
            # if we've moved all the verts according to the current function, then pick a new one
            iter = own.get("iterations", 0)
            if iter >= len(noise_functions):
                iter = 0

            own["noise_generator"] = noise_functions[iter]

            # cycle through each noise function
            iter += 1
            own["iterations"] = iter

            own["current_vert"] = 0

$\endgroup$
  • $\begingroup$ I have figured out the problem a little back, it works pretty good now doing what I see in the gif. The problem was lack of documentation as to actual code snippets as I knew what code I needed eventually from mathutils, but couldn't get the code right. I figured it out now. Thanks for help though. I bet I could've fixed my problem in less a day if I had access to your comment then and a couple lines of example code to copy. $\endgroup$ – The Blue Racoon Sep 22 '16 at 23:14
  • $\begingroup$ @TheBlueRacoon Oh dear, I intended to include the code for the example I made, but I seem to have forgotten. I apologize! I've uploaded it anyway in case it might help others who stumble across this in the future. $\endgroup$ – gandalf3 Sep 22 '16 at 23:52
0
$\begingroup$

The answer should be pretty simple: use a constant as seed.

Backbround

I do not know the implementarion of Perlin-Noise that you want to use. As long it is deterministic: If you use the same input you get the same output each time you calculate.

The coordinates (x,y) are constants already. The high (y) is output rather than input. To get a different "grid" with the same coordinates (x,y) you need to modify further input parameters. Usually that are some gradient vectors. I guess you use an implementation that allows to pre-calculate them via a pseudo-random function.

Random number generation

A pseudo-random generator expects a seed to start generating a sequence of pseudo-random numbers. The same seed results in the same sequence.

A typical pseudo-random generator implementation uses the seed of the system time. This adds a "random factor" which is time of seed generation. It is very unlikely that this time results in the same seed on two runs.

As you do not want it random, I think you better define a constant for each grid.

e.g.

  • Grid A: seed 1
  • Grid B: seed 2
  • Grid C: seed 3

I hope it helps

$\endgroup$
  • $\begingroup$ I don't know where to go to find the documentation/code to put into the blender Python to get any type of noise. I want just a normal perlin noise where you get the same numbers from the same seed, but don't know what code to put in or where to find blender Python code that works. $\endgroup$ – The Blue Racoon Aug 20 '15 at 22:24
  • $\begingroup$ So you do not even have an implementation? $\endgroup$ – Monster Aug 21 '15 at 5:35
  • $\begingroup$ just can't seem to find the code snippets used to generate noise/the right numbers in any online documentation related to the blender Python. I tried copying and pasting snippets from 1dnoise example in Python blender In a template from an above comment by mike pan, but the line dealing with pnoise1 didn't work with the Python in blender. I isolated that line of code to figure out it was the one causing the problem and I guess that blender Python uses another line of code or needs me to import a package. But I can't figure out where to get the line of code equivalent for Python on blender. $\endgroup$ – The Blue Racoon Aug 21 '15 at 21:45
  • $\begingroup$ Have you tried pypi.python.org/pypi/noise ? (I haven't I just found it). You can follow the link to github. It contains examples. A ready to use library is much better than implement your own version. $\endgroup$ – Monster Aug 24 '15 at 6:42
  • $\begingroup$ I think I figured it out, I got my code to get a random statement to work and now it bumps up the terrain up and down every 10 units. I have still to achieve my end result, but I think I am very close and the hard part is behind me. $\endgroup$ – The Blue Racoon Aug 27 '15 at 6:43

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.