From 78ab4b8598c00a37881cc827680fa1483392ca0f Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 7 Oct 2021 17:20:39 +0200 Subject: [PATCH] Changed configs --- .../lod/builders/lodBuilding/LodBuilder.java | 80 ++-- .../java/com/seibel/lod/config/LodConfig.java | 432 ++++++++---------- .../seibel/lod/enums/BufferRebuildTimes.java | 49 ++ .../com/seibel/lod/enums/VerticalQuality.java | 54 ++- .../lod/handlers/LodDimensionFileHandler.java | 11 +- .../com/seibel/lod/objects/LodDimension.java | 2 +- .../com/seibel/lod/objects/LodRegion.java | 16 +- .../com/seibel/lod/render/LodRenderer.java | 6 +- .../seibel/lod/util/DetailDistanceUtil.java | 20 +- 9 files changed, 341 insertions(+), 329 deletions(-) create mode 100644 src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java diff --git a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java index 5502462a4..e6d9b1e59 100644 --- a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java @@ -191,7 +191,7 @@ public class LodBuilder // determine how many LODs to generate vertically - VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.lodQualityMode.get(); + VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.verticalQuality.get(); byte detailLevel = detail.detailLevel; @@ -210,43 +210,25 @@ public class LodBuilder long[] data; - switch (verticalQuality) - { - default: - case HEIGHTMAP: - long singleData; - long[] dataToMergeSingle = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - singleData = DataPointUtil.mergeSingleData(dataToMergeSingle); - lodDim.addData(detailLevel, - posX, - posZ, - 0, - singleData, - false); - break; + long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight, DetailDistanceUtil.getMaxVerticalData(detailLevel)); - case VOXEL: - long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight, DetailDistanceUtil.getMaxVerticalData(detailLevel)); - - - //lodDim.clear(detailLevel, posX, posZ); - if (data != null && data.length != 0) + + //lodDim.clear(detailLevel, posX, posZ); + if (data != null && data.length != 0) + { + for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++) { - for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++) - { - - if (!DataPointUtil.doesItExist(data[verticalIndex])) - break; - lodDim.addData(detailLevel, - posX, - posZ, - verticalIndex, - data[verticalIndex], - false); - } + + if (!DataPointUtil.doesItExist(data[verticalIndex])) + break; + lodDim.addData(detailLevel, + posX, + posZ, + verticalIndex, + data[verticalIndex], + false); } - break; } } lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); @@ -742,19 +724,19 @@ public class LodBuilder private boolean useGrassTint(Block block) { return block instanceof GrassBlock - || block instanceof BushBlock - || block instanceof IGrowable - || block instanceof AbstractPlantBlock - || block instanceof AbstractTopPlantBlock - || block instanceof TallGrassBlock; + || block instanceof BushBlock + || block instanceof IGrowable + || block instanceof AbstractPlantBlock + || block instanceof AbstractTopPlantBlock + || block instanceof TallGrassBlock; } /** determine if the given block should use the biome's foliage color */ private boolean useLeafTint(Block block) { return block instanceof LeavesBlock - || block == Blocks.VINE - || block == Blocks.SUGAR_CANE; + || block == Blocks.VINE + || block == Blocks.SUGAR_CANE; } /** determine if the given block should use the biome's water color */ @@ -783,8 +765,8 @@ public class LodBuilder // block special cases // TODO: this needs to be replaced by a config file of some sort if (blockState == Blocks.AIR.defaultBlockState() - || blockState == Blocks.CAVE_AIR.defaultBlockState() - || blockState == Blocks.BARRIER.defaultBlockState()) + || blockState == Blocks.CAVE_AIR.defaultBlockState() + || blockState == Blocks.BARRIER.defaultBlockState()) { Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z)); tmp = tmp.darker(); @@ -891,9 +873,9 @@ public class LodBuilder if (avoidSmallBlock || avoidNonFullBlock) { if (!smallBlock.containsKey(blockState.getBlock()) - || smallBlock.get(blockState.getBlock()) == null - || !notFullBlock.containsKey(blockState.getBlock()) - || notFullBlock.get(blockState.getBlock()) == null + || smallBlock.get(blockState.getBlock()) == null + || !notFullBlock.containsKey(blockState.getBlock()) + || notFullBlock.get(blockState.getBlock()) == null ) { VoxelShape voxelShape = blockState.getShape(chunk, blockPos); @@ -934,8 +916,8 @@ public class LodBuilder return blockState.getBlock() != Blocks.AIR - && blockState.getBlock() != Blocks.CAVE_AIR - && blockState.getBlock() != Blocks.BARRIER; + && blockState.getBlock() != Blocks.CAVE_AIR + && blockState.getBlock() != Blocks.BARRIER; } return false; diff --git a/src/main/java/com/seibel/lod/config/LodConfig.java b/src/main/java/com/seibel/lod/config/LodConfig.java index 0962838c0..1438fd215 100644 --- a/src/main/java/com/seibel/lod/config/LodConfig.java +++ b/src/main/java/com/seibel/lod/config/LodConfig.java @@ -15,28 +15,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.seibel.lod.config; import java.nio.file.Path; import java.nio.file.Paths; +import com.seibel.lod.enums.*; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.electronwill.nightconfig.core.io.WritingMode; import com.seibel.lod.ModInfo; -import com.seibel.lod.enums.DebugMode; -import com.seibel.lod.enums.DetailDropOff; -import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.enums.FogDistance; -import com.seibel.lod.enums.FogDrawOverride; -import com.seibel.lod.enums.GenerationPriority; -import com.seibel.lod.enums.HorizontalQuality; -import com.seibel.lod.enums.HorizontalResolution; -import com.seibel.lod.enums.HorizontalScale; -import com.seibel.lod.enums.LodTemplate; -import com.seibel.lod.enums.VerticalQuality; import com.seibel.lod.render.LodRenderer.FovTest; import net.minecraftforge.common.ForgeConfigSpec; @@ -81,8 +72,6 @@ public class LodConfig public static class Graphics { - public ForgeConfigSpec.BooleanValue drawLods; - public ForgeConfigSpec.EnumValue fogDistance; public ForgeConfigSpec.EnumValue fogDrawOverride; @@ -90,9 +79,6 @@ public class LodConfig public ForgeConfigSpec.EnumValue drawResolution; -// public ForgeConfigSpec.EnumValue shadingMode; - - public ForgeConfigSpec.EnumValue detailDropOff; public ForgeConfigSpec.IntValue lodChunkRenderDistance; @@ -101,6 +87,8 @@ public class LodConfig public ForgeConfigSpec.BooleanValue alwaysDrawAtMaxQuality; + public ForgeConfigSpec.BooleanValue drawLods; + public ForgeConfigSpec.EnumValue useFovSetting; @@ -109,80 +97,80 @@ public class LodConfig builder.comment("These settings control how the LODs look.").push(this.getClass().getSimpleName()); drawLods = builder - .comment("\n\n" - + " If true, the mod is enabled and LODs will be drawn. \n" - + " If false, the mod will still generate LODs, \n" - + " but they won't be rendered. \n") - .define("drawLODs", true); + .comment("\n\n" + + " If true, the mod is enabled and LODs will be drawn. \n" + + " If false, the mod will still generate LODs, \n" + + " but they won't be rendered. \n") + .define("drawLODs", true); fogDistance = builder - .comment("\n\n" - + " At what distance should Fog be drawn on the LODs? \n" - + " If the fog cuts off ubruptly or you are using Optifine's \"fast\" fog option \n" - + " set this to " + FogDistance.NEAR + " or " + FogDistance.FAR + ". \n") - .defineEnum("fogDistance", FogDistance.NEAR_AND_FAR); + .comment("\n\n" + + " At what distance should Fog be drawn on the LODs? \n" + + " If the fog cuts off ubruptly or you are using Optifine's \"fast\" fog option \n" + + " set this to " + FogDistance.NEAR + " or " + FogDistance.FAR + ". \n") + .defineEnum("fogDistance", FogDistance.NEAR_AND_FAR); fogDrawOverride = builder - .comment("\n\n" - + " When should fog be drawn? \n" - + " " + FogDrawOverride.USE_OPTIFINE_FOG_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ". \n" - + " " + FogDrawOverride.NEVER_DRAW_FOG + ": Never draw fog on the LODs \n" - + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FAST + ": Always draw fast fog on the LODs \n" - + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n") - .defineEnum("fogDrawOverride", FogDrawOverride.ALWAYS_DRAW_FOG_FANCY); + .comment("\n\n" + + " When should fog be drawn? \n" + + " " + FogDrawOverride.USE_OPTIFINE_FOG_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ". \n" + + " " + FogDrawOverride.NEVER_DRAW_FOG + ": Never draw fog on the LODs \n" + + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FAST + ": Always draw fast fog on the LODs \n" + + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n") + .defineEnum("fogDrawOverride", FogDrawOverride.ALWAYS_DRAW_FOG_FANCY); lodTemplate = builder - .comment("\n\n" - + " How should the LODs be drawn? \n" - + " NOTE: Currently only " + LodTemplate.CUBIC + " is implemented! \n" - + " \n" - + " " + LodTemplate.CUBIC + ": LOD Chunks are drawn as rectangular prisms (boxes). \n" - + " " + LodTemplate.TRIANGULAR + ": LOD Chunks smoothly transition between other. \n" - + " " + LodTemplate.DYNAMIC + ": LOD Chunks smoothly transition between other, \n" - + " " + " unless a neighboring chunk is at a significantly different height. \n") - .defineEnum("lodTemplate", LodTemplate.CUBIC); + .comment("\n\n" + + " How should the LODs be drawn? \n" + + " NOTE: Currently only " + LodTemplate.CUBIC + " is implemented! \n" + + " \n" + + " " + LodTemplate.CUBIC + ": LOD Chunks are drawn as rectangular prisms (boxes). \n" + + " " + LodTemplate.TRIANGULAR + ": LOD Chunks smoothly transition between other. \n" + + " " + LodTemplate.DYNAMIC + ": LOD Chunks smoothly transition between other, \n" + + " " + " unless a neighboring chunk is at a significantly different height. \n") + .defineEnum("lodTemplate", LodTemplate.CUBIC); detailDropOff = builder - .comment("\n\n" - + " How smooth should the detail transition for LODs be? \n" - + DetailDropOff.FANCY + ": quality is determined per-block (best quality option, may cause stuttering when moving)\n" - + DetailDropOff.FAST + ": quality is determined per-region (performance option)\n") - .defineEnum("detailDropOff", DetailDropOff.FANCY); + .comment("\n\n" + + " How smooth should the detail transition for LODs be? \n" + + DetailDropOff.FANCY + ": quality is determined per-block (best quality option, may cause stuttering when moving)\n" + + DetailDropOff.FAST + ": quality is determined per-region (performance option)\n") + .defineEnum("detailDropOff", DetailDropOff.FANCY); drawResolution = builder - .comment("\n\n" - + " What is the maximum detail LODs should be drawn at? \n" - + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" - + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" - + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" - + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" - + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") - .defineEnum("Draw resolution", HorizontalResolution.BLOCK); + .comment("\n\n" + + " What is the maximum detail LODs should be drawn at? \n" + + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" + + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" + + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" + + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" + + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") + .defineEnum("Draw resolution", HorizontalResolution.BLOCK); lodChunkRenderDistance = builder - .comment("\n\n" - + " The mod's render distance, measured in chunks. \n") - .defineInRange("lodChunkRenderDistance", 64, 32, 1024); + .comment("\n\n" + + " The mod's render distance, measured in chunks. \n") + .defineInRange("lodChunkRenderDistance", 64, 32, 1024); useFovSetting = builder - .comment("\n\n" - + " Experimental text value. \n" - + " " + FovTest.BOTH + ": is the normal value \n") - .defineEnum("useFovSetting", FovTest.BOTH); + .comment("\n\n" + + " Experimental text value. \n" + + " " + FovTest.BOTH + ": is the normal value \n") + .defineEnum("useFovSetting", FovTest.BOTH); disableDirectionalCulling = builder - .comment("\n\n" - + " If false LODs that are behind the player's camera \n" - + " aren't drawn, increasing performance. \n\n" - + "" - + " If true all LODs are drawn, even those behind \n" - + " the player's camera, decreasing performance. \n\n" - + "" - + " Disable this if you see LODs disapearing. \n" - + " (This may happen if you are using a camera mod) \n") - .define("disableDirectionalCulling", false); - + .comment("\n\n" + + " If false LODs that are behind the player's camera \n" + + " aren't drawn, increasing performance. \n\n" + + "" + + " If true all LODs are drawn, even those behind \n" + + " the player's camera, decreasing performance. \n\n" + + "" + + " Disable this if you see LODs disapearing. \n" + + " (This may happen if you are using a camera mod) \n") + .define("disableDirectionalCulling", false); + // shadingMode = builder // .comment("\n\n" // + " What kind of shading should the LODs have? \n" @@ -196,15 +184,15 @@ public class LodConfig // .defineEnum("lightingMode", ShadingMode.GAME_SHADING); alwaysDrawAtMaxQuality = builder - .comment("\n\n" - + " Disable LOD quality falloff, " - + " all LODs will be drawn at the highest " - + " available detail level. " - + " " - + " WARNING " - + " This could cause a Out Of Memory crash on render " - + " distances higher than 128 \n") - .define("alwaysDrawAtMaxQuality", false); + .comment("\n\n" + + " Disable LOD quality falloff, " + + " all LODs will be drawn at the highest " + + " available detail level. " + + " " + + " WARNING " + + " This could cause a Out Of Memory crash on render " + + " distances higher than 128 \n") + .define("alwaysDrawAtMaxQuality", false); builder.pop(); } @@ -212,7 +200,7 @@ public class LodConfig public static class WorldGenerator { - public ForgeConfigSpec.EnumValue lodQualityMode; + public ForgeConfigSpec.EnumValue verticalQuality; public ForgeConfigSpec.EnumValue generationResolution; public ForgeConfigSpec.EnumValue distanceGenerationMode; public ForgeConfigSpec.EnumValue generationPriority; @@ -224,118 +212,120 @@ public class LodConfig { builder.comment("These settings control how LODs outside your normal view range are generated.").push(this.getClass().getSimpleName()); - lodQualityMode = builder - .comment("\n\n" - + " Use 3d lods or 2d lods? \n" - + " " + VerticalQuality.HEIGHTMAP + ": LODs are solid from the lowest point to the highest. Creates pillars for floating islands. Faster \n" - + " " + VerticalQuality.VOXEL + ": LODs have gaps between vertical blocks. Good for floating islands and caves. Slower \n" - + " " + "(Yes we know voxels are generally cubes, but voxel sounds better than rectangular_prism) \n") - .defineEnum("lodQualityMode", VerticalQuality.HEIGHTMAP); + verticalQuality = builder + .comment("\n\n" + + " this indicate how complex the vertical data will be \n" + + " the higher value will take more memory and lower the performance \n" + + " " + VerticalQuality.LOW + ": uses at max 2 column per position. (performance option)\n" + + " " + VerticalQuality.MEDIUM + ": uses at max 4 column per position. \n" + + " " + VerticalQuality.HIGH + ": uses at max 8 column per position. \n" + + " " + "(Yes we know voxels are generally cubes, but voxel sounds better than rectangular_prism) \n") + .defineEnum("Vertical Quality", VerticalQuality.MEDIUM); generationResolution = builder - .comment("\n\n" - + " What is the maximum detail level that LODs should be generated at? \n" - + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" - + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" - + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" - + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" - + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") - .defineEnum("Generation Resolution", HorizontalResolution.BLOCK); + .comment("\n\n" + + " What is the maximum detail level that LODs should be generated at? \n" + + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" + + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" + + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" + + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" + + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") + .defineEnum("Generation Resolution", HorizontalResolution.BLOCK); horizontalScale = builder - .comment("\n\n" - + " This indicates how quickly LODs drop off in quality. \n" - + " " + HorizontalScale.LOW + ": quality drops every " + HorizontalScale.LOW.distanceUnit / 16 + " chunks. \n" - + " " + HorizontalScale.MEDIUM + ": quality drops every " + HorizontalScale.MEDIUM.distanceUnit / 16 + " chunks. \n" - + " " + HorizontalScale.HIGH + ": quality drops every " + HorizontalScale.HIGH.distanceUnit / 16 + " chunks. \n") - .defineEnum("horizontal scale", HorizontalScale.MEDIUM); + .comment("\n\n" + + " This indicates how quickly LODs drop off in quality. \n" + + " " + HorizontalScale.LOW + ": quality drops every " + HorizontalScale.LOW.distanceUnit / 16 + " chunks. \n" + + " " + HorizontalScale.MEDIUM + ": quality drops every " + HorizontalScale.MEDIUM.distanceUnit / 16 + " chunks. \n" + + " " + HorizontalScale.HIGH + ": quality drops every " + HorizontalScale.HIGH.distanceUnit / 16 + " chunks. \n") + .defineEnum("horizontal scale", HorizontalScale.MEDIUM); horizontalQuality = builder - .comment("\n\n" - + " This indicates the exponential base of the quadratic drop-off \n" - + " " + HorizontalQuality.LINEAR + ": base " + HorizontalQuality.LINEAR.quadraticBase + ". \n" - + " " + HorizontalQuality.LOW + ": base " + HorizontalQuality.LOW.quadraticBase + ". \n" - + " " + HorizontalQuality.MEDIUM + ": base " + HorizontalQuality.MEDIUM.quadraticBase + ". \n" - + " " + HorizontalQuality.HIGH + ": base " + HorizontalQuality.HIGH.quadraticBase + ". \n") - .defineEnum("horizontal quality", HorizontalQuality.MEDIUM); + .comment("\n\n" + + " This indicates the exponential base of the quadratic drop-off \n" + + " " + HorizontalQuality.LINEAR + ": base " + HorizontalQuality.LINEAR.quadraticBase + ". \n" + + " " + HorizontalQuality.LOW + ": base " + HorizontalQuality.LOW.quadraticBase + ". \n" + + " " + HorizontalQuality.MEDIUM + ": base " + HorizontalQuality.MEDIUM.quadraticBase + ". \n" + + " " + HorizontalQuality.HIGH + ": base " + HorizontalQuality.HIGH.quadraticBase + ". \n") + .defineEnum("horizontal quality", HorizontalQuality.MEDIUM); generationPriority = builder - .comment("\n\n" - + " " + GenerationPriority.FAR_FIRST + " \n" - + " LODs are generated from low to high detail\n" - + " with a small priority for far regions. \n" - + " This fills in the world fastest. \n" + .comment("\n\n" + + " " + GenerationPriority.FAR_FIRST + " \n" + + " LODs are generated from low to high detail\n" + + " with a small priority for far regions. \n" + + " This fills in the world fastest. \n" - + "\n" - + " " + GenerationPriority.NEAR_FIRST + " \n" - + " LODs are generated around the player \n" - + " in a spiral, similar to vanilla minecraft. \n") - .defineEnum("Generation priority", GenerationPriority.NEAR_FIRST); + + "\n" + + " " + GenerationPriority.NEAR_FIRST + " \n" + + " LODs are generated around the player \n" + + " in a spiral, similar to vanilla minecraft. \n") + .defineEnum("Generation priority", GenerationPriority.NEAR_FIRST); distanceGenerationMode = builder - .comment("\n\n" - + " Note: The times listed here are the amount of time it took \n" - + " one of the developer's PC to generate 1 chunk, \n" - + " and are included so you can compare the \n" - + " different generation options. Your mileage may vary. \n" - + "\n" + .comment("\n\n" + + " Note: The times listed here are the amount of time it took \n" + + " one of the developer's PC to generate 1 chunk, \n" + + " and are included so you can compare the \n" + + " different generation options. Your mileage may vary. \n" + + "\n" - + " " + DistanceGenerationMode.NONE + " \n" - + " Don't run the distance generator. \n" + + " " + DistanceGenerationMode.NONE + " \n" + + " Don't run the distance generator. \n" - + " " + DistanceGenerationMode.BIOME_ONLY + " \n" - + " Only generate the biomes and use the biome's \n" - + " grass color, water color, or snow color. \n" - + " Doesn't generate height, everything is shown at sea level. \n" - + " Multithreaded - Fastest (2-5 ms) \n" + + " " + DistanceGenerationMode.BIOME_ONLY + " \n" + + " Only generate the biomes and use the biome's \n" + + " grass color, water color, or snow color. \n" + + " Doesn't generate height, everything is shown at sea level. \n" + + " Multithreaded - Fastest (2-5 ms) \n" - + "\n" - + " " + DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT + " \n" - + " Same as BIOME_ONLY, except instead \n" - + " of always using sea level as the LOD height \n" - + " different biome types (mountain, ocean, forest, etc.) \n" - + " use predetermined heights to simulate having height data. \n" - + " Multithreaded - Fastest (2-5 ms) \n" + + "\n" + + " " + DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT + " \n" + + " Same as BIOME_ONLY, except instead \n" + + " of always using sea level as the LOD height \n" + + " different biome types (mountain, ocean, forest, etc.) \n" + + " use predetermined heights to simulate having height data. \n" + + " Multithreaded - Fastest (2-5 ms) \n" - + "\n" - + " " + DistanceGenerationMode.SURFACE + " \n" - + " Generate the world surface, \n" - + " this does NOT include caves, trees, \n" - + " or structures. \n" - + " Multithreaded - Faster (10-20 ms) \n" + + "\n" + + " " + DistanceGenerationMode.SURFACE + " \n" + + " Generate the world surface, \n" + + " this does NOT include caves, trees, \n" + + " or structures. \n" + + " Multithreaded - Faster (10-20 ms) \n" - + "\n" - + " " + DistanceGenerationMode.FEATURES + " \n" - + " Generate everything except structures. \n" - + " WARNING: This may cause world generation bugs or instability! \n" - + " Multithreaded - Fast (15-20 ms) \n" + + "\n" + + " " + DistanceGenerationMode.FEATURES + " \n" + + " Generate everything except structures. \n" + + " WARNING: This may cause world generation bugs or instability! \n" + + " Multithreaded - Fast (15-20 ms) \n" - + "\n" - + " " + DistanceGenerationMode.SERVER + " \n" - + " Ask the server to generate/load each chunk. \n" - + " This is the most compatible, but causes server/simulation lag. \n" - + " This will show player made structures, which can \n" - + " be useful if you are adding the mod to a pre-existing world. \n" - + " Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) \n") - .defineEnum("distanceGenerationMode", DistanceGenerationMode.SURFACE); + + "\n" + + " " + DistanceGenerationMode.SERVER + " \n" + + " Ask the server to generate/load each chunk. \n" + + " This is the most compatible, but causes server/simulation lag. \n" + + " This will show player made structures, which can \n" + + " be useful if you are adding the mod to a pre-existing world. \n" + + " Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) \n") + .defineEnum("distanceGenerationMode", DistanceGenerationMode.SURFACE); allowUnstableFeatureGeneration = builder - .comment("\n\n" - + " When using the " + DistanceGenerationMode.FEATURES + " generation mode \n" - + " some features may not be thread safe, which could \n" - + " cause instability and crashes. \n" - + " By default (false) those features are skipped, \n" - + " improving stability, but decreasing how many features are \n" - + " actually generated. \n" - + " (for example: some tree generation is unstable, \n" - + " so some trees may not be generated.) \n" - + " By setting this to true, all features will be generated, \n" - + " but your game will be more unstable and crashes may occur. \n" - + " \n" - + " I would love to remove this option and always generate everything, \n" - + " but I'm not sure how to do that. \n" - + " If you are a Java wizard, check out the git issue here: \n" - + " https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/35 \n") - .define("allowUnstableFeatureGeneration", false); + .comment("\n\n" + + " When using the " + DistanceGenerationMode.FEATURES + " generation mode \n" + + " some features may not be thread safe, which could \n" + + " cause instability and crashes. \n" + + " By default (false) those features are skipped, \n" + + " improving stability, but decreasing how many features are \n" + + " actually generated. \n" + + " (for example: some tree generation is unstable, \n" + + " so some trees may not be generated.) \n" + + " By setting this to true, all features will be generated, \n" + + " but your game will be more unstable and crashes may occur. \n" + + " \n" + + " I would love to remove this option and always generate everything, \n" + + " but I'm not sure how to do that. \n" + + " If you are a Java wizard, check out the git issue here: \n" + + " https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/35 \n") + .define("allowUnstableFeatureGeneration", false); builder.pop(); } @@ -351,27 +341,27 @@ public class LodConfig builder.comment("These settings control how many CPU threads the mod uses for different tasks.").push(this.getClass().getSimpleName()); numberOfWorldGenerationThreads = builder - .comment("\n\n" - + " This is how many threads are used when generating LODs outside \n" - + " the normal render distance. \n" - + " If you experience stuttering when generating distant LODs, decrease \n" - + " this number. If you want to increase LOD generation speed, \n" - + " increase this number. \n" - + " \n" - + " The maximum value is the number of logical processors on your CPU. \n" - + " Requires a restart to take effect. \n") - .defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors() / 2, 1, Runtime.getRuntime().availableProcessors()); + .comment("\n\n" + + " This is how many threads are used when generating LODs outside \n" + + " the normal render distance. \n" + + " If you experience stuttering when generating distant LODs, decrease \n" + + " this number. If you want to increase LOD generation speed, \n" + + " increase this number. \n" + + " \n" + + " The maximum value is the number of logical processors on your CPU. \n" + + " Requires a restart to take effect. \n") + .defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors() / 2, 1, Runtime.getRuntime().availableProcessors()); numberOfBufferBuilderThreads = builder - .comment("\n\n" - + " This is how many threads are used when building vertex buffers \n" - + " (The things sent to your GPU to draw the LODs). \n" - + " If you experience high CPU useage when NOT generating distant \n" - + " LODs, lower this number. \n" - + " \n" - + " The maximum value is the number of logical processors on your CPU. \n" - + " Requires a restart to take effect. \n") - .defineInRange("numberOfBufferBuilderThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors()); + .comment("\n\n" + + " This is how many threads are used when building vertex buffers \n" + + " (The things sent to your GPU to draw the LODs). \n" + + " If you experience high CPU useage when NOT generating distant \n" + + " LODs, lower this number. \n" + + " \n" + + " The maximum value is the number of logical processors on your CPU. \n" + + " Requires a restart to take effect. \n") + .defineInRange("numberOfBufferBuilderThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors()); builder.pop(); } @@ -387,17 +377,17 @@ public class LodConfig builder.comment("These settings can be used to look for bugs, or see how certain aspects of the mod work.").push(this.getClass().getSimpleName()); debugMode = builder - .comment("\n\n" - + " " + DebugMode.OFF + ": LODs will draw with their normal colors. \n" - + " " + DebugMode.SHOW_DETAIL + ": LOD colors will be based on their detail level. \n" - + " " + DebugMode.SHOW_DETAIL_WIREFRAME + ": LOD colors will be based on their detail level, drawn as a wireframe. \n") - .defineEnum("debugMode", DebugMode.OFF); + .comment("\n\n" + + " " + DebugMode.OFF + ": LODs will draw with their normal colors. \n" + + " " + DebugMode.SHOW_DETAIL + ": LOD colors will be based on their detail level. \n" + + " " + DebugMode.SHOW_DETAIL_WIREFRAME + ": LOD colors will be based on their detail level, drawn as a wireframe. \n") + .defineEnum("debugMode", DebugMode.OFF); enableDebugKeybindings = builder - .comment("\n\n" - + " If true the F4 key can be used to cycle through the different debug modes. \n" - + " and the F6 key can be used to enable and disable LOD rendering.") - .define("enableDebugKeybinding", false); + .comment("\n\n" + + " If true the F4 key can be used to cycle through the different debug modes. \n" + + " and the F6 key can be used to enable and disable LOD rendering.") + .define("enableDebugKeybinding", false); builder.pop(); } @@ -405,33 +395,17 @@ public class LodConfig public static class Buffers { - public ForgeConfigSpec.IntValue bufferRebuildPlayerMoveTimeout; - public ForgeConfigSpec.IntValue bufferRebuildChunkChangeTimeout; - public ForgeConfigSpec.IntValue bufferRebuildLodChangeTimeout; + public ForgeConfigSpec.EnumValue rebuildTimes; Buffers(ForgeConfigSpec.Builder builder) { builder.comment("These settings affect when Vertex Buffers are built.").push(this.getClass().getSimpleName()); - bufferRebuildPlayerMoveTimeout = builder - .comment("\n\n" - + " How long in milliseconds should we wait to \n" - + " rebuild the vertex buffers when the player moves \n" - + " a chunk or more? \n") - .defineInRange("bufferRebuildPlayerMoveTimeout", 2000, 1, 60000); - - bufferRebuildChunkChangeTimeout = builder - .comment("\n\n" - + " How long in milliseconds should we wait to \n" - + " rebuild the vertex buffers when the vanilla rendered \n" - + " chunks change? \n") - .defineInRange("bufferRebuildChunkChangeTimeout", 1000, 1, 60000); - - bufferRebuildLodChangeTimeout = builder - .comment("\n\n" - + " How long in milliseconds should we wait to \n" - + " rebuild the vertex buffers when the LOD regions change? \n") - .defineInRange("bufferRebuildLodChangeTimeout", 5000, 1, 60000); + rebuildTimes = builder + .comment("\n\n" + + "How frequently we rebuild the buffers?" + "\n" + + "more frequent rebuild implies more stuttering" + "\n") + .defineEnum("rebuildFrequency", BufferRebuildTimes.NORMAL); builder.pop(); } @@ -451,8 +425,8 @@ public class LodConfig CLIENT_SPEC = specPair.getRight(); CLIENT = specPair.getLeft(); CommentedFileConfig clientConfig = CommentedFileConfig.builder(CONFIG_PATH) - .writingMode(WritingMode.REPLACE) - .build(); + .writingMode(WritingMode.REPLACE) + .build(); clientConfig.load(); clientConfig.save(); CLIENT_SPEC.setConfig(clientConfig); diff --git a/src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java b/src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java new file mode 100644 index 000000000..026c6b17f --- /dev/null +++ b/src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java @@ -0,0 +1,49 @@ +/* + * This file is part of the LOD Mod, licensed under the GNU GPL v3 License. + * + * Copyright (C) 2020 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.seibel.lod.enums; + +import net.minecraftforge.common.ForgeConfigSpec; + +/** + * Near_First
+ * Far_First
+ *
+ * Determines how fast the buffers need to be regenerated + * + * @author Leonardo Amato + * @version 9-25-2021 + */ +public enum BufferRebuildTimes +{ + FREQUENT(1000, 500, 2500), + + NORMAL(2000, 1000, 5000), + + RARE(5000, 2000, 10000); + + public int playerMoveTimeout; + public int renderdChunkTimeout; + public int chunkChangeTimeout; + + BufferRebuildTimes(int playerMoveTimeout, int renderdChunkTimeout, int chunkChangeTimeout) + { + this.playerMoveTimeout = playerMoveTimeout; + this.renderdChunkTimeout = renderdChunkTimeout; + this.chunkChangeTimeout = chunkChangeTimeout; + } +} diff --git a/src/main/java/com/seibel/lod/enums/VerticalQuality.java b/src/main/java/com/seibel/lod/enums/VerticalQuality.java index 43fec9e5c..500bcf3be 100644 --- a/src/main/java/com/seibel/lod/enums/VerticalQuality.java +++ b/src/main/java/com/seibel/lod/enums/VerticalQuality.java @@ -26,9 +26,53 @@ package com.seibel.lod.enums; */ public enum VerticalQuality { - /** Lods only have height and depth data */ - HEIGHTMAP, - - /** Lods expand in three dimensions */ - VOXEL; + LOW( + new int[]{2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1} + ), + + MEDIUM( + new int[]{4, + 4, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1} + ), + + HIGH( + new int[]{ + 8, + 8, + 4, + 4, + 2, + 2, + 2, + 1, + 1, + 1, + 1} + ); + + public final int[] maxVerticalData; + + VerticalQuality(int[] maxVerticalData) + { + this.maxVerticalData = maxVerticalData; + } } \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 480145d72..04c74dcb6 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -174,16 +174,7 @@ public class LodDimensionFileHandler // add the data to our region - switch (region.getVerticalQuality()) - { - default: - case HEIGHTMAP: - region.addLevelContainer(new SingleLevelContainer(data)); - break; - case VOXEL: - region.addLevelContainer(new VerticalLevelContainer(data)); - break; - } + region.addLevelContainer(new VerticalLevelContainer(data)); } catch (IOException ioEx) { diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index c98add558..432c245bd 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -387,7 +387,7 @@ public class LodDimension { DistanceGenerationMode generationMode = LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get(); ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ)); - VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.lodQualityMode.get(); + VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.verticalQuality.get(); if (lastExpandedChunk == null) diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index e033698cc..669f3e22f 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -79,16 +79,7 @@ public class LodRegion // Initialize all the different matrices for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { - switch (verticalQuality) - { - default: - case HEIGHTMAP: - dataContainer[lod] = new SingleLevelContainer(lod); - break; - case VOXEL: - dataContainer[lod] = new VerticalLevelContainer(lod); - break; - } + dataContainer[lod] = new VerticalLevelContainer(lod); } } @@ -109,10 +100,7 @@ public class LodRegion // detailLevel changes. if (this.dataContainer[detailLevel] == null) { - if (verticalQuality == VerticalQuality.HEIGHTMAP) - this.dataContainer[detailLevel] = new SingleLevelContainer(detailLevel); - else - this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel); + this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel); } this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex); diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 60ea1e2c2..856a8bb7e 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -798,7 +798,7 @@ public class LodRenderer if (LodConfig.CLIENT.graphics.detailDropOff.get() == DetailDropOff.FANCY) { // check if the player has moved - if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.get()) + if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.rebuildTimes.get().playerMoveTimeout) { if (LevelPosUtil.getDetailLevel(previousPos) == 0 || mc.getPlayer().xChunk != LevelPosUtil.getPosX(previousPos) @@ -819,7 +819,7 @@ public class LodRenderer // check if the vanilla rendered chunks changed - if (newTime - prevVanillaChunkTime > LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.get()) + if (newTime - prevVanillaChunkTime > LodConfig.CLIENT.buffers.rebuildTimes.get().renderdChunkTimeout) { if (vanillaRenderedChunksChanged) { @@ -832,7 +832,7 @@ public class LodRenderer // check if there is any newly generated terrain to show - if (newTime - prevChunkTime > LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.get()) + if (newTime - prevChunkTime > LodConfig.CLIENT.buffers.rebuildTimes.get().chunkChangeTimeout) { if (lodDim.regenDimensionBuffers) { diff --git a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java index 9dd57a706..ff8b66a66 100644 --- a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java +++ b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java @@ -3,7 +3,6 @@ package com.seibel.lod.util; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.enums.HorizontalResolution; -import com.seibel.lod.enums.VerticalQuality; public class DetailDistanceUtil { @@ -16,20 +15,7 @@ public class DetailDistanceUtil private static int minDistance = 0; private static int maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 2; - private static int[] maxVerticalData = { - 4, - 4, - 4, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1}; - - + private static HorizontalResolution[] lodGenDetails = { HorizontalResolution.BLOCK, HorizontalResolution.TWO_BLOCKS, @@ -165,9 +151,7 @@ public class DetailDistanceUtil public static int getMaxVerticalData(int detail) { - if(LodConfig.CLIENT.worldGenerator.lodQualityMode.get() == VerticalQuality.HEIGHTMAP) - return 1; - return maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)]; + return LodConfig.CLIENT.worldGenerator.verticalQuality.get().maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)]; } }