From 7e0fd93708fcbc004ea26d31ef4ed8f12ada1b11 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 17 Oct 2021 15:07:58 -0700 Subject: [PATCH] Initial commit --- common/addons/config-noise-function/README.md | 3 + .../config-noise-function/build.gradle.kts | 2 + .../dfsek/terra/addons/noise/NoiseAddon.java | 115 ++++ .../addons/noise/NoiseConfigPackTemplate.java | 30 + .../DimensionApplicableNoiseSampler.java | 29 + .../config/templates/DomainWarpTemplate.java | 27 + .../config/templates/FunctionTemplate.java | 31 + .../templates/ImageSamplerTemplate.java | 28 + .../config/templates/KernelTemplate.java | 62 ++ .../config/templates/SamplerTemplate.java | 28 + .../noise/CellularNoiseTemplate.java | 42 ++ .../noise/ConstantNoiseTemplate.java | 22 + .../noise/ExpressionFunctionTemplate.java | 97 ++++ .../templates/noise/GaborNoiseTemplate.java | 44 ++ .../config/templates/noise/NoiseTemplate.java | 20 + .../templates/noise/SimpleNoiseTemplate.java | 23 + .../noise/fractal/BrownianMotionTemplate.java | 17 + .../noise/fractal/FractalTemplate.java | 31 + .../noise/fractal/PingPongTemplate.java | 27 + .../noise/fractal/RidgedFractalTemplate.java | 17 + .../normalizer/ClampNormalizerTemplate.java | 22 + .../normalizer/LinearNormalizerTemplate.java | 22 + .../normalizer/NormalNormalizerTemplate.java | 27 + .../normalizer/NormalizerTemplate.java | 14 + .../noise/normalizer/ClampNormalizer.java | 22 + .../noise/normalizer/LinearNormalizer.java | 23 + .../noise/normalizer/NormalNormalizer.java | 47 ++ .../addons/noise/normalizer/Normalizer.java | 24 + .../defined/UserDefinedFunction.java | 52 ++ .../paralithic/noise/NoiseFunction2.java | 37 ++ .../paralithic/noise/NoiseFunction3.java | 37 ++ .../noise/paralithic/noise/SeedContext.java | 16 + .../noise/samplers/DomainWarpedSampler.java | 33 ++ .../addons/noise/samplers/ImageSampler.java | 68 +++ .../addons/noise/samplers/KernelSampler.java | 50 ++ .../noise/samplers/noise/CellularSampler.java | 537 ++++++++++++++++++ .../noise/samplers/noise/ConstantSampler.java | 22 + .../samplers/noise/ExpressionFunction.java | 45 ++ .../samplers/noise/GaborNoiseSampler.java | 107 ++++ .../noise/samplers/noise/NoiseFunction.java | 143 +++++ .../noise/fractal/BrownianMotionSampler.java | 47 ++ .../noise/fractal/FractalNoiseFunction.java | 48 ++ .../noise/fractal/PingPongSampler.java | 59 ++ .../noise/fractal/RidgedFractalSampler.java | 48 ++ .../noise/random/GaussianNoiseSampler.java | 39 ++ .../noise/random/WhiteNoiseSampler.java | 53 ++ .../noise/simplex/OpenSimplex2SSampler.java | 272 +++++++++ .../noise/simplex/OpenSimplex2Sampler.java | 153 +++++ .../samplers/noise/simplex/PerlinSampler.java | 67 +++ .../noise/simplex/SimplexSampler.java | 242 ++++++++ .../noise/simplex/SimplexStyleSampler.java | 97 ++++ .../noise/value/ValueCubicSampler.java | 102 ++++ .../samplers/noise/value/ValueSampler.java | 52 ++ .../samplers/noise/value/ValueStyleNoise.java | 23 + .../addons/noise/util/HashIntrinsic.java | 119 ++++ .../noise/util/HashMapDoubleDouble.java | 295 ++++++++++ 56 files changed, 3759 insertions(+) create mode 100644 common/addons/config-noise-function/README.md create mode 100644 common/addons/config-noise-function/build.gradle.kts create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/DimensionApplicableNoiseSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DomainWarpTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/FunctionTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/ImageSamplerTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/KernelTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/SamplerTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ConstantNoiseTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ExpressionFunctionTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/GaborNoiseTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/NoiseTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/SimpleNoiseTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/BrownianMotionTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/FractalTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/PingPongTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/RidgedFractalTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ClampNormalizerTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/LinearNormalizerTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalNormalizerTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalizerTemplate.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ClampNormalizer.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/LinearNormalizer.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/NormalNormalizer.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/Normalizer.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction2.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction3.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SeedContext.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/DomainWarpedSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/ImageSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/KernelSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ConstantSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ExpressionFunction.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/GaborNoiseSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/NoiseFunction.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/BrownianMotionSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/FractalNoiseFunction.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/PingPongSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/RidgedFractalSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/GaussianNoiseSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/WhiteNoiseSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/PerlinSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueCubicSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueSampler.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueStyleNoise.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashIntrinsic.java create mode 100644 common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashMapDoubleDouble.java diff --git a/common/addons/config-noise-function/README.md b/common/addons/config-noise-function/README.md new file mode 100644 index 000000000..435757b55 --- /dev/null +++ b/common/addons/config-noise-function/README.md @@ -0,0 +1,3 @@ +# config-noise-function + +Registers the default noise functions. \ No newline at end of file diff --git a/common/addons/config-noise-function/build.gradle.kts b/common/addons/config-noise-function/build.gradle.kts new file mode 100644 index 000000000..7d82dc72f --- /dev/null +++ b/common/addons/config-noise-function/build.gradle.kts @@ -0,0 +1,2 @@ +dependencies { +} 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 new file mode 100644 index 000000000..20ec42d17 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java @@ -0,0 +1,115 @@ +package com.dfsek.terra.addons.noise; + +import com.dfsek.tectonic.loading.object.ObjectTemplate; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; +import com.dfsek.terra.addons.noise.config.templates.DomainWarpTemplate; +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; +import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate; +import com.dfsek.terra.addons.noise.config.templates.KernelTemplate; +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.ExpressionFunctionTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.GaborNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.SimpleNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.fractal.BrownianMotionTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.fractal.PingPongTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.fractal.RidgedFractalTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.ClampNormalizerTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.LinearNormalizerTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.NormalNormalizerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler; +import com.dfsek.terra.addons.noise.samplers.noise.random.GaussianNoiseSampler; +import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2SSampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.PerlinSampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.SimplexSampler; +import com.dfsek.terra.addons.noise.samplers.noise.value.ValueCubicSampler; +import com.dfsek.terra.addons.noise.samplers.noise.value.ValueSampler; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.TerraAddon; +import com.dfsek.terra.api.addon.annotations.Addon; +import com.dfsek.terra.api.addon.annotations.Author; +import com.dfsek.terra.api.addon.annotations.Version; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +@Addon("config-noise-function") +@Author("Terra") +@Version("1.0.0") +public class NoiseAddon extends TerraAddon { + public static final TypeKey>> NOISE_SAMPLER_TOKEN = new TypeKey<>() { + }; + @Inject + private Platform plugin; + + @Override + public void initialize() { + plugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> noiseRegistry = event.getPack().getOrCreateRegistry( + NOISE_SAMPLER_TOKEN); + event.getPack() + .applyLoader(CellularSampler.DistanceFunction.class, + (t, o, l) -> CellularSampler.DistanceFunction.valueOf((String) o)) + .applyLoader(CellularSampler.ReturnType.class, (t, o, l) -> CellularSampler.ReturnType.valueOf((String) o)) + .applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new) + .applyLoader(FunctionTemplate.class, FunctionTemplate::new); + + noiseRegistry.register("LINEAR", LinearNormalizerTemplate::new); + noiseRegistry.register("NORMAL", NormalNormalizerTemplate::new); + noiseRegistry.register("CLAMP", ClampNormalizerTemplate::new); + + noiseRegistry.register("IMAGE", ImageSamplerTemplate::new); + + noiseRegistry.register("DOMAIN_WARP", DomainWarpTemplate::new); + + noiseRegistry.register("FBM", BrownianMotionTemplate::new); + noiseRegistry.register("PING_PONG", PingPongTemplate::new); + noiseRegistry.register("RIDGED", RidgedFractalTemplate::new); + + noiseRegistry.register("OPEN_SIMPLEX_2", () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new)); + noiseRegistry.register("OPEN_SIMPLEX_2S", () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new)); + noiseRegistry.register("PERLIN", () -> new SimpleNoiseTemplate(PerlinSampler::new)); + noiseRegistry.register("SIMPLEX", () -> new SimpleNoiseTemplate(SimplexSampler::new)); + noiseRegistry.register("GABOR", GaborNoiseTemplate::new); + + + noiseRegistry.register("VALUE", () -> new SimpleNoiseTemplate(ValueSampler::new)); + noiseRegistry.register("VALUE_CUBIC", () -> new SimpleNoiseTemplate(ValueCubicSampler::new)); + + noiseRegistry.register("CELLULAR", CellularNoiseTemplate::new); + + noiseRegistry.register("WHITE_NOISE", () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new)); + noiseRegistry.register("GAUSSIAN", () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new)); + + noiseRegistry.register("CONSTANT", ConstantNoiseTemplate::new); + + noiseRegistry.register("KERNEL", KernelTemplate::new); + + Map packSamplers = new LinkedHashMap<>(); + Map packFunctions = new LinkedHashMap<>(); + noiseRegistry.register("EXPRESSION", () -> new ExpressionFunctionTemplate(packSamplers, packFunctions)); + + + NoiseConfigPackTemplate template = new NoiseConfigPackTemplate(); + event.loadTemplate(template); + packSamplers.putAll(template.getSamplers()); + packFunctions.putAll(template.getFunctions()); + }) + .failThrough(); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java new file mode 100644 index 000000000..355a4509b --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.addons.noise; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ConfigTemplate; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; +import com.dfsek.terra.api.config.meta.Meta; + + +public class NoiseConfigPackTemplate implements ConfigTemplate { + @Value("noise") + private @Meta Map noiseBuilderMap; + + @Value("functions") + @Default + private @Meta LinkedHashMap expressions = new LinkedHashMap<>(); + + public Map getSamplers() { + return noiseBuilderMap; + } + + public LinkedHashMap getFunctions() { + return expressions; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/DimensionApplicableNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/DimensionApplicableNoiseSampler.java new file mode 100644 index 000000000..20e922fed --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/DimensionApplicableNoiseSampler.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.addons.noise.config; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.loading.object.ObjectTemplate; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class DimensionApplicableNoiseSampler implements ObjectTemplate { + @Value("dimensions") + private @Meta int dimensions; + + @Value(".") + private @Meta NoiseSampler sampler; + + @Override + public DimensionApplicableNoiseSampler get() { + return this; + } + + public int getDimensions() { + return dimensions; + } + + public NoiseSampler getSampler() { + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DomainWarpTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DomainWarpTemplate.java new file mode 100644 index 000000000..9fe96b1ed --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DomainWarpTemplate.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.DomainWarpedSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class DomainWarpTemplate extends SamplerTemplate { + @Value("warp") + private @Meta NoiseSampler warp; + + @Value("function") + private @Meta NoiseSampler function; + + @Value("amplitude") + @Default + private @Meta double amplitude = 1; + + @Override + public NoiseSampler get() { + return new DomainWarpedSampler(function, warp, amplitude); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/FunctionTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/FunctionTemplate.java new file mode 100644 index 000000000..41857573d --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/FunctionTemplate.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.loading.object.ObjectTemplate; + +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; + + +@SuppressWarnings("unused") +public class FunctionTemplate implements ObjectTemplate { + @Value("arguments") + private List args; + + @Value("expression") + private @Meta String function; + + @Override + public FunctionTemplate get() { + return this; + } + + public List getArgs() { + return args; + } + + public String getFunction() { + return function; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/ImageSamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/ImageSamplerTemplate.java new file mode 100644 index 000000000..f0e37eb69 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/ImageSamplerTemplate.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.annotations.Value; + +import java.awt.image.BufferedImage; + +import com.dfsek.terra.addons.noise.samplers.ImageSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class ImageSamplerTemplate extends SamplerTemplate { + + @Value("image") + private @Meta BufferedImage image; + + @Value("frequency") + private @Meta double frequency; + + @Value("channel") + private ImageSampler.@Meta Channel channel; + + @Override + public NoiseSampler get() { + return new ImageSampler(image, channel, frequency); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/KernelTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/KernelTemplate.java new file mode 100644 index 000000000..0bb4e3544 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/KernelTemplate.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.addons.noise.samplers.KernelSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class KernelTemplate extends SamplerTemplate { + + @Value("kernel") + private @Meta List<@Meta List<@Meta Double>> kernel; + + @Value("factor") + @Default + private @Meta double factor = 1; + + @Value("function") + private @Meta NoiseSampler function; + + @Value("frequency") + @Default + private @Meta double frequency = 1; + + @Override + public NoiseSampler get() { + double[][] k = new double[kernel.size()][kernel.get(0).size()]; + + for(int x = 0; x < kernel.size(); x++) { + for(int y = 0; y < kernel.get(x).size(); y++) { + k[x][y] = kernel.get(x).get(y) * factor; + } + } + + KernelSampler sampler = new KernelSampler(k, function); + sampler.setFrequency(frequency); + return sampler; + } + + @Override + public boolean validate() throws ValidationException { + + if(kernel.isEmpty()) throw new ValidationException("Kernel must not be empty."); + + int len = kernel.get(0).size(); + + if(len == 0) throw new ValidationException("Kernel row must contain data."); + + for(int i = 0; i < kernel.size(); i++) { + if(kernel.get(i).size() != len) + throw new ValidationException("Kernel row " + i + " size mismatch. Expected " + len + ", found " + kernel.get(i).size()); + } + + return super.validate(); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/SamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/SamplerTemplate.java new file mode 100644 index 000000000..b281f1d77 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/SamplerTemplate.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ValidatedConfigTemplate; +import com.dfsek.tectonic.exception.ValidationException; +import com.dfsek.tectonic.loading.object.ObjectTemplate; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("FieldMayBeFinal") +public abstract class SamplerTemplate implements ValidatedConfigTemplate, ObjectTemplate { + @Value("dimensions") + @Default + private @Meta int dimensions = 2; + + @Override + public boolean validate() throws ValidationException { + if(dimensions != 2 && dimensions != 3) throw new ValidationException("Illegal amount of dimensions: " + dimensions); + return true; + } + + public int getDimensions() { + return dimensions; + } +} 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 new file mode 100644 index 000000000..1162be34b --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.noise.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; + + +@SuppressWarnings("FieldMayBeFinal") +public class CellularNoiseTemplate extends NoiseTemplate { + @Value("distance") + @Default + private CellularSampler.@Meta DistanceFunction cellularDistanceFunction = CellularSampler.DistanceFunction.EuclideanSq; + + @Value("return") + @Default + private CellularSampler.@Meta ReturnType cellularReturnType = CellularSampler.ReturnType.Distance; + + @Value("jitter") + @Default + private @Meta double cellularJitter = 1.0D; + + + @Value("lookup") + @Default + private @Meta NoiseSampler lookup = new OpenSimplex2Sampler(); + + @Override + public NoiseSampler get() { + CellularSampler sampler = new CellularSampler(); + sampler.setNoiseLookup(lookup); + sampler.setFrequency(frequency); + sampler.setJitterModifier(cellularJitter); + sampler.setReturnType(cellularReturnType); + sampler.setDistanceFunction(cellularDistanceFunction); + sampler.setSalt(salt); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ConstantNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ConstantNoiseTemplate.java new file mode 100644 index 000000000..87eb684db --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ConstantNoiseTemplate.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.ConstantSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("FieldMayBeFinal") +public class ConstantNoiseTemplate extends SamplerTemplate { + @Value("value") + @Default + private @Meta double value = 0d; + + @Override + public NoiseSampler get() { + return new ConstantSampler(value); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ExpressionFunctionTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ExpressionFunctionTemplate.java new file mode 100644 index 000000000..27c2d39e8 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ExpressionFunctionTemplate.java @@ -0,0 +1,97 @@ +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.paralithic.functions.Function; +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.exception.ValidationException; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction; +import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2; +import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3; +import com.dfsek.terra.addons.noise.samplers.noise.ExpressionFunction; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "FieldMayBeFinal", "unused" }) +public class ExpressionFunctionTemplate extends SamplerTemplate { + private final Map otherFunctions; + @Value("variables") + @Default + private @Meta Map vars = new HashMap<>(); + + @Value("expression") + private @Meta String equation; + + @Value("samplers") + @Default + private @Meta LinkedHashMap samplers = new LinkedHashMap<>(); + + @Value("functions") + @Default + private @Meta LinkedHashMap functions = new LinkedHashMap<>(); + + private final Map globalFunctions; + + public ExpressionFunctionTemplate(Map otherFunctions, Map samplers) { + this.otherFunctions = otherFunctions; + this.globalFunctions = samplers; + } + + @Override + public NoiseSampler get() { + try { + Map noiseFunctionMap = generateFunctions(); + return new ExpressionFunction(noiseFunctionMap, equation, vars); + } catch(ParseException e) { + throw new IllegalStateException(e); + } + } + + @Override + public boolean validate() throws ValidationException { + try { + Map noiseFunctionMap = generateFunctions(); + new ExpressionFunction(noiseFunctionMap, equation, vars); + } catch(ParseException e) { + throw new ValidationException("Errors occurred while parsing noise equation: ", e); + } + return super.validate(); + } + + private Map generateFunctions() throws ParseException { + Map noiseFunctionMap = new HashMap<>(); + + for(Map.Entry entry : globalFunctions.entrySet()) { + noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), new Parser(), new Scope())); + } + + for(Map.Entry entry : functions.entrySet()) { + noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), new Parser(), new Scope())); + } + + otherFunctions.forEach((id, function) -> { + if(function.getDimensions() == 2) { + noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler())); + } else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler())); + }); + + samplers.forEach((id, function) -> { + if(function.getDimensions() == 2) { + noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler())); + } else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler())); + }); + + return noiseFunctionMap; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/GaborNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/GaborNoiseTemplate.java new file mode 100644 index 000000000..2fb5c20dd --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/GaborNoiseTemplate.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.noise.GaborNoiseSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class GaborNoiseTemplate extends NoiseTemplate { + @Value("rotation") + @Default + private @Meta double rotation = 0.25; + + @Value("isotropic") + @Default + private @Meta boolean isotropic = true; + + @Value("deviation") + @Default + private @Meta double deviation = 1.0; + + @Value("impulses") + @Default + private @Meta double impulses = 64d; + + @Value("frequency_0") + @Default + private @Meta double f0 = 0.625; + + @Override + public NoiseSampler get() { + GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler(); + gaborNoiseSampler.setFrequency(frequency); + gaborNoiseSampler.setRotation(rotation); + gaborNoiseSampler.setIsotropic(isotropic); + gaborNoiseSampler.setDeviation(deviation); + gaborNoiseSampler.setImpulsesPerKernel(impulses); + gaborNoiseSampler.setFrequency0(f0); + gaborNoiseSampler.setSalt(salt); + return gaborNoiseSampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/NoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/NoiseTemplate.java new file mode 100644 index 000000000..4ce1a07dc --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/NoiseTemplate.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; +import com.dfsek.terra.api.config.meta.Meta; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public abstract class NoiseTemplate extends SamplerTemplate { + @Value("frequency") + @Default + protected @Meta double frequency = 0.02d; + + @Value("salt") + @Default + protected @Meta long salt = 0; +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/SimpleNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/SimpleNoiseTemplate.java new file mode 100644 index 000000000..455f8642a --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/SimpleNoiseTemplate.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.noise.config.templates.noise; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class SimpleNoiseTemplate extends NoiseTemplate { + private final Supplier samplerSupplier; + + public SimpleNoiseTemplate(Supplier samplerSupplier) { + this.samplerSupplier = samplerSupplier; + } + + @Override + public NoiseSampler get() { + NoiseFunction sampler = samplerSupplier.get(); + sampler.setFrequency(frequency); + sampler.setSalt(salt); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/BrownianMotionTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/BrownianMotionTemplate.java new file mode 100644 index 000000000..801aed0a5 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/BrownianMotionTemplate.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.terra.addons.noise.samplers.noise.fractal.BrownianMotionSampler; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class BrownianMotionTemplate extends FractalTemplate { + @Override + public NoiseSampler get() { + BrownianMotionSampler sampler = new BrownianMotionSampler(function); + sampler.setGain(fractalGain); + sampler.setLacunarity(fractalLacunarity); + sampler.setOctaves(octaves); + sampler.setWeightedStrength(weightedStrength); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/FractalTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/FractalTemplate.java new file mode 100644 index 000000000..e92228663 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/FractalTemplate.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.fractal.FractalNoiseFunction; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class FractalTemplate extends SamplerTemplate { + @Value("octaves") + @Default + protected @Meta int octaves = 3; + + @Value("gain") + @Default + protected @Meta double fractalGain = 0.5D; + + @Value("lacunarity") + @Default + protected @Meta double fractalLacunarity = 2.0D; + + @Value("weighted-strength") + @Default + protected @Meta double weightedStrength = 0.0D; + + @Value("function") + protected @Meta NoiseSampler function; +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/PingPongTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/PingPongTemplate.java new file mode 100644 index 000000000..145aeea32 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/PingPongTemplate.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.noise.fractal.PingPongSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class PingPongTemplate extends FractalTemplate { + @Value("ping-pong") + @Default + private @Meta double pingPong = 2.0D; + + @Override + public NoiseSampler get() { + PingPongSampler sampler = new PingPongSampler(function); + sampler.setGain(fractalGain); + sampler.setLacunarity(fractalLacunarity); + sampler.setOctaves(octaves); + sampler.setWeightedStrength(weightedStrength); + sampler.setPingPongStrength(pingPong); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/RidgedFractalTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/RidgedFractalTemplate.java new file mode 100644 index 000000000..70d606ed0 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/RidgedFractalTemplate.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.terra.addons.noise.samplers.noise.fractal.RidgedFractalSampler; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class RidgedFractalTemplate extends FractalTemplate { + @Override + public NoiseSampler get() { + RidgedFractalSampler sampler = new RidgedFractalSampler(function); + sampler.setGain(fractalGain); + sampler.setLacunarity(fractalLacunarity); + sampler.setOctaves(octaves); + sampler.setWeightedStrength(weightedStrength); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ClampNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ClampNormalizerTemplate.java new file mode 100644 index 000000000..4e8287a0f --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ClampNormalizerTemplate.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.ClampNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class ClampNormalizerTemplate extends NormalizerTemplate { + @Value("max") + private @Meta double max; + + @Value("min") + private @Meta double min; + + @Override + public NoiseSampler get() { + return new ClampNormalizer(function, min, max); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/LinearNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/LinearNormalizerTemplate.java new file mode 100644 index 000000000..171123493 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/LinearNormalizerTemplate.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.LinearNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class LinearNormalizerTemplate extends NormalizerTemplate { + @Value("max") + private @Meta double max; + + @Value("min") + private @Meta double min; + + @Override + public NoiseSampler get() { + return new LinearNormalizer(function, min, max); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalNormalizerTemplate.java new file mode 100644 index 000000000..c55647f90 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalNormalizerTemplate.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.NormalNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class NormalNormalizerTemplate extends NormalizerTemplate { + @Value("mean") + private @Meta double mean; + + @Value("standard-deviation") + private @Meta double stdDev; + + @Value("groups") + @Default + private @Meta int groups = 16384; + + @Override + public NoiseSampler get() { + return new NormalNormalizer(function, groups, mean, stdDev); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalizerTemplate.java new file mode 100644 index 000000000..1d435acd6 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalizerTemplate.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.normalizer.Normalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class NormalizerTemplate extends SamplerTemplate { + @Value("function") + protected @Meta NoiseSampler function; +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ClampNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ClampNormalizer.java new file mode 100644 index 000000000..b8c093585 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ClampNormalizer.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.addons.noise.normalizer; + +import net.jafama.FastMath; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class ClampNormalizer extends Normalizer { + private final double min; + private final double max; + + public ClampNormalizer(NoiseSampler sampler, double min, double max) { + super(sampler); + this.min = min; + this.max = max; + } + + @Override + public double normalize(double in) { + return FastMath.max(FastMath.min(in, max), min); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/LinearNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/LinearNormalizer.java new file mode 100644 index 000000000..3d355045a --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/LinearNormalizer.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.noise.normalizer; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +/** + * Normalizer to linearly scale data's range. + */ +public class LinearNormalizer extends Normalizer { + private final double min; + private final double max; + + public LinearNormalizer(NoiseSampler sampler, double min, double max) { + super(sampler); + this.min = min; + this.max = max; + } + + @Override + public double normalize(double in) { + return (in - min) * (2 / (max - min)) - 1; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/NormalNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/NormalNormalizer.java new file mode 100644 index 000000000..16dda5430 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/NormalNormalizer.java @@ -0,0 +1,47 @@ +package com.dfsek.terra.addons.noise.normalizer; + +import net.jafama.FastMath; + +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.MathUtil; + + +/** + * Normalizer to redistribute normally distributed data to a continuous distribution via an automatically generated lookup table. + */ +public class NormalNormalizer extends Normalizer { + + private final double[] lookup; + + public NormalNormalizer(NoiseSampler sampler, int buckets, double mean, double standardDeviation) { + super(sampler); + this.lookup = new double[buckets]; + + for(int i = 0; i < buckets; i++) { + lookup[i] = MathUtil.normalInverse((double) i / buckets, mean, standardDeviation); + } + } + + @Override + public double normalize(double in) { + int start = 0; + int end = lookup.length - 1; + while(start + 1 < end) { + int mid = start + (end - start) / 2; + if(lookup[mid] <= in) { + start = mid; + } else { + end = mid; + } + } + double left = FastMath.abs(lookup[start] - in); + double right = FastMath.abs(lookup[end] - in); + + double fin; + if(left <= right) { + fin = (double) start / (lookup.length); + } else fin = (double) end / (lookup.length); + + return (fin - 0.5) * 2; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/Normalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/Normalizer.java new file mode 100644 index 000000000..c99a54a83 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/Normalizer.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.addons.noise.normalizer; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class Normalizer implements NoiseSampler { + private final NoiseSampler sampler; + + public Normalizer(NoiseSampler sampler) { + this.sampler = sampler; + } + + public abstract double normalize(double in); + + @Override + public double getNoiseSeeded(long seed, double x, double y) { + return normalize(sampler.getNoiseSeeded(seed, x, y)); + } + + @Override + public double getNoiseSeeded(long seed, double x, double y, double z) { + return normalize(sampler.getNoiseSeeded(seed, x, y, z)); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java new file mode 100644 index 000000000..db01b9a11 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.addons.noise.paralithic.defined; + +import com.dfsek.paralithic.Expression; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.paralithic.functions.dynamic.Context; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; + +import com.dfsek.paralithic.node.Statefulness; + +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; + + +public class UserDefinedFunction implements DynamicFunction { + private final Expression expression; + private final int args; + + protected UserDefinedFunction(Expression expression, int args) { + this.expression = expression; + this.args = args; + } + + public static UserDefinedFunction newInstance(FunctionTemplate template, Parser parser, Scope parent) throws ParseException { + + Scope functionScope = new Scope().withParent(parent); + + template.getArgs().forEach(functionScope::addInvocationVariable); + + return new UserDefinedFunction(parser.parse(template.getFunction(), functionScope), template.getArgs().size()); + } + + @Override + public double eval(double... args) { + return expression.evaluate(args); + } + + @Override + public double eval(Context context, double... args) { + return expression.evaluate(context, args); + } + + @Override + public int getArgNumber() { + return args; + } + + @Override + public Statefulness statefulness() { + return Statefulness.STATELESS; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction2.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction2.java new file mode 100644 index 000000000..74f2c7a2c --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction2.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.addons.noise.paralithic.noise; + +import com.dfsek.paralithic.functions.dynamic.Context; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; + +import com.dfsek.paralithic.node.Statefulness; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class NoiseFunction2 implements DynamicFunction { + private final NoiseSampler gen; + + public NoiseFunction2(NoiseSampler gen) { + this.gen = gen; + } + + @Override + public double eval(double... args) { + throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context."); + } + + @Override + public double eval(Context context, double... args) { + return gen.getNoiseSeeded(((SeedContext) context).getSeed(), args[0], args[1]); + } + + @Override + public int getArgNumber() { + return 2; + } + + @Override + public Statefulness statefulness() { + return Statefulness.CONTEXTUAL; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction3.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction3.java new file mode 100644 index 000000000..bba832440 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction3.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.addons.noise.paralithic.noise; + +import com.dfsek.paralithic.functions.dynamic.Context; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; + +import com.dfsek.paralithic.node.Statefulness; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class NoiseFunction3 implements DynamicFunction { + private final NoiseSampler gen; + + public NoiseFunction3(NoiseSampler gen) { + this.gen = gen; + } + + @Override + public double eval(double... args) { + throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context."); + } + + @Override + public double eval(Context context, double... args) { + return gen.getNoiseSeeded(((SeedContext) context).getSeed(), args[0], args[1], args[2]); + } + + @Override + public int getArgNumber() { + return 3; + } + + @Override + public Statefulness statefulness() { + return Statefulness.CONTEXTUAL; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SeedContext.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SeedContext.java new file mode 100644 index 000000000..8f4bb2bf1 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SeedContext.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.addons.noise.paralithic.noise; + +import com.dfsek.paralithic.functions.dynamic.Context; + + +public class SeedContext implements Context { + private final long seed; + + public SeedContext(long seed) { + this.seed = seed; + } + + public long getSeed() { + return seed; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/DomainWarpedSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/DomainWarpedSampler.java new file mode 100644 index 000000000..7574f8938 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/DomainWarpedSampler.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.addons.noise.samplers; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class DomainWarpedSampler implements NoiseSampler { + private final NoiseSampler function; + private final NoiseSampler warp; + private final double amplitude; + + public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, double amplitude) { + this.function = function; + this.warp = warp; + this.amplitude = amplitude; + } + + @Override + public double getNoiseSeeded(long seed, double x, double y) { + return function.getNoiseSeeded(seed++, + x + warp.getNoiseSeeded(seed++, x, y) * amplitude, + y + warp.getNoiseSeeded(seed, x, y) * amplitude + ); + } + + @Override + public double getNoiseSeeded(long seed, double x, double y, double z) { + return function.getNoiseSeeded(seed++, + x + warp.getNoiseSeeded(seed++, x, y, z) * amplitude, + y + warp.getNoiseSeeded(seed++, x, y, z) * amplitude, + z + warp.getNoiseSeeded(seed, x, y, z) * amplitude + ); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/ImageSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/ImageSampler.java new file mode 100644 index 000000000..2c64a954d --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/ImageSampler.java @@ -0,0 +1,68 @@ +package com.dfsek.terra.addons.noise.samplers; + +import net.jafama.FastMath; + +import java.awt.image.BufferedImage; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class ImageSampler implements NoiseSampler { + private final BufferedImage image; + private final Channel channel; + + private final double frequency; + + public ImageSampler(BufferedImage image, Channel channel, double frequency) { + this.image = image; + this.channel = channel; + this.frequency = frequency; + } + + @Override + public double getNoiseSeeded(long seed, double x, double y) { + return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), + FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * + 2; + } + + @Override + public double getNoiseSeeded(long seed, double x, double y, double z) { + return getNoiseSeeded(seed, x, y); + } + + public enum Channel { + RED { + @Override + public int getChannel(int mashed) { + return (mashed >> 16) & 0xff; + } + }, + GREEN { + @Override + public int getChannel(int mashed) { + return (mashed >> 8) & 0xff; + } + }, + BLUE { + @Override + public int getChannel(int mashed) { + return mashed & 0xff; + } + }, + GRAYSCALE { + @Override + public int getChannel(int mashed) { + return (RED.getChannel(mashed) + GREEN.getChannel(mashed) + BLUE.getChannel(mashed)) / 3; + } + }, + ALPHA { + @Override + public int getChannel(int mashed) { + return (mashed >> 24) & 0xff; + } + }; + + public abstract int getChannel(int mashed); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/KernelSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/KernelSampler.java new file mode 100644 index 000000000..23266b3dc --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/KernelSampler.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.addons.noise.samplers; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class KernelSampler implements NoiseSampler { + private final double[][] kernel; + private final NoiseSampler in; + private double frequency = 1; + + public KernelSampler(double[][] kernel, NoiseSampler in) { + this.kernel = kernel; + this.in = in; + } + + public void setFrequency(double frequency) { + this.frequency = frequency; + } + + @Override + public double getNoiseSeeded(long seed, double x, double y) { + x *= frequency; + y *= frequency; + double accumulator = 0; + + for(int kx = 0; kx < kernel.length; kx++) { + for(int ky = 0; ky < kernel[kx].length; ky++) { + accumulator += in.getNoiseSeeded(seed, x + kx, y + ky) * kernel[kx][ky]; + } + } + + return accumulator; + } + + @Override + public double getNoiseSeeded(long seed, double x, double y, double z) { + x *= frequency; + y *= frequency; + z *= frequency; + double accumulator = 0; + + for(int kx = 0; kx < kernel.length; kx++) { + for(int ky = 0; ky < kernel[kx].length; ky++) { + accumulator += in.getNoiseSeeded(seed, x + kx, y, z + ky) * kernel[kx][ky]; + } + } + + return accumulator; + } +} 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/CellularSampler.java new file mode 100644 index 000000000..c5ed8ea3e --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java @@ -0,0 +1,537 @@ +package com.dfsek.terra.addons.noise.samplers.noise; + +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +/** + * 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.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.5815838982d, 0.7607405838d, 0, 0.5849561111d, -0.662820239d, -0.4674352136d, 0, 0.3307171178d, 0.0391653737d, 0.94291689d, 0, + 0.8712121778d, -0.4113374369d, -0.2679381538d, 0, 0.580981015d, 0.7021915846d, 0.4115677815d, 0, 0.503756873d, 0.6330056931d, + -0.5878203852d, 0, 0.4493712205d, 0.601390195d, 0.6606022552d, 0, -0.6878403724d, 0.09018890807d, -0.7202371714d, 0, + -0.5958956522d, -0.6469350577d, 0.475797649d, 0, -0.5127052122d, 0.1946921978d, -0.8361987284d, 0, -0.9911507142d, + -0.05410276466d, -0.1212153153d, 0, -0.2149721042d, 0.9720882117d, -0.09397607749d, 0, -0.7518650936d, -0.5428057603d, + 0.3742469607d, 0, 0.5237068895d, 0.8516377189d, -0.02107817834d, 0, 0.6333504779d, 0.1926167129d, -0.7495104896d, 0, + -0.06788241606d, 0.3998305789d, 0.9140719259d, 0, -0.5538628599d, -0.4729896695d, -0.6852128902d, 0, -0.7261455366d, + -0.5911990757d, 0.3509933228d, 0, -0.9229274737d, -0.1782808786d, 0.3412049336d, 0, -0.6968815002d, 0.6511274338d, + 0.3006480328d, 0, 0.9608044783d, -0.2098363234d, -0.1811724921d, 0, 0.06817146062d, -0.9743405129d, 0.2145069156d, 0, + -0.3577285196d, -0.6697087264d, -0.6507845481d, 0, -0.1868621131d, 0.7648617052d, -0.6164974636d, 0, -0.6541697588d, + 0.3967914832d, 0.6439087246d, 0, 0.6993340405d, -0.6164538506d, 0.3618239211d, 0, -0.1546665739d, 0.6291283928d, 0.7617583057d, + 0, -0.6841612949d, -0.2580482182d, -0.6821542638d, 0, 0.5383980957d, 0.4258654885d, 0.7271630328d, 0, -0.5026987823d, + -0.7939832935d, -0.3418836993d, 0, 0.3202971715d, 0.2834415347d, 0.9039195862d, 0, 0.8683227101d, -0.0003762656404d, + -0.4959995258d, 0, 0.791120031d, -0.08511045745d, 0.6057105799d, 0, -0.04011016052d, -0.4397248749d, 0.8972364289d, 0, + 0.9145119872d, 0.3579346169d, -0.1885487608d, 0, -0.9612039066d, -0.2756484276d, 0.01024666929d, 0, 0.6510361721d, + -0.2877799159d, -0.7023778346d, 0, -0.2041786351d, 0.7365237271d, 0.644859585d, 0, -0.7718263711d, 0.3790626912d, 0.5104855816d, + 0, -0.3060082741d, -0.7692987727d, 0.5608371729d, 0, 0.454007341d, -0.5024843065d, 0.7357899537d, 0, 0.4816795475d, + 0.6021208291d, -0.6367380315d, 0, 0.6961980369d, -0.3222197429d, 0.641469197d, 0, -0.6532160499d, -0.6781148932d, 0.3368515753d, + 0, 0.5089301236d, -0.6154662304d, -0.6018234363d, 0, -0.1635919754d, -0.9133604627d, -0.372840892d, 0, 0.52408019d, + -0.8437664109d, 0.1157505864d, 0, 0.5902587356d, 0.4983817807d, -0.6349883666d, 0, 0.5863227872d, 0.494764745d, 0.6414307729d, + 0, 0.6779335087d, 0.2341345225d, 0.6968408593d, 0, 0.7177054546d, -0.6858979348d, 0.120178631d, 0, -0.5328819713d, + -0.5205125012d, 0.6671608058d, 0, -0.8654874251d, -0.0700727088d, -0.4960053754d, 0, -0.2861810166d, 0.7952089234d, + 0.5345495242d, 0, -0.04849529634d, 0.9810836427d, -0.1874115585d, 0, -0.6358521667d, 0.6058348682d, 0.4781800233d, 0, + 0.6254794696d, -0.2861619734d, 0.7258696564d, 0, -0.2585259868d, 0.5061949264d, -0.8227581726d, 0, 0.02136306781d, + 0.5064016808d, -0.8620330371d, 0, 0.200111773d, 0.8599263484d, 0.4695550591d, 0, 0.4743561372d, 0.6014985084d, -0.6427953014d, + 0, 0.6622993731d, -0.5202474575d, -0.5391679918d, 0, 0.08084972818d, -0.6532720452d, 0.7527940996d, 0, -0.6893687501d, + 0.0592860349d, 0.7219805347d, 0, -0.1121887082d, -0.9673185067d, 0.2273952515d, 0, 0.7344116094d, 0.5979668656d, -0.3210532909d, + 0, 0.5789393465d, -0.2488849713d, 0.7764570201d, 0, 0.6988182827d, 0.3557169806d, -0.6205791146d, 0, -0.8636845529d, + -0.2748771249d, -0.4224826141d, 0, -0.4247027957d, -0.4640880967d, 0.777335046d, 0, 0.5257722489d, -0.8427017621d, + 0.1158329937d, 0, 0.9343830603d, 0.316302472d, -0.1639543925d, 0, -0.1016836419d, -0.8057303073d, -0.5834887393d, 0, + -0.6529238969d, 0.50602126d, -0.5635892736d, 0, -0.2465286165d, -0.9668205684d, -0.06694497494d, 0, -0.9776897119d, + -0.2099250524d, -0.007368825344d, 0, 0.7736893337d, 0.5734244712d, 0.2694238123d, 0, -0.6095087895d, 0.4995678998d, + 0.6155736747d, 0, 0.5794535482d, 0.7434546771d, 0.3339292269d, 0, -0.8226211154d, 0.08142581855d, 0.5627293636d, 0, + -0.510385483d, 0.4703667658d, 0.7199039967d, 0, -0.5764971849d, -0.07231656274d, -0.8138926898d, 0, 0.7250628871d, + 0.3949971505d, -0.5641463116d, 0, -0.1525424005d, 0.4860840828d, -0.8604958341d, 0, -0.5550976208d, -0.4957820792d, + 0.667882296d, 0, -0.1883614327d, 0.9145869398d, 0.357841725d, 0, 0.7625556724d, -0.5414408243d, -0.3540489801d, 0, + -0.5870231946d, -0.3226498013d, -0.7424963803d, 0, 0.3051124198d, 0.2262544068d, -0.9250488391d, 0, 0.6379576059d, 0.577242424d, + -0.5097070502d, 0, -0.5966775796d, 0.1454852398d, -0.7891830656d, 0, -0.658330573d, 0.6555487542d, -0.3699414651d, 0, + 0.7434892426d, 0.2351084581d, 0.6260573129d, 0, 0.5562114096d, 0.8264360377d, -0.0873632843d, 0, -0.3028940016d, -0.8251527185d, + 0.4768419182d, 0, 0.1129343818d, -0.985888439d, -0.1235710781d, 0, 0.5937652891d, -0.5896813806d, 0.5474656618d, 0, + 0.6757964092d, -0.5835758614d, -0.4502648413d, 0, 0.7242302609d, -0.1152719764d, 0.6798550586d, 0, -0.9511914166d, + 0.0753623979d, -0.2992580792d, 0, 0.2539470961d, -0.1886339355d, 0.9486454084d, 0, 0.571433621d, -0.1679450851d, -0.8032795685d, + 0, -0.06778234979d, 0.3978269256d, 0.9149531629d, 0, 0.6074972649d, 0.733060024d, -0.3058922593d, 0, -0.5435478392d, + 0.1675822484d, 0.8224791405d, 0, -0.5876678086d, -0.3380045064d, -0.7351186982d, 0, -0.7967562402d, 0.04097822706d, + -0.6029098428d, 0, -0.1996350917d, 0.8706294745d, 0.4496111079d, 0, -0.02787660336d, -0.9106232682d, -0.4122962022d, 0, + -0.7797625996d, -0.6257634692d, 0.01975775581d, 0, -0.5211232846d, 0.7401644346d, -0.4249554471d, 0, 0.8575424857d, + 0.4053272873d, -0.3167501783d, 0, 0.1045223322d, 0.8390195772d, -0.5339674439d, 0, 0.3501822831d, 0.9242524096d, -0.1520850155d, + 0, 0.1987849858d, 0.07647613266d, 0.9770547224d, 0, 0.7845996363d, 0.6066256811d, -0.1280964233d, 0, 0.09006737436d, + -0.9750989929d, -0.2026569073d, 0, -0.8274343547d, -0.542299559d, 0.1458203587d, 0, -0.3485797732d, -0.415802277d, 0.840000362d, + 0, -0.2471778936d, -0.7304819962d, -0.6366310879d, 0, -0.3700154943d, 0.8577948156d, 0.3567584454d, 0, 0.5913394901d, + -0.548311967d, -0.5913303597d, 0, 0.1204873514d, -0.7626472379d, -0.6354935001d, 0, 0.616959265d, 0.03079647928d, 0.7863922953d, + 0, 0.1258156836d, -0.6640829889d, -0.7369967419d, 0, -0.6477565124d, -0.1740147258d, -0.7417077429d, 0, 0.6217889313d, + -0.7804430448d, -0.06547655076d, 0, 0.6589943422d, -0.6096987708d, 0.4404473475d, 0, -0.2689837504d, -0.6732403169d, + -0.6887635427d, 0, -0.3849775103d, 0.5676542638d, 0.7277093879d, 0, 0.5754444408d, 0.8110471154d, -0.1051963504d, 0, + 0.9141593684d, 0.3832947817d, 0.131900567d, 0, -0.107925319d, 0.9245493968d, 0.3654593525d, 0, 0.377977089d, 0.3043148782d, + 0.8743716458d, 0, -0.2142885215d, -0.8259286236d, 0.5214617324d, 0, 0.5802544474d, 0.4148098596d, -0.7008834116d, 0, + -0.1982660881d, 0.8567161266d, -0.4761596756d, 0, -0.03381553704d, 0.3773180787d, -0.9254661404d, 0, -0.6867922841d, + -0.6656597827d, 0.2919133642d, 0, 0.7731742607d, -0.2875793547d, -0.5652430251d, 0, -0.09655941928d, 0.9193708367d, + -0.3813575004d, 0, 0.2715702457d, -0.9577909544d, -0.09426605581d, 0, 0.2451015704d, -0.6917998565d, -0.6792188003d, 0, + 0.977700782d, -0.1753855374d, 0.1155036542d, 0, -0.5224739938d, 0.8521606816d, 0.02903615945d, 0, -0.7734880599d, + -0.5261292347d, 0.3534179531d, 0, -0.7134492443d, -0.269547243d, 0.6467878011d, 0, 0.1644037271d, 0.5105846203d, -0.8439637196d, + 0, 0.6494635788d, 0.05585611296d, 0.7583384168d, 0, -0.4711970882d, 0.5017280509d, -0.7254255765d, 0, -0.6335764307d, + -0.2381686273d, -0.7361091029d, 0, -0.9021533097d, -0.270947803d, -0.3357181763d, 0, -0.3793711033d, 0.872258117d, + 0.3086152025d, 0, -0.6855598966d, -0.3250143309d, 0.6514394162d, 0, 0.2900942212d, -0.7799057743d, -0.5546100667d, 0, + -0.2098319339d, 0.85037073d, 0.4825351604d, 0, -0.4592603758d, 0.6598504336d, -0.5947077538d, 0, 0.8715945488d, 0.09616365406d, + -0.4807031248d, 0, -0.6776666319d, 0.7118504878d, -0.1844907016d, 0, 0.7044377633d, 0.312427597d, 0.637304036d, 0, + -0.7052318886d, -0.2401093292d, -0.6670798253d, 0, 0.081921007d, -0.7207336136d, -0.6883545647d, 0, -0.6993680906d, + -0.5875763221d, -0.4069869034d, 0, -0.1281454481d, 0.6419895885d, 0.7559286424d, 0, -0.6337388239d, -0.6785471501d, + -0.3714146849d, 0, 0.5565051903d, -0.2168887573d, -0.8020356851d, 0, -0.5791554484d, 0.7244372011d, -0.3738578718d, 0, + 0.1175779076d, -0.7096451073d, 0.6946792478d, 0, -0.6134619607d, 0.1323631078d, 0.7785527795d, 0, 0.6984635305d, + -0.02980516237d, -0.715024719d, 0, 0.8318082963d, -0.3930171956d, 0.3919597455d, 0, 0.1469576422d, 0.05541651717d, + -0.9875892167d, 0, 0.708868575d, -0.2690503865d, 0.6520101478d, 0, 0.2726053183d, 0.67369766d, -0.68688995d, 0, -0.6591295371d, + 0.3035458599d, -0.6880466294d, 0, 0.4815131379d, -0.7528270071d, 0.4487723203d, 0, 0.9430009463d, 0.1675647412d, -0.2875261255d, + 0, 0.434802957d, 0.7695304522d, -0.4677277752d, 0, 0.3931996188d, 0.594473625d, 0.7014236729d, 0, 0.7254336655d, -0.603925654d, + 0.3301814672d, 0, 0.7590235227d, -0.6506083235d, 0.02433313207d, 0, -0.8552768592d, -0.3430042733d, 0.3883935666d, 0, + -0.6139746835d, 0.6981725247d, 0.3682257648d, 0, -0.7465905486d, -0.5752009504d, 0.3342849376d, 0, 0.5730065677d, 0.810555537d, + -0.1210916791d, 0, -0.9225877367d, -0.3475211012d, -0.167514036d, 0, -0.7105816789d, -0.4719692027d, -0.5218416899d, 0, + -0.08564609717d, 0.3583001386d, 0.929669703d, 0, -0.8279697606d, -0.2043157126d, 0.5222271202d, 0, 0.427944023d, 0.278165994d, + 0.8599346446d, 0, 0.5399079671d, -0.7857120652d, -0.3019204161d, 0, 0.5678404253d, -0.5495413974d, -0.6128307303d, 0, + -0.9896071041d, 0.1365639107d, -0.04503418428d, 0, -0.6154342638d, -0.6440875597d, 0.4543037336d, 0, 0.1074204368d, + -0.7946340692d, 0.5975094525d, 0, -0.3595449969d, -0.8885529948d, 0.28495784d, 0, -0.2180405296d, 0.1529888965d, 0.9638738118d, + 0, -0.7277432317d, -0.6164050508d, -0.3007234646d, 0, 0.7249729114d, -0.00669719484d, 0.6887448187d, 0, -0.5553659455d, + -0.5336586252d, 0.6377908264d, 0, 0.5137558015d, 0.7976208196d, -0.3160000073d, 0, -0.3794024848d, 0.9245608561d, + -0.03522751494d, 0, 0.8229248658d, 0.2745365933d, -0.4974176556d, 0, -0.5404114394d, 0.6091141441d, 0.5804613989d, 0, + 0.8036581901d, -0.2703029469d, 0.5301601931d, 0, 0.6044318879d, 0.6832968393d, 0.4095943388d, 0, 0.06389988817d, 0.9658208605d, + -0.2512108074d, 0, 0.1087113286d, 0.7402471173d, -0.6634877936d, 0, -0.713427712d, -0.6926784018d, 0.1059128479d, 0, + 0.6458897819d, -0.5724548511d, -0.5050958653d, 0, -0.6553931414d, 0.7381471625d, 0.159995615d, 0, 0.3910961323d, 0.9188871375d, + -0.05186755998d, 0, -0.4879022471d, -0.5904376907d, 0.6429111375d, 0, 0.6014790094d, 0.7707441366d, -0.2101820095d, 0, + -0.5677173047d, 0.7511360995d, 0.3368851762d, 0, 0.7858573506d, 0.226674665d, 0.5753666838d, 0, -0.4520345543d, -0.604222686d, + -0.6561857263d, 0, 0.002272116345d, 0.4132844051d, -0.9105991643d, 0, -0.5815751419d, -0.5162925989d, 0.6286591339d, 0, + -0.03703704785d, 0.8273785755d, 0.5604221175d, 0, -0.5119692504d, 0.7953543429d, -0.3244980058d, 0, -0.2682417366d, + -0.9572290247d, -0.1084387619d, 0, -0.2322482736d, -0.9679131102d, -0.09594243324d, 0, 0.3554328906d, -0.8881505545d, + 0.2913006227d, 0, 0.7346520519d, -0.4371373164d, 0.5188422971d, 0, 0.9985120116d, 0.04659011161d, -0.02833944577d, 0, + -0.3727687496d, -0.9082481361d, 0.1900757285d, 0, 0.91737377d, -0.3483642108d, 0.1925298489d, 0, 0.2714911074d, 0.4147529736d, + -0.8684886582d, 0, 0.5131763485d, -0.7116334161d, 0.4798207128d, 0, -0.8737353606d, 0.18886992d, -0.4482350644d, 0, + 0.8460043821d, -0.3725217914d, 0.3814499973d, 0, 0.8978727456d, -0.1780209141d, -0.4026575304d, 0, 0.2178065647d, + -0.9698322841d, -0.1094789531d, 0, -0.1518031304d, -0.7788918132d, -0.6085091231d, 0, -0.2600384876d, -0.4755398075d, + -0.8403819825d, 0, 0.572313509d, -0.7474340931d, -0.3373418503d, 0, -0.7174141009d, 0.1699017182d, -0.6756111411d, 0, + -0.684180784d, 0.02145707593d, -0.7289967412d, 0, -0.2007447902d, 0.06555605789d, -0.9774476623d, 0, -0.1148803697d, + -0.8044887315d, 0.5827524187d, 0, -0.7870349638d, 0.03447489231d, 0.6159443543d, 0, -0.2015596421d, 0.6859872284d, + 0.6991389226d, 0, -0.08581082512d, -0.10920836d, -0.9903080513d, 0, 0.5532693395d, 0.7325250401d, -0.396610771d, 0, + -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 = { + -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, + -0.9951650832d, 0.0982163789d, 0.7724397808d, -0.6350880136d, 0.7573283322d, -0.6530343002d, -0.9928004525d, -0.119780055d, + -0.0532665713d, 0.9985803285d, 0.9754253726d, -0.2203300762d, -0.7665018163d, 0.6422421394d, 0.991636706d, 0.1290606184d, + -0.994696838d, 0.1028503788d, -0.5379205513d, -0.84299554d, 0.5022815471d, -0.8647041387d, 0.4559821461d, -0.8899889226d, + -0.8659131224d, -0.5001944266d, 0.0879458407d, -0.9961252577d, -0.5051684983d, 0.8630207346d, 0.7753185226d, -0.6315704146d, + -0.6921944612d, 0.7217110418d, -0.5191659449d, -0.8546734591d, 0.8978622882d, -0.4402764035d, -0.1706774107d, 0.9853269617d, + -0.9353430106d, -0.3537420705d, -0.9992404798d, 0.03896746794d, -0.2882064021d, -0.9575683108d, -0.9663811329d, 0.2571137995d, + -0.8759714238d, -0.4823630009d, -0.8303123018d, -0.5572983775d, 0.05110133755d, -0.9986934731d, -0.8558373281d, -0.5172450752d, + 0.09887025282d, 0.9951003332d, 0.9189016087d, 0.3944867976d, -0.2439375892d, -0.9697909324d, -0.8121409387d, -0.5834613061d, + -0.9910431363d, 0.1335421355d, 0.8492423985d, -0.5280031709d, -0.9717838994d, -0.2358729591d, 0.9949457207d, 0.1004142068d, + 0.6241065508d, -0.7813392434d, 0.662910307d, 0.7486988212d, -0.7197418176d, 0.6942418282d, -0.8143370775d, -0.5803922158d, + 0.104521054d, -0.9945226741d, -0.1065926113d, -0.9943027784d, 0.445799684d, -0.8951327509d, 0.105547406d, 0.9944142724d, + -0.992790267d, 0.1198644477d, -0.8334366408d, 0.552615025d, 0.9115561563d, -0.4111755999d, 0.8285544909d, -0.5599084351d, + 0.7217097654d, -0.6921957921d, 0.4940492677d, -0.8694339084d, -0.3652321272d, -0.9309164803d, -0.9696606758d, 0.2444548501d, + 0.08925509731d, -0.996008799d, 0.5354071276d, -0.8445941083d, -0.1053576186d, 0.9944343981d, -0.9890284586d, 0.1477251101d, + 0.004856104961d, 0.9999882091d, 0.9885598478d, 0.1508291331d, 0.9286129562d, -0.3710498316d, -0.5832393863d, -0.8123003252d, + 0.3015207509d, 0.9534596146d, -0.9575110528d, 0.2883965738d, 0.9715802154d, -0.2367105511d, 0.229981792d, 0.9731949318d, + 0.955763816d, -0.2941352207d, 0.740956116d, 0.6715534485d, -0.9971513787d, -0.07542630764d, 0.6905710663d, -0.7232645452d, + -0.290713703d, -0.9568100872d, 0.5912777791d, -0.8064679708d, -0.9454592212d, -0.325740481d, 0.6664455681d, 0.74555369d, + 0.6236134912d, 0.7817328275d, 0.9126993851d, -0.4086316587d, -0.8191762011d, 0.5735419353d, -0.8812745759d, -0.4726046147d, + 0.9953313627d, 0.09651672651d, 0.9855650846d, -0.1692969699d, -0.8495980887d, 0.5274306472d, 0.6174853946d, -0.7865823463d, + 0.8508156371d, 0.52546432d, 0.9985032451d, -0.05469249926d, 0.1971371563d, -0.9803759185d, 0.6607855748d, -0.7505747292d, + -0.03097494063d, 0.9995201614d, -0.6731660801d, 0.739491331d, -0.7195018362d, -0.6944905383d, 0.9727511689d, 0.2318515979d, + 0.9997059088d, -0.0242506907d, 0.4421787429d, -0.8969269532d, 0.9981350961d, -0.061043673d, -0.9173660799d, -0.3980445648d, + -0.8150056635d, -0.5794529907d, -0.8789331304d, 0.4769450202d, 0.0158605829d, 0.999874213d, -0.8095464474d, 0.5870558317d, + -0.9165898907d, -0.3998286786d, -0.8023542565d, 0.5968480938d, -0.5176737917d, 0.8555780767d, -0.8154407307d, -0.5788405779d, + 0.4022010347d, -0.9155513791d, -0.9052556868d, -0.4248672045d, 0.7317445619d, 0.6815789728d, -0.5647632201d, -0.8252529947d, + -0.8403276335d, -0.5420788397d, -0.9314281527d, 0.363925262d, 0.5238198472d, 0.8518290719d, 0.7432803869d, -0.6689800195d, + -0.985371561d, -0.1704197369d, 0.4601468731d, 0.88784281d, 0.825855404d, 0.5638819483d, 0.6182366099d, 0.7859920446d, + 0.8331502863d, -0.553046653d, 0.1500307506d, 0.9886813308d, -0.662330369d, -0.7492119075d, -0.668598664d, 0.743623444d, + 0.7025606278d, 0.7116238924d, -0.5419389763d, -0.8404178401d, -0.3388616456d, 0.9408362159d, 0.8331530315d, 0.5530425174d, + -0.2989720662d, -0.9542618632d, 0.2638522993d, 0.9645630949d, 0.124108739d, -0.9922686234d, -0.7282649308d, -0.6852956957d, + 0.6962500149d, 0.7177993569d, -0.9183535368d, 0.3957610156d, -0.6326102274d, -0.7744703352d, -0.9331891859d, -0.359385508d, + -0.1153779357d, -0.9933216659d, 0.9514974788d, -0.3076565421d, -0.08987977445d, -0.9959526224d, 0.6678496916d, 0.7442961705d, + 0.7952400393d, -0.6062947138d, -0.6462007402d, -0.7631674805d, -0.2733598753d, 0.9619118351d, 0.9669590226d, -0.254931851d, + -0.9792894595d, 0.2024651934d, -0.5369502995d, -0.8436138784d, -0.270036471d, -0.9628500944d, -0.6400277131d, 0.7683518247d, + -0.7854537493d, -0.6189203566d, 0.06005905383d, -0.9981948257d, -0.02455770378d, 0.9996984141d, -0.65983623d, 0.751409442d, + -0.6253894466d, -0.7803127835d, -0.6210408851d, -0.7837781695d, 0.8348888491d, 0.5504185768d, -0.1592275245d, 0.9872419133d, + 0.8367622488d, 0.5475663786d, -0.8675753916d, -0.4973056806d, -0.2022662628d, -0.9793305667d, 0.9399189937d, 0.3413975472d, + 0.9877404807d, -0.1561049093d, -0.9034455656d, 0.4287028224d, 0.1269804218d, -0.9919052235d, -0.3819600854d, 0.924178821d, + 0.9754625894d, 0.2201652486d, -0.3204015856d, -0.9472818081d, -0.9874760884d, 0.1577687387d, 0.02535348474d, -0.9996785487d, + 0.4835130794d, -0.8753371362d, -0.2850799925d, -0.9585037287d, -0.06805516006d, -0.99768156d, -0.7885244045d, -0.6150034663d, + 0.3185392127d, -0.9479096845d, 0.8880043089d, 0.4598351306d, 0.6476921488d, -0.7619021462d, 0.9820241299d, 0.1887554194d, + 0.9357275128d, -0.3527237187d, -0.8894895414d, 0.4569555293d, 0.7922791302d, 0.6101588153d, 0.7483818261d, 0.6632681526d, + -0.7288929755d, -0.6846276581d, 0.8729032783d, -0.4878932944d, 0.8288345784d, 0.5594937369d, 0.08074567077d, 0.9967347374d, + 0.9799148216d, -0.1994165048d, -0.580730673d, -0.8140957471d, -0.4700049791d, -0.8826637636d, 0.2409492979d, 0.9705377045d, + 0.9437816757d, -0.3305694308d, -0.8927998638d, -0.4504535528d, -0.8069622304d, 0.5906030467d, 0.06258973166d, 0.9980393407d, + -0.9312597469d, 0.3643559849d, 0.5777449785d, 0.8162173362d, -0.3360095855d, -0.941858566d, 0.697932075d, -0.7161639607d, + -0.002008157227d, -0.9999979837d, -0.1827294312d, -0.9831632392d, -0.6523911722d, 0.7578824173d, -0.4302626911d, -0.9027037258d, + -0.9985126289d, -0.05452091251d, -0.01028102172d, -0.9999471489d, -0.4946071129d, 0.8691166802d, -0.2999350194d, 0.9539596344d, + 0.8165471961d, 0.5772786819d, 0.2697460475d, 0.962931498d, -0.7306287391d, -0.6827749597d, -0.7590952064d, -0.6509796216d, + -0.907053853d, 0.4210146171d, -0.5104861064d, -0.8598860013d, 0.8613350597d, 0.5080373165d, 0.5007881595d, -0.8655698812d, + -0.654158152d, 0.7563577938d, -0.8382755311d, -0.545246856d, 0.6940070834d, 0.7199681717d, 0.06950936031d, 0.9975812994d, + 0.1702942185d, -0.9853932612d, 0.2695973274d, 0.9629731466d, 0.5519612192d, -0.8338697815d, 0.225657487d, -0.9742067022d, + 0.4215262855d, -0.9068161835d, 0.4881873305d, -0.8727388672d, -0.3683854996d, -0.9296731273d, -0.9825390578d, 0.1860564427d, + 0.81256471d, 0.5828709909d, 0.3196460933d, -0.9475370046d, 0.9570913859d, 0.2897862643d, -0.6876655497d, -0.7260276109d, + -0.9988770922d, -0.047376731d, -0.1250179027d, 0.992154486d, -0.8280133617d, 0.560708367d, 0.9324863769d, -0.3612051451d, + 0.6394653183d, 0.7688199442d, -0.01623847064d, -0.9998681473d, -0.9955014666d, -0.09474613458d, -0.81453315d, 0.580117012d, + 0.4037327978d, -0.9148769469d, 0.9944263371d, 0.1054336766d, -0.1624711654d, 0.9867132919d, -0.9949487814d, -0.100383875d, + -0.6995302564d, 0.7146029809d, 0.5263414922d, -0.85027327d, -0.5395221479d, 0.841971408d, 0.6579370318d, 0.7530729462d, + 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; + + Vector2 center = new Vector2(x, 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; + center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); + center.setZ((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; + center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); + center.setZ((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; + center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); + center.setZ((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.getNoiseSeeded(sl, center.getX(), center.getZ()); + 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; + }; + } + + @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; + + Vector3 center = new Vector3(x, y, 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; + center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); + center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); + center.setZ((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; + center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); + center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); + center.setZ((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; + center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); + center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); + center.setZ((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.getNoiseSeeded(sl, center.getX(), center.getY(), center.getZ()); + 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; + }; + } + + public enum DistanceFunction { + Euclidean, + EuclideanSq, + Manhattan, + Hybrid + } + + + public enum ReturnType { + CellValue, + Distance, + Distance2, + Distance2Add, + Distance2Sub, + Distance2Mul, + Distance2Div, + NoiseLookup, + Distance3, + Distance3Add, + Distance3Sub, + Distance3Mul, + Distance3Div + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ConstantSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ConstantSampler.java new file mode 100644 index 000000000..eaea1382d --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ConstantSampler.java @@ -0,0 +1,22 @@ +package com.dfsek.terra.addons.noise.samplers.noise; + +/** + * Sampler3D implementation that returns a constant. + */ +public class ConstantSampler extends NoiseFunction { + private final double constant; + + public ConstantSampler(double constant) { + this.constant = constant; + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + return constant; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return constant; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ExpressionFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ExpressionFunction.java new file mode 100644 index 000000000..01011f58e --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ExpressionFunction.java @@ -0,0 +1,45 @@ +package com.dfsek.terra.addons.noise.samplers.noise; + +import com.dfsek.paralithic.Expression; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.paralithic.functions.Function; + +import java.util.Map; + +import com.dfsek.terra.addons.noise.paralithic.noise.SeedContext; + + +/** + * NoiseSampler implementation using a Paralithic expression. + */ +public class ExpressionFunction extends NoiseFunction { + private final Expression expression; + + public ExpressionFunction(Map functions, String eq, Map vars) throws ParseException { + Parser p = new Parser(); + Scope scope = new Scope(); + + scope.addInvocationVariable("x"); + scope.addInvocationVariable("y"); + scope.addInvocationVariable("z"); + + vars.forEach(scope::create); + + functions.forEach(p::registerFunction); + + expression = p.parse(eq, scope); + frequency = 1; + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + return expression.evaluate(new SeedContext(seed), x, 0, y); + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return expression.evaluate(new SeedContext(seed), x, y, z); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/GaborNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/GaborNoiseSampler.java new file mode 100644 index 000000000..fbe7afdae --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/GaborNoiseSampler.java @@ -0,0 +1,107 @@ +package com.dfsek.terra.addons.noise.samplers.noise; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler; + + +public class GaborNoiseSampler extends NoiseFunction { + private final WhiteNoiseSampler rand; + private double k = 1.0; + private double a = 0.1; + private double f0 = 0.625; + private double kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / a); + private double omega0 = Math.PI * 0.25; + private boolean isotropic = true; + private double impulsesPerKernel = 64d; + private double impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius)); + private double impulsesPerCell = impulseDensity * kernelRadius * kernelRadius; + private double g = FastMath.exp(-impulsesPerCell); + + + public GaborNoiseSampler() { + rand = new WhiteNoiseSampler(); + } + + private void recalculateRadiusAndDensity() { + kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / this.a); + impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius)); + impulsesPerCell = impulseDensity * kernelRadius * kernelRadius; + g = FastMath.exp(-impulsesPerCell); + } + + private double gaborNoise(long seed, double x, double y) { + x /= kernelRadius; + y /= kernelRadius; + int xi = fastFloor(x); + int yi = fastFloor(y); + double xf = x - xi; + double yf = y - yi; + double noise = 0; + for(int dx = -1; dx <= 1; dx++) { + for(int dz = -1; dz <= 1; dz++) { + noise += calculateCell(seed, xi + dx, yi + dz, xf - dx, yf - dz); + } + } + return noise; + } + + private double calculateCell(long seed, int xi, int yi, double x, double y) { + long mashedSeed = murmur64(31L * xi + yi) + seed; + + double gaussianSource = (rand.getNoiseRaw(mashedSeed++) + 1) / 2; + int impulses = 0; + while(gaussianSource > g) { + impulses++; + gaussianSource *= (rand.getNoiseRaw(mashedSeed++) + 1) / 2; + } + + double noise = 0; + for(int i = 0; i < impulses; i++) { + noise += rand.getNoiseRaw(mashedSeed++) * gabor(isotropic ? (rand.getNoiseRaw(mashedSeed++) + 1) * Math.PI : omega0, + x * kernelRadius, y * kernelRadius); + } + return noise; + } + + private double gabor(double omega_0, double x, double y) { + return k * (FastMath.exp(-Math.PI * (a * a) * (x * x + y * y)) * fastCos(2 * Math.PI * f0 * (x * fastCos(omega_0) + y * fastSin( + omega_0)))); + } + + public void setA(double a) { + this.a = a; + recalculateRadiusAndDensity(); + } + + public void setDeviation(double k) { + this.k = k; + } + + public void setFrequency0(double f0) { + this.f0 = f0; + } + + public void setImpulsesPerKernel(double impulsesPerKernel) { + this.impulsesPerKernel = impulsesPerKernel; + recalculateRadiusAndDensity(); + } + + public void setIsotropic(boolean isotropic) { + this.isotropic = isotropic; + } + + public void setRotation(double omega0) { + this.omega0 = Math.PI * omega0; + } + + @Override + public double getNoiseRaw(long seed, double x, double z) { + return gaborNoise(seed, x, z); + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return gaborNoise(seed, x, z); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/NoiseFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/NoiseFunction.java new file mode 100644 index 000000000..d3b6a3045 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/NoiseFunction.java @@ -0,0 +1,143 @@ +package com.dfsek.terra.addons.noise.samplers.noise; + +import net.jafama.FastMath; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("ManualMinMaxCalculation") +public abstract class NoiseFunction implements NoiseSampler { + // Hashing + protected static final int PRIME_X = 501125321; + protected static final int PRIME_Y = 1136930381; + protected static final int PRIME_Z = 1720413743; + static final int precision = 100; + static final int modulus = 360 * precision; + static final double[] sin = new double[360 * 100]; // lookup table + static { + for(int i = 0; i < sin.length; i++) { + sin[i] = (float) Math.sin((double) (i) / (precision)); + } + } + protected double frequency = 0.02d; + protected long salt; + + public NoiseFunction() { + this.salt = 0; + } + + protected static int fastFloor(double f) { + return f >= 0 ? (int) f : (int) f - 1; + } + + protected static int hash(int seed, int xPrimed, int yPrimed, int zPrimed) { + int hash = seed ^ xPrimed ^ yPrimed ^ zPrimed; + + hash *= 0x27d4eb2d; + return hash; + } + + protected static int hash(int seed, int xPrimed, int yPrimed) { + int hash = seed ^ xPrimed ^ yPrimed; + + hash *= 0x27d4eb2d; + return hash; + } + + protected static int fastRound(double f) { + return f >= 0 ? (int) (f + 0.5f) : (int) (f - 0.5); + } + + protected static double lerp(double a, double b, double t) { + return a + t * (b - a); + } + + protected static double interpHermite(double t) { + return t * t * (3 - 2 * t); + } + + protected static double interpQuintic(double t) { + return t * t * t * (t * (t * 6 - 15) + 10); + } + + protected static double cubicLerp(double a, double b, double c, double d, double t) { + double p = (d - c) - (a - b); + return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b; + } + + protected static double fastMin(double a, double b) { + return a < b ? a : b; + } + + protected static double fastMax(double a, double b) { + return a > b ? a : b; + } + + protected static double fastAbs(double f) { + return f < 0 ? -f : f; + } + + protected static double fastSqrt(double f) { + return FastMath.sqrt(f); + } + + protected static int fastCeil(double f) { + int i = (int) f; + if(i < f) i++; + return i; + } + + /** + * Murmur64 hashing function + * + * @param h Input value + * + * @return Hashed value + */ + protected static long murmur64(long h) { + h ^= h >>> 33; + h *= 0xff51afd7ed558ccdL; + h ^= h >>> 33; + h *= 0xc4ceb9fe1a85ec53L; + h ^= h >>> 33; + return h; + } + + protected static double fastSin(double a) { + return sinLookup((int) (a * precision + 0.5f)); + } + + protected static double fastCos(double a) { + return sinLookup((int) ((a + Math.PI / 2) * precision + 0.5f)); + } + + private static double sinLookup(int a) { + return a >= 0 ? sin[a % (modulus)] : -sin[-a % (modulus)]; + } + + public void setSalt(long salt) { + this.salt = salt; + } + + public double getFrequency() { + return frequency; + } + + public void setFrequency(double frequency) { + this.frequency = frequency; + } + + @Override + public double getNoiseSeeded(long seed, double x, double y) { + return getNoiseRaw(seed + salt, x * frequency, y * frequency); + } + + @Override + public double getNoiseSeeded(long seed, double x, double y, double z) { + return getNoiseRaw(seed + salt, x * frequency, y * frequency, z * frequency); + } + + public abstract double getNoiseRaw(long seed, double x, double y); + + public abstract double getNoiseRaw(long seed, double x, double y, double z); +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/BrownianMotionSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/BrownianMotionSampler.java new file mode 100644 index 000000000..f7e636ae6 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/BrownianMotionSampler.java @@ -0,0 +1,47 @@ +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class BrownianMotionSampler extends FractalNoiseFunction { + public BrownianMotionSampler(NoiseSampler input) { + super(input); + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + double sum = 0; + double amp = fractalBounding; + + for(int i = 0; i < octaves; i++) { + double noise = input.getNoiseSeeded(seed++, x, y); + sum += noise * amp; + amp *= lerp(1.0, fastMin(noise + 1, 2) * 0.5, weightedStrength); + + x *= lacunarity; + y *= lacunarity; + amp *= gain; + } + + return sum; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + double sum = 0; + double amp = fractalBounding; + + for(int i = 0; i < octaves; i++) { + double noise = input.getNoiseSeeded(seed++, x, y, z); + sum += noise * amp; + amp *= lerp(1.0, (noise + 1) * 0.5, weightedStrength); + + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + amp *= gain; + } + + return sum; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/FractalNoiseFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/FractalNoiseFunction.java new file mode 100644 index 000000000..0f3455c72 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/FractalNoiseFunction.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class FractalNoiseFunction extends NoiseFunction { + protected final NoiseSampler input; + protected double fractalBounding = 1 / 1.75; + protected int octaves = 3; + protected double gain = 0.5; + protected double lacunarity = 2.0d; + protected double weightedStrength = 0.0d; + + public FractalNoiseFunction(NoiseSampler input) { + this.input = input; + frequency = 1; + } + + protected void calculateFractalBounding() { + double gain = fastAbs(this.gain); + double amp = gain; + double ampFractal = 1.0; + for(int i = 1; i < octaves; i++) { + ampFractal += amp; + amp *= gain; + } + fractalBounding = 1 / ampFractal; + } + + public void setGain(double gain) { + this.gain = gain; + calculateFractalBounding(); + } + + public void setLacunarity(double lacunarity) { + this.lacunarity = lacunarity; + } + + public void setOctaves(int octaves) { + this.octaves = octaves; + calculateFractalBounding(); + } + + public void setWeightedStrength(double weightedStrength) { + this.weightedStrength = weightedStrength; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/PingPongSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/PingPongSampler.java new file mode 100644 index 000000000..3c712db61 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/PingPongSampler.java @@ -0,0 +1,59 @@ +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class PingPongSampler extends FractalNoiseFunction { + private double pingPongStrength = 2.0; + + public PingPongSampler(NoiseSampler input) { + super(input); + } + + + private static double pingPong(double t) { + t -= (int) (t * 0.5f) << 1; + return t < 1 ? t : 2 - t; + } + + public void setPingPongStrength(double strength) { + this.pingPongStrength = strength; + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + double sum = 0; + double amp = fractalBounding; + + for(int i = 0; i < octaves; i++) { + double noise = pingPong((input.getNoiseSeeded(seed++, x, y) + 1) * pingPongStrength); + sum += (noise - 0.5) * 2 * amp; + amp *= lerp(1.0, noise, weightedStrength); + + x *= lacunarity; + y *= lacunarity; + amp *= gain; + } + + return sum; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + double sum = 0; + double amp = fractalBounding; + + for(int i = 0; i < octaves; i++) { + double noise = pingPong((input.getNoiseSeeded(seed++, x, y, z) + 1) * pingPongStrength); + sum += (noise - 0.5) * 2 * amp; + amp *= lerp(1.0, noise, weightedStrength); + + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + amp *= gain; + } + + return sum; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/RidgedFractalSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/RidgedFractalSampler.java new file mode 100644 index 000000000..6c6f53592 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/RidgedFractalSampler.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class RidgedFractalSampler extends FractalNoiseFunction { + + public RidgedFractalSampler(NoiseSampler input) { + super(input); + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + double sum = 0; + double amp = fractalBounding; + + for(int i = 0; i < octaves; i++) { + double noise = fastAbs(input.getNoiseSeeded(seed++, x, y)); + sum += (noise * -2 + 1) * amp; + amp *= lerp(1.0, 1 - noise, weightedStrength); + + x *= lacunarity; + y *= lacunarity; + amp *= gain; + } + + return sum; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + double sum = 0; + double amp = fractalBounding; + + for(int i = 0; i < octaves; i++) { + double noise = fastAbs(input.getNoiseSeeded(seed++, x, y, z)); + sum += (noise * -2 + 1) * amp; + amp *= lerp(1.0, 1 - noise, weightedStrength); + + x *= lacunarity; + y *= lacunarity; + z *= lacunarity; + amp *= gain; + } + + return sum; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/GaussianNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/GaussianNoiseSampler.java new file mode 100644 index 000000000..159dfffc0 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/GaussianNoiseSampler.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.addons.noise.samplers.noise.random; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; + + +/** + * NoiseSampler implementation to provide random, normally distributed (Gaussian) noise. + */ +public class GaussianNoiseSampler extends NoiseFunction { + private final WhiteNoiseSampler whiteNoiseSampler; // Back with a white noise sampler. + + public GaussianNoiseSampler() { + whiteNoiseSampler = new WhiteNoiseSampler(); + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + double v1, v2, s; + do { + v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y); + v2 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y); + s = v1 * v1 + v2 * v2; + } while(s >= 1 || s == 0); + double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); + return v1 * multiplier; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + double v1, v2, s; + do { + v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y, z); + v2 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y, z); + s = v1 * v1 + v2 * v2; + } while(s >= 1 || s == 0); + double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); + return v1 * multiplier; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/WhiteNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/WhiteNoiseSampler.java new file mode 100644 index 000000000..8ec5d0d2b --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/WhiteNoiseSampler.java @@ -0,0 +1,53 @@ +package com.dfsek.terra.addons.noise.samplers.noise.random; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; + + +/** + * NoiseSampler implementation to produce random, uniformly distributed (white) noise. + */ +public class WhiteNoiseSampler extends NoiseFunction { + private static final long POSITIVE_POW1 = 0b01111111111L << 52; + // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1. + + public WhiteNoiseSampler() { + } + + public long randomBits(long seed, double x, double y, double z) { + long hashX = Double.doubleToRawLongBits(x) ^ seed; + long hashZ = Double.doubleToRawLongBits(y) ^ seed; + long hash = (((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed) + Double.doubleToRawLongBits(z); + return murmur64(hash); + } + + public long randomBits(long seed, double x, double y) { + long hashX = Double.doubleToRawLongBits(x) ^ seed; + long hashZ = Double.doubleToRawLongBits(y) ^ seed; + long hash = ((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed; + return murmur64(hash); + } + + public double getNoiseRaw(long seed) { + return (Double.longBitsToDouble((murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - 1.5) * 2; + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + return (getNoiseUnmapped(seed, x, y) - 1.5) * 2; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return (getNoiseUnmapped(seed, x, y, z) - 1.5) * 2; + } + + public double getNoiseUnmapped(long seed, double x, double y, double z) { + long base = ((randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } + + public double getNoiseUnmapped(long seed, double x, double y) { + long base = (randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java new file mode 100644 index 000000000..24c36cb34 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java @@ -0,0 +1,272 @@ +package com.dfsek.terra.addons.noise.samplers.noise.simplex; + +/** + * NoiseSampler implementation to provide OpenSimplex2 (Smooth Variant) noise. + */ +public class OpenSimplex2SSampler extends SimplexStyleSampler { + @Override + @SuppressWarnings("NumericOverflow") + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; + // 2D OpenSimplex2S case is a modified 2D simplex noise. + + final double SQRT3 = 1.7320508075688772935274463415059; + final double G2 = (3 - SQRT3) / 6; + + final double F2 = 0.5f * (SQRT3 - 1); + double s = (x + y) * F2; + x += s; + y += s; + + + int i = fastFloor(x); + int j = fastFloor(y); + double xi = x - i; + double yi = y - j; + + i *= PRIME_X; + j *= PRIME_Y; + int i1 = i + PRIME_X; + int j1 = j + PRIME_Y; + + double t = (xi + yi) * G2; + double x0 = xi - t; + double y0 = yi - t; + + double a0 = (2.0 / 3.0) - x0 * x0 - y0 * y0; + double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i, j, x0, y0); + + double a1 = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a0); + double x1 = x0 - (1 - 2 * G2); + double y1 = y0 - (1 - 2 * G2); + value += (a1 * a1) * (a1 * a1) * gradCoord(seed, i1, j1, x1, y1); + + // Nested conditionals were faster than compact bit logic/arithmetic. + double xmyi = xi - yi; + if(t > G2) { + if(xi + xmyi > 1) { + double x2 = x0 + (3 * G2 - 2); + double y2 = y0 + (3 * G2 - 1); + double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (PRIME_X << 1), j + PRIME_Y, x2, y2); + } + } else { + double x2 = x0 + G2; + double y2 = y0 + (G2 - 1); + double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j + PRIME_Y, x2, y2); + } + } + + if(yi - xmyi > 1) { + double x3 = x0 + (3 * G2 - 1); + double y3 = y0 + (3 * G2 - 2); + double a3 = (2.0 / 3.0) - x3 * x3 - y3 * y3; + if(a3 > 0) { + value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + PRIME_X, j + (PRIME_Y << 1), x3, y3); + } + } else { + double x3 = x0 + (G2 - 1); + double y3 = y0 + G2; + double a3 = (2.0 / 3.0) - x3 * x3 - y3 * y3; + if(a3 > 0) { + value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + PRIME_X, j, x3, y3); + } + } + } else { + if(xi + xmyi < 0) { + double x2 = x0 + (1 - G2); + double y2 = y0 - G2; + double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i - PRIME_X, j, x2, y2); + } + } else { + double x2 = x0 + (G2 - 1); + double y2 = y0 + G2; + double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + PRIME_X, j, x2, y2); + } + } + + if(yi < xmyi) { + double x2 = x0 - G2; + double y2 = y0 - (G2 - 1); + double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j - PRIME_Y, x2, y2); + } + } else { + double x2 = x0 + G2; + double y2 = y0 + (G2 - 1); + double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2; + if(a2 > 0) { + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j + PRIME_Y, x2, y2); + } + } + } + + return value * 18.24196194486065; + } + + @Override + @SuppressWarnings("NumericOverflow") + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; + // 3D OpenSimplex2S case uses two offset rotated cube grids. + final double R3 = (2.0 / 3.0); + double r = (x + y + z) * R3; // Rotation, not skew + x = r - x; + y = r - y; + z = r - z; + + + int i = fastFloor(x); + int j = fastFloor(y); + int k = fastFloor(z); + double xi = x - i; + double yi = y - j; + double zi = z - k; + + i *= PRIME_X; + j *= PRIME_Y; + k *= PRIME_Z; + int seed2 = seed + 1293373; + + int xNMask = (int) (-0.5 - xi); + int yNMask = (int) (-0.5 - yi); + int zNMask = (int) (-0.5 - zi); + + double x0 = xi + xNMask; + double y0 = yi + yNMask; + double z0 = zi + zNMask; + double a0 = 0.75 - x0 * x0 - y0 * y0 - z0 * z0; + double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, + y0, + z0); + + double x1 = xi - 0.5; + double y1 = yi - 0.5; + double z1 = zi - 0.5; + double a1 = 0.75 - x1 * x1 - y1 * y1 - z1 * z1; + value += (a1 * a1) * (a1 * a1) * gradCoord(seed2, i + PRIME_X, j + PRIME_Y, k + PRIME_Z, x1, y1, z1); + + double xAFlipMask0 = ((xNMask | 1) << 1) * x1; + double yAFlipMask0 = ((yNMask | 1) << 1) * y1; + double zAFlipMask0 = ((zNMask | 1) << 1) * z1; + double xAFlipMask1 = (-2 - (xNMask << 2)) * x1 - 1.0; + double yAFlipMask1 = (-2 - (yNMask << 2)) * y1 - 1.0; + double zAFlipMask1 = (-2 - (zNMask << 2)) * z1 - 1.0; + + boolean skip5 = false; + double a2 = xAFlipMask0 + a0; + if(a2 > 0) { + double x2 = x0 - (xNMask | 1); + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x2, + y0, + z0); + } else { + double a3 = yAFlipMask0 + zAFlipMask0 + a0; + if(a3 > 0) { + double y3 = y0 - (yNMask | 1); + double z3 = z0 - (zNMask | 1); + value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), + x0, + y3, z3); + } + + double a4 = xAFlipMask1 + a1; + if(a4 > 0) { + double x4 = (xNMask | 1) + x1; + value += (a4 * a4) * (a4 * a4) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + PRIME_Z, x4, y1, z1); + skip5 = true; + } + } + + boolean skip9 = false; + double a6 = yAFlipMask0 + a0; + if(a6 > 0) { + double y6 = y0 - (yNMask | 1); + value += (a6 * a6) * (a6 * a6) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, + y6, + z0); + } else { + double a7 = xAFlipMask0 + zAFlipMask0 + a0; + if(a7 > 0) { + double x7 = x0 - (xNMask | 1); + double z7 = z0 - (zNMask | 1); + value += (a7 * a7) * (a7 * a7) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), + x7, + y0, z7); + } + + double a8 = yAFlipMask1 + a1; + if(a8 > 0) { + double y8 = (yNMask | 1) + y1; + value += (a8 * a8) * (a8 * a8) * gradCoord(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z, x1, y8, z1); + skip9 = true; + } + } + + boolean skipD = false; + double aA = zAFlipMask0 + a0; + if(aA > 0) { + double zA = z0 - (zNMask | 1); + value += (aA * aA) * (aA * aA) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0, + y0, + zA); + } else { + double aB = xAFlipMask0 + yAFlipMask0 + a0; + if(aB > 0) { + double xB = x0 - (xNMask | 1); + double yB = y0 - (yNMask | 1); + value += (aB * aB) * (aB * aB) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), + xB, + yB, z0); + } + + double aC = zAFlipMask1 + a1; + if(aC > 0) { + double zC = (zNMask | 1) + z1; + value += (aC * aC) * (aC * aC) * gradCoord(seed2, i + PRIME_X, j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), x1, y1, zC); + skipD = true; + } + } + + if(!skip5) { + double a5 = yAFlipMask1 + zAFlipMask1 + a1; + if(a5 > 0) { + double y5 = (yNMask | 1) + y1; + double z5 = (zNMask | 1) + z1; + value += (a5 * a5) * (a5 * a5) * gradCoord(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + (zNMask & (PRIME_Z << 1)), + x1, y5, z5); + } + } + + if(!skip9) { + double a9 = xAFlipMask1 + zAFlipMask1 + a1; + if(a9 > 0) { + double x9 = (xNMask | 1) + x1; + double z9 = (zNMask | 1) + z1; + value += (a9 * a9) * (a9 * a9) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), + x9, + y1, z9); + } + } + + if(!skipD) { + double aD = xAFlipMask1 + yAFlipMask1 + a1; + if(aD > 0) { + double xD = (xNMask | 1) + x1; + double yD = (yNMask | 1) + y1; + value += (aD * aD) * (aD * aD) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z, + xD, yD, z1); + } + } + + return value * 9.046026385208288; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java new file mode 100644 index 000000000..410176b2e --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java @@ -0,0 +1,153 @@ +package com.dfsek.terra.addons.noise.samplers.noise.simplex; + +/** + * NoiseSampler implementation to provide OpenSimplex2 noise. + */ +public class OpenSimplex2Sampler extends SimplexStyleSampler { + private static final double SQRT3 = 1.7320508075688772935274463415059; + + @Override + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; + // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex. + final double G2 = (3 - SQRT3) / 6; + + final double F2 = 0.5f * (SQRT3 - 1); + double s = (x + y) * F2; + x += s; + y += s; + + + int i = fastFloor(x); + int j = fastFloor(y); + double xi = x - i; + double yi = y - j; + + double t = (xi + yi) * G2; + double x0 = xi - t; + double y0 = yi - t; + + i *= PRIME_X; + j *= PRIME_Y; + + double n0, n1, n2; + + double a = 0.5 - x0 * x0 - y0 * y0; + if(a <= 0) n0 = 0; + else { + n0 = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0); + } + + double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a); + if(c <= 0) n2 = 0; + else { + double x2 = x0 + (2 * G2 - 1); + double y2 = y0 + (2 * G2 - 1); + n2 = (c * c) * (c * c) * gradCoord(seed, i + PRIME_X, j + PRIME_Y, x2, y2); + } + + if(y0 > x0) { + double x1 = x0 + G2; + double y1 = y0 + (G2 - 1); + double b = 0.5 - x1 * x1 - y1 * y1; + if(b <= 0) n1 = 0; + else { + n1 = (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1); + } + } else { + double x1 = x0 + (G2 - 1); + double y1 = y0 + G2; + double b = 0.5 - x1 * x1 - y1 * y1; + if(b <= 0) n1 = 0; + else { + n1 = (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1); + } + } + + return (n0 + n1 + n2) * 99.83685446303647f; + } + + @Override + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; + // 3D OpenSimplex2Sampler case uses two offset rotated cube grids. + final double R3 = (2.0 / 3.0); + double r = (x + y + z) * R3; // Rotation, not skew + x = r - x; + y = r - y; + z = r - z; + + + int i = fastRound(x); + int j = fastRound(y); + int k = fastRound(z); + double x0 = x - i; + double y0 = y - j; + double z0 = z - k; + + int xNSign = (int) (-1.0 - x0) | 1; + int yNSign = (int) (-1.0 - y0) | 1; + int zNSign = (int) (-1.0 - z0) | 1; + + double ax0 = xNSign * -x0; + double ay0 = yNSign * -y0; + double az0 = zNSign * -z0; + + i *= PRIME_X; + j *= PRIME_Y; + k *= PRIME_Z; + + double value = 0; + double a = (0.6f - x0 * x0) - (y0 * y0 + z0 * z0); + + for(int l = 0; ; l++) { + if(a > 0) { + value += (a * a) * (a * a) * gradCoord(seed, i, j, k, x0, y0, z0); + } + + if(ax0 >= ay0 && ax0 >= az0) { + double b = a + ax0 + ax0; + if(b > 1) { + b -= 1; + value += (b * b) * (b * b) * gradCoord(seed, i - xNSign * PRIME_X, j, k, x0 + xNSign, y0, z0); + } + } else if(ay0 > ax0 && ay0 >= az0) { + double b = a + ay0 + ay0; + if(b > 1) { + b -= 1; + value += (b * b) * (b * b) * gradCoord(seed, i, j - yNSign * PRIME_Y, k, x0, y0 + yNSign, z0); + } + } else { + double b = a + az0 + az0; + if(b > 1) { + b -= 1; + value += (b * b) * (b * b) * gradCoord(seed, i, j, k - zNSign * PRIME_Z, x0, y0, z0 + zNSign); + } + } + + if(l == 1) break; + + ax0 = 0.5 - ax0; + ay0 = 0.5 - ay0; + az0 = 0.5 - az0; + + x0 = xNSign * ax0; + y0 = yNSign * ay0; + z0 = zNSign * az0; + + a += (0.75 - ax0) - (ay0 + az0); + + i += (xNSign >> 1) & PRIME_X; + j += (yNSign >> 1) & PRIME_Y; + k += (zNSign >> 1) & PRIME_Z; + + xNSign = -xNSign; + yNSign = -yNSign; + zNSign = -zNSign; + + seed = ~seed; + } + + return value * 32.69428253173828125; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/PerlinSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/PerlinSampler.java new file mode 100644 index 000000000..047e02ce5 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/PerlinSampler.java @@ -0,0 +1,67 @@ +package com.dfsek.terra.addons.noise.samplers.noise.simplex; + +/** + * NoiseSampler implementation to provide Perlin Noise. + */ +public class PerlinSampler extends SimplexStyleSampler { + @Override + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; + int x0 = fastFloor(x); + int y0 = fastFloor(y); + + double xd0 = x - x0; + double yd0 = y - y0; + double xd1 = xd0 - 1; + double yd1 = yd0 - 1; + + double xs = interpQuintic(xd0); + double ys = interpQuintic(yd0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + + double xf0 = lerp(gradCoord(seed, x0, y0, xd0, yd0), gradCoord(seed, x1, y0, xd1, yd0), xs); + double xf1 = lerp(gradCoord(seed, x0, y1, xd0, yd1), gradCoord(seed, x1, y1, xd1, yd1), xs); + + return lerp(xf0, xf1, ys) * 1.4247691104677813; + } + + @Override + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; + int x0 = fastFloor(x); + int y0 = fastFloor(y); + int z0 = fastFloor(z); + + double xd0 = x - x0; + double yd0 = y - y0; + double zd0 = z - z0; + double xd1 = xd0 - 1; + double yd1 = yd0 - 1; + double zd1 = zd0 - 1; + + double xs = interpQuintic(xd0); + double ys = interpQuintic(yd0); + double zs = interpQuintic(zd0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + z0 *= PRIME_Z; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + int z1 = z0 + PRIME_Z; + + double xf00 = lerp(gradCoord(seed, x0, y0, z0, xd0, yd0, zd0), gradCoord(seed, x1, y0, z0, xd1, yd0, zd0), xs); + double xf10 = lerp(gradCoord(seed, x0, y1, z0, xd0, yd1, zd0), gradCoord(seed, x1, y1, z0, xd1, yd1, zd0), xs); + double xf01 = lerp(gradCoord(seed, x0, y0, z1, xd0, yd0, zd1), gradCoord(seed, x1, y0, z1, xd1, yd0, zd1), xs); + double xf11 = lerp(gradCoord(seed, x0, y1, z1, xd0, yd1, zd1), gradCoord(seed, x1, y1, z1, xd1, yd1, zd1), xs); + + double yf0 = lerp(xf00, xf10, ys); + double yf1 = lerp(xf01, xf11, ys); + + return lerp(yf0, yf1, zs) * 0.964921414852142333984375; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexSampler.java new file mode 100644 index 000000000..dfaaf5bc6 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexSampler.java @@ -0,0 +1,242 @@ +package com.dfsek.terra.addons.noise.samplers.noise.simplex; + +public class SimplexSampler extends SimplexStyleSampler { + private static final Double2[] GRAD_2D = { + new Double2(-1, -1), new Double2(1, -1), new Double2(-1, 1), new Double2(1, 1), + new Double2(0, -1), new Double2(-1, 0), new Double2(0, 1), new Double2(1, 0), + }; + private static final Double3[] GRAD_3D = { + new Double3(1, 1, 0), new Double3(-1, 1, 0), new Double3(1, -1, 0), new Double3(-1, -1, 0), + new Double3(1, 0, 1), new Double3(-1, 0, 1), new Double3(1, 0, -1), new Double3(-1, 0, -1), + new Double3(0, 1, 1), new Double3(0, -1, 1), new Double3(0, 1, -1), new Double3(0, -1, -1), + new Double3(1, 1, 0), new Double3(0, -1, 1), new Double3(-1, 1, 0), new Double3(0, -1, -1), + }; + + private static final double F2 = 1.0 / 2.0; + private static final double F3 = (1.0 / 3.0); + private static final double G2 = 1.0 / 4.0; + private static final double G3 = (1.0 / 6.0); + private static final double G33 = G3 * 3 - 1; + + private static final int X_PRIME = 1619; + private static final int Y_PRIME = 31337; + private static final int Z_PRIME = 6971; + + + private static double gradCoord3D(int seed, int x, int y, int z, double xd, double yd, double zd) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + hash ^= Z_PRIME * z; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + Double3 g = GRAD_3D[hash & 15]; + + return xd * g.x + yd * g.y + zd * g.z; + } + + private static double gradCoord2D(int seed, int x, int y, double xd, double yd) { + int hash = seed; + hash ^= X_PRIME * x; + hash ^= Y_PRIME * y; + + hash = hash * hash * hash * 60493; + hash = (hash >> 13) ^ hash; + + Double2 g = GRAD_2D[hash & 7]; + + return xd * g.x + yd * g.y; + } + + @Override + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; + double t = (x + y) * F2; + int i = fastFloor(x + t); + int j = fastFloor(y + t); + + t = (i + j) * G2; + double X0 = i - t; + double Y0 = j - t; + + double x0 = x - X0; + double y0 = y - Y0; + + int i1, j1; + if(x0 > y0) { + i1 = 1; + j1 = 0; + } else { + i1 = 0; + j1 = 1; + } + + double x1 = x0 - i1 + G2; + double y1 = y0 - j1 + G2; + double x2 = x0 - 1 + F2; + double y2 = y0 - 1 + F2; + + double n0, n1, n2; + + t = 0.5 - x0 * x0 - y0 * y0; + if(t < 0) { + n0 = 0; + } else { + t *= t; + n0 = t * t * gradCoord2D(seed, i, j, x0, y0); + } + + t = 0.5 - x1 * x1 - y1 * y1; + if(t < 0) { + n1 = 0; + } else { + t *= t; + n1 = t * t * gradCoord2D(seed, i + i1, j + j1, x1, y1); + } + + t = 0.5 - x2 * x2 - y2 * y2; + if(t < 0) { + n2 = 0; + } else { + t *= t; + n2 = t * t * gradCoord2D(seed, i + 1, j + 1, x2, y2); + } + + return 50 * (n0 + n1 + n2); + } + + @Override + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; + double t = (x + y + z) * F3; + int i = fastFloor(x + t); + int j = fastFloor(y + t); + int k = fastFloor(z + t); + + t = (i + j + k) * G3; + double x0 = x - (i - t); + double y0 = y - (j - t); + double z0 = z - (k - t); + + int i1, j1, k1; + int i2, j2, k2; + + if(x0 >= y0) { + if(y0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } else if(x0 >= z0) { + i1 = 1; + j1 = 0; + k1 = 0; + i2 = 1; + j2 = 0; + k2 = 1; + } else // x0 < z0 + { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 1; + j2 = 0; + k2 = 1; + } + } else // x0 < y0 + { + if(y0 < z0) { + i1 = 0; + j1 = 0; + k1 = 1; + i2 = 0; + j2 = 1; + k2 = 1; + } else if(x0 < z0) { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 0; + j2 = 1; + k2 = 1; + } else // x0 >= z0 + { + i1 = 0; + j1 = 1; + k1 = 0; + i2 = 1; + j2 = 1; + k2 = 0; + } + } + + double x1 = x0 - i1 + G3; + double y1 = y0 - j1 + G3; + double z1 = z0 - k1 + G3; + double x2 = x0 - i2 + F3; + double y2 = y0 - j2 + F3; + double z2 = z0 - k2 + F3; + double x3 = x0 + G33; + double y3 = y0 + G33; + double z3 = z0 + G33; + + double n0, n1, n2, n3; + + t = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; + if(t < 0) n0 = 0; + else { + t *= t; + n0 = t * t * gradCoord3D(seed, i, j, k, x0, y0, z0); + } + + t = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; + if(t < 0) { + n1 = 0; + } else { + t *= t; + n1 = t * t * gradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1); + } + + t = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; + if(t < 0) { + n2 = 0; + } else { + t *= t; + n2 = t * t * gradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2); + } + + t = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; + if(t < 0) { + n3 = 0; + } else { + t *= t; + n3 = t * t * gradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3); + } + + return 32 * (n0 + n1 + n2 + n3); + } + + private static class Double2 { + public final double x, y; + + public Double2(double x, double y) { + this.x = x; + this.y = y; + } + } + + + private static class Double3 { + public final double x, y, z; + + public Double3(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java new file mode 100644 index 000000000..d924f2833 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java @@ -0,0 +1,97 @@ +package com.dfsek.terra.addons.noise.samplers.noise.simplex; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; + + +/** + * Abstract NoiseSampler implementation for simplex-style noise functions. + */ +public abstract class SimplexStyleSampler extends NoiseFunction { + protected static final double[] GRADIENTS_2_D = { + 0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d, + 0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d, + 0.99144486137381d, -0.130526192220051d, 0.923879532511287d, -0.38268343236509d, 0.793353340291235d, -0.60876142900872d, + 0.608761429008721d, -0.793353340291235d, 0.38268343236509d, -0.923879532511287d, 0.130526192220052d, -0.99144486137381d, + -0.130526192220052d, -0.99144486137381d, -0.38268343236509d, -0.923879532511287d, -0.608761429008721d, -0.793353340291235d, + -0.793353340291235d, -0.608761429008721d, -0.923879532511287d, -0.38268343236509d, -0.99144486137381d, -0.130526192220052d, + -0.99144486137381d, 0.130526192220051d, -0.923879532511287d, 0.38268343236509d, -0.793353340291235d, 0.608761429008721d, + -0.608761429008721d, 0.793353340291235d, -0.38268343236509d, 0.923879532511287d, -0.130526192220052d, 0.99144486137381d, + 0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d, + 0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d, + 0.99144486137381d, -0.130526192220051d, 0.923879532511287d, -0.38268343236509d, 0.793353340291235d, -0.60876142900872d, + 0.608761429008721d, -0.793353340291235d, 0.38268343236509d, -0.923879532511287d, 0.130526192220052d, -0.99144486137381d, + -0.130526192220052d, -0.99144486137381d, -0.38268343236509d, -0.923879532511287d, -0.608761429008721d, -0.793353340291235d, + -0.793353340291235d, -0.608761429008721d, -0.923879532511287d, -0.38268343236509d, -0.99144486137381d, -0.130526192220052d, + -0.99144486137381d, 0.130526192220051d, -0.923879532511287d, 0.38268343236509d, -0.793353340291235d, 0.608761429008721d, + -0.608761429008721d, 0.793353340291235d, -0.38268343236509d, 0.923879532511287d, -0.130526192220052d, 0.99144486137381d, + 0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d, + 0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d, + 0.99144486137381d, -0.130526192220051d, 0.923879532511287d, -0.38268343236509d, 0.793353340291235d, -0.60876142900872d, + 0.608761429008721d, -0.793353340291235d, 0.38268343236509d, -0.923879532511287d, 0.130526192220052d, -0.99144486137381d, + -0.130526192220052d, -0.99144486137381d, -0.38268343236509d, -0.923879532511287d, -0.608761429008721d, -0.793353340291235d, + -0.793353340291235d, -0.608761429008721d, -0.923879532511287d, -0.38268343236509d, -0.99144486137381d, -0.130526192220052d, + -0.99144486137381d, 0.130526192220051d, -0.923879532511287d, 0.38268343236509d, -0.793353340291235d, 0.608761429008721d, + -0.608761429008721d, 0.793353340291235d, -0.38268343236509d, 0.923879532511287d, -0.130526192220052d, 0.99144486137381d, + 0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d, + 0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d, + 0.99144486137381d, -0.130526192220051d, 0.923879532511287d, -0.38268343236509d, 0.793353340291235d, -0.60876142900872d, + 0.608761429008721d, -0.793353340291235d, 0.38268343236509d, -0.923879532511287d, 0.130526192220052d, -0.99144486137381d, + -0.130526192220052d, -0.99144486137381d, -0.38268343236509d, -0.923879532511287d, -0.608761429008721d, -0.793353340291235d, + -0.793353340291235d, -0.608761429008721d, -0.923879532511287d, -0.38268343236509d, -0.99144486137381d, -0.130526192220052d, + -0.99144486137381d, 0.130526192220051d, -0.923879532511287d, 0.38268343236509d, -0.793353340291235d, 0.608761429008721d, + -0.608761429008721d, 0.793353340291235d, -0.38268343236509d, 0.923879532511287d, -0.130526192220052d, 0.99144486137381d, + 0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d, + 0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d, + 0.99144486137381d, -0.130526192220051d, 0.923879532511287d, -0.38268343236509d, 0.793353340291235d, -0.60876142900872d, + 0.608761429008721d, -0.793353340291235d, 0.38268343236509d, -0.923879532511287d, 0.130526192220052d, -0.99144486137381d, + -0.130526192220052d, -0.99144486137381d, -0.38268343236509d, -0.923879532511287d, -0.608761429008721d, -0.793353340291235d, + -0.793353340291235d, -0.608761429008721d, -0.923879532511287d, -0.38268343236509d, -0.99144486137381d, -0.130526192220052d, + -0.99144486137381d, 0.130526192220051d, -0.923879532511287d, 0.38268343236509d, -0.793353340291235d, 0.608761429008721d, + -0.608761429008721d, 0.793353340291235d, -0.38268343236509d, 0.923879532511287d, -0.130526192220052d, 0.99144486137381d, + 0.38268343236509d, 0.923879532511287d, 0.923879532511287d, 0.38268343236509d, 0.923879532511287d, -0.38268343236509d, + 0.38268343236509d, -0.923879532511287d, -0.38268343236509d, -0.923879532511287d, -0.923879532511287d, -0.38268343236509d, + -0.923879532511287d, 0.38268343236509d, -0.38268343236509d, 0.923879532511287d, + }; + + protected static final double[] GRADIENTS_3D = { + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, + 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, + 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, + 1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0 + }; + + protected static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) { + int hash = hash(seed, xPrimed, yPrimed); + hash ^= hash >> 15; + hash &= 127 << 1; + + double xg = GRADIENTS_2_D[hash]; + double yg = GRADIENTS_2_D[hash | 1]; + + return xd * xg + yd * yg; + } + + protected static double gradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, double xd, double yd, double zd) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + hash ^= hash >> 15; + hash &= 63 << 2; + + double xg = GRADIENTS_3D[hash]; + double yg = GRADIENTS_3D[hash | 1]; + double zg = GRADIENTS_3D[hash | 2]; + + return xd * xg + yd * yg + zd * zg; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueCubicSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueCubicSampler.java new file mode 100644 index 000000000..d490126f1 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueCubicSampler.java @@ -0,0 +1,102 @@ +package com.dfsek.terra.addons.noise.samplers.noise.value; + +public class ValueCubicSampler extends ValueStyleNoise { + @Override + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; + int x1 = fastFloor(x); + int y1 = fastFloor(y); + + double xs = x - x1; + double ys = y - y1; + + x1 *= PRIME_X; + y1 *= PRIME_Y; + int x0 = x1 - PRIME_X; + int y0 = y1 - PRIME_Y; + int x2 = x1 + PRIME_X; + int y2 = y1 + PRIME_Y; + int x3 = x1 + (PRIME_X << 1); + int y3 = y1 + (PRIME_Y << 1); + + return cubicLerp( + cubicLerp(valCoord(seed, x0, y0), valCoord(seed, x1, y0), valCoord(seed, x2, y0), valCoord(seed, x3, y0), + xs), + cubicLerp(valCoord(seed, x0, y1), valCoord(seed, x1, y1), valCoord(seed, x2, y1), valCoord(seed, x3, y1), + xs), + cubicLerp(valCoord(seed, x0, y2), valCoord(seed, x1, y2), valCoord(seed, x2, y2), valCoord(seed, x3, y2), + xs), + cubicLerp(valCoord(seed, x0, y3), valCoord(seed, x1, y3), valCoord(seed, x2, y3), valCoord(seed, x3, y3), + xs), + ys) * (1 / (1.5 * 1.5)); + } + + @Override + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; + int x1 = fastFloor(x); + int y1 = fastFloor(y); + int z1 = fastFloor(z); + + double xs = x - x1; + double ys = y - y1; + double zs = z - z1; + + x1 *= PRIME_X; + y1 *= PRIME_Y; + z1 *= PRIME_Z; + + int x0 = x1 - PRIME_X; + int y0 = y1 - PRIME_Y; + int z0 = z1 - PRIME_Z; + int x2 = x1 + PRIME_X; + int y2 = y1 + PRIME_Y; + int z2 = z1 + PRIME_Z; + int x3 = x1 + (PRIME_X << 1); + int y3 = y1 + (PRIME_Y << 1); + int z3 = z1 + (PRIME_Z << 1); + + return cubicLerp( + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0), valCoord(seed, x2, y0, z0), + valCoord(seed, x3, y0, z0), xs), + cubicLerp(valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0), valCoord(seed, x2, y1, z0), + valCoord(seed, x3, y1, z0), xs), + cubicLerp(valCoord(seed, x0, y2, z0), valCoord(seed, x1, y2, z0), valCoord(seed, x2, y2, z0), + valCoord(seed, x3, y2, z0), xs), + cubicLerp(valCoord(seed, x0, y3, z0), valCoord(seed, x1, y3, z0), valCoord(seed, x2, y3, z0), + valCoord(seed, x3, y3, z0), xs), + ys), + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1), valCoord(seed, x2, y0, z1), + valCoord(seed, x3, y0, z1), xs), + cubicLerp(valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1), valCoord(seed, x2, y1, z1), + valCoord(seed, x3, y1, z1), xs), + cubicLerp(valCoord(seed, x0, y2, z1), valCoord(seed, x1, y2, z1), valCoord(seed, x2, y2, z1), + valCoord(seed, x3, y2, z1), xs), + cubicLerp(valCoord(seed, x0, y3, z1), valCoord(seed, x1, y3, z1), valCoord(seed, x2, y3, z1), + valCoord(seed, x3, y3, z1), xs), + ys), + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z2), valCoord(seed, x1, y0, z2), valCoord(seed, x2, y0, z2), + valCoord(seed, x3, y0, z2), xs), + cubicLerp(valCoord(seed, x0, y1, z2), valCoord(seed, x1, y1, z2), valCoord(seed, x2, y1, z2), + valCoord(seed, x3, y1, z2), xs), + cubicLerp(valCoord(seed, x0, y2, z2), valCoord(seed, x1, y2, z2), valCoord(seed, x2, y2, z2), + valCoord(seed, x3, y2, z2), xs), + cubicLerp(valCoord(seed, x0, y3, z2), valCoord(seed, x1, y3, z2), valCoord(seed, x2, y3, z2), + valCoord(seed, x3, y3, z2), xs), + ys), + cubicLerp( + cubicLerp(valCoord(seed, x0, y0, z3), valCoord(seed, x1, y0, z3), valCoord(seed, x2, y0, z3), + valCoord(seed, x3, y0, z3), xs), + cubicLerp(valCoord(seed, x0, y1, z3), valCoord(seed, x1, y1, z3), valCoord(seed, x2, y1, z3), + valCoord(seed, x3, y1, z3), xs), + cubicLerp(valCoord(seed, x0, y2, z3), valCoord(seed, x1, y2, z3), valCoord(seed, x2, y2, z3), + valCoord(seed, x3, y2, z3), xs), + cubicLerp(valCoord(seed, x0, y3, z3), valCoord(seed, x1, y3, z3), valCoord(seed, x2, y3, z3), + valCoord(seed, x3, y3, z3), xs), + ys), + zs) * (1 / (1.5 * 1.5 * 1.5)); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueSampler.java new file mode 100644 index 000000000..15c200633 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueSampler.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.addons.noise.samplers.noise.value; + +public class ValueSampler extends ValueStyleNoise { + @Override + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; + int x0 = fastFloor(x); + int y0 = fastFloor(y); + + double xs = interpHermite(x - x0); + double ys = interpHermite(y - y0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + + double xf0 = lerp(valCoord(seed, x0, y0), valCoord(seed, x1, y0), xs); + double xf1 = lerp(valCoord(seed, x0, y1), valCoord(seed, x1, y1), xs); + + return lerp(xf0, xf1, ys); + } + + @Override + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; + int x0 = fastFloor(x); + int y0 = fastFloor(y); + int z0 = fastFloor(z); + + double xs = interpHermite(x - x0); + double ys = interpHermite(y - y0); + double zs = interpHermite(z - z0); + + x0 *= PRIME_X; + y0 *= PRIME_Y; + z0 *= PRIME_Z; + int x1 = x0 + PRIME_X; + int y1 = y0 + PRIME_Y; + int z1 = z0 + PRIME_Z; + + double xf00 = lerp(valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0), xs); + double xf10 = lerp(valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0), xs); + double xf01 = lerp(valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1), xs); + double xf11 = lerp(valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1), xs); + + double yf0 = lerp(xf00, xf10, ys); + double yf1 = lerp(xf01, xf11, ys); + + return lerp(yf0, yf1, zs); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueStyleNoise.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueStyleNoise.java new file mode 100644 index 000000000..74804a00b --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueStyleNoise.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.noise.samplers.noise.value; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; + + +public abstract class ValueStyleNoise extends NoiseFunction { + + protected static double valCoord(int seed, int xPrimed, int yPrimed) { + int hash = hash(seed, xPrimed, yPrimed); + + hash *= hash; + hash ^= hash << 19; + return hash * (1 / 2147483648.0); + } + + protected static double valCoord(int seed, int xPrimed, int yPrimed, int zPrimed) { + int hash = hash(seed, xPrimed, yPrimed, zPrimed); + + hash *= hash; + hash ^= hash << 19; + return hash * (1 / 2147483648.0); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashIntrinsic.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashIntrinsic.java new file mode 100644 index 000000000..8e0def4ca --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashIntrinsic.java @@ -0,0 +1,119 @@ +/* +Copyright 2009 Sandia Corporation. Under the terms of Contract +DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government +retains certain rights in this software. + +BSD Open Source License. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Sandia National Laboratories nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + */ + +package com.dfsek.terra.addons.noise.util; + +import java.io.Serializable; + + +public abstract class HashIntrinsic implements Serializable { + public static final int FLOAT_EXP_BIT_MASK = 2139095040; + public static final int FLOAT_SIGNIF_BIT_MASK = 8388607; + public static final long DOUBLE_EXP_BIT_MASK = 9218868437227405312L; + public static final long DOUBLE_SIGNIF_BIT_MASK = 4503599627370495L; + protected static final int DEFAULT_INITIAL_CAPACITY = 16; + protected static final int MAXIMUM_CAPACITY = 1073741824; + protected static final float DEFAULT_LOAD_FACTOR = 0.75F; + private static final long serialVersionUID = 8058099372006904458L; + protected int size; + protected int threshold; + protected float loadFactor; + protected int capMinus1; + + protected HashIntrinsic(int initialCapacity, float loadFactor) { + if(initialCapacity <= 0) { + throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); + } else if(!(loadFactor <= 0.0F) && !Float.isNaN(loadFactor)) { + if(initialCapacity > 1073741824) { + initialCapacity = 1073741824; + } + + int capacity; + for(capacity = 1; capacity < initialCapacity; capacity <<= 1) { + } + + this.capMinus1 = capacity - 1; + this.loadFactor = loadFactor; + this.threshold = (int) ((float) capacity * loadFactor); + } else { + throw new IllegalArgumentException("Illegal load factor: " + loadFactor); + } + } + + public static int floatToIntBits(float value) { + int result = Float.floatToRawIntBits(value); + if((result & 2139095040) == 2139095040 && (result & 8388607) != 0) { + result = 2143289344; + } + + return result; + } + + public static long doubleToLongBits(double value) { + long result = Double.doubleToRawLongBits(value); + if((result & 9218868437227405312L) == 9218868437227405312L && (result & 4503599627370495L) != 0L) { + result = 9221120237041090560L; + } + + return result; + } + + protected static int hashCodeLong(long value) { + return (int) (value ^ value >>> 32); + } + + protected static int hashCodeFloat(float value) { + return floatToIntBits(value); + } + + protected static int hashCodeDouble(double value) { + long bits = doubleToLongBits(value); + return (int) (bits ^ bits >>> 32); + } + + protected static int tableIndex(int hc, int lm1) { + hc ^= hc >>> 20 ^ hc >>> 12; + hc ^= hc >>> 7 ^ hc >>> 4; + return hc & lm1; + } + + public int size() { + return this.size; + } + + public abstract void clear(); + + public boolean isEmpty() { + return this.size == 0; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashMapDoubleDouble.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashMapDoubleDouble.java new file mode 100644 index 000000000..a07d2cd74 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/util/HashMapDoubleDouble.java @@ -0,0 +1,295 @@ +/* +Copyright 2009 Sandia Corporation. Under the terms of Contract +DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government +retains certain rights in this software. + +BSD Open Source License. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Sandia National Laboratories nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + */ + +package com.dfsek.terra.addons.noise.util; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.NoSuchElementException; + + +public class HashMapDoubleDouble extends HashIntrinsic { + private static final long serialVersionUID = 2109458761298324234L; + private HashMapDoubleDouble.Entry[] table; + + public HashMapDoubleDouble(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + this.table = this.createTable(this.capMinus1 + 1); + } + + public HashMapDoubleDouble(int initialCapacity) { + this(initialCapacity, 0.75F); + } + + public HashMapDoubleDouble() { + this(16, 0.75F); + } + + public final boolean contains(double key) { + int i = tableIndex(hashCodeDouble(key), this.capMinus1); + + for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { + if(e.key == key) { + return true; + } + } + + return false; + } + + public boolean containsValue(double value) { + for(Entry entry : this.table) { + for(Entry e = entry; e != null; e = e.next) { + if(value == e.value) { + return true; + } + } + } + + return false; + } + + public double get(double key) { + int i = tableIndex(hashCodeDouble(key), this.capMinus1); + + for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { + if(key == e.key) { + return e.value; + } + } + + return 4.9E-324D; + } + + public double put(double key, double value) { + int i = tableIndex(hashCodeDouble(key), this.capMinus1); + + for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { + if(key == e.key) { + double oldValue = e.value; + e.value = value; + return oldValue; + } + } + + this.addEntry(key, value, i); + return 4.9E-324D; + } + + public void resize(int newCapacity) { + int oldCapacity = this.table.length; + if(oldCapacity == 1073741824) { + this.threshold = 2147483647; + } else { + HashMapDoubleDouble.Entry[] newTable = this.createTable(newCapacity); + this.capMinus1 = newCapacity - 1; + this.transfer(newTable); + this.table = newTable; + this.threshold = (int) ((float) newCapacity * this.loadFactor); + } + } + + public final HashMapDoubleDouble.Entry remove(double key) { + int i = tableIndex(hashCodeDouble(key), this.capMinus1); + HashMapDoubleDouble.Entry prev = this.table[i]; + + HashMapDoubleDouble.Entry e; + HashMapDoubleDouble.Entry next; + for(e = prev; e != null; e = next) { + next = e.next; + if(key == e.key) { + --this.size; + if(prev == e) { + this.table[i] = next; + } else { + prev.next = next; + } + + return e; + } + + prev = e; + } + + return e; + } + + public void clear() { + Arrays.fill(this.table, null); + + this.size = 0; + } + + public long memoryEstimate(int ptrsize) { + return (long) ptrsize * (long) (this.capMinus1 + this.size + 1) + (this.size * 64L / 4); + } + + public HashMapDoubleDouble.Iterator iterator() { + return new HashMapDoubleDouble.Iterator(); + } + + private void addEntry(double key, double value, int index) { + HashMapDoubleDouble.Entry e = this.table[index]; + this.table[index] = new HashMapDoubleDouble.Entry(key, value, e); + if(this.size++ >= this.threshold) { + this.resize(2 * this.table.length); + } + + } + + private void transfer(HashMapDoubleDouble.Entry[] newTable) { + for(int j = 0; j < this.table.length; ++j) { + HashMapDoubleDouble.Entry e = this.table[j]; + if(e != null) { + this.table[j] = null; + + HashMapDoubleDouble.Entry next; + do { + next = e.next; + int i = tableIndex(hashCodeDouble(e.key), this.capMinus1); + e.next = newTable[i]; + newTable[i] = e; + e = next; + } while(next != null); + } + } + + } + + private HashMapDoubleDouble.Entry[] createTable(int capacity) { + return new HashMapDoubleDouble.Entry[capacity]; + } + + public HashMapDoubleDouble.Entry getEntry(double key) { + int i = tableIndex(hashCodeDouble(key), this.capMinus1); + + for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { + if(key == e.key) { + return e; + } + } + + return null; + } + + + public static class Entry implements Serializable { + private static final long serialVersionUID = 7972173983741231238L; + private final double key; + private double value; + private HashMapDoubleDouble.Entry next; + + public Entry(double key, double val, HashMapDoubleDouble.Entry n) { + this.key = key; + this.value = val; + this.next = n; + } + + public final double setValue(double newValue) { + double oldValue = this.value; + this.value = newValue; + return oldValue; + } + + public final double getKey() { + return this.key; + } + + public final double getValue() { + return this.value; + } + + public final int hashCode() { + return hashCodeDouble(key) + hashCodeDouble(value); + } + + public final boolean equals(Object o) { + HashMapDoubleDouble.Entry e = (HashMapDoubleDouble.Entry) o; + return this.key == e.key && this.value == e.value; + } + + public final String toString() { + return this.key + " = " + this.value; + } + } + + + public class Iterator { + HashMapDoubleDouble.Entry next; + int index; + HashMapDoubleDouble.Entry current; + + Iterator() { + if(HashMapDoubleDouble.this.size > 0) { + while(this.index < HashMapDoubleDouble.this.table.length && + (this.next = HashMapDoubleDouble.this.table[this.index++]) == null) { + } + } + + } + + public HashMapDoubleDouble.Entry nextEntry() { + HashMapDoubleDouble.Entry e = this.next; + if(e == null) { + throw new NoSuchElementException(); + } else { + if((this.next = e.next) == null) { + while(this.index < HashMapDoubleDouble.this.table.length && + (this.next = HashMapDoubleDouble.this.table[this.index++]) == null) { + } + } + + this.current = e; + return e; + } + } + + public double next() { + return this.nextEntry().value; + } + + public void remove() { + if(this.current == null) { + throw new IllegalStateException(); + } else { + double k = this.current.key; + this.current = null; + HashMapDoubleDouble.this.remove(k); + } + } + + public final boolean hasNext() { + return this.next != null; + } + } +}