mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-08 00:36:15 +00:00
build chunk generator addon
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
package com.dfsek.terra.api.util;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.Generator;
|
||||
import com.dfsek.terra.api.world.generator.Palette;
|
||||
import com.dfsek.terra.api.world.generator.Sampler;
|
||||
|
||||
public final class PaletteUtil {
|
||||
public static Palette getPalette(int x, int y, int z, Generator c, Sampler sampler) {
|
||||
|
||||
/*
|
||||
SlantHolder slant = c.getSlant();
|
||||
if(slant != null) {
|
||||
double slope = MathUtil.derivative(sampler, x, y, z);
|
||||
if(slope > slant.getMinSlope()) {
|
||||
return slant.getPalette(slope).getPalette(y);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
return c.getPaletteSettings().getPalette(y);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.dfsek.terra.world;
|
||||
|
||||
import com.dfsek.terra.api.world.ChunkAccess;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
public interface Carver {
|
||||
void carve(World world, int chunkX, int chunkZ, ChunkAccess chunk);
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.util.Range;
|
||||
import com.dfsek.terra.api.world.ChunkAccess;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.world.Carver;
|
||||
import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator;
|
||||
import com.dfsek.terra.api.world.Carver;
|
||||
import com.dfsek.terra.api.world.generator.ChunkInterpolator;
|
||||
import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator3D;
|
||||
|
||||
public class NoiseCarver implements Carver {
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.generators;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.BlockType;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.block.state.properties.base.Properties;
|
||||
import com.dfsek.terra.api.block.state.properties.enums.Direction;
|
||||
import com.dfsek.terra.api.block.state.properties.enums.Half;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.math.range.ConstantRange;
|
||||
import com.dfsek.terra.api.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.api.util.PaletteUtil;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.BiomeGrid;
|
||||
import com.dfsek.terra.api.world.TerraWorld;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.Generator;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generator.ChunkData;
|
||||
import com.dfsek.terra.api.world.generator.Palette;
|
||||
import com.dfsek.terra.api.world.generator.Sampler;
|
||||
import com.dfsek.terra.api.world.generator.TerraBlockPopulator;
|
||||
import com.dfsek.terra.api.world.generator.TerraChunkGenerator;
|
||||
import com.dfsek.terra.world.Carver;
|
||||
import com.dfsek.terra.world.carving.NoiseCarver;
|
||||
import com.dfsek.terra.world.generation.math.samplers.Sampler3D;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class DefaultChunkGenerator3D implements TerraChunkGenerator {
|
||||
private final ConfigPack configPack;
|
||||
private final TerraPlugin main;
|
||||
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
|
||||
|
||||
private final Carver carver;
|
||||
|
||||
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) {
|
||||
this.configPack = c;
|
||||
this.main = main;
|
||||
|
||||
carver = new NoiseCarver(new ConstantRange(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getConfigPack() {
|
||||
return configPack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraPlugin getMain() {
|
||||
return main;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"try"})
|
||||
public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
BiomeProvider grid = tw.getBiomeProvider();
|
||||
|
||||
if(!tw.isSafe()) return chunk;
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
|
||||
Sampler sampler = tw.getConfig().getSamplerCache().getChunk(chunkX, chunkZ);
|
||||
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
int paletteLevel = 0;
|
||||
|
||||
int cx = xOrig + x;
|
||||
int cz = zOrig + z;
|
||||
|
||||
TerraBiome b = grid.getBiome(cx, cz);
|
||||
Generator g = b.getGenerator(world);
|
||||
|
||||
//int sea = c.getSeaLevel();
|
||||
//Palette seaPalette = c.getOceanPalette();
|
||||
|
||||
boolean justSet = false;
|
||||
BlockState data = null;
|
||||
for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) {
|
||||
if(sampler.sample(x, y, z) > 0) {
|
||||
justSet = true;
|
||||
data = PaletteUtil.getPalette(x, y, z, g, sampler).get(paletteLevel, cx, y, cz);
|
||||
chunk.setBlock(x, y, z, data);
|
||||
|
||||
paletteLevel++;
|
||||
} /*else if(y <= sea) {
|
||||
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig));
|
||||
|
||||
justSet = false;
|
||||
paletteLevel = 0;
|
||||
} */else {
|
||||
|
||||
justSet = false;
|
||||
paletteLevel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(configPack.doBetaCarvers()) {
|
||||
carver.carve(world, chunkX, chunkZ, chunk);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean placeStair(BlockState orig, ChunkData chunk, Vector3 block, double thresh, Sampler sampler, BlockState stairNew) {
|
||||
|
||||
if(sampler.sample(block.getBlockX() - 0.55, block.getY(), block.getZ()) > thresh) {
|
||||
stairNew.set(Properties.DIRECTION, Direction.WEST);
|
||||
} else if(sampler.sample(block.getBlockX(), block.getY(), block.getZ() - 0.55) > thresh) {
|
||||
stairNew.set(Properties.DIRECTION, Direction.NORTH);
|
||||
} else if(sampler.sample(block.getBlockX(), block.getY(), block.getZ() + 0.55) > thresh) {
|
||||
stairNew.set(Properties.DIRECTION, Direction.SOUTH);
|
||||
} else if(sampler.sample(block.getX() + 0.55, block.getY(), block.getZ()) > thresh) {
|
||||
stairNew.set(Properties.DIRECTION, Direction.EAST);
|
||||
} else stairNew = null;
|
||||
if(stairNew != null) {
|
||||
stairNew.setIfPresent(Properties.WATERLOGGED, orig.getBlockType().isWater());
|
||||
chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), stairNew);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"try"})
|
||||
static void biomes(@NotNull World world, int chunkX, int chunkZ, @NotNull BiomeGrid biome, TerraPlugin main) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("biomes")) {
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
|
||||
for(int x = 0; x < 4; x++) {
|
||||
for(int z = 0; z < 4; z++) {
|
||||
int cx = xOrig + (x << 2);
|
||||
int cz = zOrig + (z << 2);
|
||||
TerraBiome b = grid.getBiome(cx, cz);
|
||||
|
||||
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) {
|
||||
biomes(world, chunkX, chunkZ, biome, main);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
|
||||
return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TerraBlockPopulator> getPopulators() {
|
||||
return blockPopulators;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.util.MathUtil;
|
||||
import com.dfsek.terra.api.world.TerraWorld;
|
||||
import com.dfsek.terra.api.world.generator.Sampler;
|
||||
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;
|
||||
|
||||
public class SamplerCacheImpl implements com.dfsek.terra.api.world.generator.SamplerCache {
|
||||
private final LoadingCache<Long, Sampler> cache;
|
||||
|
||||
public SamplerCacheImpl(TerraPlugin main, TerraWorld world) {
|
||||
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache())
|
||||
.build(new CacheLoader<Long, Sampler>() {
|
||||
@Override
|
||||
public Sampler load(@NotNull Long key) {
|
||||
int cx = (int) (key >> 32);
|
||||
int cz = (int) key.longValue();
|
||||
return world.getWorld().getTerraGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().elevationBlend());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sampler get(int x, int z) {
|
||||
int cx = FastMath.floorDiv(x, 16);
|
||||
int cz = FastMath.floorDiv(z, 16);
|
||||
return getChunk(cx, cz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sampler getChunk(int cx, int cz) {
|
||||
long key = MathUtil.squash(cx, cz);
|
||||
return cache.getUnchecked(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
cache.invalidateAll();
|
||||
cache.cleanUp();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.interpolation;
|
||||
|
||||
import com.dfsek.terra.api.util.mutable.MutableInteger;
|
||||
import com.dfsek.terra.api.world.biome.Generator;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ChunkInterpolator {
|
||||
/**
|
||||
* Gets the noise at a pair of internal chunk coordinates.
|
||||
*
|
||||
* @param x The internal X coordinate (0-15).
|
||||
* @param z The internal Z coordinate (0-15).
|
||||
* @return double - The interpolated noise at the coordinates.
|
||||
*/
|
||||
double getNoise(double x, double y, double z);
|
||||
|
||||
default double getNoise(int x, int y, int z) { // Floating-point modulus operations are expensive. This allows implementations to optionally handle integers separately.
|
||||
return getNoise((double) x, y, z);
|
||||
}
|
||||
|
||||
|
||||
default double computeNoise(Map<Generator, MutableInteger> gens, double x, double y, double z) {
|
||||
double n = 0;
|
||||
double div = 0;
|
||||
for(Map.Entry<Generator, MutableInteger> entry : gens.entrySet()) {
|
||||
Generator gen = entry.getKey();
|
||||
int weight = entry.getValue().get();
|
||||
double noise = computeNoise(gen, x, y, z);
|
||||
|
||||
n += noise * weight;
|
||||
div += gen.getWeight() * weight;
|
||||
}
|
||||
return n / div;
|
||||
}
|
||||
|
||||
double computeNoise(Generator generator, double x, double y, double z);
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.interpolation;
|
||||
|
||||
import com.dfsek.terra.api.util.mutable.MutableInteger;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.Generator;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Class to abstract away the Interpolators needed to generate a chunk.<br>
|
||||
* Contains method to get interpolated noise at a coordinate within the chunk.
|
||||
*/
|
||||
public class ChunkInterpolator2D implements ChunkInterpolator {
|
||||
private final Interpolator[][] interpGrid = new Interpolator[4][4];
|
||||
private final BiFunction<Generator, Vector3, Double> noiseGetter;
|
||||
|
||||
/**
|
||||
* Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates.
|
||||
*
|
||||
* @param chunkX X coordinate of the chunk.
|
||||
* @param chunkZ Z coordinate of the chunk.
|
||||
* @param provider Biome Provider to use for biome fetching.
|
||||
*/
|
||||
public ChunkInterpolator2D(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction<Generator, Vector3, Double> noiseGetter) {
|
||||
this.noiseGetter = noiseGetter;
|
||||
int xOrigin = chunkX << 4;
|
||||
int zOrigin = chunkZ << 4;
|
||||
|
||||
double[][] noiseStorage = new double[5][5];
|
||||
|
||||
for(int x = 0; x < 5; x++) {
|
||||
for(int z = 0; z < 5; z++) {
|
||||
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
|
||||
Map<Generator, MutableInteger> genMap = new HashMap<>();
|
||||
|
||||
int step = generator.getBlendStep();
|
||||
int blend = generator.getBlendDistance();
|
||||
|
||||
for(int xi = -blend; xi <= blend; xi++) {
|
||||
for(int zi = -blend; zi <= blend; zi++) {
|
||||
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
|
||||
}
|
||||
}
|
||||
|
||||
noiseStorage[x][z] = computeNoise(genMap, (x << 2) + xOrigin, 0, (z << 2) + zOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = 0; x < 4; x++) {
|
||||
for(int z = 0; z < 4; z++) {
|
||||
interpGrid[x][z] = new Interpolator(
|
||||
noiseStorage[x][z],
|
||||
noiseStorage[x + 1][z],
|
||||
noiseStorage[x][z + 1],
|
||||
noiseStorage[x + 1][z + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int reRange(int value, int high) {
|
||||
return FastMath.max(FastMath.min(value, high), 0);
|
||||
}
|
||||
|
||||
public double computeNoise(Generator generator, double x, double y, double z) {
|
||||
return noiseGetter.apply(generator, new Vector3(x, y, z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the noise at a pair of internal chunk coordinates.
|
||||
*
|
||||
* @param x The internal X coordinate (0-15).
|
||||
* @param z The internal Z coordinate (0-15).
|
||||
* @return double - The interpolated noise at the coordinates.
|
||||
*/
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return interpGrid[reRange(((int) x) / 4, 3)][reRange(((int) z) / 4, 3)].bilerp((x % 4) / 4, (z % 4) / 4);
|
||||
}
|
||||
|
||||
public double getNoise(int x, int y, int z) {
|
||||
return interpGrid[x / 4][z / 4].bilerp((double) (x % 4) / 4, (double) (z % 4) / 4);
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.interpolation;
|
||||
|
||||
import com.dfsek.terra.api.util.mutable.MutableInteger;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.Generator;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Class to abstract away the Interpolators needed to generate a chunk.<br>
|
||||
* Contains method to get interpolated noise at a coordinate within the chunk.
|
||||
*/
|
||||
public class ChunkInterpolator3D implements ChunkInterpolator {
|
||||
private final Interpolator3[][][] interpGrid;
|
||||
private final BiFunction<Generator, Vector3, Double> noiseGetter;
|
||||
|
||||
private final int min;
|
||||
private final int max;
|
||||
|
||||
/**
|
||||
* Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates.
|
||||
*
|
||||
* @param chunkX X coordinate of the chunk.
|
||||
* @param chunkZ Z coordinate of the chunk.
|
||||
* @param provider Biome Provider to use for biome fetching.
|
||||
*/
|
||||
public ChunkInterpolator3D(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction<Generator, Vector3, Double> noiseGetter) {
|
||||
this.noiseGetter = noiseGetter;
|
||||
int xOrigin = chunkX << 4;
|
||||
int zOrigin = chunkZ << 4;
|
||||
|
||||
this.max = w.getMaxHeight();
|
||||
this.min = w.getMinHeight();
|
||||
int range = max - min + 1;
|
||||
|
||||
int size = range >> 2;
|
||||
|
||||
interpGrid = new Interpolator3[4][size][4];
|
||||
|
||||
double[][][] noiseStorage = new double[5][5][size + 1];
|
||||
|
||||
for(int x = 0; x < 5; x++) {
|
||||
for(int z = 0; z < 5; z++) {
|
||||
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
|
||||
Map<Generator, MutableInteger> genMap = new HashMap<>();
|
||||
|
||||
int step = generator.getBlendStep();
|
||||
int blend = generator.getBlendDistance();
|
||||
|
||||
for(int xi = -blend; xi <= blend; xi++) {
|
||||
for(int zi = -blend; zi <= blend; zi++) {
|
||||
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0; y < size + 1; y++) {
|
||||
noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + min, (z << 2) + zOrigin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = 0; x < 4; x++) {
|
||||
for(int z = 0; z < 4; z++) {
|
||||
for(int y = 0; y < size; y++) {
|
||||
interpGrid[x][y][z] = new Interpolator3(
|
||||
noiseStorage[x][z][y],
|
||||
noiseStorage[x + 1][z][y],
|
||||
noiseStorage[x][z][y + 1],
|
||||
noiseStorage[x + 1][z][y + 1],
|
||||
noiseStorage[x][z + 1][y],
|
||||
noiseStorage[x + 1][z + 1][y],
|
||||
noiseStorage[x][z + 1][y + 1],
|
||||
noiseStorage[x + 1][z + 1][y + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double computeNoise(Generator generator, double x, double y, double z) {
|
||||
return noiseGetter.apply(generator, new Vector3(x, y, z));
|
||||
}
|
||||
|
||||
private static int reRange(int value, int high) {
|
||||
return FastMath.max(FastMath.min(value, high), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the noise at a pair of internal chunk coordinates.
|
||||
*
|
||||
* @param x The internal X coordinate (0-15).
|
||||
* @param z The internal Z coordinate (0-15).
|
||||
* @return double - The interpolated noise at the coordinates.
|
||||
*/
|
||||
@Override
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return interpGrid[reRange(((int) x) / 4, 3)][(FastMath.max(FastMath.min(((int) y), max), min) - min) / 4][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4);
|
||||
}
|
||||
|
||||
public double getNoise(int x, int y, int z) {
|
||||
return interpGrid[x / 4][(y - min) / 4][z / 4].trilerp((double) (x % 4) / 4, (double) (y % 4) / 4, (double) (z % 4) / 4);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.interpolation;
|
||||
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.Generator;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
|
||||
public class ElevationInterpolator {
|
||||
private final double[][] values = new double[18][18];
|
||||
|
||||
public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeProvider provider, int smooth) {
|
||||
int xOrigin = chunkX << 4;
|
||||
int zOrigin = chunkZ << 4;
|
||||
|
||||
Generator[][] gens = new Generator[18 + 2 * smooth][18 + 2 * smooth];
|
||||
|
||||
// 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] = provider.getBiome(xOrigin + x, zOrigin + z).getGenerator(world);
|
||||
}
|
||||
}
|
||||
|
||||
for(int x = -1; x <= 16; x++) {
|
||||
for(int z = -1; z <= 16; z++) {
|
||||
double noise = 0;
|
||||
double div = 0;
|
||||
for(int xi = -smooth; xi <= smooth; xi++) {
|
||||
for(int zi = -smooth; zi <= smooth; zi++) {
|
||||
Generator gen = gens[x + 1 + smooth + xi][z + 1 + smooth + zi];
|
||||
noise += gen.getElevationSampler().getNoise(xOrigin + x, zOrigin + z) * gen.getElevationWeight();
|
||||
div += gen.getElevationWeight();
|
||||
}
|
||||
}
|
||||
values[x + 1][z + 1] = noise / div;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double getElevation(int x, int z) {
|
||||
return values[x + 1][z + 1];
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.interpolation;
|
||||
|
||||
/**
|
||||
* Class for bilinear interpolation of values arranged on a unit square.
|
||||
*/
|
||||
public class Interpolator {
|
||||
private final double v0, v1, v2, v3;
|
||||
|
||||
/**
|
||||
* Constructs an interpolator with given values as vertices of a unit square.
|
||||
*
|
||||
* @param v0 - (0,0)
|
||||
* @param v1 - (1,0)
|
||||
* @param v2 - (0,1)
|
||||
* @param v3 - (1,1)
|
||||
*/
|
||||
public Interpolator(double v0, double v1, double v2, double v3) {
|
||||
this.v0 = v0;
|
||||
this.v1 = v1;
|
||||
this.v2 = v2;
|
||||
this.v3 = v3;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1D Linear interpolation between 2 points 1 unit apart.
|
||||
*
|
||||
* @param t - Distance from v0. Total distance between v0 and v1 is 1 unit.
|
||||
* @param v0 - Value at v0.
|
||||
* @param v1 - Value at v1.
|
||||
* @return double - The interpolated value.
|
||||
*/
|
||||
public static double lerp(double t, double v0, double v1) {
|
||||
return v0 + t * (v1 - v0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 2D Bilinear interpolation between 4 points on a unit square.
|
||||
*
|
||||
* @param s - X value
|
||||
* @param t - Z value
|
||||
* @return double - The interpolated value.
|
||||
*/
|
||||
public double bilerp(double s, double t) {
|
||||
double v01 = lerp(s, v0, v1);
|
||||
double v23 = lerp(s, v2, v3);
|
||||
return lerp(t, v01, v23);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.interpolation;
|
||||
|
||||
/**
|
||||
* Class for bilinear interpolation of values arranged on a unit square.
|
||||
*/
|
||||
public class Interpolator3 {
|
||||
private final Interpolator bottom;
|
||||
private final Interpolator top;
|
||||
|
||||
/**
|
||||
* Constructs an interpolator with given values as vertices of a unit cube.
|
||||
* * @param _000 The value at <code>(t, u, v) = (0, 0, 0)</code>.
|
||||
* * @param _100 The value at <code>(t, u, v) = (1, 0, 0)</code>.
|
||||
* * @param _010 The value at <code>(t, u, v) = (0, 1, 0)</code>.
|
||||
* * @param _110 The value at <code>(t, u, v) = (1, 1, 0)</code>.
|
||||
* * @param _001 The value at <code>(t, u, v) = (0, 0, 1)</code>.
|
||||
* * @param _101 The value at <code>(t, u, v) = (1, 0, 1)</code>.
|
||||
* * @param _011 The value at <code>(t, u, v) = (0, 1, 1)</code>.
|
||||
* * @param _111 The value at <code>(t, u, v) = (1, 1, 1)</code>.
|
||||
*/
|
||||
public Interpolator3(double _000, double _100,
|
||||
double _010, double _110,
|
||||
double _001, double _101,
|
||||
double _011, double _111) {
|
||||
this.top = new Interpolator(_000, _010, _001, _011);
|
||||
this.bottom = new Interpolator(_100, _110, _101, _111);
|
||||
}
|
||||
|
||||
public double trilerp(double x, double y, double z) {
|
||||
return Interpolator.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z));
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.samplers;
|
||||
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generator.Sampler;
|
||||
import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator2D;
|
||||
import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public class Sampler2D implements Sampler {
|
||||
private final ChunkInterpolator2D interpolator;
|
||||
private final ElevationInterpolator elevationInterpolator;
|
||||
|
||||
public Sampler2D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) {
|
||||
this.interpolator = new ChunkInterpolator2D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord));
|
||||
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample(double x, double y, double z) {
|
||||
return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample(int x, int y, int z) {
|
||||
return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z));
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.dfsek.terra.world.generation.math.samplers;
|
||||
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generator.Sampler;
|
||||
import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator3D;
|
||||
import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public class Sampler3D implements Sampler {
|
||||
private final ChunkInterpolator3D interpolator;
|
||||
private final ElevationInterpolator elevationInterpolator;
|
||||
|
||||
public Sampler3D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) {
|
||||
this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord));
|
||||
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample(double x, double y, double z) {
|
||||
return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample(int x, int y, int z) {
|
||||
return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user