package net.glowstone.util.noise;
import org.bukkit.util.noise.PerlinNoiseGenerator;
import java.util.Random;
public class PerlinNoise extends PerlinNoiseGenerator {
public PerlinNoise(Random rand) {
offsetX = rand.nextDouble() * 256;
offsetY = rand.nextDouble() * 256;
offsetZ = rand.nextDouble() * 256;
// The only reason why I'm re-implementing the constructor code is that I've read
// on at least 3 different sources that the permutation table should initially be
// populated with indices.
// "The permutation table is his answer to the issue of random numbers.
// First take an array of decent length, usually 256 values. Fill it sequentially
// with each number in that range: so index 1 gets 1, index 8 gets 8, index 251 gets 251, etc...
// Then randomly shuffle the values so you have a table of 256 random values, but only
// contains the values between 0 and 255."
// source: https://code.google.com/p/fractalterraingeneration/wiki/Perlin_Noise
for (int i = 0; i < 256; i++) {
perm[i] = i;
}
for (int i = 0; i < 256; i++) {
int pos = rand.nextInt(256 - i) + i;
int old = perm[i];
perm[i] = perm[pos];
perm[pos] = old;
perm[i + 256] = perm[i];
}
}
public static int floor(double x) {
int iX = (int) x;
return x < iX ? iX - 1 : iX;
}
public double[] getNoise(double[] noise, double x, double y, double z, int sizeX, int sizeY, int sizeZ, double scaleX, double scaleY, double scaleZ, double amplitude) {
if (sizeY == 1) {
return get2dNoise(noise, x, z, sizeX, sizeZ, scaleX, scaleZ, amplitude);
} else {
return get3dNoise(noise, x, y, z, sizeX, sizeY, sizeZ, scaleX, scaleY, scaleZ, amplitude);
}
}
protected double[] get2dNoise(double[] noise, double x, double z, int sizeX, int sizeZ, double scaleX, double scaleZ, double amplitude) {
int index = 0;
for (int i = 0; i < sizeX; i++) {
double dX = x + offsetX + i * scaleX;
int floorX = floor(dX);
int iX = floorX & 255;
dX -= floorX;
double fX = fade(dX);
for (int j = 0; j < sizeZ; j++) {
double dZ = z + offsetZ + j * scaleZ;
int floorZ = floor(dZ);
int iZ = floorZ & 255;
dZ -= floorZ;
double fZ = fade(dZ);
// Hash coordinates of the square corners
int a = perm[iX] + 0;
int aa = perm[a] + iZ;
int b = perm[iX + 1] + 0;
int ba = perm[b] + iZ;
double x1 = lerp(fX, grad(perm[aa], dX, 0, dZ), grad(perm[ba], dX - 1, 0, dZ));
double x2 = lerp(fX, grad(perm[aa + 1], dX, 0, dZ - 1), grad(perm[ba + 1], dX - 1, 0, dZ - 1));
noise[index++] += lerp(fZ, x1, x2) * amplitude;
}
}
return noise;
}
protected double[] get3dNoise(double[] noise, double x, double y, double z, int sizeX, int sizeY, int sizeZ, double scaleX, double scaleY, double scaleZ, double amplitude) {
int n = -1;
double x1 = 0;
double x2 = 0;
double x3 = 0;
double x4 = 0;
int index = 0;
for (int i = 0; i < sizeX; i++) {
double dX = x + offsetX + i * scaleX;
int floorX = floor(dX);
int iX = floorX & 255;
dX -= floorX;
double fX = fade(dX);
for (int j = 0; j < sizeZ; j++) {
double dZ = z + offsetZ + j * scaleZ;
int floorZ = floor(dZ);
int iZ = floorZ & 255;
dZ -= floorZ;
double fZ = fade(dZ);
for (int k = 0; k < sizeY; k++) {
double dY = y + offsetY + k * scaleY;
int floorY = floor(dY);
int iY = floorY & 255;
dY -= floorY;
double fY = fade(dY);
if (k == 0 || iY != n) {
n = iY;
// Hash coordinates of the cube corners
int a = perm[iX] + iY;
int aa = perm[a] + iZ;
int ab = perm[a + 1] + iZ;
int b = perm[iX + 1] + iY;
int ba = perm[b] + iZ;
int bb = perm[b + 1] + iZ;
x1 = lerp(fX, grad(perm[aa], dX, dY, dZ), grad(perm[ba], dX - 1, dY, dZ));
x2 = lerp(fX, grad(perm[ab], dX, dY - 1, dZ), grad(perm[bb], dX - 1, dY - 1, dZ));
x3 = lerp(fX, grad(perm[aa + 1], dX, dY, dZ - 1), grad(perm[ba + 1], dX - 1, dY, dZ - 1));
x4 = lerp(fX, grad(perm[ab + 1], dX, dY - 1, dZ - 1), grad(perm[bb + 1], dX - 1, dY - 1, dZ - 1));
}
double y1 = lerp(fY, x1, x2);
double y2 = lerp(fY, x3, x4);
noise[index++] += lerp(fZ, y1, y2) * amplitude;
}
}
}
return noise;
}
}