214 lines
6.3 KiB
Java
214 lines
6.3 KiB
Java
package com.hypixel.hytale.builtin.hytalegenerator.fields.noise;
|
|
|
|
import java.util.Random;
|
|
import javax.annotation.Nonnull;
|
|
|
|
public class SimplexNoiseField extends NoiseField {
|
|
private final long seed;
|
|
@Nonnull
|
|
private final double[] offsetX;
|
|
@Nonnull
|
|
private final double[] offsetY;
|
|
@Nonnull
|
|
private final double[] offsetZ;
|
|
@Nonnull
|
|
private final double[] offsetW;
|
|
private final int numberOfOctaves;
|
|
@Nonnull
|
|
private final double[] octaveFrequency;
|
|
@Nonnull
|
|
private final double[] octaveAmplitude;
|
|
private final double normalizer;
|
|
|
|
public SimplexNoiseField(long seed, double octaveAmplitudeMultiplier, double octaveFrequencyMultiplier, int numberOfOctaves) {
|
|
if (numberOfOctaves <= 0) {
|
|
throw new IllegalArgumentException("octaves can't be smaller than 1");
|
|
} else {
|
|
this.seed = seed;
|
|
this.numberOfOctaves = numberOfOctaves;
|
|
Random rand = new Random(seed);
|
|
this.offsetX = new double[numberOfOctaves];
|
|
this.offsetY = new double[numberOfOctaves];
|
|
this.offsetZ = new double[numberOfOctaves];
|
|
this.offsetW = new double[numberOfOctaves];
|
|
|
|
for (int i = 0; i < numberOfOctaves; i++) {
|
|
this.offsetX[i] = rand.nextDouble() * 256.0;
|
|
this.offsetY[i] = rand.nextDouble() * 256.0;
|
|
this.offsetZ[i] = rand.nextDouble() * 256.0;
|
|
this.offsetW[i] = rand.nextDouble() * 256.0;
|
|
}
|
|
|
|
this.octaveAmplitude = new double[numberOfOctaves];
|
|
this.octaveFrequency = new double[numberOfOctaves];
|
|
double frequency = 1.0;
|
|
double amplitude = 1.0;
|
|
double maxAmplitude = 0.0;
|
|
|
|
for (int i = 0; i < numberOfOctaves; i++) {
|
|
this.octaveAmplitude[i] = amplitude;
|
|
this.octaveFrequency[i] = frequency;
|
|
maxAmplitude += amplitude;
|
|
amplitude *= octaveAmplitudeMultiplier;
|
|
frequency *= octaveFrequencyMultiplier;
|
|
}
|
|
|
|
this.normalizer = 1.0 / maxAmplitude;
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
public static SimplexNoiseField.Builder builder() {
|
|
return new SimplexNoiseField.Builder();
|
|
}
|
|
|
|
@Override
|
|
public double valueAt(double x, double y, double z, double w) {
|
|
x /= this.scaleX;
|
|
y /= this.scaleY;
|
|
z /= this.scaleZ;
|
|
w /= this.scaleW;
|
|
double octaveX = 0.0;
|
|
double octaveY = 0.0;
|
|
double octaveZ = 0.0;
|
|
double octaveW = 0.0;
|
|
double value = 0.0;
|
|
|
|
for (int i = 0; i < this.numberOfOctaves; i++) {
|
|
octaveX = x + this.offsetX[i];
|
|
octaveY = y + this.offsetY[i];
|
|
octaveZ = z + this.offsetZ[i];
|
|
octaveW = w + this.offsetW[i];
|
|
value += Simplex.noise(
|
|
octaveX * this.octaveFrequency[i], octaveY * this.octaveFrequency[i], octaveZ * this.octaveFrequency[i], octaveW * this.octaveFrequency[i]
|
|
)
|
|
* this.octaveAmplitude[i];
|
|
}
|
|
|
|
return value * this.normalizer;
|
|
}
|
|
|
|
@Override
|
|
public double valueAt(double x, double y, double z) {
|
|
x /= this.scaleX;
|
|
y /= this.scaleY;
|
|
z /= this.scaleZ;
|
|
double octaveX = 0.0;
|
|
double octaveY = 0.0;
|
|
double octaveZ = 0.0;
|
|
double value = 0.0;
|
|
|
|
for (int i = 0; i < this.numberOfOctaves; i++) {
|
|
octaveX = x + this.offsetX[i];
|
|
octaveY = y + this.offsetY[i];
|
|
octaveZ = z + this.offsetZ[i];
|
|
value += Simplex.noise(octaveX * this.octaveFrequency[i], octaveY * this.octaveFrequency[i], octaveZ * this.octaveFrequency[i])
|
|
* this.octaveAmplitude[i];
|
|
}
|
|
|
|
return value * this.normalizer;
|
|
}
|
|
|
|
@Override
|
|
public double valueAt(double x, double y) {
|
|
x /= this.scaleX;
|
|
y /= this.scaleY;
|
|
double octaveX = 0.0;
|
|
double octaveY = 0.0;
|
|
double value = 0.0;
|
|
|
|
for (int i = 0; i < this.numberOfOctaves; i++) {
|
|
octaveX = x + this.offsetX[i];
|
|
octaveY = y + this.offsetY[i];
|
|
value += Simplex.noise(octaveX * this.octaveFrequency[i], octaveY * this.octaveFrequency[i]) * this.octaveAmplitude[i];
|
|
}
|
|
|
|
return value * this.normalizer;
|
|
}
|
|
|
|
@Override
|
|
public double valueAt(double x) {
|
|
x /= this.scaleX;
|
|
double octaveX = 0.0;
|
|
double value = 0.0;
|
|
|
|
for (int i = 0; i < this.numberOfOctaves; i++) {
|
|
octaveX = x + this.offsetX[i];
|
|
value += Simplex.noise(octaveX * this.octaveFrequency[i], 0.0) * this.octaveAmplitude[i];
|
|
}
|
|
|
|
return value * this.normalizer;
|
|
}
|
|
|
|
public long getSeed() {
|
|
return this.seed;
|
|
}
|
|
|
|
public static class Builder {
|
|
private long seed = 1L;
|
|
private double octaveAmplitudeMultiplier = 0.5;
|
|
private double octaveFrequencyMultiplier = 2.0;
|
|
private int numberOfOctaves = 4;
|
|
private double scaleX;
|
|
private double scaleY;
|
|
private double scaleZ;
|
|
private double scaleW;
|
|
|
|
private Builder() {
|
|
}
|
|
|
|
@Nonnull
|
|
public SimplexNoiseField build() {
|
|
SimplexNoiseField g = new SimplexNoiseField(this.seed, this.octaveAmplitudeMultiplier, this.octaveFrequencyMultiplier, this.numberOfOctaves);
|
|
g.setScale(this.scaleX, this.scaleY, this.scaleZ, this.scaleW);
|
|
return g;
|
|
}
|
|
|
|
@Nonnull
|
|
public SimplexNoiseField.Builder withScale(double s) {
|
|
this.scaleX = s;
|
|
this.scaleY = s;
|
|
this.scaleZ = s;
|
|
this.scaleW = s;
|
|
return this;
|
|
}
|
|
|
|
@Nonnull
|
|
public SimplexNoiseField.Builder withScale(double x, double y, double z, double w) {
|
|
this.scaleX = x;
|
|
this.scaleY = y;
|
|
this.scaleZ = z;
|
|
this.scaleW = w;
|
|
return this;
|
|
}
|
|
|
|
@Nonnull
|
|
public SimplexNoiseField.Builder withNumberOfOctaves(int n) {
|
|
if (n <= 0) {
|
|
throw new IllegalArgumentException("invalid number");
|
|
} else {
|
|
this.numberOfOctaves = n;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
public SimplexNoiseField.Builder withFrequencyMultiplier(double f) {
|
|
this.octaveFrequencyMultiplier = f;
|
|
return this;
|
|
}
|
|
|
|
@Nonnull
|
|
public SimplexNoiseField.Builder withAmplitudeMultiplier(double a) {
|
|
this.octaveAmplitudeMultiplier = a;
|
|
return this;
|
|
}
|
|
|
|
@Nonnull
|
|
public SimplexNoiseField.Builder withSeed(long s) {
|
|
this.seed = s;
|
|
return this;
|
|
}
|
|
}
|
|
}
|