mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-18 10:32:30 +00:00
Implement Elevation
This commit is contained in:
parent
48e45dfe23
commit
922f971c8e
@ -19,6 +19,6 @@ public final class FailoverGenerator extends UserDefinedGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FailoverGenerator() throws ParseException {
|
public FailoverGenerator() throws ParseException {
|
||||||
super("0", Collections.emptyList(), palette, false);
|
super("0", null, Collections.emptyList(), palette, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,9 +168,12 @@ public class BiomeConfig extends TerraConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String elevation = getString("elevation-equation", null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get UserDefinedBiome instance representing this config.
|
// Get UserDefinedBiome instance representing this config.
|
||||||
this.biome = new UserDefinedBiome(vanillaBiome, dec, new UserDefinedGenerator(eq, Collections.emptyList(), palette.getPaletteMap(), getBoolean("prevent-smooth", false)), getBoolean("erodible", false), biomeID);
|
UserDefinedGenerator gen = new UserDefinedGenerator(eq, elevation, Collections.emptyList(), palette.getPaletteMap(), getBoolean("prevent-smooth", false));
|
||||||
|
this.biome = new UserDefinedBiome(vanillaBiome, dec, gen, getBoolean("erodible", false), biomeID);
|
||||||
} catch(ParseException e) {
|
} catch(ParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new ConfigException("Unable to parse noise equation!", getID());
|
throw new ConfigException("Unable to parse noise equation!", getID());
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.dfsek.terra.generation;
|
||||||
|
|
||||||
|
import com.dfsek.terra.math.NoiseFunction2;
|
||||||
|
import org.polydev.gaea.math.FastNoiseLite;
|
||||||
|
import parsii.eval.Expression;
|
||||||
|
import parsii.eval.Parser;
|
||||||
|
import parsii.eval.Scope;
|
||||||
|
import parsii.eval.Variable;
|
||||||
|
import parsii.tokenizer.ParseException;
|
||||||
|
|
||||||
|
public class ElevationEquation {
|
||||||
|
private static final Object noiseLock = new Object();
|
||||||
|
private final Expression delegate;
|
||||||
|
private final Scope s = new Scope();
|
||||||
|
private final NoiseFunction2 n2 = new NoiseFunction2();
|
||||||
|
|
||||||
|
private final Variable xVar = s.getVariable("x");
|
||||||
|
private final Variable zVar = s.getVariable("z");
|
||||||
|
|
||||||
|
public ElevationEquation(String equation) throws ParseException {
|
||||||
|
Parser p = new Parser();
|
||||||
|
p.registerFunction("noise2", n2);
|
||||||
|
delegate = p.parse(equation, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getNoise(double x, double z, FastNoiseLite noiseLite) {
|
||||||
|
synchronized(noiseLock) {
|
||||||
|
xVar.setValue(x);
|
||||||
|
zVar.setValue(z);
|
||||||
|
|
||||||
|
n2.setNoise(noiseLite);
|
||||||
|
return delegate.evaluate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.dfsek.terra.generation;
|
||||||
|
|
||||||
|
import com.dfsek.terra.biome.TerraBiomeGrid;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.polydev.gaea.biome.Generator;
|
||||||
|
import org.polydev.gaea.generation.GenerationPhase;
|
||||||
|
import org.polydev.gaea.math.FastNoiseLite;
|
||||||
|
import org.polydev.gaea.math.Interpolator;
|
||||||
|
|
||||||
|
public class ElevationInterpolator {
|
||||||
|
private final UserDefinedGenerator[][] gens = new UserDefinedGenerator[7][7];
|
||||||
|
private final double[][] values = new double[16][16];
|
||||||
|
private final FastNoiseLite noise;
|
||||||
|
private final int xOrigin;
|
||||||
|
private final int zOrigin;
|
||||||
|
|
||||||
|
public ElevationInterpolator(World w, int chunkX, int chunkZ, TerraBiomeGrid grid, FastNoiseLite noise) {
|
||||||
|
this.xOrigin = chunkX << 4;
|
||||||
|
this.zOrigin = chunkZ << 4;
|
||||||
|
this.noise = noise;
|
||||||
|
|
||||||
|
for(int x = -1; x < 6; x++) {
|
||||||
|
for(int z = -1; z < 6; z++) {
|
||||||
|
gens[x + 1][z + 1] = (UserDefinedGenerator) grid.getBiome(xOrigin + x * 4, zOrigin + z * 4, GenerationPhase.BASE).getGenerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(byte x = 0; x < 16; x++) {
|
||||||
|
for(byte z = 0; z < 16; z++) {
|
||||||
|
if(compareGens((x / 4) + 1, (z / 4) + 1)) {
|
||||||
|
Interpolator interpolator = new Interpolator(biomeAvg(x / 4, z / 4),
|
||||||
|
biomeAvg((x / 4) + 1, z / 4),
|
||||||
|
biomeAvg(x / 4, (z / 4) + 1),
|
||||||
|
biomeAvg((x / 4) + 1, (z / 4) + 1),
|
||||||
|
Interpolator.Type.LINEAR);
|
||||||
|
values[x][z] = interpolator.bilerp((double) (x % 4) / 4, (double) (z % 4) / 4);
|
||||||
|
} else values[x][z] = elevate(gens[x / 4][z / 4], xOrigin + x, zOrigin + z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean compareGens(int x, int z) {
|
||||||
|
Generator comp = gens[x][z];
|
||||||
|
if(!comp.equals(gens[x + 1][z])) return true;
|
||||||
|
|
||||||
|
if(!comp.equals(gens[x][z + 1])) return true;
|
||||||
|
|
||||||
|
if(!comp.equals(gens[x - 1][z])) return true;
|
||||||
|
|
||||||
|
if(!comp.equals(gens[x][z - 1])) return true;
|
||||||
|
|
||||||
|
if(!comp.equals(gens[x + 1][z + 1])) return true;
|
||||||
|
|
||||||
|
if(!comp.equals(gens[x - 1][z - 1])) return true;
|
||||||
|
|
||||||
|
if(!comp.equals(gens[x + 1][z - 1])) return true;
|
||||||
|
|
||||||
|
return !comp.equals(gens[x - 1][z + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double biomeAvg(int x, int z) {
|
||||||
|
return (elevate(gens[x + 2][z + 1], x * 4 + 4 + xOrigin, z * 4 + zOrigin)
|
||||||
|
+ elevate(gens[x][z + 1], x * 4 - 4 + xOrigin, z * 4 + zOrigin)
|
||||||
|
+ elevate(gens[x + 1][z + 2], x * 4 + xOrigin, z * 4 + 4 + zOrigin)
|
||||||
|
+ elevate(gens[x + 1][z], x * 4 + xOrigin, z * 4 - 4 + zOrigin)
|
||||||
|
+ elevate(gens[x + 1][z + 1], x * 4 + xOrigin, z * 4 + zOrigin)) / 5D;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double elevate(UserDefinedGenerator g, int x, int z) {
|
||||||
|
if(g.getElevationEquation() != null) return g.getElevationEquation().getNoise(x, z, noise);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getElevation(int x, int z) {
|
||||||
|
return values[x][z];
|
||||||
|
}
|
||||||
|
}
|
@ -80,19 +80,19 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
|||||||
popMan.attachProfiler(p);
|
popMan.attachProfiler(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Palette<BlockData> getPalette(int x, int y, int z, BiomeConfig c, ChunkInterpolator interpolator) {
|
private static Palette<BlockData> getPalette(int x, int y, int z, BiomeConfig c, ChunkInterpolator interpolator, int elevate) {
|
||||||
Palette<BlockData> slant = c.getSlant();
|
Palette<BlockData> slant = c.getSlant();
|
||||||
if(slant != null) {
|
if(slant != null) {
|
||||||
double xzOffset = c.getXZSlantOffset();
|
double xzOffset = c.getXZSlantOffset();
|
||||||
boolean north = interpolator.getNoise(x, y, z + xzOffset) > 0;
|
boolean north = interpolator.getNoise(x, y + elevate, z + xzOffset) > 0;
|
||||||
boolean south = interpolator.getNoise(x, y, z - xzOffset) > 0;
|
boolean south = interpolator.getNoise(x, y + elevate, z - xzOffset) > 0;
|
||||||
boolean east = interpolator.getNoise(x + xzOffset, y, z) > 0;
|
boolean east = interpolator.getNoise(x + xzOffset, y + elevate, z) > 0;
|
||||||
boolean west = interpolator.getNoise(x - xzOffset, y, z) > 0;
|
boolean west = interpolator.getNoise(x - xzOffset, y + elevate, z) > 0;
|
||||||
|
|
||||||
double ySlantOffsetTop = c.getYSlantOffsetTop();
|
double ySlantOffsetTop = c.getYSlantOffsetTop();
|
||||||
double ySlantOffsetBottom = c.getYSlantOffsetBottom();
|
double ySlantOffsetBottom = c.getYSlantOffsetBottom();
|
||||||
boolean top = interpolator.getNoise(x, y + ySlantOffsetTop, z) > 0;
|
boolean top = interpolator.getNoise(x, y + ySlantOffsetTop + elevate, z) > 0;
|
||||||
boolean bottom = interpolator.getNoise(x, y - ySlantOffsetBottom, z) > 0;
|
boolean bottom = interpolator.getNoise(x, y - ySlantOffsetBottom + elevate, z) > 0;
|
||||||
|
|
||||||
if((top && bottom) && (north || south || east || west) && (!(north && south && east && west))) return slant;
|
if((top && bottom) && (north || south || east || west) && (!(north && south && east && west))) return slant;
|
||||||
}
|
}
|
||||||
@ -141,19 +141,27 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
|||||||
int xOrig = (chunkX << 4);
|
int xOrig = (chunkX << 4);
|
||||||
int zOrig = (chunkZ << 4);
|
int zOrig = (chunkZ << 4);
|
||||||
org.polydev.gaea.biome.BiomeGrid grid = getBiomeGrid(world);
|
org.polydev.gaea.biome.BiomeGrid grid = getBiomeGrid(world);
|
||||||
|
|
||||||
|
ElevationInterpolator elevationInterpolator = new ElevationInterpolator(world, chunkX, chunkZ, tw.getGrid(), getNoiseGenerator());
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
Biome b = grid.getBiome(xOrig + x, zOrig + z, GenerationPhase.PALETTE_APPLY);
|
Biome b = grid.getBiome(xOrig + x, zOrig + z, GenerationPhase.PALETTE_APPLY);
|
||||||
BiomeConfig c = config.getBiome((UserDefinedBiome) b);
|
BiomeConfig c = config.getBiome((UserDefinedBiome) b);
|
||||||
|
|
||||||
|
int elevate = (int) elevationInterpolator.getElevation(x, z);
|
||||||
|
|
||||||
BiomeSlabConfig slab = c.getSlabs();
|
BiomeSlabConfig slab = c.getSlabs();
|
||||||
int sea = c.getOcean().getSeaLevel();
|
int sea = c.getOcean().getSeaLevel();
|
||||||
Palette<BlockData> seaPalette = c.getOcean().getOcean();
|
Palette<BlockData> seaPalette = c.getOcean().getOcean();
|
||||||
for(int y = world.getMaxHeight() - 1; y >= 0; y--) {
|
for(int y = world.getMaxHeight() - 1; y >= 0; y--) {
|
||||||
if(interpolator.getNoise(x, y, z) > 0) {
|
if(interpolator.getNoise(x, y - elevate, z) > 0) {
|
||||||
BlockData data = getPalette(x, y, z, c, interpolator).get(paletteLevel, cx, cz);
|
BlockData data = getPalette(x, y, z, c, interpolator, elevate).get(paletteLevel, cx, cz);
|
||||||
chunk.setBlock(x, y, z, data);
|
chunk.setBlock(x, y, z, data);
|
||||||
if(paletteLevel == 0 && slab != null && y < 255) {
|
if(paletteLevel == 0 && slab != null && y < 255) {
|
||||||
prepareBlockPart(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector(x, y + 1, z), slab.getSlabs(),
|
prepareBlockPart(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector(x, y + 1, z), slab.getSlabs(),
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.dfsek.terra.generation;
|
package com.dfsek.terra.generation;
|
||||||
|
|
||||||
|
import com.dfsek.terra.Debug;
|
||||||
import com.dfsek.terra.math.NoiseFunction2;
|
import com.dfsek.terra.math.NoiseFunction2;
|
||||||
import com.dfsek.terra.math.NoiseFunction3;
|
import com.dfsek.terra.math.NoiseFunction3;
|
||||||
import com.dfsek.terra.util.DataUtil;
|
import com.dfsek.terra.util.DataUtil;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.polydev.gaea.biome.Generator;
|
import org.polydev.gaea.biome.Generator;
|
||||||
import org.polydev.gaea.math.FastNoiseLite;
|
import org.polydev.gaea.math.FastNoiseLite;
|
||||||
import org.polydev.gaea.math.Interpolator;
|
import org.polydev.gaea.math.Interpolator;
|
||||||
@ -30,10 +32,11 @@ public class UserDefinedGenerator extends Generator {
|
|||||||
private final Palette<BlockData>[] palettes = new Palette[256];
|
private final Palette<BlockData>[] palettes = new Palette[256];
|
||||||
private final NoiseFunction2 n2 = new NoiseFunction2();
|
private final NoiseFunction2 n2 = new NoiseFunction2();
|
||||||
private final NoiseFunction3 n3 = new NoiseFunction3();
|
private final NoiseFunction3 n3 = new NoiseFunction3();
|
||||||
|
private final ElevationEquation elevationEquation;
|
||||||
private final boolean preventSmooth;
|
private final boolean preventSmooth;
|
||||||
|
|
||||||
|
|
||||||
public UserDefinedGenerator(String equation, List<Variable> userVariables, Map<Integer, Palette<BlockData>> paletteMap, boolean preventSmooth)
|
public UserDefinedGenerator(String equation, @Nullable String elevateEquation, List<Variable> userVariables, Map<Integer, Palette<BlockData>> paletteMap, boolean preventSmooth)
|
||||||
throws ParseException {
|
throws ParseException {
|
||||||
Parser p = new Parser();
|
Parser p = new Parser();
|
||||||
p.registerFunction("noise2", n2);
|
p.registerFunction("noise2", n2);
|
||||||
@ -48,6 +51,10 @@ public class UserDefinedGenerator extends Generator {
|
|||||||
}
|
}
|
||||||
palettes[y] = d;
|
palettes[y] = d;
|
||||||
}
|
}
|
||||||
|
if(elevateEquation != null) {
|
||||||
|
Debug.info("Using elevation equation");
|
||||||
|
this.elevationEquation = new ElevationEquation(elevateEquation);
|
||||||
|
} else this.elevationEquation = null;
|
||||||
this.noiseExp = p.parse(equation, s);
|
this.noiseExp = p.parse(equation, s);
|
||||||
this.preventSmooth = preventSmooth;
|
this.preventSmooth = preventSmooth;
|
||||||
}
|
}
|
||||||
@ -112,4 +119,8 @@ public class UserDefinedGenerator extends Generator {
|
|||||||
public Interpolator.Type getInterpolationType() {
|
public Interpolator.Type getInterpolationType() {
|
||||||
return Interpolator.Type.LINEAR;
|
return Interpolator.Type.LINEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ElevationEquation getElevationEquation() {
|
||||||
|
return elevationEquation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
noise-equation: "((-((y / 64)^2)) + 1) + min(floor(((|noise2(x/2.5, z/2.5)|) + 0.1)*4), 3)/2.5 + |noise2(x/2.5, z/2.5)|"
|
noise-equation: "((-((y / 64)^2)) + 1) + |noise2(x/2.5, z/2.5)|"
|
||||||
|
elevation-equation: "min(floor(((|noise2(x/2.5, z/2.5)|) + 0.1)*4)*5, 15)"
|
||||||
|
|
||||||
id: "ARID_MOUNTAINS"
|
id: "ARID_MOUNTAINS"
|
||||||
extends: "BASIC_ORES"
|
extends: "BASIC_ORES"
|
||||||
|
17
src/test/java/NoiseInstancePerformanceTest.java
Normal file
17
src/test/java/NoiseInstancePerformanceTest.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.polydev.gaea.math.FastNoiseLite;
|
||||||
|
|
||||||
|
public class NoiseInstancePerformanceTest {
|
||||||
|
@Test
|
||||||
|
public void performance() {
|
||||||
|
FastNoiseLite noiseLite = new FastNoiseLite(2403);
|
||||||
|
long l = System.nanoTime();
|
||||||
|
for(int i = 0; i < 10000000; i++) noiseLite.getNoise(i, i);
|
||||||
|
System.out.println("No instantiation: " + (System.nanoTime() - l) / 1000000 + "ms");
|
||||||
|
for(int i = 0; i < 10000000; i++) {
|
||||||
|
FastNoiseLite noiseLite1 = new FastNoiseLite(2403);
|
||||||
|
noiseLite1.getNoise(i, i);
|
||||||
|
}
|
||||||
|
System.out.println("Instantiation: " + (System.nanoTime() - l) / 1000000 + "ms");
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user