minecraft-src/net/minecraft/world/level/levelgen/synth/SimplexNoise.java
2025-07-04 01:41:11 +03:00

206 lines
4.6 KiB
Java

package net.minecraft.world.level.levelgen.synth;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
/**
* A generator for a single octave of Simplex noise.
*/
public class SimplexNoise {
protected static final int[][] GRADIENT = new int[][]{
{1, 1, 0},
{-1, 1, 0},
{1, -1, 0},
{-1, -1, 0},
{1, 0, 1},
{-1, 0, 1},
{1, 0, -1},
{-1, 0, -1},
{0, 1, 1},
{0, -1, 1},
{0, 1, -1},
{0, -1, -1},
{1, 1, 0},
{0, -1, 1},
{-1, 1, 0},
{0, -1, -1}
};
private static final double SQRT_3 = Math.sqrt(3.0);
private static final double F2 = 0.5 * (SQRT_3 - 1.0);
private static final double G2 = (3.0 - SQRT_3) / 6.0;
/**
* A permutation array used in noise generation.
* This is populated with the values [0, 256) and shuffled. Despite the array declared as 512 length, only the first 256 values are used.
*
* @see #p(int)
*/
private final int[] p = new int[512];
public final double xo;
public final double yo;
public final double zo;
public SimplexNoise(RandomSource random) {
this.xo = random.nextDouble() * 256.0;
this.yo = random.nextDouble() * 256.0;
this.zo = random.nextDouble() * 256.0;
int i = 0;
while (i < 256) {
this.p[i] = i++;
}
for (int ix = 0; ix < 256; ix++) {
int j = random.nextInt(256 - ix);
int k = this.p[ix];
this.p[ix] = this.p[j + ix];
this.p[j + ix] = k;
}
}
private int p(int index) {
return this.p[index & 0xFF];
}
/**
* @return The dot product of the provided three-dimensional gradient vector and the vector (x, y, z)
*/
protected static double dot(int[] gradient, double x, double y, double z) {
return gradient[0] * x + gradient[1] * y + gradient[2] * z;
}
private double getCornerNoise3D(int gradientIndex, double x, double y, double z, double offset) {
double d = offset - x * x - y * y - z * z;
double e;
if (d < 0.0) {
e = 0.0;
} else {
d *= d;
e = d * d * dot(GRADIENT[gradientIndex], x, y, z);
}
return e;
}
public double getValue(double x, double y) {
double d = (x + y) * F2;
int i = Mth.floor(x + d);
int j = Mth.floor(y + d);
double e = (i + j) * G2;
double f = i - e;
double g = j - e;
double h = x - f;
double k = y - g;
int l;
int m;
if (h > k) {
l = 1;
m = 0;
} else {
l = 0;
m = 1;
}
double n = h - l + G2;
double o = k - m + G2;
double p = h - 1.0 + 2.0 * G2;
double q = k - 1.0 + 2.0 * G2;
int r = i & 0xFF;
int s = j & 0xFF;
int t = this.p(r + this.p(s)) % 12;
int u = this.p(r + l + this.p(s + m)) % 12;
int v = this.p(r + 1 + this.p(s + 1)) % 12;
double w = this.getCornerNoise3D(t, h, k, 0.0, 0.5);
double z = this.getCornerNoise3D(u, n, o, 0.0, 0.5);
double aa = this.getCornerNoise3D(v, p, q, 0.0, 0.5);
return 70.0 * (w + z + aa);
}
public double getValue(double x, double y, double z) {
double d = 0.3333333333333333;
double e = (x + y + z) * 0.3333333333333333;
int i = Mth.floor(x + e);
int j = Mth.floor(y + e);
int k = Mth.floor(z + e);
double f = 0.16666666666666666;
double g = (i + j + k) * 0.16666666666666666;
double h = i - g;
double l = j - g;
double m = k - g;
double n = x - h;
double o = y - l;
double p = z - m;
int q;
int r;
int s;
int t;
int u;
int v;
if (n >= o) {
if (o >= p) {
q = 1;
r = 0;
s = 0;
t = 1;
u = 1;
v = 0;
} else if (n >= p) {
q = 1;
r = 0;
s = 0;
t = 1;
u = 0;
v = 1;
} else {
q = 0;
r = 0;
s = 1;
t = 1;
u = 0;
v = 1;
}
} else if (o < p) {
q = 0;
r = 0;
s = 1;
t = 0;
u = 1;
v = 1;
} else if (n < p) {
q = 0;
r = 1;
s = 0;
t = 0;
u = 1;
v = 1;
} else {
q = 0;
r = 1;
s = 0;
t = 1;
u = 1;
v = 0;
}
double w = n - q + 0.16666666666666666;
double aa = o - r + 0.16666666666666666;
double ab = p - s + 0.16666666666666666;
double ac = n - t + 0.3333333333333333;
double ad = o - u + 0.3333333333333333;
double ae = p - v + 0.3333333333333333;
double af = n - 1.0 + 0.5;
double ag = o - 1.0 + 0.5;
double ah = p - 1.0 + 0.5;
int ai = i & 0xFF;
int aj = j & 0xFF;
int ak = k & 0xFF;
int al = this.p(ai + this.p(aj + this.p(ak))) % 12;
int am = this.p(ai + q + this.p(aj + r + this.p(ak + s))) % 12;
int an = this.p(ai + t + this.p(aj + u + this.p(ak + v))) % 12;
int ao = this.p(ai + 1 + this.p(aj + 1 + this.p(ak + 1))) % 12;
double ap = this.getCornerNoise3D(al, n, o, p, 0.6);
double aq = this.getCornerNoise3D(am, w, aa, ab, 0.6);
double ar = this.getCornerNoise3D(an, ac, ad, ae, 0.6);
double as = this.getCornerNoise3D(ao, af, ag, ah, 0.6);
return 32.0 * (ap + aq + ar + as);
}
}