New PerlinNoise

This commit is contained in:
IntegratedQuantum 2019-03-23 22:34:43 +01:00
parent 4a79ea0b5a
commit ea804535d2
3 changed files with 92 additions and 4 deletions

View File

@ -81,6 +81,8 @@ public class Chunk {
* @param z
*/
public void addBlock(Block b, int x, int y, int z) {
if(y >= World.WORLD_HEIGHT)
return;
int rx = x - (ox << 4);
if (rx < 0) {
// Determines if the block is part of another chunk.
@ -154,6 +156,8 @@ public class Chunk {
for (int py = 0; py < 16; py++) {
float value = map[px][py];
int y = (int) (value * World.WORLD_HEIGHT);
if(y == World.WORLD_HEIGHT)
y--;
for (int j = y > SEA_LEVEL ? y : SEA_LEVEL; j >= 0; j--) {
BlockInstance bi = null;
if(j > y) {

View File

@ -168,9 +168,9 @@ public class LocalWorld extends World {
public void synchronousGenerate(Chunk ch) {
int x = ch.getX() * 16; int y = ch.getZ() * 16;
float[][] heightMap = Noise.generateMapFragment(x, y, 16, 16, 300, seed);
float[][] vegetationMap = Noise.generateMapFragment(x, y, 16, 16, 300, seed + 3 * (seed + 1 & Integer.MAX_VALUE));
float[][] oreMap = Noise.generateMapFragment(x, y, 16, 16, 300, seed - 3 * (seed - 1 & Integer.MAX_VALUE));
float[][] heightMap = Noise.generateMapFragment(x, y, 16, 16, 256, seed);
float[][] vegetationMap = Noise.generateMapFragment(x, y, 16, 16, 128, seed + 3 * (seed + 1 & Integer.MAX_VALUE));
float[][] oreMap = Noise.generateMapFragment(x, y, 16, 16, 128, seed - 3 * (seed - 1 & Integer.MAX_VALUE));
ch.generateFrom(heightMap, vegetationMap, oreMap);
}

View File

@ -1,10 +1,13 @@
package io.cubyz.world;
import java.util.Random;
/**
* Perlin Noise generator for Worlds
* @author zenith391
*/
public class Noise {
private static Random r = new Random();
static float get2DPerlinNoiseValue(float x, float y, float res, int seed)
{
@ -75,6 +78,83 @@ public class Noise {
return 0.5f*(1+Li1 + Cy*(Li2-Li1));
}
private static int seed;
private static int resolution;
private static int resolution2;
// Calculate the gradient instead of storing it.
// This is inefficient(since it is called every time), but allows infinite chunk generation.
// TODO: Make this faster
private static float getGradient(int x, int y, int i) {
r.setSeed(seed);
r.setSeed(r.nextLong()*x+r.nextLong()*y+r.nextLong()*i);
return 2 * r.nextFloat() - 1;
}
/* Function to linearly interpolate between a0 and a1
* Weight w should be in the range [0.0, 1.0]
*
* as an alternative, this slightly faster equivalent function (macro) can be used:
* #define lerp(a0, a1, w) (a0 + w*(a1 - a0))
*/
private static float lerp(float a0, float a1, float w) {
return (1.0f - w)*a0 + w*a1;
}
// Computes the dot product of the distance and gradient vectors.
private static float dotGridGradient(int ix, int iy, int x, int y) {
// Precomputed (or otherwise) gradient vectors at each grid node
// Compute the distance vector
float dx = x/(float)resolution - ix;
float dy = y/(float)resolution - iy;
// Compute the dot-product
float gx = getGradient(ix, iy, 0);
float gy = getGradient(ix, iy, 1);
float gr = (float)Math.sqrt((gx*gx+gy*gy));
gx /= gr;
gy /= gr;
return (dx*gx + dy*gy);
}
// Compute Perlin noise at coordinates x, y
private static float perlin(int x, int y) {
// Determine grid cell coordinates
int x0 = x/resolution;
if(x < 0) {
x0 = (x-resolution2)/resolution;
}
int x1 = x0 + 1;
int y0 = y/resolution;
if(y < 0) {
y0 = (y-resolution2)/resolution;
}
int y1 = y0 + 1;
// Determine interpolation weights
// Could also use higher order polynomial/s-curve here
float sx = (x&resolution2)/(float)resolution;
float sy = (y&resolution2)/(float)resolution;
// Interpolate between grid point gradients
float n0, n1, ix0, ix1, value;
n0 = dotGridGradient(x0, y0, x, y);
n1 = dotGridGradient(x1, y0, x, y);
ix0 = lerp(n0, n1, sx);
n0 = dotGridGradient(x0, y1, x, y);
n1 = dotGridGradient(x1, y1, x, y);
ix1 = lerp(n0, n1, sx);
value = lerp(ix0, ix1, sy);
value = 0.5F * value + 0.5F;
if(value > 1)
value = 1;
return value;
}
public static float[][] generateMap(int width, int height, int scale, int seed) {
return generateMapFragment(0, 0, width, height, scale, seed);
@ -82,10 +162,14 @@ public class Noise {
public static float[][] generateMapFragment(int x, int y, int width, int height, int scale, int seed) {
float[][] map = new float[width][height];
resolution = scale;
resolution2 = resolution-1;
Noise.seed = seed;
for (int x1 = x; x1 < width + x; x1++) {
for (int y1 = y; y1 < height + y; y1++) {
map[x1 - x][y1 - y] = get2DPerlinNoiseValue(x1, y1, scale, seed);
//map[x1 - x][y1 - y] = get2DPerlinNoiseValue(x1, y1, scale, seed);
map[x1 - x][y1 - y] = perlin(x1, y1);
}
}