mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-03 16:35:50 +00:00
improve elevation interp (TEMP DISABLE CARVING)
This commit is contained in:
parent
cbc2885c16
commit
c1fdfa94f1
@ -2515,7 +2515,8 @@ public class FastNoiseLite implements NoiseSampler {
|
|||||||
Perlin,
|
Perlin,
|
||||||
ValueCubic,
|
ValueCubic,
|
||||||
Value,
|
Value,
|
||||||
WhiteNoise
|
WhiteNoise,
|
||||||
|
Constant
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,25 +1,31 @@
|
|||||||
package com.dfsek.terra.biome;
|
package com.dfsek.terra.biome;
|
||||||
|
|
||||||
import com.dfsek.tectonic.exception.ConfigException;
|
import com.dfsek.tectonic.exception.ConfigException;
|
||||||
|
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||||
import com.dfsek.terra.api.math.vector.Vector2;
|
import com.dfsek.terra.api.math.vector.Vector2;
|
||||||
import com.dfsek.terra.api.platform.TerraPlugin;
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||||
import com.dfsek.terra.biome.pipeline.BiomeHolder;
|
import com.dfsek.terra.biome.pipeline.BiomeHolder;
|
||||||
import com.dfsek.terra.biome.pipeline.BiomePipeline;
|
import com.dfsek.terra.biome.pipeline.BiomePipeline;
|
||||||
|
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
public class StandardBiomeProvider implements BiomeProvider {
|
public class StandardBiomeProvider implements BiomeProvider {
|
||||||
private final LoadingCache<Vector2, BiomeHolder> holderCache;
|
private final LoadingCache<Vector2, BiomeHolder> holderCache;
|
||||||
private final LoadingCache<Vector2, TerraBiome> biomeCache;
|
private final BiomePipeline pipeline;
|
||||||
private int resolution = 1;
|
private int resolution = 1;
|
||||||
|
private final NoiseSampler xSampler;
|
||||||
|
private final NoiseSampler zSampler;
|
||||||
|
private final int noiseAmp;
|
||||||
|
|
||||||
protected StandardBiomeProvider(BiomePipeline pipeline, TerraPlugin main) {
|
protected StandardBiomeProvider(BiomePipeline pipeline, TerraPlugin main, NoiseSampler xSampler, NoiseSampler zSampler, int noiseAmp) {
|
||||||
|
this.xSampler = xSampler;
|
||||||
|
this.zSampler = zSampler;
|
||||||
|
this.noiseAmp = noiseAmp;
|
||||||
holderCache = CacheBuilder.newBuilder()
|
holderCache = CacheBuilder.newBuilder()
|
||||||
.maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache())
|
.maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache())
|
||||||
.build(
|
.build(
|
||||||
@ -30,27 +36,16 @@ public class StandardBiomeProvider implements BiomeProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
biomeCache = CacheBuilder.newBuilder()
|
this.pipeline = pipeline;
|
||||||
.maximumSize(main == null ? 512 : main.getTerraConfig().getBiomeCache())
|
|
||||||
.build(
|
|
||||||
new CacheLoader<Vector2, TerraBiome>() {
|
|
||||||
@Override
|
|
||||||
public TerraBiome load(@NotNull Vector2 key) throws ExecutionException {
|
|
||||||
int x = FastMath.floorToInt(key.getX());
|
|
||||||
int z = FastMath.floorToInt(key.getZ());
|
|
||||||
x /= resolution;
|
|
||||||
z /= resolution;
|
|
||||||
int fdX = FastMath.floorDiv(x, pipeline.getSize());
|
|
||||||
int fdZ = FastMath.floorDiv(z, pipeline.getSize());
|
|
||||||
return holderCache.get(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TerraBiome getBiome(int x, int z) {
|
public TerraBiome getBiome(int x, int z) {
|
||||||
return biomeCache.getUnchecked(new Vector2(x, z));
|
x = FastMath.floorToInt(FastMath.floorDiv(x, resolution) + xSampler.getNoise(x, z) * noiseAmp);
|
||||||
|
z = FastMath.floorToInt(FastMath.floorDiv(z, resolution) + zSampler.getNoise(x, z) * noiseAmp);
|
||||||
|
int fdX = FastMath.floorDiv(x, pipeline.getSize());
|
||||||
|
int fdZ = FastMath.floorDiv(z, pipeline.getSize());
|
||||||
|
return holderCache.getUnchecked(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getResolution() {
|
public int getResolution() {
|
||||||
@ -68,16 +63,33 @@ public class StandardBiomeProvider implements BiomeProvider {
|
|||||||
public static final class StandardBiomeProviderBuilder implements BiomeProviderBuilder {
|
public static final class StandardBiomeProviderBuilder implements BiomeProviderBuilder {
|
||||||
private final ExceptionalFunction<Long, BiomePipeline> pipelineBuilder;
|
private final ExceptionalFunction<Long, BiomePipeline> pipelineBuilder;
|
||||||
private final TerraPlugin main;
|
private final TerraPlugin main;
|
||||||
|
private int resolution = 1;
|
||||||
|
private int noiseAmp = 2;
|
||||||
|
private NoiseBuilder builder = new NoiseBuilder();
|
||||||
|
|
||||||
public StandardBiomeProviderBuilder(ExceptionalFunction<Long, BiomePipeline> pipelineBuilder, TerraPlugin main) {
|
public StandardBiomeProviderBuilder(ExceptionalFunction<Long, BiomePipeline> pipelineBuilder, TerraPlugin main) {
|
||||||
this.pipelineBuilder = pipelineBuilder;
|
this.pipelineBuilder = pipelineBuilder;
|
||||||
this.main = main;
|
this.main = main;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setResolution(int resolution) {
|
||||||
|
this.resolution = resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBuilder(NoiseBuilder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNoiseAmp(int noiseAmp) {
|
||||||
|
this.noiseAmp = noiseAmp;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StandardBiomeProvider build(long seed) {
|
public StandardBiomeProvider build(long seed) {
|
||||||
try {
|
try {
|
||||||
return new StandardBiomeProvider(pipelineBuilder.apply(seed), main);
|
StandardBiomeProvider provider = new StandardBiomeProvider(pipelineBuilder.apply(seed), main, builder.build((int) seed), builder.build((int) (seed + 1)), noiseAmp);
|
||||||
|
provider.setResolution(resolution);
|
||||||
|
return provider;
|
||||||
} catch(ConfigException e) {
|
} catch(ConfigException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -182,10 +182,7 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate {
|
|||||||
@Override
|
@Override
|
||||||
public boolean validate() throws ValidationException {
|
public boolean validate() throws ValidationException {
|
||||||
if(!MathUtil.equals(FastMath.log(baseBlend) / FastMath.log(2d), FastMath.round(FastMath.log(baseBlend) / FastMath.log(2d)))) {
|
if(!MathUtil.equals(FastMath.log(baseBlend) / FastMath.log(2d), FastMath.round(FastMath.log(baseBlend) / FastMath.log(2d)))) {
|
||||||
throw new ValidationException("TerraBiome base blend value \"" + baseBlend + "\" is not a power of 2.");
|
throw new ValidationException("Biome base blend value \"" + baseBlend + "\" is not a power of 2.");
|
||||||
}
|
|
||||||
if(!MathUtil.equals(FastMath.log(elevationBlend) / FastMath.log(2d), FastMath.round(FastMath.log(elevationBlend) / FastMath.log(2d)))) {
|
|
||||||
throw new ValidationException("TerraBiome elevation blend value \"" + baseBlend + "\" is not a power of 2.");
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,10 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) {
|
public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException {
|
||||||
Map<String, Object> map = (Map<String, Object>) c;
|
Map<String, Object> map = (Map<String, Object>) c;
|
||||||
|
|
||||||
return new StandardBiomeProvider.StandardBiomeProviderBuilder(seed -> {
|
StandardBiomeProvider.StandardBiomeProviderBuilder builder = new StandardBiomeProvider.StandardBiomeProviderBuilder(seed -> {
|
||||||
Map<String, Object> source = (Map<String, Object>) map.get("source");
|
Map<String, Object> source = (Map<String, Object>) map.get("source");
|
||||||
ProbabilityCollection<TerraBiome> sourceBiomes = (ProbabilityCollection<TerraBiome>) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes"));
|
ProbabilityCollection<TerraBiome> sourceBiomes = (ProbabilityCollection<TerraBiome>) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes"));
|
||||||
NoiseSampler sourceNoise = new NoiseBuilderLoader().load(NoiseBuilder.class, source.get("noise"), loader).build(FastMath.toInt(seed));
|
NoiseSampler sourceNoise = new NoiseBuilderLoader().load(NoiseBuilder.class, source.get("noise"), loader).build(FastMath.toInt(seed));
|
||||||
@ -76,5 +76,13 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
|
|||||||
Debug.info("Biome Pipeline scale factor: " + pipeline.getSize());
|
Debug.info("Biome Pipeline scale factor: " + pipeline.getSize());
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}, main);
|
}, main);
|
||||||
|
if(map.containsKey("resolution")) builder.setResolution(Integer.parseInt(map.get("resolution").toString()));
|
||||||
|
if(map.containsKey("blend")) {
|
||||||
|
Map<String, Object> blend = (Map<String, Object>) map.get("blend");
|
||||||
|
if(blend.containsKey("amplitude")) builder.setNoiseAmp(Integer.parseInt(blend.get("amplitude").toString()));
|
||||||
|
if(blend.containsKey("noise"))
|
||||||
|
builder.setBuilder(new NoiseBuilderLoader().load(NoiseBuilder.class, blend.get("noise"), loader));
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ public class SamplerCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class Container {
|
private class Container {
|
||||||
private final World world;
|
|
||||||
private final TerraWorld terraWorld;
|
private final TerraWorld terraWorld;
|
||||||
private final LoadingCache<Long, Sampler> cache;
|
private final LoadingCache<Long, Sampler> cache;
|
||||||
|
|
||||||
@ -46,10 +45,9 @@ public class SamplerCache {
|
|||||||
public Sampler load(@NotNull Long key) {
|
public Sampler load(@NotNull Long key) {
|
||||||
int cx = (int) (key >> 32);
|
int cx = (int) (key >> 32);
|
||||||
int cz = (int) key.longValue();
|
int cz = (int) key.longValue();
|
||||||
return new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend());
|
return new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getElevationBlend(), terraWorld.getConfig().getTemplate().getBaseBlend());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.world = world;
|
|
||||||
terraWorld = main.getWorld(world);
|
terraWorld = main.getWorld(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,76 +6,32 @@ import com.dfsek.terra.generation.config.WorldGenerator;
|
|||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
|
|
||||||
public class ElevationInterpolator {
|
public class ElevationInterpolator {
|
||||||
private final WorldGenerator[][] gens;
|
|
||||||
private final double[][] values = new double[18][18];
|
private final double[][] values = new double[18][18];
|
||||||
private final int xOrigin;
|
|
||||||
private final int zOrigin;
|
|
||||||
private final BiomeProvider provider;
|
|
||||||
private final int smooth;
|
|
||||||
private final int pow;
|
|
||||||
private final World world;
|
|
||||||
|
|
||||||
public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeProvider provider, int smooth) {
|
public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeProvider provider, int smooth) {
|
||||||
this.xOrigin = chunkX << 4;
|
int xOrigin = chunkX << 4;
|
||||||
this.zOrigin = chunkZ << 4;
|
int zOrigin = chunkZ << 4;
|
||||||
this.provider = provider;
|
|
||||||
this.smooth = smooth;
|
|
||||||
this.pow = FastMath.log2(smooth);
|
|
||||||
this.gens = new WorldGenerator[6 + 2 * pow][6 + 2 * pow];
|
|
||||||
this.world = world;
|
|
||||||
|
|
||||||
|
WorldGenerator[][] gens = new WorldGenerator[18 + 2 * smooth][18 + 2 * smooth];
|
||||||
|
|
||||||
for(int x = -pow; x < 6 + pow; x++) {
|
// Precompute generators.
|
||||||
for(int z = -pow; z < 6 + pow; z++) {
|
for(int x = -1 - smooth; x <= 16 + smooth; x++) {
|
||||||
gens[x + pow][z + pow] = (WorldGenerator) provider.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth)).getGenerator(world);
|
for(int z = -1 - smooth; z <= 16 + smooth; z++) {
|
||||||
|
gens[x + 1 + smooth][z + 1 + smooth] = (WorldGenerator) provider.getBiome(xOrigin + x, zOrigin + z).getGenerator(world);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(byte x = -1; x <= 16; x++) {
|
for(int x = -1; x <= 16; x++) {
|
||||||
for(byte z = -1; z <= 16; z++) {
|
for(int z = -1; z <= 16; z++) {
|
||||||
WorldGenerator generator = getGenerator(x, z);
|
double noise = 0;
|
||||||
if(compareGens((x / smooth), (z / smooth), generator) && generator.interpolateElevation()) {
|
for(int xi = -smooth; xi <= smooth; xi++) {
|
||||||
Interpolator interpolator = new Interpolator(biomeAvg(x / smooth, z / smooth),
|
for(int zi = -smooth; zi <= smooth; zi++) {
|
||||||
biomeAvg((x / smooth) + 1, z / smooth),
|
noise += gens[x + 1 + smooth + xi][z + 1 + smooth + zi].getElevation(xOrigin + x, zOrigin + z);
|
||||||
biomeAvg(x / smooth, (z / smooth) + 1),
|
|
||||||
biomeAvg((x / smooth) + 1, (z / smooth) + 1));
|
|
||||||
values[x + 1][z + 1] = interpolator.bilerp((double) (x % smooth) / smooth, (double) (z % smooth) / smooth);
|
|
||||||
} else values[x + 1][z + 1] = elevate(generator, xOrigin + x, zOrigin + z);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
values[x + 1][z + 1] = noise / FastMath.pow2(smooth * 2 + 1);
|
||||||
|
|
||||||
private WorldGenerator getGenerator(int x, int z) {
|
|
||||||
return (WorldGenerator) provider.getBiome(xOrigin + x, zOrigin + z).getGenerator(world);
|
|
||||||
}
|
|
||||||
|
|
||||||
private WorldGenerator getStoredGen(int x, int z) {
|
|
||||||
return gens[x + pow][z + pow];
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean compareGens(int x, int z, WorldGenerator comp) {
|
|
||||||
for(int xi = x - pow; xi <= x + pow; xi++) {
|
|
||||||
for(int zi = z - pow; zi <= z + pow; zi++) {
|
|
||||||
if(!comp.equals(getStoredGen(xi, zi))) return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double biomeAvg(int x, int z) {
|
|
||||||
return (elevate(getStoredGen(x + 1, z), (x * smooth) + smooth + xOrigin, (z * smooth) + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x - 1, z), (x * smooth) - smooth + xOrigin, (z * smooth) + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x, z + 1), (x * smooth) + xOrigin, (z * smooth) + smooth + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x, z - 1), (x * smooth) + xOrigin, (z * smooth) - smooth + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x, z), (x * smooth) + xOrigin, (z * smooth) + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x - 1, z - 1), (x * smooth) - smooth + xOrigin, (z * smooth) - smooth + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x - 1, z + 1), (x * smooth) - smooth + xOrigin, (z * smooth) + smooth + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x + 1, z - 1), (x * smooth) + smooth + xOrigin, (z * smooth) - smooth + zOrigin)
|
|
||||||
+ elevate(getStoredGen(x + 1, z + 1), (x * smooth) + smooth + xOrigin, (z * smooth) + smooth + zOrigin)) / 9D;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double elevate(WorldGenerator g, int x, int z) {
|
|
||||||
return g.getElevation(x, z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getElevation(int x, int z) {
|
public double getElevation(int x, int z) {
|
||||||
|
@ -10,7 +10,6 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
|||||||
import com.dfsek.terra.bukkit.world.BukkitBiomeGrid;
|
import com.dfsek.terra.bukkit.world.BukkitBiomeGrid;
|
||||||
import com.dfsek.terra.config.lang.LangUtil;
|
import com.dfsek.terra.config.lang.LangUtil;
|
||||||
import com.dfsek.terra.debug.Debug;
|
import com.dfsek.terra.debug.Debug;
|
||||||
import com.dfsek.terra.population.CavePopulator;
|
|
||||||
import com.dfsek.terra.population.FloraPopulator;
|
import com.dfsek.terra.population.FloraPopulator;
|
||||||
import com.dfsek.terra.population.OrePopulator;
|
import com.dfsek.terra.population.OrePopulator;
|
||||||
import com.dfsek.terra.population.StructurePopulator;
|
import com.dfsek.terra.population.StructurePopulator;
|
||||||
@ -90,7 +89,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
|
public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
|
||||||
return Stream.of(new CavePopulator(main), new StructurePopulator(main), popMan).map(BukkitPopulatorWrapper::new).collect(Collectors.toList());
|
return Stream.of(new StructurePopulator(main), popMan).map(BukkitPopulatorWrapper::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user