mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-08 16:56:07 +00:00
basic noise carver implementation
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
|
||||
/**
|
||||
* Sampler implementation that returns a constant.
|
||||
*/
|
||||
public class ConstantSampler implements NoiseSampler {
|
||||
private final double constant;
|
||||
|
||||
|
||||
@@ -1351,6 +1351,8 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
|
||||
double distance0 = Double.MAX_VALUE;
|
||||
double distance1 = Double.MAX_VALUE;
|
||||
double distance2 = Double.MAX_VALUE;
|
||||
|
||||
int closestHash = 0;
|
||||
|
||||
double cellularJitter = 0.43701595 * mCellularJitterModifier;
|
||||
@@ -1382,6 +1384,11 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / mFrequency);
|
||||
center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / mFrequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
@@ -1407,6 +1414,11 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / mFrequency);
|
||||
center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / mFrequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
@@ -1432,6 +1444,11 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / mFrequency);
|
||||
center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / mFrequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
yPrimed += PRIME_Y;
|
||||
}
|
||||
@@ -1464,6 +1481,8 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
return distance0 / distance1 - 1;
|
||||
case NoiseLookup:
|
||||
return cellularNoiseLookup.getNoise(center.getX(), center.getZ());
|
||||
case Distance3Div:
|
||||
return distance0 / distance2 - 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1477,6 +1496,7 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
|
||||
double distance0 = Double.MAX_VALUE;
|
||||
double distance1 = Double.MAX_VALUE;
|
||||
double distance2 = Double.MAX_VALUE;
|
||||
int closestHash = 0;
|
||||
|
||||
double cellularJitter = 0.39614353 * mCellularJitterModifier;
|
||||
@@ -1506,13 +1526,17 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
|
||||
double newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;
|
||||
|
||||
distance1 = fastMax(fastMin(distance1, newDistance), distance0);
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / mFrequency);
|
||||
center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / mFrequency);
|
||||
center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / mFrequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
zPrimed += PRIME_Z;
|
||||
}
|
||||
@@ -1538,13 +1562,17 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
|
||||
double newDistance = fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ);
|
||||
|
||||
distance1 = fastMax(fastMin(distance1, newDistance), distance0);
|
||||
if(newDistance < distance0) {
|
||||
distance0 = newDistance;
|
||||
closestHash = hash;
|
||||
center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / mFrequency);
|
||||
center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / mFrequency);
|
||||
center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / mFrequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
zPrimed += PRIME_Z;
|
||||
}
|
||||
@@ -1578,6 +1606,11 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / mFrequency);
|
||||
center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / mFrequency);
|
||||
center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / mFrequency);
|
||||
} else if(newDistance < distance1) {
|
||||
distance2 = distance1;
|
||||
distance1 = newDistance;
|
||||
} else if(newDistance < distance2) {
|
||||
distance2 = newDistance;
|
||||
}
|
||||
zPrimed += PRIME_Z;
|
||||
}
|
||||
@@ -1614,6 +1647,8 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
return distance0 / distance1 - 1;
|
||||
case NoiseLookup:
|
||||
return cellularNoiseLookup.getNoise(center.getX(), center.getY(), center.getZ());
|
||||
case Distance3Div:
|
||||
return distance0 / distance2 - 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -2603,7 +2638,8 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
Distance2Sub,
|
||||
Distance2Mul,
|
||||
Distance2Div,
|
||||
NoiseLookup
|
||||
NoiseLookup,
|
||||
Distance3Div
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,16 +6,25 @@ import com.dfsek.terra.api.world.palette.Palette;
|
||||
|
||||
public interface Generator {
|
||||
/**
|
||||
* Gets the 3D noise at a pair of coordinates using the provided FastNoiseLite instance.
|
||||
* Gets the noise sampler instance to use for base terrain.
|
||||
*
|
||||
* @param x - The x coordinate.
|
||||
* @param y - The y coordinate.
|
||||
* @param z - The z coordinate.
|
||||
* @return double - Noise value at the specified coordinates.
|
||||
* @return NoiseSampler for terrain
|
||||
*/
|
||||
double getNoise(double x, double y, double z);
|
||||
NoiseSampler getBaseSampler();
|
||||
|
||||
double getElevation(int x, int z);
|
||||
/**
|
||||
* Gets the noise sampler to use for elevation
|
||||
*
|
||||
* @return NoiseSampler for elevation.
|
||||
*/
|
||||
NoiseSampler getElevationSampler();
|
||||
|
||||
/**
|
||||
* Gets the noise sampler to use for carving.
|
||||
*
|
||||
* @return NoiseSampler for carving.
|
||||
*/
|
||||
NoiseSampler getCarver();
|
||||
|
||||
int getBlendDistance();
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.dfsek.terra.carving;
|
||||
|
||||
import com.dfsek.terra.api.platform.world.ChunkAccess;
|
||||
import com.dfsek.terra.api.platform.world.World;
|
||||
|
||||
public interface Carver {
|
||||
void carve(int chunkX, int chunkZ, ChunkAccess chunk);
|
||||
void carve(World world, int chunkX, int chunkZ, ChunkAccess chunk);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ public class GeneratorBuilder {
|
||||
|
||||
private String elevationEquation;
|
||||
|
||||
private String carvingEquation;
|
||||
|
||||
private Scope varScope;
|
||||
|
||||
private Map<String, NoiseBuilder> noiseBuilderMap;
|
||||
@@ -51,13 +53,15 @@ public class GeneratorBuilder {
|
||||
return gens.computeIfAbsent(seed, k -> {
|
||||
NoiseSampler noise;
|
||||
NoiseSampler elevation;
|
||||
NoiseSampler carving;
|
||||
try {
|
||||
noise = new ExpressionSampler(noiseEquation, varScope, seed, noiseBuilderMap);
|
||||
elevation = elevationEquation == null ? new ConstantSampler(0) : new ExpressionSampler(elevationEquation, varScope, seed, noiseBuilderMap);
|
||||
carving = new ExpressionSampler(carvingEquation, varScope, seed, noiseBuilderMap);
|
||||
} catch(ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new WorldGenerator(palettes, slantPalettes, noise, elevation, noise2d, base, biomeNoise.build((int) seed), elevationWeight, blendDistance, blendStep, blendWeight);
|
||||
return new WorldGenerator(palettes, slantPalettes, noise, elevation, carving, noise2d, base, biomeNoise.build((int) seed), elevationWeight, blendDistance, blendStep, blendWeight);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -114,6 +118,10 @@ public class GeneratorBuilder {
|
||||
this.elevationEquation = elevationEquation;
|
||||
}
|
||||
|
||||
public void setCarvingEquation(String carvingEquation) {
|
||||
this.carvingEquation = carvingEquation;
|
||||
}
|
||||
|
||||
public Scope getVarScope() {
|
||||
return varScope;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
|
||||
GeneratorBuilder generatorBuilder = new GeneratorBuilder();
|
||||
generatorBuilder.setElevationEquation(template.getElevationEquation());
|
||||
generatorBuilder.setNoiseEquation(template.getNoiseEquation());
|
||||
generatorBuilder.setCarvingEquation(template.getCarvingEquation());
|
||||
generatorBuilder.setNoiseBuilderMap(template.getPack().getTemplate().getNoiseBuilderMap());
|
||||
generatorBuilder.setPalettes(template.getPalette());
|
||||
generatorBuilder.setSlantPalettes(template.getSlantPalette());
|
||||
|
||||
@@ -42,6 +42,11 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
@Default
|
||||
private String extend = null;
|
||||
|
||||
@Value("carving.equation")
|
||||
@Abstractable
|
||||
@Default
|
||||
private String carvingEquation = "0";
|
||||
|
||||
@Value("noise-2d.enable")
|
||||
@Default
|
||||
@Abstractable
|
||||
@@ -235,6 +240,10 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
return elevationEquation;
|
||||
}
|
||||
|
||||
public String getCarvingEquation() {
|
||||
return carvingEquation;
|
||||
}
|
||||
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
@@ -317,6 +326,12 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
|
||||
throw new ValidationException("Invalid noise equation: ", e);
|
||||
}
|
||||
|
||||
try {
|
||||
tester.parse(carvingEquation, testScope);
|
||||
} catch(ParseException e) {
|
||||
throw new ValidationException("Invalid carving equation: ", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if(elevationEquation != null) tester.parse(elevationEquation, testScope);
|
||||
} catch(ParseException e) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.generation;
|
||||
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.api.math.Range;
|
||||
import com.dfsek.terra.api.math.vector.Vector3;
|
||||
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||
import com.dfsek.terra.api.platform.block.BlockData;
|
||||
@@ -19,10 +20,12 @@ import com.dfsek.terra.api.world.palette.Palette;
|
||||
import com.dfsek.terra.biome.BiomeProvider;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.biome.palette.SinglePalette;
|
||||
import com.dfsek.terra.carving.Carver;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.templates.BiomeTemplate;
|
||||
import com.dfsek.terra.generation.math.Sampler;
|
||||
import com.dfsek.terra.generation.math.SamplerCache;
|
||||
import com.dfsek.terra.population.items.carving.NoiseCarver;
|
||||
import com.dfsek.terra.profiler.ProfileFuture;
|
||||
import com.dfsek.terra.util.PaletteUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -38,12 +41,15 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
private final MaterialData water;
|
||||
private final SinglePalette<BlockData> blank;
|
||||
|
||||
private final Carver carver;
|
||||
|
||||
private final SamplerCache cache;
|
||||
|
||||
|
||||
public MasterChunkGenerator(ConfigPack c, TerraPlugin main, SamplerCache cache) {
|
||||
this.configPack = c;
|
||||
this.main = main;
|
||||
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
|
||||
water = main.getWorldHandle().createMaterialData("minecraft:water");
|
||||
blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air"));
|
||||
this.cache = cache;
|
||||
@@ -90,54 +96,55 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
BiomeProvider grid = tw.getBiomeProvider();
|
||||
try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) {
|
||||
if(!tw.isSafe()) return chunk;
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
if(!tw.isSafe()) return chunk;
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
|
||||
Sampler sampler = cache.getChunk(world, chunkX, chunkZ);
|
||||
Sampler sampler = cache.getChunk(world, chunkX, chunkZ);
|
||||
|
||||
for(byte x = 0; x < 16; x++) {
|
||||
for(byte z = 0; z < 16; z++) {
|
||||
int paletteLevel = 0;
|
||||
for(byte x = 0; x < 16; x++) {
|
||||
for(byte z = 0; z < 16; z++) {
|
||||
int paletteLevel = 0;
|
||||
|
||||
int cx = xOrig + x;
|
||||
int cz = zOrig + z;
|
||||
int cx = xOrig + x;
|
||||
int cz = zOrig + z;
|
||||
|
||||
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z);
|
||||
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
|
||||
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z);
|
||||
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
|
||||
|
||||
int sea = c.getSeaLevel();
|
||||
Palette<BlockData> seaPalette = c.getOceanPalette();
|
||||
int sea = c.getSeaLevel();
|
||||
Palette<BlockData> seaPalette = c.getOceanPalette();
|
||||
|
||||
boolean justSet = false;
|
||||
BlockData data = null;
|
||||
for(int y = world.getMaxHeight() - 1; y >= 0; y--) {
|
||||
if(sampler.sample(x, y, z) > 0) {
|
||||
justSet = true;
|
||||
data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, y, cz);
|
||||
chunk.setBlock(x, y, z, data);
|
||||
if(paletteLevel == 0 && c.doSlabs() && y < 255) {
|
||||
prepareBlockPartFloor(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector3(x, y + 1, z), c.getSlabPalettes(),
|
||||
c.getStairPalettes(), c.getSlabThreshold(), sampler);
|
||||
}
|
||||
paletteLevel++;
|
||||
} else if(y <= sea) {
|
||||
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig));
|
||||
if(justSet && c.doSlabs()) {
|
||||
prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler);
|
||||
}
|
||||
justSet = false;
|
||||
paletteLevel = 0;
|
||||
} else {
|
||||
if(justSet && c.doSlabs()) {
|
||||
prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler);
|
||||
}
|
||||
justSet = false;
|
||||
paletteLevel = 0;
|
||||
boolean justSet = false;
|
||||
BlockData data = null;
|
||||
for(int y = world.getMaxHeight() - 1; y >= 0; y--) {
|
||||
if(sampler.sample(x, y, z) > 0) {
|
||||
justSet = true;
|
||||
data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, y, cz);
|
||||
chunk.setBlock(x, y, z, data);
|
||||
if(paletteLevel == 0 && c.doSlabs() && y < 255) {
|
||||
prepareBlockPartFloor(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector3(x, y + 1, z), c.getSlabPalettes(),
|
||||
c.getStairPalettes(), c.getSlabThreshold(), sampler);
|
||||
}
|
||||
paletteLevel++;
|
||||
} else if(y <= sea) {
|
||||
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig));
|
||||
if(justSet && c.doSlabs()) {
|
||||
prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler);
|
||||
}
|
||||
justSet = false;
|
||||
paletteLevel = 0;
|
||||
} else {
|
||||
if(justSet && c.doSlabs()) {
|
||||
prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler);
|
||||
}
|
||||
justSet = false;
|
||||
paletteLevel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
carver.carve(world, chunkX, chunkZ, chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public class WorldGenerator implements Generator {
|
||||
|
||||
private final NoiseSampler noise;
|
||||
private final NoiseSampler elevation;
|
||||
private final NoiseSampler carving;
|
||||
|
||||
private final boolean noise2d;
|
||||
private final double base;
|
||||
@@ -23,11 +24,12 @@ public class WorldGenerator implements Generator {
|
||||
private final int blendStep;
|
||||
private final double blendWeight;
|
||||
|
||||
public WorldGenerator(PaletteHolder palettes, PaletteHolder slantPalettes, NoiseSampler noise, NoiseSampler elevation, boolean noise2d, double base, NoiseSampler biomeNoise, double elevationWeight, int blendDistance, int blendStep, double blendWeight) {
|
||||
public WorldGenerator(PaletteHolder palettes, PaletteHolder slantPalettes, NoiseSampler noise, NoiseSampler elevation, NoiseSampler carving, boolean noise2d, double base, NoiseSampler biomeNoise, double elevationWeight, int blendDistance, int blendStep, double blendWeight) {
|
||||
this.palettes = palettes;
|
||||
this.slantPalettes = slantPalettes;
|
||||
this.noise = noise;
|
||||
this.elevation = elevation;
|
||||
this.carving = carving;
|
||||
|
||||
this.noise2d = noise2d;
|
||||
this.base = base;
|
||||
@@ -39,8 +41,18 @@ public class WorldGenerator implements Generator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized double getElevation(int x, int z) {
|
||||
return elevation.getNoise(x, z);
|
||||
public NoiseSampler getBaseSampler() {
|
||||
return noise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler getElevationSampler() {
|
||||
return elevation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler getCarver() {
|
||||
return carving;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,11 +65,6 @@ public class WorldGenerator implements Generator {
|
||||
return blendWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized double getNoise(double x, double y, double z) {
|
||||
return noise.getNoise(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the BlockPalette to generate the biome with.
|
||||
*
|
||||
|
||||
@@ -11,11 +11,19 @@ public class Sampler {
|
||||
private final ElevationInterpolator elevationInterpolator;
|
||||
|
||||
public Sampler(int x, int z, BiomeProvider provider, World world, int elevationSmooth) {
|
||||
this.interpolator = new BiomeChunkInterpolator(world, x, z, provider);
|
||||
this.interpolator = new BiomeChunkInterpolator(world, x, z, provider, (generator, coord) -> {
|
||||
if(generator.is2d())
|
||||
return generator.getBaseSampler().getNoise(coord.getX(), 0, coord.getZ()) + noise2dExtrude(coord.getY(), generator.get2dBase());
|
||||
else return generator.getBaseSampler().getNoise(coord);
|
||||
});
|
||||
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth);
|
||||
}
|
||||
|
||||
public double sample(double x, double y, double z) {
|
||||
return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z));
|
||||
}
|
||||
|
||||
public static double noise2dExtrude(double y, double base) {
|
||||
return ((-FastMath.pow2((y / base))) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.generation.math.interpolation;
|
||||
|
||||
import com.dfsek.terra.api.math.vector.Vector3;
|
||||
import com.dfsek.terra.api.platform.world.World;
|
||||
import com.dfsek.terra.api.util.mutable.MutableInteger;
|
||||
import com.dfsek.terra.api.world.biome.Generator;
|
||||
@@ -8,6 +9,7 @@ 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>
|
||||
@@ -15,6 +17,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class BiomeChunkInterpolator implements ChunkInterpolator {
|
||||
private final Interpolator3[][][] interpGrid = new Interpolator3[4][64][4];
|
||||
private final BiFunction<Generator, Vector3, Double> noiseGetter;
|
||||
|
||||
/**
|
||||
* Instantiates a 3D BiomeChunkInterpolator at a pair of chunk coordinates.
|
||||
@@ -23,7 +26,8 @@ public class BiomeChunkInterpolator implements ChunkInterpolator {
|
||||
* @param chunkZ Z coordinate of the chunk.
|
||||
* @param provider Biome Provider to use for biome fetching.
|
||||
*/
|
||||
public BiomeChunkInterpolator(World w, int chunkX, int chunkZ, BiomeProvider provider) {
|
||||
public BiomeChunkInterpolator(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction<Generator, Vector3, Double> noiseGetter) {
|
||||
this.noiseGetter = noiseGetter;
|
||||
int xOrigin = chunkX << 4;
|
||||
int zOrigin = chunkZ << 4;
|
||||
|
||||
@@ -66,7 +70,7 @@ public class BiomeChunkInterpolator implements ChunkInterpolator {
|
||||
}
|
||||
}
|
||||
|
||||
private static double computeNoise(Map<Generator, MutableInteger> gens, double x, double y, double z) {
|
||||
private 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()) {
|
||||
@@ -80,19 +84,14 @@ public class BiomeChunkInterpolator implements ChunkInterpolator {
|
||||
return n / div;
|
||||
}
|
||||
|
||||
private static double computeNoise(Generator generator, double x, double y, double z) {
|
||||
if(generator.is2d()) return generator.getNoise(x, 0, z) + noise2dExtrude(y, generator.get2dBase());
|
||||
else return generator.getNoise(x, y, z);
|
||||
private 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);
|
||||
}
|
||||
|
||||
private static double noise2dExtrude(double y, double base) {
|
||||
return ((-FastMath.pow2((y / base))) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the noise at a pair of internal chunk coordinates.
|
||||
*
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ElevationInterpolator {
|
||||
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.getElevation(xOrigin + x, zOrigin + z) * gen.getElevationWeight();
|
||||
noise += gen.getElevationSampler().getNoise(xOrigin + x, zOrigin + z) * gen.getElevationWeight();
|
||||
div += gen.getElevationWeight();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,35 @@
|
||||
package com.dfsek.terra.population.items.carving;
|
||||
|
||||
import com.dfsek.terra.api.math.Range;
|
||||
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||
import com.dfsek.terra.api.platform.block.BlockData;
|
||||
import com.dfsek.terra.api.platform.world.ChunkAccess;
|
||||
import com.dfsek.terra.api.platform.world.World;
|
||||
import com.dfsek.terra.carving.Carver;
|
||||
import com.dfsek.terra.generation.math.interpolation.NoiseChunkInterpolator;
|
||||
import com.dfsek.terra.generation.math.interpolation.BiomeChunkInterpolator;
|
||||
import com.dfsek.terra.generation.math.interpolation.ChunkInterpolator;
|
||||
|
||||
public class NoiseCarver implements Carver {
|
||||
private final NoiseSampler noise;
|
||||
private final Range range;
|
||||
private final BlockData data;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public NoiseCarver(NoiseSampler noise, Range range) {
|
||||
this.noise = noise;
|
||||
public NoiseCarver(Range range, BlockData data, TerraPlugin main) {
|
||||
this.range = range;
|
||||
this.data = data;
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void carve(int chunkX, int chunkZ, ChunkAccess chunk) {
|
||||
NoiseChunkInterpolator chunkInterpolator = new NoiseChunkInterpolator(chunkX, chunkZ, noise);
|
||||
|
||||
public void carve(World world, int chunkX, int chunkZ, ChunkAccess chunk) {
|
||||
ChunkInterpolator interpolator = new BiomeChunkInterpolator(world, chunkX, chunkZ, main.getWorld(world).getBiomeProvider(), (gen, coord) -> gen.getCarver().getNoise(coord));
|
||||
for(int y : range) {
|
||||
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
double n = interpolator.getNoise(x, y, z);
|
||||
if(n > 0) chunk.setBlock(x, y, z, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user