finn b
finn b

Reputation: 23

Trouble finding chunk loading noise algorithm

I am working on a basic 2d terrain generator and currently It generates a 1024x1024 'swatch' of terrain using perlin-numpy. I am interested in having the option to generate another 'chunk' (like Minecraft) above my current terrain that is different, but fits smoothly above my current terrain.

TL;DR: the noise function I'm using takes generate_fractal_noise_2d((1024, 1024), octaves=6)
I want to be able to do generate_fractal_noise_2d((1024, 1024), location=(<x coord of chunk (pixels)>, <y coord of chunk (pixels)>), octaves=6)

Upvotes: 1

Views: 412

Answers (1)

KdotJPG
KdotJPG

Reputation: 861

Generally this is very easy with noise, because noise is a point evaluation function. This library would work if it provided an "offset" parameter, but it doesn't seem to. Also, is there a reason you are using a "Perlin" noise library and not an (Open)Simplex? Perlin is an older function for noise, which produces visually significant grid bias. (Open)Simplex can be noticeably better about that. You can see in this image that the Perlin on top has a lot of 45 and 90 degree parts. Terrain features won't be distributed along a more interesting variety of directions.

Here's what I would do:

  • Use Python OpenSimplex instead.
  • Implement octave summation manually, since the lib doesn't have it.
class OpenSimplexFractal(object):

    def __init__(self, seed=0, octaves=6):
        self._instances = []
        for i in range(octaves):
            self._instances[i] = OpenSimplex(seed + i)
    
    def fractalNoise2(x, y, persistence=0.5, lacunarity=2, frequency=1, amplitude=1):
        value = 0
        for i in range(len(self._instances)):
            value += self._instances[i].noise2d(x * frequency, y * frequency) * amplitude
            amplitude *= persistence
            frequency *= lacunarity
        return value
  • Populate your array manually. Here it is with a simple loop, but if you're familiar enough with numpy you could write it with its syntax.
    
    def arrayFractalNoise2(shape, offset, persistence=0.5, lacunarity=2, frequency=1, amplitude=1):
        noise = np.zeros(shape)
        for y in range(shape[0]):
            for x in range(shape[1]):
                noise[y+offset[1],x+offset[0]] = fractalNoise2(x, y, persistence, lacunarity, frequency, amplitude)
    return noise

When generating the chunk at the origin, you would do arrayFractalNoise2((1024, 1024), (0, 0), ...). But when generating the next chunk in X, you would do arrayFractalNoise2((1024, 1024), (1024, 0), ...) and so-on.

I may have made errors in my code, but I hope it's helpful as it is.

(I hereby release these code snippets under CC0).

Upvotes: 1

Related Questions