# mods, can you please delete this? I have written a better tutorial on the subject

Discussion in 'Resources' started by jtjj222, Apr 21, 2012.

Not open for further replies.
1. Offline

### jtjj222

Hello, I still haven't tinkered with all the values, but I just figured how to use 3-d simplex noise to create interesting terrain features. It could be used to make mountains and overhangs, although I'm still tinkering around to figure out how to do that. I would have personally liked to know about this sooner, and so I would like to share what I know with you. I'm not very experienced with this stuff, but If in any way this post helps you, please let me know

This tutorial assumes that you have used two dimensional simplex noise (or as many know it, a simplexoctavegenerator). codename_B has a nice tutorial on it: http://forums.bukkit.org/threads/in...errain-generation-using-simplexoctaves.28855/

First things first, when using 3d noise, think of the noise as density. If the noise is above a certain threshold, make it solid. Notch explains this: http://notch.tumblr.com/post/3746989361/terrain-generation-part-1
Code:java
`public class ChunkGenerator extends org.bukkit.generator.ChunkGenerator {double scale = 32.0; //how far apart the tops of the hills are public List<BlockPopulator> getDefaultPopulators(World world) {          //Block populators go here          return null;}  /** 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) {                    //do nothing          }} @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);          byte[][] chunk = new byte[world.getMaxHeight() / 16][];           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 = 0.0; //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;                               for (int y=1;y<256;y++) {                                        if(gen.noise(real_x, y, real_z, 0.5, 0.5) > threshold)  //explained above                                                  setBlock(x,y,z,chunk,Material.GLOWSTONE); //set the block solid                              }                    }          }          return chunk;}}`

Sorry for the indenting, the code tag screwed it up.
If anything above isn't clear to you, pm me.
If you use it as-is, with scale at 32 and threshold at 0.0, it creates nether-like terrain:
http://dl.dropbox.com/u/12637402/tutorial1/scale32.png
http://dl.dropbox.com/u/12637402/tutorial1/scale32pic2.png
http://dl.dropbox.com/u/12637402/tutorial1/scale32pic3.png
Scale 64, threshold 0:
http://dl.dropbox.com/u/12637402/tutorial1/scale64.png
http://dl.dropbox.com/u/12637402/tutorial1/scale64pic2.png
http://dl.dropbox.com/u/12637402/tutorial1/scale64pic3.png
Scale 256, threshold 0:
http://dl.dropbox.com/u/12637402/tutorial1/scale256.png
Now, we can play with the threshold a bit. The larger the threshold, the less solid blocks, and the less "connected" everything looks:
Scale 256, threshold 0.7:
http://dl.dropbox.com/u/12637402/tutorial1/thresholdPOINT7.png
If I get a good response from this tutorial, I'll make another one that explains how to use multiple 2d simplexoctavegenerators together to make more interesting terrain, and also how you can use 2d noise along with 3d noise to make cool floating islands. I may also do one on biomes.

EDIT2: Updated for the new method generateBlockSections
edit3: xpansive showed me how to use voronoi noise in terrain generation, so if I can figure that out, expect a tutorial on it.
EDIT3: Fixed formatting

#1
ferrybig and hypothete like this.
2. Offline

### xpansive

The generate method is deprecated. You should update the tutorial to use the new methods. Check the javadocs for details.

#2
3. Offline

### jtjj222

**updated, thanks

#3
4. Offline

### codename_B

This is very very awesome

I never quite got my head around the 3d simplex as I could never really picture it in my head (2d I just picture the height as shades of gray, so basically a heightmap) so explaining it as density is excellent.

When I've got the inclination I might make a few more WGENs based off of this - I've got a decent bank of populators put together that I can just fire into generated terrain now too lol.

#4
5. Offline

### codename_B

#5
jtjj222 likes this.
6. Offline

### jtjj222

...how? That's epic. that looks like a high scale and low threshold, but there is something different I just can't put my finger on...

#6
7. Offline

### codename_B

I'm also layering it with 2d perlin as a max noise level (and generating set 2d perlin below x coordinates) want to see the code?

#7
8. Offline

#8
9. Offline

### codename_B

Code:
```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;
}
}
```

#9
jtjj222 likes this.
10. Offline

### jtjj222

That's awesome, thanks

#10