package org.bukkit.util.noise; import org.bukkit.World; import java.util.Random; /** * Generates simplex-based noise. *
* This is a modified version of the freely published version in the paper by
* Stefan Gustavson at http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
*/
public class SimplexNoiseGenerator extends PerlinNoiseGenerator {
protected static final double SQRT_3 = Math.sqrt(3);
protected static final double SQRT_5 = Math.sqrt(5);
protected static final double F2 = 0.5 * (SQRT_3 - 1);
protected static final double G2 = (3 - SQRT_3) / 6;
protected static final double G22 = G2 * 2.0 - 1;
protected static final double F3 = 1.0 / 3.0;
protected static final double G3 = 1.0 / 6.0;
protected static final double F4 = (SQRT_5 - 1.0) / 4.0;
protected static final double G4 = (5.0 - SQRT_5) / 20.0;
protected static final double G42 = G4 * 2.0;
protected static final double G43 = G4 * 3.0;
protected static final double G44 = G4 * 4.0 - 1.0;
protected static final int grad4[][] = { { 0, 1, 1, 1 }, { 0, 1, 1, -1 }, { 0, 1, -1, 1 }, { 0, 1, -1, -1 }, { 0, -1, 1, 1 }, { 0, -1, 1, -1 }, { 0, -1, -1, 1 }, { 0, -1, -1, -1 }, { 1, 0, 1, 1 }, { 1, 0, 1, -1 }, { 1, 0, -1, 1 }, { 1, 0, -1, -1 }, { -1, 0, 1, 1 }, { -1, 0, 1, -1 }, { -1, 0, -1, 1 }, { -1, 0, -1, -1 }, { 1, 1, 0, 1 }, { 1, 1, 0, -1 }, { 1, -1, 0, 1 }, { 1, -1, 0, -1 }, { -1, 1, 0, 1 }, { -1, 1, 0, -1 }, { -1, -1, 0, 1 }, { -1, -1, 0, -1 }, { 1, 1, 1, 0 }, { 1, 1, -1, 0 }, { 1, -1, 1, 0 }, { 1, -1, -1, 0 }, { -1, 1, 1, 0 }, { -1, 1, -1, 0 }, { -1, -1, 1, 0 }, { -1, -1, -1, 0 } };
protected static final int simplex[][] = { { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, { 0, 0, 0, 0 }, { 0, 2, 3, 1 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 1, 2, 3, 0 }, { 0, 2, 1, 3 }, { 0, 0, 0, 0 }, { 0, 3, 1, 2 }, { 0, 3, 2, 1 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 1, 3, 2, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 1, 2, 0, 3 }, { 0, 0, 0, 0 }, { 1, 3, 0, 2 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 2, 3, 0, 1 }, { 2, 3, 1, 0 }, { 1, 0, 2, 3 }, { 1, 0, 3, 2 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 2, 0, 3, 1 }, { 0, 0, 0, 0 }, { 2, 1, 3, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 2, 0, 1, 3 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 3, 0, 1, 2 }, { 3, 0, 2, 1 }, { 0, 0, 0, 0 }, { 3, 1, 2, 0 }, { 2, 1, 0, 3 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 3, 1, 0, 2 }, { 0, 0, 0, 0 }, { 3, 2, 0, 1 }, { 3, 2, 1, 0 } };
protected static double offsetW;
private static final SimplexNoiseGenerator instance = new SimplexNoiseGenerator();
protected SimplexNoiseGenerator() {
super();
}
/**
* Creates a seeded simplex noise generator for the given world
*
* @param world World to construct this generator for
*/
public SimplexNoiseGenerator(World world) {
this(new Random(world.getSeed()));
}
/**
* Creates a seeded simplex noise generator for the given seed
*
* @param seed Seed to construct this generator for
*/
public SimplexNoiseGenerator(long seed) {
this(new Random(seed));
}
/**
* Creates a seeded simplex noise generator with the given Random
*
* @param rand Random to construct with
*/
public SimplexNoiseGenerator(Random rand) {
super(rand);
offsetW = rand.nextDouble() * 256;
}
protected static double dot(int g[], double x, double y) {
return g[0] * x + g[1] * y;
}
protected static double dot(int g[], double x, double y, double z) {
return g[0] * x + g[1] * y + g[2] * z;
}
protected static double dot(int g[], double x, double y, double z, double w) {
return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
}
/**
* Computes and returns the 1D unseeded simplex noise for the given coordinates in 1D space
*
* @param xin X coordinate
* @return Noise at given location, from range -1 to 1
*/
public static double getNoise(double xin) {
return instance.noise(xin);
}
/**
* Computes and returns the 2D unseeded simplex noise for the given coordinates in 2D space
*
* @param xin X coordinate
* @param yin Y coordinate
* @return Noise at given location, from range -1 to 1
*/
public static double getNoise(double xin, double yin) {
return instance.noise(xin, yin);
}
/**
* Computes and returns the 3D unseeded simplex noise for the given coordinates in 3D space
*
* @param xin X coordinate
* @param yin Y coordinate
* @param zin Z coordinate
* @return Noise at given location, from range -1 to 1
*/
public static double getNoise(double xin, double yin, double zin) {
return instance.noise(xin, yin, zin);
}
/**
* Computes and returns the 4D simplex noise for the given coordinates in 4D space
*
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
* @param w W coordinate
* @return Noise at given location, from range -1 to 1
*/
public static double getNoise(double x, double y, double z, double w) {
return instance.noise(x, y, z, w);
}
@Override
public double noise(double xin, double yin, double zin) {
xin += offsetX;
yin += offsetY;
zin += offsetZ;
double n0, n1, n2, n3; // Noise contributions from the four corners
// Skew the input space to determine which simplex cell we're in
double s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D
int i = floor(xin + s);
int j = floor(yin + s);
int k = floor(zin + s);
double t = (i + j + k) * G3;
double X0 = i - t; // Unskew the cell origin back to (x,y,z) space
double Y0 = j - t;
double Z0 = k - t;
double x0 = xin - X0; // The x,y,z distances from the cell origin
double y0 = yin - Y0;
double z0 = zin - Z0;
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
// Determine which simplex we are in.
int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
if (x0 >= y0) {
if (y0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 1;
k2 = 0;
} // X Y Z order
else if (x0 >= z0) {
i1 = 1;
j1 = 0;
k1 = 0;
i2 = 1;
j2 = 0;
k2 = 1;
} // X Z Y order
else {
i1 = 0;
j1 = 0;
k1 = 1;
i2 = 1;
j2 = 0;
k2 = 1;
} // Z X Y order
} else { // x0