package net.glowstone.util.noise;
import org.bukkit.util.noise.NoiseGenerator;
import org.bukkit.util.noise.OctaveGenerator;
import java.util.Random;
public class PerlinOctaveGenerator extends OctaveGenerator {
protected final int xSize;
protected final int ySize;
protected final int zSize;
protected double[] noise;
public PerlinOctaveGenerator(Random rand, int octaves, int xSize, int zSize) {
this(rand, octaves, xSize, 1, zSize);
}
public PerlinOctaveGenerator(Random rand, int octaves, int xSize, int ySize, int zSize) {
this(createOctaves(rand, octaves), rand, xSize, ySize, zSize);
}
public PerlinOctaveGenerator(NoiseGenerator[] octaves, Random rand, int xSize, int ySize, int zSize) {
super(octaves);
this.xSize = xSize;
this.ySize = ySize;
this.zSize = zSize;
noise = new double[xSize * ySize * zSize];
}
public double[] fBm(double x, double z, double lacunarity, double persistence) {
return fBm(x, 0, z, lacunarity, persistence);
}
public double[] fBm(double x, double y, double z, double lacunarity, double persistence) {
for (int i = 0; i < noise.length; i++) {
noise[i] = 0;
}
double freq = 1;
double amp = 1;
x = x * xScale;
y = y * yScale;
z = z * zScale;
// fBm
// the noise have to be periodic over x and z axis: otherwise it can go crazy with high input,
// leading to strange oddities in terrain generation like the old minecraft farland symptoms.
for (NoiseGenerator octave : octaves) {
double dX = x * freq;
double dY = y * freq;
double dZ = z * freq;
// compute integer part
long lX = floor(dX);
long lZ = floor(dZ);
// compute fractional part
dX -= lX;
dZ -= lZ;
// wrap integer part to 0..16777216
lX %= 16777216;
lZ %= 16777216;
// add to fractional part
dX += lX;
dZ += lZ;
noise = ((PerlinNoise) octave).getNoise(noise, dX, dY, dZ, xSize, ySize, zSize, xScale * freq, yScale * freq, zScale * freq, amp);
freq *= lacunarity;
amp *= persistence;
}
return noise;
}
protected static NoiseGenerator[] createOctaves(Random rand, int octaves) {
NoiseGenerator[] result = new NoiseGenerator[octaves];
for (int i = 0; i < octaves; i++) {
result[i] = new PerlinNoise(rand);
}
return result;
}
protected static long floor(double x) {
return x >= 0 ? (long) x : (long) x - 1;
}
}