diff --git a/common/addons/config-noise-function/src/jmh/java/com/dfsek/terra/noise_bench/Cellular.java b/common/addons/config-noise-function/src/jmh/java/com/dfsek/terra/noise_bench/Cellular.java index 3fa84a66f..e485e1f9c 100644 --- a/common/addons/config-noise-function/src/jmh/java/com/dfsek/terra/noise_bench/Cellular.java +++ b/common/addons/config-noise-function/src/jmh/java/com/dfsek/terra/noise_bench/Cellular.java @@ -1,7 +1,6 @@ package com.dfsek.terra.noise_bench; -import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler; -import com.dfsek.terra.api.block.state.properties.enums.RailShape; +import com.dfsek.terra.addons.noise.samplers.noise.cellular.CellularSampler; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.noise_bench.old.OldCellularSampler; @@ -11,7 +10,6 @@ import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Level; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; @@ -73,37 +71,37 @@ public class Cellular { } @Benchmark() - @Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS) + @Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS) @Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS) @Fork(warmups = 2, value = 3) - @BenchmarkMode(Mode.AverageTime) + @BenchmarkMode(Mode.Throughput) public void old2D(OldCellularParameters parameters, Blackhole blackhole) { blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y)); } @Benchmark - @Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS) + @Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS) @Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS) @Fork(warmups = 2, value = 3) - @BenchmarkMode(Mode.AverageTime) + @BenchmarkMode(Mode.Throughput) public void old3D(OldCellularParameters parameters, Blackhole blackhole) { blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y, parameters.z)); } @Benchmark - @Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS) + @Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS) @Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS) @Fork(warmups = 2, value = 3) - @BenchmarkMode(Mode.AverageTime) + @BenchmarkMode(Mode.Throughput) public void new2D(CellularParameters parameters, Blackhole blackhole) { blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y)); } @Benchmark - @Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS) + @Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS) @Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS) @Fork(warmups = 2, value = 3) - @BenchmarkMode(Mode.AverageTime) + @BenchmarkMode(Mode.Throughput) public void new3D(CellularParameters parameters, Blackhole blackhole) { blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y, parameters.z)); } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java index f06dff182..996abef98 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java @@ -40,7 +40,7 @@ import com.dfsek.terra.addons.noise.samplers.arithmetic.MaxSampler; import com.dfsek.terra.addons.noise.samplers.arithmetic.MinSampler; import com.dfsek.terra.addons.noise.samplers.arithmetic.MultiplicationSampler; import com.dfsek.terra.addons.noise.samplers.arithmetic.SubtractionSampler; -import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler; +import com.dfsek.terra.addons.noise.samplers.noise.cellular.CellularSampler; import com.dfsek.terra.addons.noise.samplers.noise.random.GaussianNoiseSampler; import com.dfsek.terra.addons.noise.samplers.noise.random.PositiveWhiteNoiseSampler; import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler; diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java index 48468b995..73dff8fd3 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java @@ -10,7 +10,7 @@ package com.dfsek.terra.addons.noise.config.templates.noise; import com.dfsek.tectonic.api.config.template.annotations.Default; import com.dfsek.tectonic.api.config.template.annotations.Value; -import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler; +import com.dfsek.terra.addons.noise.samplers.noise.cellular.CellularSampler; import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.noise.NoiseSampler; diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/cellular/CellularSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/cellular/CellularSampler.java new file mode 100644 index 000000000..ee91cb2dc --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/cellular/CellularSampler.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.cellular; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; +import com.dfsek.terra.api.noise.NoiseSampler; + + +/** + * NoiseSampler implementation for Cellular (Voronoi/Worley) Noise. + */ +public class CellularSampler extends NoiseFunction { + private DistanceFunction distanceFunction = DistanceFunction.EuclideanSq; + private ReturnType returnType = ReturnType.Distance; + private double jitterModifier = 1.0; + + private NoiseSampler noiseLookup; + + public CellularSampler() { + noiseLookup = new OpenSimplex2Sampler(); + } + + public void setDistanceFunction(DistanceFunction distanceFunction) { + this.distanceFunction = distanceFunction; + } + + public void setJitterModifier(double jitterModifier) { + this.jitterModifier = jitterModifier; + } + + public void setNoiseLookup(NoiseSampler noiseLookup) { + this.noiseLookup = noiseLookup; + } + + public void setReturnType(ReturnType returnType) { + this.returnType = returnType; + } + + @Override + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; + int xr = fastRound(x); + int yr = fastRound(y); + + double distance0 = Double.MAX_VALUE; + double distance1 = Double.MAX_VALUE; + double distance2 = Double.MAX_VALUE; + + int closestHash = 0; + + double cellularJitter = 0.43701595 * jitterModifier; + + int xPrimed = (xr - 1) * PRIME_X; + int yPrimedBase = (yr - 1) * PRIME_Y; + + double centerX = x; + double centerY = y; + + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int hash = hash(seed, xPrimed, yPrimed); + int idx = hash & (255 << 1); + + double vecX = (xi - x) + RandomVectors.RAND_VECS_2D[idx] * cellularJitter; + double vecY = (yi - y) + RandomVectors.RAND_VECS_2D[idx | 1] * cellularJitter; + + double newDistance = distanceFunction.getDistance(vecX, vecY); + + distance1 = fastMax(fastMin(distance1, newDistance), distance0); + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + centerX = ((xi + RandomVectors.RAND_VECS_2D[idx] * cellularJitter) / frequency); + centerY = ((yi + RandomVectors.RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); + } else if(newDistance < distance1) { + distance2 = distance1; + distance1 = newDistance; + } else if(newDistance < distance2) { + distance2 = newDistance; + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + + if(distanceFunction == DistanceFunction.Euclidean && returnType != ReturnType.CellValue) { + distance0 = fastSqrt(distance0); + if(returnType != ReturnType.CellValue) { + distance1 = fastSqrt(distance1); + } + } + + return switch(returnType) { + case CellValue -> closestHash * (1 / 2147483648.0); + case Distance -> distance0 - 1; + case Distance2 -> distance1 - 1; + case Distance2Add -> (distance1 + distance0) * 0.5 - 1; + case Distance2Sub -> distance1 - distance0 - 1; + case Distance2Mul -> distance1 * distance0 * 0.5 - 1; + case Distance2Div -> distance0 / distance1 - 1; + case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY); + case Distance3 -> distance2 - 1; + case Distance3Add -> (distance2 + distance0) * 0.5 - 1; + case Distance3Sub -> distance2 - distance0 - 1; + case Distance3Mul -> distance2 * distance0 - 1; + case Distance3Div -> distance0 / distance2 - 1; + case Angle -> FastMath.atan2(y / frequency - centerY, x / frequency - centerX); + }; + } + + @Override + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; + int xr = fastRound(x); + int yr = fastRound(y); + int zr = fastRound(z); + + double distance0 = Double.MAX_VALUE; + double distance1 = Double.MAX_VALUE; + double distance2 = Double.MAX_VALUE; + int closestHash = 0; + + double cellularJitter = 0.39614353 * jitterModifier; + + int xPrimed = (xr - 1) * PRIME_X; + int yPrimedBase = (yr - 1) * PRIME_Y; + int zPrimedBase = (zr - 1) * PRIME_Z; + + double centerX = x; + double centerY = y; + double centerZ = z; + + for(int xi = xr - 1; xi <= xr + 1; xi++) { + int yPrimed = yPrimedBase; + + for(int yi = yr - 1; yi <= yr + 1; yi++) { + int zPrimed = zPrimedBase; + + for(int zi = zr - 1; zi <= zr + 1; zi++) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + int idx = hash & (255 << 2); + + double vecX = (xi - x) + RandomVectors.RAND_VECS_3D[idx] * cellularJitter; + double vecY = (yi - y) + RandomVectors.RAND_VECS_3D[idx | 1] * cellularJitter; + double vecZ = (zi - z) + RandomVectors.RAND_VECS_3D[idx | 2] * cellularJitter; + + double newDistance = distanceFunction.getDistance(vecX, vecY, vecZ); + + if(newDistance < distance0) { + distance0 = newDistance; + closestHash = hash; + centerX = ((xi + RandomVectors.RAND_VECS_3D[idx] * cellularJitter) / frequency); + centerY = ((yi + RandomVectors.RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); + centerZ = ((zi + RandomVectors.RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); + } else if(newDistance < distance1) { + distance2 = distance1; + distance1 = newDistance; + } else if(newDistance < distance2) { + distance2 = newDistance; + } + zPrimed += PRIME_Z; + } + yPrimed += PRIME_Y; + } + xPrimed += PRIME_X; + } + + + if(distanceFunction == DistanceFunction.Euclidean && + returnType != ReturnType.CellValue) { // optimisation: dont compute sqrt until end + distance0 = fastSqrt(distance0); + if(returnType != ReturnType.CellValue) { + distance1 = fastSqrt(distance1); + } + } + + return switch(returnType) { + case CellValue -> closestHash * (1 / 2147483648.0); + case Distance -> distance0 - 1; + case Distance2 -> distance1 - 1; + case Distance2Add -> (distance1 + distance0) * 0.5 - 1; + case Distance2Sub -> distance1 - distance0 - 1; + case Distance2Mul -> distance1 * distance0 * 0.5 - 1; + case Distance2Div -> distance0 / distance1 - 1; + case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY, centerZ); + case Distance3 -> distance2 - 1; + case Distance3Add -> (distance2 + distance0) * 0.5 - 1; + case Distance3Sub -> distance2 - distance0 - 1; + case Distance3Mul -> distance2 * distance0 - 1; + case Distance3Div -> distance0 / distance2 - 1; + case Angle -> FastMath.atan2(y / frequency - centerY, x / frequency - centerX); + }; + } + + public enum DistanceFunction { + + Euclidean { + @Override + public double getDistance(double x, double y) { + return x * x + y * y; // optimisation: dont compute sqrt until end + } + + @Override + public double getDistance(double x, double y, double z) { + return x * x + y * y + z * z; // optimisation: dont compute sqrt until end + } + }, + EuclideanSq { + @Override + public double getDistance(double x, double y) { + return x * x + y * y; + } + + @Override + public double getDistance(double x, double y, double z) { + return x * x + y * y + z + z; + } + }, + Manhattan { + @Override + public double getDistance(double x, double y) { + return fastAbs(x) + fastAbs(y); + } + + @Override + public double getDistance(double x, double y, double z) { + return fastAbs(x) + fastAbs(y) + fastAbs(z); + } + }, + Hybrid { + @Override + public double getDistance(double x, double y) { + return (fastAbs(x) + fastAbs(y)) + + (x * x + y * y); + } + + @Override + public double getDistance(double x, double y, double z) { + return (fastAbs(x) + fastAbs(y) + fastAbs(z)) + + (x * x + y * y + z * z); + } + }; + + public abstract double getDistance(double x, double y); + + public abstract double getDistance(double x, double y, double z); + } + + + public enum ReturnType { + CellValue, + Distance, + Distance2, + Distance2Add, + Distance2Sub, + Distance2Mul, + Distance2Div, + NoiseLookup, + Distance3, + Distance3Add, + Distance3Sub, + Distance3Mul, + Distance3Div, + Angle + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/cellular/RandomVectors.java similarity index 57% rename from common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/cellular/RandomVectors.java index f31f81a3f..78efe8a5d 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/cellular/RandomVectors.java @@ -1,23 +1,7 @@ -/* - * Copyright (c) 2020-2021 Polyhedral Development - * - * The Terra Core Addons are licensed under the terms of the MIT License. For more details, - * reference the LICENSE file in this module's root directory. - */ +package com.dfsek.terra.addons.noise.samplers.noise.cellular; -package com.dfsek.terra.addons.noise.samplers.noise; - -import net.jafama.FastMath; - -import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; -import com.dfsek.terra.api.noise.NoiseSampler; - - -/** - * NoiseSampler implementation for Cellular (Voronoi/Worley) Noise. - */ -public class CellularSampler extends NoiseFunction { - private static final double[] RAND_VECS_3D = { +public class RandomVectors { + static final double[] RAND_VECS_3D = { -0.7292736885d, -0.6618439697d, 0.1735581948d, 0, 0.790292081d, -0.5480887466d, -0.2739291014d, 0, 0.7217578935d, 0.6226212466d, -0.3023380997d, 0, 0.565683137d, -0.8208298145d, -0.0790000257d, 0, 0.760049034d, -0.5555979497d, -0.3370999617d, 0, 0.3713945616d, 0.5011264475d, 0.7816254623d, 0, -0.1277062463d, -0.4254438999d, -0.8959289049d, 0, -0.2881560924d, @@ -125,8 +109,7 @@ public class CellularSampler extends NoiseFunction { -0.1842489331d, -0.9777375055d, -0.1004076743d, 0, 0.0775473789d, -0.9111505856d, 0.4047110257d, 0, 0.1399838409d, 0.7601631212d, -0.6344734459d, 0, 0.4484419361d, -0.845289248d, 0.2904925424d, 0 }; - - private static final double[] RAND_VECS_2D = { + static final double[] RAND_VECS_2D = { -0.2700222198d, -0.9628540911d, 0.3863092627d, -0.9223693152d, 0.04444859006d, -0.999011673d, -0.5992523158d, -0.8005602176d, -0.7819280288d, 0.6233687174d, 0.9464672271d, 0.3227999196d, -0.6514146797d, -0.7587218957d, 0.9378472289d, 0.347048376d, -0.8497875957d, -0.5271252623d, -0.879042592d, 0.4767432447d, -0.892300288d, -0.4514423508d, -0.379844434d, -0.9250503802d, @@ -192,359 +175,4 @@ public class CellularSampler extends NoiseFunction { 0.01426758847d, -0.9998982128d, -0.6734383991d, 0.7392433447d, 0.639412098d, -0.7688642071d, 0.9211571421d, 0.3891908523d, -0.146637214d, -0.9891903394d, -0.782318098d, 0.6228791163d, -0.5039610839d, -0.8637263605d, -0.7743120191d, -0.6328039957d, }; - - - private DistanceFunction distanceFunction = DistanceFunction.EuclideanSq; - private ReturnType returnType = ReturnType.Distance; - private double jitterModifier = 1.0; - - private NoiseSampler noiseLookup; - - public CellularSampler() { - noiseLookup = new OpenSimplex2Sampler(); - } - - public void setDistanceFunction(DistanceFunction distanceFunction) { - this.distanceFunction = distanceFunction; - } - - public void setJitterModifier(double jitterModifier) { - this.jitterModifier = jitterModifier; - } - - public void setNoiseLookup(NoiseSampler noiseLookup) { - this.noiseLookup = noiseLookup; - } - - public void setReturnType(ReturnType returnType) { - this.returnType = returnType; - } - - @Override - public double getNoiseRaw(long sl, double x, double y) { - int seed = (int) sl; - int xr = fastRound(x); - int yr = fastRound(y); - - double distance0 = Double.MAX_VALUE; - double distance1 = Double.MAX_VALUE; - double distance2 = Double.MAX_VALUE; - - int closestHash = 0; - - double cellularJitter = 0.43701595 * jitterModifier; - - int xPrimed = (xr - 1) * PRIME_X; - int yPrimedBase = (yr - 1) * PRIME_Y; - - double centerX = x; - double centerY = y; - - switch(distanceFunction) { - default: - case Euclidean: - case EuclideanSq: - for(int xi = xr - 1; xi <= xr + 1; xi++) { - int yPrimed = yPrimedBase; - - for(int yi = yr - 1; yi <= yr + 1; yi++) { - int hash = hash(seed, xPrimed, yPrimed); - int idx = hash & (255 << 1); - - double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; - double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; - - double newDistance = vecX * vecX + vecY * vecY; - - distance1 = fastMax(fastMin(distance1, newDistance), distance0); - if(newDistance < distance0) { - distance0 = newDistance; - closestHash = hash; - centerX = ((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); - centerY = ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); - } else if(newDistance < distance1) { - distance2 = distance1; - distance1 = newDistance; - } else if(newDistance < distance2) { - distance2 = newDistance; - } - yPrimed += PRIME_Y; - } - xPrimed += PRIME_X; - } - break; - case Manhattan: - for(int xi = xr - 1; xi <= xr + 1; xi++) { - int yPrimed = yPrimedBase; - - for(int yi = yr - 1; yi <= yr + 1; yi++) { - int hash = hash(seed, xPrimed, yPrimed); - int idx = hash & (255 << 1); - - double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; - double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; - - double newDistance = fastAbs(vecX) + fastAbs(vecY); - - distance1 = fastMax(fastMin(distance1, newDistance), distance0); - if(newDistance < distance0) { - distance0 = newDistance; - closestHash = hash; - centerX = ((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); - centerY = ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); - } else if(newDistance < distance1) { - distance2 = distance1; - distance1 = newDistance; - } else if(newDistance < distance2) { - distance2 = newDistance; - } - yPrimed += PRIME_Y; - } - xPrimed += PRIME_X; - } - break; - case Hybrid: - for(int xi = xr - 1; xi <= xr + 1; xi++) { - int yPrimed = yPrimedBase; - - for(int yi = yr - 1; yi <= yr + 1; yi++) { - int hash = hash(seed, xPrimed, yPrimed); - int idx = hash & (255 << 1); - - double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; - double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; - - double newDistance = (fastAbs(vecX) + fastAbs(vecY)) + (vecX * vecX + vecY * vecY); - - distance1 = fastMax(fastMin(distance1, newDistance), distance0); - if(newDistance < distance0) { - distance0 = newDistance; - closestHash = hash; - centerX = ((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); - centerY = ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); - } else if(newDistance < distance1) { - distance2 = distance1; - distance1 = newDistance; - } else if(newDistance < distance2) { - distance2 = newDistance; - } - yPrimed += PRIME_Y; - } - xPrimed += PRIME_X; - } - break; - } - - if(distanceFunction == DistanceFunction.Euclidean && returnType != ReturnType.CellValue) { - distance0 = fastSqrt(distance0); - if(returnType != ReturnType.CellValue) { - distance1 = fastSqrt(distance1); - } - } - - return switch(returnType) { - case CellValue -> closestHash * (1 / 2147483648.0); - case Distance -> distance0 - 1; - case Distance2 -> distance1 - 1; - case Distance2Add -> (distance1 + distance0) * 0.5 - 1; - case Distance2Sub -> distance1 - distance0 - 1; - case Distance2Mul -> distance1 * distance0 * 0.5 - 1; - case Distance2Div -> distance0 / distance1 - 1; - case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY); - case Distance3 -> distance2 - 1; - case Distance3Add -> (distance2 + distance0) * 0.5 - 1; - case Distance3Sub -> distance2 - distance0 - 1; - case Distance3Mul -> distance2 * distance0 - 1; - case Distance3Div -> distance0 / distance2 - 1; - case Angle -> FastMath.atan2(y / frequency - centerY, x / frequency - centerX); - }; - } - - @Override - public double getNoiseRaw(long sl, double x, double y, double z) { - int seed = (int) sl; - int xr = fastRound(x); - int yr = fastRound(y); - int zr = fastRound(z); - - double distance0 = Double.MAX_VALUE; - double distance1 = Double.MAX_VALUE; - double distance2 = Double.MAX_VALUE; - int closestHash = 0; - - double cellularJitter = 0.39614353 * jitterModifier; - - int xPrimed = (xr - 1) * PRIME_X; - int yPrimedBase = (yr - 1) * PRIME_Y; - int zPrimedBase = (zr - 1) * PRIME_Z; - - double centerX = x; - double centerY = y; - double centerZ = z; - - switch(distanceFunction) { - case Euclidean: - case EuclideanSq: - for(int xi = xr - 1; xi <= xr + 1; xi++) { - int yPrimed = yPrimedBase; - - for(int yi = yr - 1; yi <= yr + 1; yi++) { - int zPrimed = zPrimedBase; - - for(int zi = zr - 1; zi <= zr + 1; zi++) { - int hash = hash(seed, xPrimed, yPrimed, zPrimed); - int idx = hash & (255 << 2); - - double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; - double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; - double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; - - double newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; - - if(newDistance < distance0) { - distance0 = newDistance; - closestHash = hash; - centerX = ((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); - centerY = ((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); - centerZ = ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); - } else if(newDistance < distance1) { - distance2 = distance1; - distance1 = newDistance; - } else if(newDistance < distance2) { - distance2 = newDistance; - } - zPrimed += PRIME_Z; - } - yPrimed += PRIME_Y; - } - xPrimed += PRIME_X; - } - break; - case Manhattan: - for(int xi = xr - 1; xi <= xr + 1; xi++) { - int yPrimed = yPrimedBase; - - for(int yi = yr - 1; yi <= yr + 1; yi++) { - int zPrimed = zPrimedBase; - - for(int zi = zr - 1; zi <= zr + 1; zi++) { - int hash = hash(seed, xPrimed, yPrimed, zPrimed); - int idx = hash & (255 << 2); - - double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; - double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; - double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; - - double newDistance = fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ); - - if(newDistance < distance0) { - distance0 = newDistance; - closestHash = hash; - centerX = ((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); - centerY = ((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); - centerZ = ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); - } else if(newDistance < distance1) { - distance2 = distance1; - distance1 = newDistance; - } else if(newDistance < distance2) { - distance2 = newDistance; - } - zPrimed += PRIME_Z; - } - yPrimed += PRIME_Y; - } - xPrimed += PRIME_X; - } - break; - case Hybrid: - for(int xi = xr - 1; xi <= xr + 1; xi++) { - int yPrimed = yPrimedBase; - - for(int yi = yr - 1; yi <= yr + 1; yi++) { - int zPrimed = zPrimedBase; - - for(int zi = zr - 1; zi <= zr + 1; zi++) { - int hash = hash(seed, xPrimed, yPrimed, zPrimed); - int idx = hash & (255 << 2); - - double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; - double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; - double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; - - double newDistance = (fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ)) + - (vecX * vecX + vecY * vecY + vecZ * vecZ); - - distance1 = fastMax(fastMin(distance1, newDistance), distance0); - if(newDistance < distance0) { - distance0 = newDistance; - closestHash = hash; - centerX = ((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); - centerY = ((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); - centerZ = ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); - } else if(newDistance < distance1) { - distance2 = distance1; - distance1 = newDistance; - } else if(newDistance < distance2) { - distance2 = newDistance; - } - zPrimed += PRIME_Z; - } - yPrimed += PRIME_Y; - } - xPrimed += PRIME_X; - } - break; - default: - break; - } - - if(distanceFunction == DistanceFunction.Euclidean && returnType != ReturnType.CellValue) { - distance0 = fastSqrt(distance0); - if(returnType != ReturnType.CellValue) { - distance1 = fastSqrt(distance1); - } - } - - return switch(returnType) { - case CellValue -> closestHash * (1 / 2147483648.0); - case Distance -> distance0 - 1; - case Distance2 -> distance1 - 1; - case Distance2Add -> (distance1 + distance0) * 0.5 - 1; - case Distance2Sub -> distance1 - distance0 - 1; - case Distance2Mul -> distance1 * distance0 * 0.5 - 1; - case Distance2Div -> distance0 / distance1 - 1; - case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY, centerZ); - case Distance3 -> distance2 - 1; - case Distance3Add -> (distance2 + distance0) * 0.5 - 1; - case Distance3Sub -> distance2 - distance0 - 1; - case Distance3Mul -> distance2 * distance0 - 1; - case Distance3Div -> distance0 / distance2 - 1; - case Angle -> FastMath.atan2(y / frequency - centerY, x / frequency - centerX); - }; - } - - public enum DistanceFunction { - Euclidean, - EuclideanSq, - Manhattan, - Hybrid - } - - - public enum ReturnType { - CellValue, - Distance, - Distance2, - Distance2Add, - Distance2Sub, - Distance2Mul, - Distance2Div, - NoiseLookup, - Distance3, - Distance3Add, - Distance3Sub, - Distance3Mul, - Distance3Div, - Angle - } }