diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/KernelSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/KernelSampler.java new file mode 100644 index 000000000..695135e5c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/KernelSampler.java @@ -0,0 +1,59 @@ +package com.dfsek.terra.api.math.noise.samplers; + +import com.dfsek.terra.api.math.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; + } + + @Override + public double getNoise(double x, double y) { + return getNoiseSeeded(0, x, y); + } + + @Override + public double getNoise(double x, double y, double z) { + return getNoiseSeeded(0, x, y, z); + } + + @Override + public double getNoiseSeeded(int 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.getNoise(x + kx, y + ky) * kernel[kx][ky]; + } + } + + return accumulator; + } + + @Override + public double getNoiseSeeded(int 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.getNoise(x + kx, y, z + ky) * kernel[kx][ky]; + } + } + + return accumulator; + } + + public void setFrequency(double frequency) { + this.frequency = frequency; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/KernelTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/KernelTemplate.java new file mode 100644 index 000000000..0fc8db115 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/KernelTemplate.java @@ -0,0 +1,61 @@ +package com.dfsek.terra.config.loaders.config.sampler.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.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.math.noise.samplers.KernelSampler; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; + +import java.util.List; + +@SuppressWarnings({"unused", "FieldMayBeFinal"}) +public class KernelTemplate extends SamplerTemplate implements ValidatedConfigTemplate { + + @Value("kernel") + private List> kernel; + + @Value("factor") + @Default + private double factor = 1; + + @Value("function") + private NoiseSeeded function; + + @Value("frequency") + @Default + private double frequency = 1; + + @Override + public NoiseSampler apply(Long seed) { + 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.apply(seed)); + 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/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java index dcb281cf1..b281bd40c 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java @@ -28,7 +28,8 @@ public class ExpressionFunctionTemplate extends SamplerTemplate functions; + @Default + private Map functions = new HashMap<>(); @Override public NoiseSampler apply(Long seed) { diff --git a/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java index fd48d156e..4531dd5df 100644 --- a/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java @@ -10,6 +10,7 @@ import com.dfsek.terra.api.math.noise.samplers.noise.value.ValueSampler; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.config.loaders.config.sampler.templates.DomainWarpTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.KernelTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.CellularNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.ConstantNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.noise.ExpressionFunctionTemplate; @@ -52,5 +53,7 @@ public class NoiseRegistry extends TerraRegistry new SimpleNoiseTemplate(WhiteNoiseSampler::new)); add("CONSTANT", ConstantNoiseTemplate::new); + + add("KERNEL", KernelTemplate::new); } } diff --git a/common/src/test/java/biome/DistributionTest.java b/common/src/test/java/biome/DistributionTest.java index f6fc1eb52..6ffe4da82 100644 --- a/common/src/test/java/biome/DistributionTest.java +++ b/common/src/test/java/biome/DistributionTest.java @@ -141,7 +141,7 @@ public class DistributionTest { private static BiomeProvider getProvider(long seed) throws ConfigException, IOException { System.out.println(seed); - File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/"); + File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/betterend/"); FolderLoader folderLoader = new FolderLoader(pack.toPath()); AbstractConfigLoader loader = new AbstractConfigLoader();