# The always up-to-date definitive guide to terrain generation: Part 5 - 3d noise

Discussion in 'Resources' started by jtjj222, Aug 18, 2012.

Not open for further replies.
1. Offline

### jtjj222

Part one
Part Two
Part Three
Part Four

This is starting to get interesting. Thus far, we have covered the basics. Now let's get into some advanced stuff. 3d noise. Trust me, it's a lot cooler than it sounds. By the end of this tutorial, we will have build something similar to this, but with better grass:

We will also cover making terrain similar to this:

I have already written on the subject, but the tutorial I wrote was, frankly, half assed and half hearted. With that out of the way, let's begin.

For this tutorial, we will cover using the 3d version of bukkit's SimplexOctaveGenerator. In a later tutorial, we will cover using other forms of noise, but for now, we will only concern our self with bukkit's implementation.
Last chapter, I talked about how you should think of 3d noise. Notch also talked about it, but never delivered on his promise of a series on the subject. Think of it as returning the "density" of the location you give it. The extreme values are the centers of the blobs. If you allow only blocks with a density above a certain threshold to be solid, you get usable terrain. The smaller the threshold, the more blocks are solid, and the more "connected" everything looks.

The scale of the generator (among other things) can be used to manipulate the terrain. The picture above has a pretty low scale compared to:

Remember: scale is how "stretched" everything is.

At this point, the examples look a little boring, but they will get better, trust me. Here is the code for the above examples. The only difference between them is the scale.

If you have made it this far in the tutorial series, you probably understand that code. If not, post below, or pm me. We loop through all of the blocks in the chunk, find their density, and make them solid if their density is above a certain threshold. Note that 3d noise is very slow, and this is a very inefficient (and boring) way of using it. Now onto some uses.

Using 3d noise with 2d noise:
This part explains how to use 3d noise to add overhangs to a 2d noise generator. To do this, we calculate the 2d noise for the top of the overhangs, and calculate the 2d noise for the bottom terrain. We then fill the bottom terrain solid, and loop through the blocks in between the bottom and top terrain, check their density, and make them solid if their density is above a certain threshold. Example. The terrain that that generates looks alright, but the overhangs are a bit off.
Now, I still haven't played with all of the values for everything, so if you can figure out how to make the terrain look better, let me know, and it will be included in this tutorial along with your name, and how awesome you are.
That code above, with threshold at 0.3:

You can combine more than one base generator to give the hills below more character, and in a later chapter, when we cover biomes, this code could make an interesting mountain biome. It only needs one more thing: grass. Adding grass is pretty simple, but It would be better explained in code. We loop through all the blocks once again, check if there is air above them, and stone beneath them, and if so, set them to grass.
Here is the world with grass:

There you go!

Making that glass catacomb:
The way I made the glass catacomb was by checking if the density of the block was between 0.3 and 0.4. If so, I set it to glass. With a little extra work, that could be turned into a hollow world used for a survival game, among other things.

Project files:
Glass catacomb.
Grassy overhanging mountains.

At this point, we have barely scratched the surface of what we can do with terrain generation. I thought this part was going to be a lot longer. codename_B has managed to make some epic looking skylands with 3d noise, so I would highly recommend you go check that out here. I am also working on Vast tracks 'o mountain . Minecraft itself also used 3d perlin noise to make some of it's terrain features.
There is a lot more to come in this series, so stay tuned, and please leave a suggestion as to what topic I should write about next. If there is anything that you think I should add to the series, PLEASE let me know . Happy terrain, uhh, generating?

Part 6
Part 7 - The long awaited biomes tutorial (Written!)

Updating all the posts when I add a new tutorial is getting too cumbersome, so I am just going to daisy chain them

As a reply to my earlier tutorial on 3d simplex noise, codename_b showed us this:

I think it is so relevant to this post, that I am including it here. This is in no way my work; All credit goes to codename_b. Thank him.
Code:java
` package de.bananaco.gen; import java.util.ArrayList;import java.util.List;import java.util.Random; import org.bukkit.Material;import org.bukkit.World;import org.bukkit.generator.BlockPopulator;import org.bukkit.util.noise.PerlinOctaveGenerator;import org.bukkit.util.noise.SimplexOctaveGenerator;   public class ChunkGenerator extends org.bukkit.generator.ChunkGenerator {    double scale = 32.0; //how far apart the tops of the hills are    double threshold = 0.0; // the cutoff point for terrain    int middle = 70; // the "middle" of the road     public List<BlockPopulator> getDefaultPopulators(World world) {        return new ArrayList();     }      /*     * Sets a block in the chunk. If the Block section doesn't exist, it allocates it.     * [y>>4] the section id (y/16)     * the math for the second offset confuses me     */    void setBlock(int x, int y, int z, byte[][] chunk, Material material) {        if (chunk[y>>4] == null)            chunk[y>>4] = new byte[16*16*16];        if (!(y<=256 && y >= 0 && x <= 16 && x >= 0 && z <= 16 && z >= 0))            return; //Out of bounds        try {            chunk[y>>4][((y & 0xF) << 8) | (z << 4) | x] = (byte)material.getId();        } catch (Exception e) {            e.printStackTrace();        }    }     @Override    //Generates block sections. Each block section is 16*16*16 blocks, stacked above each other. //There are world height / 16 sections. section number is world height / 16 (>>4)    //returns a byte[world height / 16][], formatted [section id][Blocks]. If there are no blocks in a section, it need not be allocated.    public byte[][] generateBlockSections(World world, Random rand,            int ChunkX, int ChunkZ, BiomeGrid biomes) {        Random random = new Random(world.getSeed());        SimplexOctaveGenerator gen = new SimplexOctaveGenerator(random, 8);        PerlinOctaveGenerator gen2 = new PerlinOctaveGenerator(world.getSeed(), 8);         byte[][] chunk = new byte[world.getMaxHeight() / 16][];         gen2.setScale(1/scale);        gen.setScale(1/scale); //The distance between peaks of the terrain. Scroll down more to see what happens when you play with this        double threshold = this.threshold; //scroll down to see what happens when you play with this.         for (int x=0;x<16;x++) {            for (int z=0;z<16;z++) {                int real_x = x+ChunkX * 16;                int real_z = z+ChunkZ*16;                 double height = middle+gen2.noise(real_x, real_z, 0.5, 0.5)*middle/3; // generate some smoother terrain                 for (int y=1; y<height && y<256; y++) {                    if(y > middle-middle/3) {                        double noise = gen.noise(real_x, y, real_z, 0.5, 0.5);                        if(noise > threshold) //explained above                            setBlock(x,y,z,chunk,Material.STONE); //set the block solid                    } else {                        setBlock(x,y,z,chunk,Material.STONE);                    }                }            }        }        return chunk;    }}`

EDIT by Moderator: merged posts, please use the edit button instead of double posting.

Last edited by a moderator: May 27, 2016
#1
2. Offline

### Icyene

Is it just me or does the first video terrain look like a strangled snake, and the second video like that Rainbow Road thing in Mario Kart? And is that a satellite - dish like terrain in the first picture? Anyways, thanks for all these great tutorials! They helped alot

#2
jtjj222 likes this.
3. Offline

### hypothete

Hey jtjj222 and codename_b, thanks for the examples. I was wondering whether you could help me understand the output of the noise function better, and its relation to the threshold. Here's what I'm trying to accomplish: a Skylands-type environment with islands varying in "density" from y=96 - 192. My initial thought would be to vary the threshold by height (so like sin(y/255*2Pi)) but that didn't seem to work. I also tried adjusting the amplitude and frequency of the noise by height, but the results were not noticeable. Any ideas on how I could make density vary by height? Thanks!

Here's my code for reference. If I leave in the threshold varying with height (commented), MV2 tells me it fails. link

EDIT by Moderator: merged posts, please use the edit button instead of double posting.

Last edited by a moderator: May 27, 2016
#3
4. Offline

### jtjj222

I don't really understand what you are trying to do. Can you explain that a bit better? Also, can you get a stack trace for the error that you are describing?

#4
5. Offline

### hypothete

I'm just trying to make it so from Y 1-96 there are almost no islands, Y 96 - 224 there are a lot of islands, and then 225-256 almost none again. I ended up just generating the islands in that middle bit, but that slices through some of the lower and higher blobs, which IMO looks bad.

#5
6. Offline

### jtjj222

Add a displacement to the noise based on the y value.

#6
7. Offline

### Hoolean

Next, could you show us how to add trees and biomes, as it would be very much appreciated! Thank you!

#7
8. Offline

Very good tutorials!!!!

#8
9. Offline

### Corgano

Please continue making tut's! These are probably the most epic things I've seen bukkit do!

#9
10. Offline

### Limeth

I agree!

#10
slowbuild and MrBluebear3 like this.
11. Offline

### ignirtoq

Any chance the part detailing biomes will be out any time soon?

#11
12. Offline

### jtjj222

Haha, I know it's been a while. School has been keeping me busy

#12
13. Offline

### Corgano

Don't make me beg!

#13
14. Offline

What would I have to do to retain Mc's default terrain generation but alter the distribution and look of ore veins?

#14
15. Offline

### jtjj222

Well, you could copy the source code directly form a decompled version of minecraft. If that's too much, you could just add a new block populator to the existing world to add ores (create an event handler for the onWorldInit event, then add the populator using world.getBlockPopulators().add() or something like that).

#15
16. Offline

### jtjj222

Biomes are out!

#16