mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-03 16:35:50 +00:00
Fix empty slant holders attempting to calculate slant
This occurs when the NoiseChunkGenerator3D#getSlant method is invoked at a position where the biome has an empty slant holder, currently possible when using the slant locator addon. This is fixed by making slant calculation independent of SlantHolders. Some minor refactoring has also been done as a result of this change.
This commit is contained in:
parent
6681bdfbf2
commit
271e7f3c69
@ -13,6 +13,7 @@ import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
|
|||||||
import com.dfsek.terra.addons.chunkgenerator.config.palette.BiomePaletteTemplate;
|
import com.dfsek.terra.addons.chunkgenerator.config.palette.BiomePaletteTemplate;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.config.palette.slant.SlantLayerTemplate;
|
import com.dfsek.terra.addons.chunkgenerator.config.palette.slant.SlantLayerTemplate;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D;
|
import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D;
|
||||||
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||||
@ -45,8 +46,8 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
|
|||||||
.priority(1000)
|
.priority(1000)
|
||||||
.then(event -> {
|
.then(event -> {
|
||||||
|
|
||||||
event.getPack().applyLoader(SlantHolder.CalculationMethod.class,
|
event.getPack().applyLoader(SlantCalculationMethod.class,
|
||||||
(type, o, loader, depthTracker) -> SlantHolder.CalculationMethod.valueOf((String) o));
|
(type, o, loader, depthTracker) -> SlantCalculationMethod.valueOf((String) o));
|
||||||
|
|
||||||
NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate());
|
NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate());
|
||||||
event.getPack().getContext().put(config);
|
event.getPack().getContext().put(config);
|
||||||
@ -57,7 +58,7 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
|
|||||||
pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(),
|
pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(),
|
||||||
config.getHorizontalRes(),
|
config.getHorizontalRes(),
|
||||||
config.getVerticalRes(), noisePropertiesPropertyKey,
|
config.getVerticalRes(), noisePropertiesPropertyKey,
|
||||||
paletteInfoPropertyKey));
|
paletteInfoPropertyKey, config.getSlantCalculationMethod()));
|
||||||
event.getPack()
|
event.getPack()
|
||||||
.applyLoader(SlantHolder.Layer.class, SlantLayerTemplate::new);
|
.applyLoader(SlantHolder.Layer.class, SlantLayerTemplate::new);
|
||||||
})
|
})
|
||||||
|
@ -4,7 +4,7 @@ import com.dfsek.tectonic.api.config.template.ConfigTemplate;
|
|||||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
import com.dfsek.terra.api.config.meta.Meta;
|
||||||
import com.dfsek.terra.api.properties.Properties;
|
import com.dfsek.terra.api.properties.Properties;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Pr
|
|||||||
|
|
||||||
@Value("slant.calculation-method")
|
@Value("slant.calculation-method")
|
||||||
@Default
|
@Default
|
||||||
private SlantHolder.@Meta CalculationMethod slantCalculationMethod = SlantHolder.CalculationMethod.Derivative;
|
private @Meta SlantCalculationMethod slantCalculationMethod = SlantCalculationMethod.Derivative;
|
||||||
|
|
||||||
public int getElevationBlend() {
|
public int getElevationBlend() {
|
||||||
return elevationBlend;
|
return elevationBlend;
|
||||||
@ -38,7 +38,7 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Pr
|
|||||||
return verticalRes;
|
return verticalRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlantHolder.CalculationMethod getSlantCalculationMethod() {
|
public SlantCalculationMethod getSlantCalculationMethod() {
|
||||||
return slantCalculationMethod;
|
return slantCalculationMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||||
@ -27,7 +28,7 @@ import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
|||||||
|
|
||||||
public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
|
public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
|
||||||
private final Platform platform;
|
private final Platform platform;
|
||||||
private final SlantHolder.CalculationMethod slantCalculationMethod;
|
private final SlantCalculationMethod slantCalculationMethod;
|
||||||
@Value("slant")
|
@Value("slant")
|
||||||
@Default
|
@Default
|
||||||
@Description("The slant palettes to use in this biome.")
|
@Description("The slant palettes to use in this biome.")
|
||||||
@ -56,7 +57,7 @@ public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
|
|||||||
@Default
|
@Default
|
||||||
private @Meta boolean updatePalette = false;
|
private @Meta boolean updatePalette = false;
|
||||||
|
|
||||||
public BiomePaletteTemplate(Platform platform, SlantHolder.CalculationMethod slantCalculationMethod) {
|
public BiomePaletteTemplate(Platform platform, SlantCalculationMethod slantCalculationMethod) {
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this.slantCalculationMethod = slantCalculationMethod;
|
this.slantCalculationMethod = slantCalculationMethod;
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,13 @@
|
|||||||
package com.dfsek.terra.addons.chunkgenerator.generation;
|
package com.dfsek.terra.addons.chunkgenerator.generation;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
|
import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.PaletteUtil;
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.LazilyEvaluatedInterpolator;
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.LazilyEvaluatedInterpolator;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider;
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider;
|
||||||
@ -42,16 +45,19 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
|||||||
private final PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey;
|
private final PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey;
|
||||||
private final PropertyKey<BiomeNoiseProperties> noisePropertiesKey;
|
private final PropertyKey<BiomeNoiseProperties> noisePropertiesKey;
|
||||||
|
|
||||||
|
private final SlantCalculationMethod slantCalculationMethod;
|
||||||
|
|
||||||
public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution,
|
public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution,
|
||||||
int carverVerticalResolution,
|
int carverVerticalResolution,
|
||||||
PropertyKey<BiomeNoiseProperties> noisePropertiesKey,
|
PropertyKey<BiomeNoiseProperties> noisePropertiesKey,
|
||||||
PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey) {
|
PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey, SlantCalculationMethod slantCalculationMethod) {
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this.air = platform.getWorldHandle().air();
|
this.air = platform.getWorldHandle().air();
|
||||||
this.carverHorizontalResolution = carverHorizontalResolution;
|
this.carverHorizontalResolution = carverHorizontalResolution;
|
||||||
this.carverVerticalResolution = carverVerticalResolution;
|
this.carverVerticalResolution = carverVerticalResolution;
|
||||||
this.paletteInfoPropertyKey = paletteInfoPropertyKey;
|
this.paletteInfoPropertyKey = paletteInfoPropertyKey;
|
||||||
this.noisePropertiesKey = noisePropertiesKey;
|
this.noisePropertiesKey = noisePropertiesKey;
|
||||||
|
this.slantCalculationMethod = slantCalculationMethod;
|
||||||
int maxBlend = pack
|
int maxBlend = pack
|
||||||
.getBiomeProvider()
|
.getBiomeProvider()
|
||||||
.stream()
|
.stream()
|
||||||
@ -63,6 +69,17 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
|||||||
this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey, maxBlend);
|
this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey, maxBlend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Palette paletteAt(int x, int y, int z, Sampler3D sampler, BiomePaletteInfo paletteInfo, int depth) {
|
||||||
|
SlantHolder slantHolder = paletteInfo.slantHolder();
|
||||||
|
if(slantHolder.isAboveDepth(depth)) {
|
||||||
|
double slant = slantCalculationMethod.slant(sampler, x, y, z);
|
||||||
|
if(slantHolder.isInSlantThreshold(slant)) {
|
||||||
|
return slantHolder.getPalette(slant).getPalette(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paletteInfo.paletteHolder().getPalette(y);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("try")
|
@SuppressWarnings("try")
|
||||||
public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world,
|
public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world,
|
||||||
@ -103,8 +120,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
|||||||
|
|
||||||
if(sampler.sample(x, y, z) > 0) {
|
if(sampler.sample(x, y, z) > 0) {
|
||||||
if(carver.sample(x, y, z) <= 0) {
|
if(carver.sample(x, y, z) <= 0) {
|
||||||
data = PaletteUtil
|
data = paletteAt(x, y, z, sampler, paletteInfo, paletteLevel)
|
||||||
.getPalette(x, y, z, sampler, paletteInfo, paletteLevel)
|
|
||||||
.get(paletteLevel, cx, y, cz, seed);
|
.get(paletteLevel, cx, y, cz, seed);
|
||||||
chunk.setBlock(x, y, z, data);
|
chunk.setBlock(x, y, z, data);
|
||||||
paletteLevel++;
|
paletteLevel++;
|
||||||
@ -135,7 +151,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
|||||||
int fdX = Math.floorMod(x, 16);
|
int fdX = Math.floorMod(x, 16);
|
||||||
int fdZ = Math.floorMod(z, 16);
|
int fdZ = Math.floorMod(z, 16);
|
||||||
|
|
||||||
Palette palette = PaletteUtil.getPalette(fdX, y, fdZ, sampler, paletteInfo, 0);
|
Palette palette = paletteAt(fdX, y, fdZ, sampler, paletteInfo, 0);
|
||||||
double noise = sampler.sample(fdX, y, fdZ);
|
double noise = sampler.sample(fdX, y, fdZ);
|
||||||
if(noise > 0) {
|
if(noise > 0) {
|
||||||
int level = 0;
|
int level = 0;
|
||||||
@ -157,11 +173,8 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
|||||||
public double getSlant(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) {
|
public double getSlant(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) {
|
||||||
int fdX = Math.floorMod(x, 16);
|
int fdX = Math.floorMod(x, 16);
|
||||||
int fdZ = Math.floorMod(z, 16);
|
int fdZ = Math.floorMod(z, 16);
|
||||||
return biomeProvider.getBiome(x, y, z, world.getSeed())
|
Sampler3D sampler = samplerCache.get(x, z, world, biomeProvider);
|
||||||
.getContext()
|
return slantCalculationMethod.slant(sampler, fdX, y, fdZ);
|
||||||
.get(paletteInfoPropertyKey)
|
|
||||||
.slantHolder()
|
|
||||||
.calculateSlant(samplerCache.get(x, z, world, biomeProvider), fdX, y, fdZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SamplerProvider samplerProvider() {
|
public SamplerProvider samplerProvider() {
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020-2023 Polyhedral Development
|
|
||||||
*
|
|
||||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
|
||||||
* reference the LICENSE file in this module's root directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.dfsek.terra.addons.chunkgenerator.generation.math;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
|
||||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
|
||||||
|
|
||||||
|
|
||||||
public final class PaletteUtil {
|
|
||||||
|
|
||||||
public static Palette getPalette(int x, int y, int z, Sampler3D sampler, BiomePaletteInfo paletteInfo, int depth) {
|
|
||||||
SlantHolder slantHolder = paletteInfo.slantHolder();
|
|
||||||
if(slantHolder.isAboveDepth(depth)) {
|
|
||||||
double slant = slantHolder.calculateSlant(sampler, x, y, z);
|
|
||||||
if(slantHolder.isInSlantThreshold(slant)) {
|
|
||||||
return slantHolder.getPalette(slant).getPalette(y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return paletteInfo.paletteHolder().getPalette(y);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.dfsek.terra.addons.chunkgenerator.generation.math;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
||||||
|
import com.dfsek.terra.api.util.vector.Vector3;
|
||||||
|
|
||||||
|
|
||||||
|
public enum SlantCalculationMethod {
|
||||||
|
DotProduct {
|
||||||
|
private static final Vector3 DOT_PRODUCT_DIRECTION = Vector3.of(0, 1, 0);
|
||||||
|
|
||||||
|
private static final Vector3[] DOT_PRODUCT_SAMPLE_POINTS = {
|
||||||
|
Vector3.of(0, 0, -DERIVATIVE_DIST),
|
||||||
|
Vector3.of(0, 0, DERIVATIVE_DIST),
|
||||||
|
Vector3.of(0, -DERIVATIVE_DIST, 0),
|
||||||
|
Vector3.of(0, DERIVATIVE_DIST, 0),
|
||||||
|
Vector3.of(-DERIVATIVE_DIST, 0, 0),
|
||||||
|
Vector3.of(DERIVATIVE_DIST, 0, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double slant(Sampler3D sampler, double x, double y, double z) {
|
||||||
|
Vector3.Mutable normalApproximation = Vector3.Mutable.of(0, 0, 0);
|
||||||
|
for(Vector3 point : DOT_PRODUCT_SAMPLE_POINTS) {
|
||||||
|
var scalar = -sampler.sample(x + point.getX(), y + point.getY(), z + point.getZ());
|
||||||
|
normalApproximation.add(point.mutable().multiply(scalar));
|
||||||
|
}
|
||||||
|
return DOT_PRODUCT_DIRECTION.dot(normalApproximation.normalize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean floorToThreshold() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Derivative {
|
||||||
|
@Override
|
||||||
|
public double slant(Sampler3D sampler, double x, double y, double z) {
|
||||||
|
double baseSample = sampler.sample(x, y, z);
|
||||||
|
|
||||||
|
double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
||||||
|
|
||||||
|
return Math.sqrt(
|
||||||
|
((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean floorToThreshold() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final double DERIVATIVE_DIST = 0.55;
|
||||||
|
|
||||||
|
public abstract double slant(Sampler3D sampler, double x, double y, double z);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controls whether palettes should be applied before or after their respective thresholds.
|
||||||
|
*
|
||||||
|
* If true, slant values will map to the palette of the next floor threshold, otherwise they
|
||||||
|
* will map to the ceiling.
|
||||||
|
*/
|
||||||
|
public abstract boolean floorToThreshold();
|
||||||
|
}
|
@ -14,6 +14,7 @@ import java.util.TreeMap;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ public class MultipleSlantHolder extends SlantHolderImpl {
|
|||||||
private final NavigableMap<Double, PaletteHolder> layers;
|
private final NavigableMap<Double, PaletteHolder> layers;
|
||||||
private final double slantThreshold;
|
private final double slantThreshold;
|
||||||
|
|
||||||
MultipleSlantHolder(List<SlantHolder.Layer> slant, int slantDepth, CalculationMethod calculationMethod) {
|
MultipleSlantHolder(List<SlantHolder.Layer> slant, int slantDepth, SlantCalculationMethod calculationMethod) {
|
||||||
super(slantDepth, calculationMethod);
|
super(slantDepth, calculationMethod);
|
||||||
NavigableMap<Double, PaletteHolder> layers = new TreeMap<>(
|
NavigableMap<Double, PaletteHolder> layers = new TreeMap<>(
|
||||||
slant.stream().collect(Collectors.toMap(SlantHolder.Layer::threshold, SlantHolder.Layer::palette)));
|
slant.stream().collect(Collectors.toMap(SlantHolder.Layer::threshold, SlantHolder.Layer::palette)));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||||
|
|
||||||
|
|
||||||
@ -7,7 +8,7 @@ final class SingleSlantHolder extends SlantHolderImpl {
|
|||||||
|
|
||||||
private final SlantHolder.Layer layer;
|
private final SlantHolder.Layer layer;
|
||||||
|
|
||||||
public SingleSlantHolder(SlantHolder.Layer layer, int slantDepth, CalculationMethod calculationMethod) {
|
public SingleSlantHolder(SlantHolder.Layer layer, int slantDepth, SlantCalculationMethod calculationMethod) {
|
||||||
super(slantDepth, calculationMethod);
|
super(slantDepth, calculationMethod);
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,13 @@ package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public interface SlantHolder {
|
public interface SlantHolder {
|
||||||
|
|
||||||
SlantHolder EMPTY = new SlantHolder() {
|
SlantHolder EMPTY = new SlantHolder() {
|
||||||
@Override
|
|
||||||
public double calculateSlant(Sampler3D sampler, double x, double y, double z) {
|
|
||||||
throw new UnsupportedOperationException("Empty holder should not calculate slant");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAboveDepth(int depth) {
|
public boolean isAboveDepth(int depth) {
|
||||||
return false;
|
return false;
|
||||||
@ -31,7 +25,7 @@ public interface SlantHolder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static SlantHolder of(List<SlantHolder.Layer> layers, int slantDepth, CalculationMethod calculationMethod) {
|
static SlantHolder of(List<SlantHolder.Layer> layers, int slantDepth, SlantCalculationMethod calculationMethod) {
|
||||||
if(layers.isEmpty()) {
|
if(layers.isEmpty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else if(layers.size() == 1) {
|
} else if(layers.size() == 1) {
|
||||||
@ -40,8 +34,6 @@ public interface SlantHolder {
|
|||||||
return new MultipleSlantHolder(layers, slantDepth, calculationMethod);
|
return new MultipleSlantHolder(layers, slantDepth, calculationMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
double calculateSlant(Sampler3D sampler, double x, double y, double z);
|
|
||||||
|
|
||||||
boolean isAboveDepth(int depth);
|
boolean isAboveDepth(int depth);
|
||||||
|
|
||||||
boolean isInSlantThreshold(double slant);
|
boolean isInSlantThreshold(double slant);
|
||||||
@ -49,71 +41,6 @@ public interface SlantHolder {
|
|||||||
PaletteHolder getPalette(double slant);
|
PaletteHolder getPalette(double slant);
|
||||||
|
|
||||||
|
|
||||||
enum CalculationMethod {
|
|
||||||
DotProduct {
|
|
||||||
private static final Vector3 DOT_PRODUCT_DIRECTION = Vector3.of(0, 1, 0);
|
|
||||||
|
|
||||||
private static final Vector3[] DOT_PRODUCT_SAMPLE_POINTS = {
|
|
||||||
Vector3.of(0, 0, -DERIVATIVE_DIST),
|
|
||||||
Vector3.of(0, 0, DERIVATIVE_DIST),
|
|
||||||
Vector3.of(0, -DERIVATIVE_DIST, 0),
|
|
||||||
Vector3.of(0, DERIVATIVE_DIST, 0),
|
|
||||||
Vector3.of(-DERIVATIVE_DIST, 0, 0),
|
|
||||||
Vector3.of(DERIVATIVE_DIST, 0, 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double slant(Sampler3D sampler, double x, double y, double z) {
|
|
||||||
Vector3.Mutable normalApproximation = Vector3.Mutable.of(0, 0, 0);
|
|
||||||
for(Vector3 point : DOT_PRODUCT_SAMPLE_POINTS) {
|
|
||||||
var scalar = -sampler.sample(x + point.getX(), y + point.getY(), z + point.getZ());
|
|
||||||
normalApproximation.add(point.mutable().multiply(scalar));
|
|
||||||
}
|
|
||||||
return DOT_PRODUCT_DIRECTION.dot(normalApproximation.normalize());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean floorToThreshold() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Derivative {
|
|
||||||
@Override
|
|
||||||
public double slant(Sampler3D sampler, double x, double y, double z) {
|
|
||||||
double baseSample = sampler.sample(x, y, z);
|
|
||||||
|
|
||||||
double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
|
||||||
double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
|
|
||||||
double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
|
||||||
double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
|
|
||||||
double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
|
||||||
double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
|
|
||||||
|
|
||||||
return Math.sqrt(
|
|
||||||
((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean floorToThreshold() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final double DERIVATIVE_DIST = 0.55;
|
|
||||||
|
|
||||||
public abstract double slant(Sampler3D sampler, double x, double y, double z);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Controls whether palettes should be applied before or after their respective thresholds.
|
|
||||||
*
|
|
||||||
* If true, slant values will map to the palette of the next floor threshold, otherwise they
|
|
||||||
* will map to the ceiling.
|
|
||||||
*/
|
|
||||||
public abstract boolean floorToThreshold();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
record Layer(PaletteHolder palette, double threshold) {
|
record Layer(PaletteHolder palette, double threshold) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,19 @@
|
|||||||
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
|
||||||
|
|
||||||
|
|
||||||
public abstract class SlantHolderImpl implements SlantHolder {
|
public abstract class SlantHolderImpl implements SlantHolder {
|
||||||
protected final boolean floorToThreshold;
|
protected final boolean floorToThreshold;
|
||||||
private final SlantHolder.CalculationMethod calculationMethod;
|
|
||||||
private final int slantDepth;
|
private final int slantDepth;
|
||||||
|
|
||||||
protected SlantHolderImpl(int slantDepth, CalculationMethod calculationMethod) {
|
protected SlantHolderImpl(int slantDepth, SlantCalculationMethod calculationMethod) {
|
||||||
this.floorToThreshold = calculationMethod.floorToThreshold();
|
this.floorToThreshold = calculationMethod.floorToThreshold();
|
||||||
this.calculationMethod = calculationMethod;
|
|
||||||
this.slantDepth = slantDepth;
|
this.slantDepth = slantDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract double getSlantThreshold();
|
protected abstract double getSlantThreshold();
|
||||||
|
|
||||||
@Override
|
|
||||||
public final double calculateSlant(Sampler3D sampler, double x, double y, double z) {
|
|
||||||
return calculationMethod.slant(sampler, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isAboveDepth(int depth) {
|
public final boolean isAboveDepth(int depth) {
|
||||||
return depth <= slantDepth;
|
return depth <= slantDepth;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user