mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-03 16:35:50 +00:00
clean up CellularSampler
This commit is contained in:
parent
cef185b07d
commit
3f48b616fe
@ -1,7 +1,6 @@
|
|||||||
package com.dfsek.terra.noise_bench;
|
package com.dfsek.terra.noise_bench;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler;
|
import com.dfsek.terra.addons.noise.samplers.noise.cellular.CellularSampler;
|
||||||
import com.dfsek.terra.api.block.state.properties.enums.RailShape;
|
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
|
||||||
import com.dfsek.terra.noise_bench.old.OldCellularSampler;
|
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.Level;
|
||||||
import org.openjdk.jmh.annotations.Measurement;
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
import org.openjdk.jmh.annotations.Mode;
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
import org.openjdk.jmh.annotations.Param;
|
|
||||||
import org.openjdk.jmh.annotations.Scope;
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
import org.openjdk.jmh.annotations.Setup;
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
import org.openjdk.jmh.annotations.State;
|
import org.openjdk.jmh.annotations.State;
|
||||||
@ -73,37 +71,37 @@ public class Cellular {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark()
|
@Benchmark()
|
||||||
@Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS)
|
@Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Fork(warmups = 2, value = 3)
|
@Fork(warmups = 2, value = 3)
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.Throughput)
|
||||||
public void old2D(OldCellularParameters parameters, Blackhole blackhole) {
|
public void old2D(OldCellularParameters parameters, Blackhole blackhole) {
|
||||||
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y));
|
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS)
|
@Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Fork(warmups = 2, value = 3)
|
@Fork(warmups = 2, value = 3)
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.Throughput)
|
||||||
public void old3D(OldCellularParameters parameters, Blackhole blackhole) {
|
public void old3D(OldCellularParameters parameters, Blackhole blackhole) {
|
||||||
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y, parameters.z));
|
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y, parameters.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS)
|
@Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Fork(warmups = 2, value = 3)
|
@Fork(warmups = 2, value = 3)
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.Throughput)
|
||||||
public void new2D(CellularParameters parameters, Blackhole blackhole) {
|
public void new2D(CellularParameters parameters, Blackhole blackhole) {
|
||||||
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y));
|
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@Warmup(iterations = 25, time = 300, timeUnit = MILLISECONDS)
|
@Warmup(iterations = 25, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
@Measurement(iterations = 15, time = 200, timeUnit = MILLISECONDS)
|
||||||
@Fork(warmups = 2, value = 3)
|
@Fork(warmups = 2, value = 3)
|
||||||
@BenchmarkMode(Mode.AverageTime)
|
@BenchmarkMode(Mode.Throughput)
|
||||||
public void new3D(CellularParameters parameters, Blackhole blackhole) {
|
public void new3D(CellularParameters parameters, Blackhole blackhole) {
|
||||||
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y, parameters.z));
|
blackhole.consume(parameters.sampler.noise(parameters.seed, parameters.x, parameters.y, parameters.z));
|
||||||
}
|
}
|
||||||
|
@ -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.MinSampler;
|
||||||
import com.dfsek.terra.addons.noise.samplers.arithmetic.MultiplicationSampler;
|
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.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.GaussianNoiseSampler;
|
||||||
import com.dfsek.terra.addons.noise.samplers.noise.random.PositiveWhiteNoiseSampler;
|
import com.dfsek.terra.addons.noise.samplers.noise.random.PositiveWhiteNoiseSampler;
|
||||||
import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler;
|
import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler;
|
||||||
|
@ -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.Default;
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
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.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +1,7 @@
|
|||||||
/*
|
package com.dfsek.terra.addons.noise.samplers.noise.cellular;
|
||||||
* 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;
|
public class RandomVectors {
|
||||||
|
static final double[] RAND_VECS_3D = {
|
||||||
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 = {
|
|
||||||
-0.7292736885d, -0.6618439697d, 0.1735581948d, 0, 0.790292081d, -0.5480887466d, -0.2739291014d, 0, 0.7217578935d, 0.6226212466d,
|
-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.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,
|
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.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
|
0.7601631212d, -0.6344734459d, 0, 0.4484419361d, -0.845289248d, 0.2904925424d, 0
|
||||||
};
|
};
|
||||||
|
static final double[] RAND_VECS_2D = {
|
||||||
private static final double[] RAND_VECS_2D = {
|
|
||||||
-0.2700222198d, -0.9628540911d, 0.3863092627d, -0.9223693152d, 0.04444859006d, -0.999011673d, -0.5992523158d, -0.8005602176d,
|
-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.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,
|
-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.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,
|
-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
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user