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