From 02198e1b881f25704c4763d9009b760037dd2f44 Mon Sep 17 00:00:00 2001 From: Astrash Date: Tue, 18 Jul 2023 14:29:28 +1000 Subject: [PATCH] Implement distance sampler --- .../dfsek/terra/addons/noise/NoiseAddon.java | 4 ++ .../noise/DistanceSamplerTemplate.java | 42 ++++++++++++ .../noise/samplers/noise/DistanceSampler.java | 66 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/DistanceSamplerTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/DistanceSampler.java 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 2417921e7..b002f29a4 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 @@ -24,6 +24,7 @@ import com.dfsek.terra.addons.noise.config.templates.LinearHeightmapSamplerTempl import com.dfsek.terra.addons.noise.config.templates.TranslateSamplerTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.CellularNoiseTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.ConstantNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.DistanceSamplerTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.ExpressionFunctionTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.GaborNoiseTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.SimpleNoiseTemplate; @@ -44,6 +45,7 @@ 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.DistanceSampler; 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; @@ -85,6 +87,8 @@ public class NoiseAddon implements AddonInitializer { (type, o, loader, depthTracker) -> CellularSampler.DistanceFunction.valueOf((String) o)) .applyLoader(CellularSampler.ReturnType.class, (type, o, loader, depthTracker) -> CellularSampler.ReturnType.valueOf((String) o)) + .applyLoader(DistanceSampler.DistanceFunction.class, + (type, o, loader, depthTracker) -> DistanceSampler.DistanceFunction.valueOf((String) o)) .applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new) .applyLoader(FunctionTemplate.class, FunctionTemplate::new); diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/DistanceSamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/DistanceSamplerTemplate.java new file mode 100644 index 000000000..1bd6fb2dc --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/DistanceSamplerTemplate.java @@ -0,0 +1,42 @@ +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.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.DistanceSampler; +import com.dfsek.terra.addons.noise.samplers.noise.DistanceSampler.DistanceFunction; +import com.dfsek.terra.api.config.meta.Meta; + + +public class DistanceSamplerTemplate extends SamplerTemplate { + + @Value("distance-function") + @Default + private DistanceSampler.@Meta DistanceFunction distanceFunction = DistanceFunction.Euclidean; + + @Value("point.x") + @Default + private @Meta double x = 0; + + @Value("point.y") + @Default + private @Meta double y = 0; + + @Value("point.z") + @Default + private @Meta double z = 0; + + @Value("normalize") + @Default + private @Meta boolean normalize = false; + + @Value("radius") + @Default + private @Meta double normalizeRadius = 100; + + @Override + public DistanceSampler get() { + return new DistanceSampler(distanceFunction, x, y, z, normalize, normalizeRadius); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/DistanceSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/DistanceSampler.java new file mode 100644 index 000000000..1e083fb86 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/DistanceSampler.java @@ -0,0 +1,66 @@ +package com.dfsek.terra.addons.noise.samplers.noise; + + +public class DistanceSampler extends NoiseFunction { + + private final DistanceFunction distanceFunction; + private final double ox, oy, oz; + private final boolean normalize; + private final double radius; + + private final double distanceAtRadius; + + public DistanceSampler(DistanceFunction distanceFunction, double ox, double oy, double oz, boolean normalize, double radius) { + frequency = 1; + this.distanceFunction = distanceFunction; + this.ox = ox; + this.oy = oy; + this.oz = oz; + this.normalize = normalize; + this.radius = radius; + this.distanceAtRadius = distance2d(distanceFunction, radius, 0); // distance2d and distance3d should return the same value + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + double dx = x - ox; + double dy = y - oz; + if (normalize && (fastAbs(dx) > radius || fastAbs(dy) > radius)) return 1; + double dist = distance2d(distanceFunction, dx, dy); + if (normalize) return fastMin(((2*dist)/distanceAtRadius)-1, 1); + return dist; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + double dx = x - ox; + double dy = y - oy; + double dz = z - oz; + if(normalize && (fastAbs(dx) > radius || fastAbs(dy) > radius || fastAbs(dz) > radius)) return 1; + double dist = distance3d(distanceFunction, dx, dy, dz); + if (normalize) return fastMin(((2*dist)/distanceAtRadius)-1, 1); + return dist; + } + + private static double distance2d(DistanceFunction distanceFunction, double x, double z) { + return switch(distanceFunction) { + case Euclidean -> fastSqrt(x*x + z*z); + case EuclideanSq -> x*x + z*z; + case Manhattan -> fastAbs(x) + fastAbs(z); + }; + } + + private static double distance3d(DistanceFunction distanceFunction, double x, double y, double z) { + return switch(distanceFunction) { + case Euclidean -> fastSqrt(x*x + y*y + z*z); + case EuclideanSq -> x*x + y*y + z*z; + case Manhattan -> fastAbs(x) + fastAbs(y) + fastAbs(z); + }; + } + + public enum DistanceFunction { + Euclidean, + EuclideanSq, + Manhattan + } +}