83 lines
2.7 KiB
Java
83 lines
2.7 KiB
Java
package net.minecraft.world.level.levelgen.synth;
|
|
|
|
import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
|
|
import it.unimi.dsi.fastutil.ints.IntSortedSet;
|
|
import java.util.List;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
|
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
|
|
|
/**
|
|
* This class generates multiple octaves of simplex noise. Each individual octave is an instance of {@link net.minecraft.world.level.levelgen.synth.SimplexNoise}.
|
|
* Mojang uses the term 'Perlin' to describe octaves or fBm (Fractal Brownian Motion) noise and this class does not actually generate Perlin noise.
|
|
*/
|
|
public class PerlinSimplexNoise {
|
|
private final SimplexNoise[] noiseLevels;
|
|
private final double highestFreqValueFactor;
|
|
private final double highestFreqInputFactor;
|
|
|
|
public PerlinSimplexNoise(RandomSource random, List<Integer> octaves) {
|
|
this(random, new IntRBTreeSet(octaves));
|
|
}
|
|
|
|
private PerlinSimplexNoise(RandomSource random, IntSortedSet octaves) {
|
|
if (octaves.isEmpty()) {
|
|
throw new IllegalArgumentException("Need some octaves!");
|
|
} else {
|
|
int i = -octaves.firstInt();
|
|
int j = octaves.lastInt();
|
|
int k = i + j + 1;
|
|
if (k < 1) {
|
|
throw new IllegalArgumentException("Total number of octaves needs to be >= 1");
|
|
} else {
|
|
SimplexNoise simplexNoise = new SimplexNoise(random);
|
|
int l = j;
|
|
this.noiseLevels = new SimplexNoise[k];
|
|
if (j >= 0 && j < k && octaves.contains(0)) {
|
|
this.noiseLevels[j] = simplexNoise;
|
|
}
|
|
|
|
for (int m = j + 1; m < k; m++) {
|
|
if (m >= 0 && octaves.contains(l - m)) {
|
|
this.noiseLevels[m] = new SimplexNoise(random);
|
|
} else {
|
|
random.consumeCount(262);
|
|
}
|
|
}
|
|
|
|
if (j > 0) {
|
|
long n = (long)(simplexNoise.getValue(simplexNoise.xo, simplexNoise.yo, simplexNoise.zo) * 9.223372E18F);
|
|
RandomSource randomSource = new WorldgenRandom(new LegacyRandomSource(n));
|
|
|
|
for (int o = l - 1; o >= 0; o--) {
|
|
if (o < k && octaves.contains(l - o)) {
|
|
this.noiseLevels[o] = new SimplexNoise(randomSource);
|
|
} else {
|
|
randomSource.consumeCount(262);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.highestFreqInputFactor = Math.pow(2.0, j);
|
|
this.highestFreqValueFactor = 1.0 / (Math.pow(2.0, k) - 1.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
public double getValue(double x, double y, boolean useNoiseOffsets) {
|
|
double d = 0.0;
|
|
double e = this.highestFreqInputFactor;
|
|
double f = this.highestFreqValueFactor;
|
|
|
|
for (SimplexNoise simplexNoise : this.noiseLevels) {
|
|
if (simplexNoise != null) {
|
|
d += simplexNoise.getValue(x * e + (useNoiseOffsets ? simplexNoise.xo : 0.0), y * e + (useNoiseOffsets ? simplexNoise.yo : 0.0)) * f;
|
|
}
|
|
|
|
e /= 2.0;
|
|
f *= 2.0;
|
|
}
|
|
|
|
return d;
|
|
}
|
|
}
|