mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-02-16 10:30:42 +00:00
Merge branch 'ver/6.3.0' into dev/img-lib
fogor import
This commit is contained in:
@@ -11,6 +11,7 @@ import net.jafama.FastMath;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@@ -97,6 +98,11 @@ public class PipelineBiomeProvider implements BiomeProvider {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Biome> getBaseBiome(int x, int z, long seed) {
|
||||
return Optional.of(getBiome(x, z, seed));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Column<Biome> getColumn(int x, int z, long seed, int min, int max) {
|
||||
return new BiomePipelineColumn(this, min, max, x, z, seed);
|
||||
|
||||
@@ -11,9 +11,10 @@ import com.dfsek.terra.addons.chunkgenerator.config.NoiseChunkGeneratorPackConfi
|
||||
import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseConfigTemplate;
|
||||
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.PaletteInfo;
|
||||
import com.dfsek.terra.addons.chunkgenerator.config.palette.SlantLayer;
|
||||
import com.dfsek.terra.addons.chunkgenerator.config.palette.slant.SlantLayerTemplate;
|
||||
import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
@@ -36,15 +37,20 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
PropertyKey<PaletteInfo> paletteInfoPropertyKey = Context.create(PaletteInfo.class);
|
||||
PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey = Context.create(BiomePaletteInfo.class);
|
||||
PropertyKey<BiomeNoiseProperties> noisePropertiesPropertyKey = Context.create(BiomeNoiseProperties.class);
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.priority(1000)
|
||||
.then(event -> {
|
||||
|
||||
event.getPack().applyLoader(SlantHolder.CalculationMethod.class,
|
||||
(type, o, loader, depthTracker) -> SlantHolder.CalculationMethod.valueOf((String) o));
|
||||
|
||||
NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate());
|
||||
|
||||
event.getPack().getContext().put(config);
|
||||
|
||||
event.getPack()
|
||||
.getOrCreateRegistry(ChunkGeneratorProvider.class)
|
||||
.register(addon.key("NOISE_3D"),
|
||||
@@ -53,7 +59,7 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
|
||||
config.getVerticalRes(), noisePropertiesPropertyKey,
|
||||
paletteInfoPropertyKey));
|
||||
event.getPack()
|
||||
.applyLoader(SlantLayer.class, SlantLayer::new);
|
||||
.applyLoader(SlantHolder.Layer.class, SlantLayerTemplate::new);
|
||||
})
|
||||
.failThrough();
|
||||
|
||||
@@ -62,8 +68,10 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
|
||||
.register(addon, ConfigurationLoadEvent.class)
|
||||
.then(event -> {
|
||||
if(event.is(Biome.class)) {
|
||||
NoiseChunkGeneratorPackConfigTemplate config = event.getPack().getContext().get(NoiseChunkGeneratorPackConfigTemplate.class);
|
||||
|
||||
event.getLoadedObject(Biome.class).getContext().put(paletteInfoPropertyKey,
|
||||
event.load(new BiomePaletteTemplate(platform)).get());
|
||||
event.load(new BiomePaletteTemplate(platform, config.getSlantCalculationMethod())).get());
|
||||
event.getLoadedObject(Biome.class).getContext().put(noisePropertiesPropertyKey,
|
||||
event.load(new BiomeNoiseConfigTemplate()).get());
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ 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.Value;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate {
|
||||
public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Properties {
|
||||
@Value("blend.terrain.elevation")
|
||||
@Default
|
||||
private @Meta int elevationBlend = 4;
|
||||
@@ -20,6 +22,10 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate {
|
||||
@Default
|
||||
private @Meta int verticalRes = 2;
|
||||
|
||||
@Value("slant.calculation-method")
|
||||
@Default
|
||||
private SlantHolder.@Meta CalculationMethod slantCalculationMethod = SlantHolder.CalculationMethod.Derivative;
|
||||
|
||||
public int getElevationBlend() {
|
||||
return elevationBlend;
|
||||
}
|
||||
@@ -31,4 +37,8 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate {
|
||||
public int getVerticalRes() {
|
||||
return verticalRes;
|
||||
}
|
||||
|
||||
public SlantHolder.CalculationMethod getSlantCalculationMethod() {
|
||||
return slantCalculationMethod;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,25 +15,23 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolderBuilder;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.SlantHolder;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
public class BiomePaletteTemplate implements ObjectTemplate<PaletteInfo> {
|
||||
public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
|
||||
private final Platform platform;
|
||||
|
||||
@Value("slant")
|
||||
@Default
|
||||
@Description("The slant palettes to use in this biome.")
|
||||
private @Meta List<@Meta SlantLayer> slant = Collections.emptyList();
|
||||
private @Meta List<SlantHolder.@Meta Layer> slantLayers = Collections.emptyList();
|
||||
|
||||
@Value("slant-depth")
|
||||
@Default
|
||||
@@ -63,27 +61,16 @@ public class BiomePaletteTemplate implements ObjectTemplate<PaletteInfo> {
|
||||
@Default
|
||||
private @Meta boolean updatePalette = false;
|
||||
|
||||
public BiomePaletteTemplate(Platform platform) { this.platform = platform; }
|
||||
private final SlantHolder.CalculationMethod slantCalculationMethod;
|
||||
|
||||
public BiomePaletteTemplate(Platform platform, SlantHolder.CalculationMethod slantCalculationMethod) {
|
||||
this.platform = platform;
|
||||
this.slantCalculationMethod = slantCalculationMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaletteInfo get() {
|
||||
PaletteHolderBuilder builder = new PaletteHolderBuilder();
|
||||
for(Map<Palette, Integer> layer : palettes) {
|
||||
for(Entry<Palette, Integer> entry : layer.entrySet()) {
|
||||
builder.add(entry.getValue(), entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
TreeMap<Double, PaletteHolder> slantLayers = new TreeMap<>();
|
||||
double minThreshold = Double.MAX_VALUE;
|
||||
|
||||
for(SlantLayer layer : slant) {
|
||||
double threshold = layer.getThreshold();
|
||||
if(threshold < minThreshold) minThreshold = threshold;
|
||||
slantLayers.put(threshold, layer.getPalette());
|
||||
}
|
||||
|
||||
return new PaletteInfo(builder.build(), SlantHolder.of(slantLayers, minThreshold), oceanPalette, seaLevel, slantDepth,
|
||||
updatePalette);
|
||||
public BiomePaletteInfo get() {
|
||||
return new BiomePaletteInfo(PaletteHolder.of(palettes), SlantHolder.of(slantLayers, slantDepth, slantCalculationMethod),
|
||||
oceanPalette, seaLevel, updatePalette);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addons.chunkgenerator.config.palette;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.SlantHolder;
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
public record PaletteInfo(PaletteHolder paletteHolder,
|
||||
SlantHolder slantHolder,
|
||||
Palette ocean,
|
||||
int seaLevel,
|
||||
int maxSlantDepth,
|
||||
boolean updatePaletteWhenCarving) implements Properties {
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.dfsek.terra.addons.chunkgenerator.config.palette;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolderBuilder;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
public class SlantLayer implements ObjectTemplate<SlantLayer> {
|
||||
@Value("threshold")
|
||||
private @Meta double threshold;
|
||||
|
||||
@Value("palette")
|
||||
private @Meta List<@Meta Map<@Meta Palette, @Meta Integer>> palettes;
|
||||
|
||||
@Override
|
||||
public SlantLayer get() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getThreshold() {
|
||||
return threshold;
|
||||
}
|
||||
|
||||
public PaletteHolder getPalette() {
|
||||
PaletteHolderBuilder builder = new PaletteHolderBuilder();
|
||||
for(Map<Palette, Integer> layer : palettes) {
|
||||
for(Entry<Palette, Integer> entry : layer.entrySet()) {
|
||||
builder.add(entry.getValue(), entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.dfsek.terra.addons.chunkgenerator.config.palette.slant;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
public class SlantLayerTemplate implements ObjectTemplate<SlantHolder.Layer> {
|
||||
|
||||
@Value("threshold")
|
||||
private @Meta double threshold;
|
||||
|
||||
@Value("palette")
|
||||
private @Meta List<@Meta Map<@Meta Palette, @Meta Integer>> palettes;
|
||||
|
||||
@Override
|
||||
public SlantHolder.Layer get() {
|
||||
return new SlantHolder.Layer(PaletteHolder.of(palettes), threshold);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import net.jafama.FastMath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
|
||||
import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
||||
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.samplers.Sampler3D;
|
||||
@@ -40,13 +40,13 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
||||
private final int carverHorizontalResolution;
|
||||
private final int carverVerticalResolution;
|
||||
|
||||
private final PropertyKey<PaletteInfo> paletteInfoPropertyKey;
|
||||
private final PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey;
|
||||
private final PropertyKey<BiomeNoiseProperties> noisePropertiesKey;
|
||||
|
||||
public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution,
|
||||
int carverVerticalResolution,
|
||||
PropertyKey<BiomeNoiseProperties> noisePropertiesKey,
|
||||
PropertyKey<PaletteInfo> paletteInfoPropertyKey) {
|
||||
PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey) {
|
||||
this.platform = platform;
|
||||
this.air = platform.getWorldHandle().air();
|
||||
this.carverHorizontalResolution = carverHorizontalResolution;
|
||||
@@ -97,7 +97,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
||||
for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) {
|
||||
Biome biome = biomeColumn.get(y);
|
||||
|
||||
PaletteInfo paletteInfo = biome.getContext().get(paletteInfoPropertyKey);
|
||||
BiomePaletteInfo paletteInfo = biome.getContext().get(paletteInfoPropertyKey);
|
||||
|
||||
int sea = paletteInfo.seaLevel();
|
||||
Palette seaPalette = paletteInfo.ocean();
|
||||
@@ -131,7 +131,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
|
||||
Biome biome = biomeProvider.getBiome(x, y, z, world.getSeed());
|
||||
Sampler3D sampler = samplerCache.get(x, z, world, biomeProvider);
|
||||
|
||||
PaletteInfo paletteInfo = biome.getContext().get(paletteInfoPropertyKey);
|
||||
BiomePaletteInfo paletteInfo = biome.getContext().get(paletteInfoPropertyKey);
|
||||
|
||||
int fdX = FastMath.floorMod(x, 16);
|
||||
int fdZ = FastMath.floorMod(z, 16);
|
||||
|
||||
@@ -7,40 +7,23 @@
|
||||
|
||||
package com.dfsek.terra.addons.chunkgenerator.generation.math;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
|
||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.SlantHolder;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
public final class PaletteUtil {
|
||||
/**
|
||||
* Derivative constant.
|
||||
*/
|
||||
private static final double DERIVATIVE_DIST = 0.55;
|
||||
|
||||
public static Palette getPalette(int x, int y, int z, Sampler3D sampler, PaletteInfo paletteInfo, int depth) {
|
||||
SlantHolder slant = paletteInfo.slantHolder();
|
||||
if(!slant.isEmpty() && depth <= paletteInfo.maxSlantDepth()) {
|
||||
double slope = derivative(sampler, x, y, z);
|
||||
if(slope > slant.getMinSlope()) {
|
||||
return slant.getPalette(slope).getPalette(y);
|
||||
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);
|
||||
}
|
||||
|
||||
public static double derivative(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)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
public record BiomePaletteInfo(PaletteHolder paletteHolder,
|
||||
SlantHolder slantHolder,
|
||||
Palette ocean,
|
||||
int seaLevel,
|
||||
boolean updatePaletteWhenCarving) implements Properties {
|
||||
}
|
||||
@@ -7,6 +7,13 @@
|
||||
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
@@ -27,4 +34,43 @@ public class PaletteHolder {
|
||||
: palettes[palettes.length - 1]
|
||||
: palettes[0];
|
||||
}
|
||||
|
||||
public static PaletteHolder of(List<Map<Palette, Integer>> palettes) {
|
||||
PaletteHolderBuilder builder = new PaletteHolderBuilder();
|
||||
for(Map<Palette, Integer> layer : palettes) {
|
||||
for(Entry<Palette, Integer> entry : layer.entrySet()) {
|
||||
builder.add(entry.getValue(), entry.getKey());
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static class PaletteHolderBuilder {
|
||||
private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>();
|
||||
|
||||
public PaletteHolderBuilder add(int y, Palette palette) {
|
||||
paletteMap.put(y, palette);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaletteHolder build() {
|
||||
|
||||
int min = FastMath.min(paletteMap.keySet().stream().min(Integer::compareTo).orElse(0), 0);
|
||||
int max = FastMath.max(paletteMap.keySet().stream().max(Integer::compareTo).orElse(255), 255);
|
||||
|
||||
Palette[] palettes = new Palette[paletteMap.lastKey() + 1 - min];
|
||||
for(int y = min; y <= FastMath.max(paletteMap.lastKey(), max); y++) {
|
||||
Palette d = null;
|
||||
for(Entry<Integer, Palette> e : paletteMap.entrySet()) {
|
||||
if(e.getKey() >= y) {
|
||||
d = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(d == null) throw new IllegalArgumentException("No palette for Y=" + y);
|
||||
palettes[y - min] = d;
|
||||
}
|
||||
return new PaletteHolder(palettes, -min);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
|
||||
|
||||
|
||||
public class PaletteHolderBuilder {
|
||||
private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>();
|
||||
|
||||
public PaletteHolderBuilder add(int y, Palette palette) {
|
||||
paletteMap.put(y, palette);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaletteHolder build() {
|
||||
|
||||
int min = FastMath.min(paletteMap.keySet().stream().min(Integer::compareTo).orElse(0), 0);
|
||||
int max = FastMath.max(paletteMap.keySet().stream().max(Integer::compareTo).orElse(255), 255);
|
||||
|
||||
Palette[] palettes = new Palette[paletteMap.lastKey() + 1 - min];
|
||||
for(int y = min; y <= FastMath.max(paletteMap.lastKey(), max); y++) {
|
||||
Palette d = null;
|
||||
for(Map.Entry<Integer, Palette> e : paletteMap.entrySet()) {
|
||||
if(e.getKey() >= y) {
|
||||
d = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(d == null) throw new IllegalArgumentException("No palette for Y=" + y);
|
||||
palettes[y - min] = d;
|
||||
}
|
||||
return new PaletteHolder(palettes, -min);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette;
|
||||
|
||||
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
|
||||
|
||||
public class SlantHolder {
|
||||
private final TreeMap<Double, PaletteHolder> layers;
|
||||
private final double minSlope;
|
||||
|
||||
private SlantHolder(TreeMap<Double, PaletteHolder> layers, double minSlope) {
|
||||
this.layers = layers;
|
||||
this.minSlope = minSlope;
|
||||
}
|
||||
|
||||
public static SlantHolder of(TreeMap<Double, PaletteHolder> layers, double minSlope) {
|
||||
if(layers.size() == 1) {
|
||||
Entry<Double, PaletteHolder> firstEntry = layers.firstEntry();
|
||||
return new Single(firstEntry.getValue(), minSlope);
|
||||
}
|
||||
return new SlantHolder(layers, minSlope);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return layers.isEmpty();
|
||||
}
|
||||
|
||||
public PaletteHolder getPalette(double slope) {
|
||||
return layers.floorEntry(slope).getValue();
|
||||
}
|
||||
|
||||
public double getMinSlope() {
|
||||
return minSlope;
|
||||
}
|
||||
|
||||
private static final class Single extends SlantHolder {
|
||||
|
||||
private final PaletteHolder layers;
|
||||
|
||||
public Single(PaletteHolder layers, double minSlope) {
|
||||
super(of(minSlope, layers), minSlope);
|
||||
this.layers = layers;
|
||||
}
|
||||
|
||||
private static TreeMap<Double, PaletteHolder> of(double v, PaletteHolder layer) {
|
||||
TreeMap<Double, PaletteHolder> map = new TreeMap<>();
|
||||
map.put(v, layer);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaletteHolder getPalette(double slope) {
|
||||
return layers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||
|
||||
|
||||
public class MultipleSlantHolder extends SlantHolderImpl {
|
||||
private final NavigableMap<Double, PaletteHolder> layers;
|
||||
private final double slantThreshold;
|
||||
|
||||
MultipleSlantHolder(List<SlantHolder.Layer> slant, int slantDepth, CalculationMethod calculationMethod) {
|
||||
super(slantDepth, calculationMethod);
|
||||
NavigableMap<Double, PaletteHolder> layers = new TreeMap<>(slant.stream().collect(Collectors.toMap(SlantHolder.Layer::threshold, SlantHolder.Layer::palette)));
|
||||
Stream<Double> thresholds = layers.keySet().stream();
|
||||
double slantThreshold = floorToThreshold ?
|
||||
thresholds.min(Double::compare).orElseThrow() :
|
||||
thresholds.max(Double::compare).orElseThrow();
|
||||
this.layers = layers;
|
||||
this.slantThreshold = slantThreshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getSlantThreshold() {
|
||||
return slantThreshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaletteHolder getPalette(double slant) {
|
||||
return (floorToThreshold ?
|
||||
layers.floorEntry(slant) :
|
||||
layers.ceilingEntry(slant)
|
||||
).getValue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||
|
||||
|
||||
final class SingleSlantHolder extends SlantHolderImpl {
|
||||
|
||||
private final SlantHolder.Layer layer;
|
||||
|
||||
public SingleSlantHolder(SlantHolder.Layer layer, int slantDepth, CalculationMethod calculationMethod) {
|
||||
super(slantDepth, calculationMethod);
|
||||
this.layer = layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaletteHolder getPalette(double slant) {
|
||||
return layer.palette();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getSlantThreshold() {
|
||||
return layer.threshold();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
||||
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
|
||||
import com.dfsek.terra.api.util.vector.Vector3;
|
||||
|
||||
|
||||
public interface SlantHolder {
|
||||
|
||||
static SlantHolder of(List<SlantHolder.Layer> layers, int slantDepth, CalculationMethod calculationMethod) {
|
||||
if(layers.isEmpty()) {
|
||||
return EMPTY;
|
||||
} else if(layers.size() == 1) {
|
||||
return new SingleSlantHolder(layers.get(0), slantDepth, calculationMethod);
|
||||
}
|
||||
return new MultipleSlantHolder(layers, slantDepth, calculationMethod);
|
||||
}
|
||||
|
||||
double calculateSlant(Sampler3D sampler, double x, double y, double z);
|
||||
|
||||
boolean isAboveDepth(int depth);
|
||||
|
||||
boolean isInSlantThreshold(double slant);
|
||||
|
||||
PaletteHolder getPalette(double slant);
|
||||
|
||||
record Layer(PaletteHolder palette, double threshold) {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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
|
||||
public boolean isAboveDepth(int depth) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInSlantThreshold(double slant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PaletteHolder getPalette(double slant) {
|
||||
throw new UnsupportedOperationException("Empty holder cannot return a palette");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
|
||||
|
||||
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
|
||||
|
||||
|
||||
public abstract class SlantHolderImpl implements SlantHolder {
|
||||
private final SlantHolder.CalculationMethod calculationMethod;
|
||||
|
||||
private final int slantDepth;
|
||||
|
||||
protected final boolean floorToThreshold;
|
||||
|
||||
protected SlantHolderImpl(int slantDepth, CalculationMethod calculationMethod) {
|
||||
this.floorToThreshold = calculationMethod.floorToThreshold();
|
||||
this.calculationMethod = calculationMethod;
|
||||
this.slantDepth = slantDepth;
|
||||
}
|
||||
|
||||
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
|
||||
public final boolean isAboveDepth(int depth) {
|
||||
return depth <= slantDepth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isInSlantThreshold(double slant) {
|
||||
return (floorToThreshold ?
|
||||
slant > getSlantThreshold() :
|
||||
slant < getSlantThreshold()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user