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,
|
||||
ValueCubic,
|
||||
Value,
|
||||
WhiteNoise
|
||||
WhiteNoise,
|
||||
Constant
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,25 +1,31 @@
|
||||
package com.dfsek.terra.biome;
|
||||
|
||||
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.platform.TerraPlugin;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.biome.pipeline.BiomeHolder;
|
||||
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.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import net.jafama.FastMath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class StandardBiomeProvider implements BiomeProvider {
|
||||
private final LoadingCache<Vector2, BiomeHolder> holderCache;
|
||||
private final LoadingCache<Vector2, TerraBiome> biomeCache;
|
||||
private final BiomePipeline pipeline;
|
||||
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()
|
||||
.maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache())
|
||||
.build(
|
||||
@ -30,27 +36,16 @@ public class StandardBiomeProvider implements BiomeProvider {
|
||||
}
|
||||
}
|
||||
);
|
||||
biomeCache = CacheBuilder.newBuilder()
|
||||
.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());
|
||||
}
|
||||
}
|
||||
);
|
||||
this.pipeline = pipeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
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() {
|
||||
@ -68,16 +63,33 @@ public class StandardBiomeProvider implements BiomeProvider {
|
||||
public static final class StandardBiomeProviderBuilder implements BiomeProviderBuilder {
|
||||
private final ExceptionalFunction<Long, BiomePipeline> pipelineBuilder;
|
||||
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) {
|
||||
this.pipelineBuilder = pipelineBuilder;
|
||||
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
|
||||
public StandardBiomeProvider build(long seed) {
|
||||
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) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -182,10 +182,7 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate {
|
||||
@Override
|
||||
public boolean validate() throws ValidationException {
|
||||
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.");
|
||||
}
|
||||
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.");
|
||||
throw new ValidationException("Biome base blend value \"" + baseBlend + "\" is not a power of 2.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -36,10 +36,10 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
return new StandardBiomeProvider.StandardBiomeProviderBuilder(seed -> {
|
||||
StandardBiomeProvider.StandardBiomeProviderBuilder builder = new StandardBiomeProvider.StandardBiomeProviderBuilder(seed -> {
|
||||
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"));
|
||||
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());
|
||||
return pipeline;
|
||||
}, 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 final World world;
|
||||
private final TerraWorld terraWorld;
|
||||
private final LoadingCache<Long, Sampler> cache;
|
||||
|
||||
@ -46,10 +45,9 @@ public class SamplerCache {
|
||||
public Sampler load(@NotNull Long key) {
|
||||
int cx = (int) (key >> 32);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -6,78 +6,34 @@ import com.dfsek.terra.generation.config.WorldGenerator;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public class ElevationInterpolator {
|
||||
private final WorldGenerator[][] gens;
|
||||
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) {
|
||||
this.xOrigin = chunkX << 4;
|
||||
this.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;
|
||||
int xOrigin = chunkX << 4;
|
||||
int zOrigin = chunkZ << 4;
|
||||
|
||||
WorldGenerator[][] gens = new WorldGenerator[18 + 2 * smooth][18 + 2 * smooth];
|
||||
|
||||
for(int x = -pow; x < 6 + pow; x++) {
|
||||
for(int z = -pow; z < 6 + pow; z++) {
|
||||
gens[x + pow][z + pow] = (WorldGenerator) provider.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth)).getGenerator(world);
|
||||
// Precompute generators.
|
||||
for(int x = -1 - smooth; x <= 16 + smooth; x++) {
|
||||
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(byte z = -1; z <= 16; z++) {
|
||||
WorldGenerator generator = getGenerator(x, z);
|
||||
if(compareGens((x / smooth), (z / smooth), generator) && generator.interpolateElevation()) {
|
||||
Interpolator interpolator = new Interpolator(biomeAvg(x / smooth, z / smooth),
|
||||
biomeAvg((x / smooth) + 1, z / smooth),
|
||||
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);
|
||||
for(int x = -1; x <= 16; x++) {
|
||||
for(int z = -1; z <= 16; z++) {
|
||||
double noise = 0;
|
||||
for(int xi = -smooth; xi <= smooth; xi++) {
|
||||
for(int zi = -smooth; zi <= smooth; zi++) {
|
||||
noise += gens[x + 1 + smooth + xi][z + 1 + smooth + zi].getElevation(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) {
|
||||
return values[x + 1][z + 1];
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
|
||||
import com.dfsek.terra.bukkit.world.BukkitBiomeGrid;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.debug.Debug;
|
||||
import com.dfsek.terra.population.CavePopulator;
|
||||
import com.dfsek.terra.population.FloraPopulator;
|
||||
import com.dfsek.terra.population.OrePopulator;
|
||||
import com.dfsek.terra.population.StructurePopulator;
|
||||
@ -90,7 +89,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
|
||||
|
||||
@Override
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user