From d6c476b4a3c36bf156d77377546ac8ac60364e9c Mon Sep 17 00:00:00 2001 From: austin Date: Tue, 29 Oct 2024 14:58:06 -0400 Subject: [PATCH] true terrain regen, gen algo tweaks --- assets/Data/game/biomes.json | 37 ++++++++++++++- .../terrain/cache/ClientTerrainCache.java | 9 ++++ .../client/terrain/cells/DrawCellManager.java | 2 +- .../terrain/manager/ClientTerrainManager.java | 7 +++ .../client/ui/menu/debug/ImGuiTestGen.java | 42 +++++++++++++++++ .../game/data/biome/BiomeData.java | 12 ++--- .../biome/BiomeSurfaceGenerationParams.java | 36 +++++++++++++++ .../datacell/GriddedDataCellManager.java | 1 + .../TestGenerationChunkGenerator.java | 19 +++++--- .../generation/heightmap/HillsGen.java | 15 ++++++- .../generation/heightmap/PlainsGen.java | 3 +- .../terrain/manager/ServerTerrainManager.java | 8 ++++ .../server/terrain/models/TerrainModel.java | 45 +++++++++++++++++-- 13 files changed, 214 insertions(+), 22 deletions(-) create mode 100644 src/main/java/electrosphere/game/data/biome/BiomeSurfaceGenerationParams.java diff --git a/assets/Data/game/biomes.json b/assets/Data/game/biomes.json index fd8e83b8..b6049077 100644 --- a/assets/Data/game/biomes.json +++ b/assets/Data/game/biomes.json @@ -22,7 +22,37 @@ ] } ], - "heightGenerator": "plains" + "surfaceGenerationParams": { + "surfaceGenTag": "plains", + "heightOffset": 10 + } + }, + { + "id": "hills", + "displayName": "Hills", + "isAerial": false, + "isSurface": true, + "isSubterranean": false, + "regions": [ + { + "frequency": 1.0, + "baseFloorVoxel": 1, + "floorVariants": [ + { + "voxelId": 2, + "frequency": 1.0, + "dispersion": 1.0, + "priority": 1.0 + } + ], + "foliageDescription": [ + ] + } + ], + "surfaceGenerationParams": { + "surfaceGenTag": "hills", + "heightOffset": 10 + } }, { "id": "sky", @@ -38,7 +68,10 @@ "foliageDescription": [] } ], - "heightGenerator": "empty" + "surfaceGenerationParams": { + "surfaceGenTag": "empty", + "heightOffset": 0 + } } ], "files": [ diff --git a/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java b/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java index ec92fa29..4bb90b52 100644 --- a/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java +++ b/src/main/java/electrosphere/client/terrain/cache/ClientTerrainCache.java @@ -46,6 +46,15 @@ public class ClientTerrainCache { cacheMap.remove(currentChunk); } } + + /** + * Evicts all chunks from the cache + */ + public void evictAll(){ + this.cacheList.clear(); + this.cacheMap.clear(); + this.chunkPositionMap.clear(); + } /** diff --git a/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java b/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java index 0960b318..8b76ea40 100644 --- a/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java +++ b/src/main/java/electrosphere/client/terrain/cells/DrawCellManager.java @@ -488,7 +488,7 @@ public class DrawCellManager { requested.clear(); drawable.clear(); undrawable.clear(); - updateable.clear(); + updateable.clear(); } diff --git a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java index d8d19347..baf4d774 100644 --- a/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java +++ b/src/main/java/electrosphere/client/terrain/manager/ClientTerrainManager.java @@ -100,6 +100,13 @@ public class ClientTerrainManager { messageQueue.add(message); } } + + /** + * Evicts all cached terrain + */ + public void evictAll(){ + this.terrainCache.evictAll(); + } /** * Attaches a terrain message to the queue of messages that this manager needs to process diff --git a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiTestGen.java b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiTestGen.java index 1e0f6490..a15e476e 100644 --- a/src/main/java/electrosphere/client/ui/menu/debug/ImGuiTestGen.java +++ b/src/main/java/electrosphere/client/ui/menu/debug/ImGuiTestGen.java @@ -4,7 +4,10 @@ import electrosphere.engine.Globals; import electrosphere.renderer.ui.imgui.ImGuiWindow; import electrosphere.renderer.ui.imgui.ImGuiWindow.ImGuiWindowCallback; import electrosphere.server.datacell.GriddedDataCellManager; +import electrosphere.server.terrain.generation.TestGenerationChunkGenerator; +import electrosphere.server.terrain.models.TerrainModel; import imgui.ImGui; +import imgui.type.ImInt; /** * Menu for altering parameters of the test terrain generator @@ -26,17 +29,56 @@ public class ImGuiTestGen { */ protected static void createTestGenDebugWindow(){ testGenWindow = new ImGuiWindow("Test Terrain Generation"); + int[] macroDataScaleInput = new int[1]; + int[] seedInput = new int[1]; + ImInt biome00 = new ImInt(0); + ImInt biome10 = new ImInt(0); + ImInt biome01 = new ImInt(0); + ImInt biome11 = new ImInt(0); testGenWindow.setCallback(new ImGuiWindowCallback() { @Override public void exec() { //ui framework text ImGui.text("Test Terrain Generation"); + TerrainModel terrainModel = Globals.realmManager.first().getServerWorldData().getServerTerrainManager().getModel(); + //regenerate the test area if(ImGui.button("Regenerate")){ GriddedDataCellManager gridManager = (GriddedDataCellManager)Globals.realmManager.first().getDataCellManager(); gridManager.evictAll(); Globals.drawCellManager.evictAll(); + Globals.clientTerrainManager.evictAll(); + } + + //set macro data scale in terrain model + if(ImGui.sliderInt("Macro Data Scale", macroDataScaleInput, TestGenerationChunkGenerator.GENERATOR_REALM_SIZE / terrainModel.getBiome().length, TerrainModel.DEFAULT_MACRO_DATA_SCALE)){ + terrainModel.setMacroDataScale(macroDataScaleInput[0]); + } + + //set macro data scale in terrain model + if(ImGui.sliderInt("Seed", seedInput, 0, 100)){ + terrainModel.setSeed(seedInput[0]); + } + + //sets the (surface) biome[0][0] value + if(ImGui.inputInt("biome[0][0]", biome00)){ + terrainModel.getBiome()[0][0] = biome00.shortValue(); + } + + //sets the (surface) biome[1][0] value + if(ImGui.inputInt("biome[1][0]", biome10)){ + terrainModel.getBiome()[1][0] = biome10.shortValue(); + } + + //sets the (surface) biome[0][1] value + if(ImGui.inputInt("biome[0][1]", biome01)){ + terrainModel.getBiome()[0][1] = biome01.shortValue(); + } + + //sets the (surface) biome[1][1] value + if(ImGui.inputInt("biome[1][1]", biome11)){ + terrainModel.getBiome()[1][1] = biome11.shortValue(); } } diff --git a/src/main/java/electrosphere/game/data/biome/BiomeData.java b/src/main/java/electrosphere/game/data/biome/BiomeData.java index 75bf5da1..47fad22c 100644 --- a/src/main/java/electrosphere/game/data/biome/BiomeData.java +++ b/src/main/java/electrosphere/game/data/biome/BiomeData.java @@ -38,9 +38,9 @@ public class BiomeData { Boolean isSubterranean; /** - * Tag for the heightmap generator to source from + * The surface generation params */ - String heightGenerator; + BiomeSurfaceGenerationParams surfaceGenerationParams; @@ -93,11 +93,11 @@ public class BiomeData { } /** - * Gets the tag for the heightmap generator to source from - * @return The tag for the heightmap generator to source from + * Gets the surface generation params + * @return The surface generation params */ - public String getHeightGenerator(){ - return heightGenerator; + public BiomeSurfaceGenerationParams getSurfaceGenerationParams(){ + return surfaceGenerationParams; } } diff --git a/src/main/java/electrosphere/game/data/biome/BiomeSurfaceGenerationParams.java b/src/main/java/electrosphere/game/data/biome/BiomeSurfaceGenerationParams.java new file mode 100644 index 00000000..705e767d --- /dev/null +++ b/src/main/java/electrosphere/game/data/biome/BiomeSurfaceGenerationParams.java @@ -0,0 +1,36 @@ +package electrosphere.game.data.biome; + +/** + * Params for the surface generation algorithm + */ +public class BiomeSurfaceGenerationParams { + + /** + * The tag for the generation algorithm for generating the surface + */ + String surfaceGenTag; + + /** + * The offset from baseline for height generation with this biome + */ + Float heightOffset; + + /** + * Gets the tag for the generation algorithm for generating the surface + * @return The tag for the generation algorithm for generating the surface + */ + public String getSurfaceGenTag() { + return surfaceGenTag; + } + + /** + * Gets the offset from baseline for height generation with this biome + * @return The offset from baseline for height generation with this biome + */ + public Float getHeightOffset() { + return heightOffset; + } + + + +} diff --git a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java index eabdaf0c..93138b0f 100644 --- a/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java +++ b/src/main/java/electrosphere/server/datacell/GriddedDataCellManager.java @@ -343,6 +343,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager ClientEntityUtils.destroyEntity(entity); } } + this.serverTerrainManager.evictAll(); toCleanQueue.clear(); } diff --git a/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java b/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java index d6b90be9..00773fff 100644 --- a/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java +++ b/src/main/java/electrosphere/server/terrain/generation/TestGenerationChunkGenerator.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.Map; import electrosphere.game.data.biome.BiomeData; +import electrosphere.game.data.biome.BiomeSurfaceGenerationParams; import electrosphere.game.server.world.ServerWorldData; import electrosphere.server.terrain.generation.heightmap.EmptySkyGen; import electrosphere.server.terrain.generation.heightmap.HeightmapGenerator; @@ -22,7 +23,12 @@ public class TestGenerationChunkGenerator implements ChunkGenerator { /** * The size of the realm for testing generation */ - public static final int GENERATOR_REALM_SIZE = 10; + public static final int GENERATOR_REALM_SIZE = 32; + + /** + * The default biome index + */ + public static final int DEFAULT_BIOME_INDEX = 1; /** * The terreain model for the generator @@ -47,7 +53,6 @@ public class TestGenerationChunkGenerator implements ChunkGenerator { registerGenerator(new EmptySkyGen()); registerGenerator(new HillsGen()); registerGenerator(new PlainsGen()); - } /** @@ -130,9 +135,10 @@ public class TestGenerationChunkGenerator implements ChunkGenerator { TerrainModel terrainModel, BiomeData surfaceBiome ){ - HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceBiome.getHeightGenerator()); + BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams(); + HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag()); if(heightmapGen == null){ - throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceBiome.getHeightGenerator()); + throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag()); } double realX = this.serverWorldData.convertVoxelToRealSpace(chunkX,worldX); @@ -165,9 +171,10 @@ public class TestGenerationChunkGenerator implements ChunkGenerator { TerrainModel terrainModel, BiomeData surfaceBiome ){ - HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceBiome.getHeightGenerator()); + BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams(); + HeightmapGenerator heightmapGen = this.tagGeneratorMap.get(surfaceParams.getSurfaceGenTag()); if(heightmapGen == null){ - throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceBiome.getHeightGenerator()); + throw new Error("Undefined heightmap generator in biome! " + surfaceBiome.getId() + " " + surfaceBiome.getDisplayName() + " " + surfaceParams.getSurfaceGenTag()); } double realX = this.serverWorldData.convertVoxelToRealSpace(chunkX,worldX); diff --git a/src/main/java/electrosphere/server/terrain/generation/heightmap/HillsGen.java b/src/main/java/electrosphere/server/terrain/generation/heightmap/HillsGen.java index c16256a0..5522085f 100644 --- a/src/main/java/electrosphere/server/terrain/generation/heightmap/HillsGen.java +++ b/src/main/java/electrosphere/server/terrain/generation/heightmap/HillsGen.java @@ -12,6 +12,16 @@ public class HillsGen implements HeightmapGenerator { */ static final float HEIGHT_OFFSET = 10; + /** + * Scales the input positions + */ + static final float POSITION_SCALE = 0.005f; + + /** + * Scales the output height + */ + static final float VERTICAL_SCALE = 200.0f; + /** * The different scales of noise to sample from */ @@ -38,7 +48,9 @@ public class HillsGen implements HeightmapGenerator { * @return The height */ public float getHeight(long SEED, double x, double y){ - return gradientHeight(SEED, x, y); + double scaledX = x * POSITION_SCALE; + double scaledY = y * POSITION_SCALE; + return gradientHeight(SEED, scaledX, scaledY) * VERTICAL_SCALE + HEIGHT_OFFSET; } @@ -71,7 +83,6 @@ public class HillsGen implements HeightmapGenerator { //add to height rVal = rVal + (float)(OpenSimplex2S.noise2_ImproveX(SEED, x * GRAD_NOISE[n][0], y * GRAD_NOISE[n][0]) * GRAD_NOISE[n][1]) * influence; } - rVal = rVal + HEIGHT_OFFSET; return rVal; } diff --git a/src/main/java/electrosphere/server/terrain/generation/heightmap/PlainsGen.java b/src/main/java/electrosphere/server/terrain/generation/heightmap/PlainsGen.java index 29c902fb..fae93bad 100644 --- a/src/main/java/electrosphere/server/terrain/generation/heightmap/PlainsGen.java +++ b/src/main/java/electrosphere/server/terrain/generation/heightmap/PlainsGen.java @@ -35,7 +35,7 @@ public class PlainsGen implements HeightmapGenerator { * @return The height */ public float getHeight(long SEED, double x, double y){ - return sampleAllNoise(SEED, x, y); + return sampleAllNoise(SEED, x, y) + HEIGHT_OFFSET; } @@ -53,7 +53,6 @@ public class PlainsGen implements HeightmapGenerator { for(int n = 0; n < NOISE_SCALES.length; n++){ rVal = rVal + (float)(OpenSimplex2S.noise2_ImproveX(SEED, scaledX * NOISE_SCALES[n][0], scaledY * NOISE_SCALES[n][0]) * NOISE_SCALES[n][1]); } - rVal = rVal + HEIGHT_OFFSET; return rVal; } diff --git a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java index c9bcf770..66bb1277 100644 --- a/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java +++ b/src/main/java/electrosphere/server/terrain/manager/ServerTerrainManager.java @@ -161,6 +161,14 @@ public class ServerTerrainManager { this.model = TerrainModel.generateTestModel(); chunkGen.setModel(model); } + + /** + * Evicts all cached terrain + */ + public void evictAll(){ + this.chunkCache.clear(); + this.chunkCacheContents.clear(); + } public float[][] getTerrainAtChunk(int x, int y){ return model.getElevationForChunk(x, y); diff --git a/src/main/java/electrosphere/server/terrain/models/TerrainModel.java b/src/main/java/electrosphere/server/terrain/models/TerrainModel.java index dc7bf8ba..7c97cb86 100644 --- a/src/main/java/electrosphere/server/terrain/models/TerrainModel.java +++ b/src/main/java/electrosphere/server/terrain/models/TerrainModel.java @@ -17,7 +17,7 @@ public class TerrainModel { /** * The scale of the macro data */ - static final int MACRO_DATA_SCALE = 32; + public static final int DEFAULT_MACRO_DATA_SCALE = 32; /** @@ -66,6 +66,14 @@ public class TerrainModel { * The seed of the terrain */ long seed = 0; + + /** + * The macro data scale + *

+ * !!NOTE!!: macroDataScale * biome.length must be greater than or equal to the number of chunks that are generateable + *

+ */ + int macroDataScale = DEFAULT_MACRO_DATA_SCALE; /** * Private constructor @@ -120,6 +128,10 @@ public class TerrainModel { rVal.discreteArrayDimension = TestGenerationChunkGenerator.GENERATOR_REALM_SIZE; rVal.dynamicInterpolationRatio = 1; rVal.biome = new short[2][2]; + rVal.biome[0][0] = TestGenerationChunkGenerator.DEFAULT_BIOME_INDEX; + rVal.biome[1][0] = TestGenerationChunkGenerator.DEFAULT_BIOME_INDEX; + rVal.biome[0][1] = TestGenerationChunkGenerator.DEFAULT_BIOME_INDEX; + rVal.biome[1][1] = TestGenerationChunkGenerator.DEFAULT_BIOME_INDEX; return rVal; } @@ -130,6 +142,14 @@ public class TerrainModel { public float[][] getElevation(){ return elevation; } + + /** + * Gets the macro biome data for the terrain model + * @return The macro biome data + */ + public short[][] getBiome(){ + return biome; + } /** * Gets the interpolation random dampener @@ -497,8 +517,8 @@ public class TerrainModel { * @return The biome */ public BiomeData getSurfaceBiome(int worldX, int worldY, int worldZ){ - int macroX = worldX / MACRO_DATA_SCALE; - int macroZ = worldZ / MACRO_DATA_SCALE; + int macroX = worldX / macroDataScale; + int macroZ = worldZ / macroDataScale; int surfaceBiomeIndex = this.biome[macroX][macroZ]; BiomeData biome = Globals.gameConfigCurrent.getBiomeMap().getBiomeByIndex(surfaceBiomeIndex); return biome; @@ -511,5 +531,24 @@ public class TerrainModel { public long getSeed(){ return seed; } + + /** + * Sets the seed of the terrain model + * @param seed The seed + */ + public void setSeed(long seed){ + this.seed = seed; + } + + /** + * Sets the scale of the macro data + *

+ * !!NOTE!!: macroDataScale * biome.length must be greater than or equal to the number of chunks that are generateable + *

+ * @param scale The scale + */ + public void setMacroDataScale(int scale){ + this.macroDataScale = scale; + } }