14
\$\begingroup\$

I'm currently trying to generate a Minecraft like voxel terrain with 3D Simplex Noise and also want to implement caves.

I found the method of Perlin Worms in this thread, which generates really nice results. However, I have no clue on how to generate it on a chunk by chunk basis. Is this possible or are there any alternatives that produce a similar worm like cave on a chunk by chunk basis?

Edit: This is the problem which I don't know how to solve.

Edit2: This is the result from combining 2D Ridged Multifractal Noise with a Simplex Noise heightmap. Still needs some tweaking, but this is pretty much the result I wanted. Thanks to Byte56.

\$\endgroup\$
2
  • \$\begingroup\$ You should use direct formulas for terrain generation if possible. If you can calculate a voxel just based on its coordinates and without information about adjacent ones, chunks aren't a problem anymore. If you want to use perlin worms, which I guess can't be calculated for each voxel individually, take a look on the last paragraph in the accepted answer of the question you linked. \$\endgroup\$
    – danijar
    Commented Apr 6, 2013 at 12:15
  • 1
    \$\begingroup\$ Basically, that is my question. The basic terrain is easy to calculate with just the coordinates given, but I don't know how to calculate, whether there is a cave or not. \$\endgroup\$ Commented Apr 6, 2013 at 12:22

2 Answers 2

6
\$\begingroup\$

Most perlin noise algorithms will allow you to retrieve the noise value at any given location, with something like noise(x,y,z). This makes it fairly trivial to generate noise on a chunk by chunk basis. All you need to do is pass the global position, instead of the chunk position.

for(int i = 0; i < CHUNKMAX_X; i++)
    for(int j = 0; j < CHUNKMAX_Y; j++)
        for(int k = 0; k < CHUNKMAX_Z; k++)
            if(isSolid(perlinNoise.get(chunkPosition.x + i,
                                         chunkPosition.y + j,
                                         chunkPosition.z + k))
                thisChunk[i,j,k] = new Voxel(solid);
            else
                thisChunk[i,j,k] = new Voxel(air);

So you can see, we're generating terrain for the chunk, by iterating over the chunk bounds, and checking to see if that global position is solid or not. This is likely the same methodology you're using to generate the terrain in general.

perlinNoise.get takes a global position and returns its density. Where isSolid would just be a simple test to see if the voxel is "dense enough" to qualify for solid.

perlinNoise.get can be more complex than just a simple noise algorithm. You can have checks based on the depth of the voxel in your world. For example, if the voxel is below what you've decided is "absolute base ground level" then it can use the perlin worms algorithm to return a density, if it's above the absolute base, it can use a normal density function to give you more varied terrain. I would recommend some blending between the two however.

Combining different Perlin noise functions is just something you have to play with and see what works. It's best to set up your environment so that you can just change some values and hot-swap the terrain without needing to reload your game. Happy experimenting.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Thanks for the answer. However, I don't know how to use "regular" Perlin or Simplex Noise to create the worm-like caves. They are either spherical, scaled into one direction or not very long. And for the Perlin Worms algorithm, I don't know how to determine whether the current position is inside a worm, without knowing the head position. \$\endgroup\$ Commented Apr 6, 2013 at 16:00
  • 1
    \$\begingroup\$ The worms algorithm does not rely on knowing the "head position". From what you're saying, it appears your problem is not with generating noise on a chunk by chunk basis. There are tutorials on the question you linked for implementing perlin worms. How to generate "regular" terrain can be found here. \$\endgroup\$
    – House
    Commented Apr 6, 2013 at 16:10
  • \$\begingroup\$ The basic terrain generation with 3D Simplex Noise works fine, but I don't know how to determine a worms position/segment inside a chunk. From what I understood, you give the worm a head position and n segments and calculate the angle between the segments with the noise function. Here is an image that may better explain, what my problem is: link. \$\endgroup\$ Commented Apr 6, 2013 at 16:49
  • 2
    \$\begingroup\$ There are different types of noise. Using a head position and following from there is one method. If you look near the bottom of this page, you'll find some noise that creates the kind noise you want without needing a head position first. \$\endgroup\$
    – House
    Commented Apr 6, 2013 at 17:19
  • \$\begingroup\$ Thanks for the hint on that. I implemented the 3D Ridged Multifractal Noise, though, the result with it was rather unsatisfying. I will try to combine it in 2D with a 2D Heightmap and then report again. This may create more worm-like caves. \$\endgroup\$ Commented Apr 6, 2013 at 19:35
5
\$\begingroup\$

I think this is how it works in Minecraft. Each worm has a maximum length (let's call it M). The heads of each worm are calculated based on the chunk position. When you render each chunk, you have to check all chunks within an M radius, and follow all of their worms. It's not ideal in terms of performance, but it does work.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .