From aa3dbe8f32311841f489efeceb5ea049da680970 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 9 Sep 2021 14:10:45 +0200 Subject: [PATCH 01/30] Fixed the allocation of long[] --- .../java/com/seibel/lod/builders/LodBufferBuilder.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index e0d0f84bf..a5be6152c 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -249,7 +249,7 @@ public class LodBufferBuilder int chunkZdist; short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length / 2 - 1); long dataPoint; - long[] adjData; + long[] adjData = new long[NUMBER_OF_DIRECTION]; for (int index = 0; index < posToRender.getNumberOfPos(); index++) { detailLevel = posToRender.getNthDetailLevel(index); @@ -273,7 +273,6 @@ public class LodBufferBuilder dataPoint = lodDim.getData(detailLevel, posX, posZ); if(DataPoint.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPoint.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH) continue; - adjData = new long[NUMBER_OF_DIRECTION]; for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++) { xAdj = posX + ADJ_DIRECTION[direction][0]; @@ -287,12 +286,16 @@ public class LodBufferBuilder && posToRender.contains(detailLevel, xAdj, zAdj)) { adjData[direction]= lodDim.getData(detailLevel, xAdj, zAdj); + }else{ + adjData[direction]= 0; } } else { if (posToRender.contains(detailLevel, xAdj, zAdj)) { adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj); + }else{ + adjData[direction]= 0; } } } From 4f0639555753c0334ddf2e35a37f3be36c05239e Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 9 Sep 2021 14:36:05 +0200 Subject: [PATCH 02/30] Fixed glass color --- src/main/java/com/seibel/lod/builders/LodBuilder.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index fc412e617..88d647e09 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -34,13 +34,7 @@ import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; import com.seibel.lod.wrappers.MinecraftWrapper; -import net.minecraft.block.AbstractPlantBlock; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.BushBlock; -import net.minecraft.block.GrassBlock; -import net.minecraft.block.IGrowable; -import net.minecraft.block.LeavesBlock; +import net.minecraft.block.*; import net.minecraft.block.material.MaterialColor; import net.minecraft.world.DimensionType; import net.minecraft.world.IWorld; @@ -381,11 +375,10 @@ public class LodBuilder { int colorInt = 0; BlockState blockState = null; - if (chunkSections[i] != null) { blockState = chunkSections[i].getBlockState(x, y, z); - colorInt = blockState.materialColor.col; + colorInt = blockState.getBlock().defaultMaterialColor().col; } if (colorInt == 0 && config.useSolidBlocksInColorGen) From e876d7bec6aa61841aa0169382d3c091915a3d44 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 9 Sep 2021 14:43:04 +0200 Subject: [PATCH 03/30] Fixed the lod not showing at screen corner bug --- src/main/java/com/seibel/lod/render/LodRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 974976102..fbc923e69 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -562,7 +562,7 @@ public class LodRenderer // it is possible to see the near clip plane, but // you have to be flying quickly in spectator mode through ungenerated // terrain, so I don't think it is much of an issue. - mc.getRenderDistance(), + 1, farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2); // add the screen space distortions From 878714dae3dc7ec116c0a9adc2de35c6b7e4f82b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 9 Sep 2021 15:51:14 +0200 Subject: [PATCH 04/30] Fixed the lod not showing at screen corner bug --- src/main/java/com/seibel/lod/render/LodRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index fbc923e69..59e5e75da 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -562,7 +562,7 @@ public class LodRenderer // it is possible to see the near clip plane, but // you have to be flying quickly in spectator mode through ungenerated // terrain, so I don't think it is much of an issue. - 1, + mc.getRenderDistance()/2, farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2); // add the screen space distortions From 21140593e26269db142749b269b12e75f175e25b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 01:05:12 +0200 Subject: [PATCH 05/30] Started convertion for vertical data --- build.gradle | 2 +- .../seibel/lod/builders/LodBufferBuilder.java | 6 +- .../com/seibel/lod/builders/LodBuilder.java | 6 +- .../lodTemplates/CubicLodTemplate.java | 24 +-- .../worldGeneration/LodWorldGenerator.java | 2 +- .../lod/handlers/LodDimensionFileHandler.java | 4 +- .../com/seibel/lod/objects/DataPoint.java | 97 ----------- .../seibel/lod/objects/LevelContainer.java | 67 +------- .../com/seibel/lod/objects/LodDimension.java | 3 +- .../com/seibel/lod/objects/LodRegion.java | 40 ++--- .../lod/objects/PosToGenerateContainer.java | 2 + .../lod/objects/PosToRenderContainer.java | 1 + .../lod/objects/SingleLevelContainer.java | 134 ++++++++++++++++ .../lod/objects/VerticalLevelContainer.java | 143 +++++++++++++++++ .../com/seibel/lod/render/LodRenderer.java | 2 +- .../com/seibel/lod/util/DataPointUtil.java | 150 ++++++++++++++++++ .../seibel/lod/util/DetailDistanceUtil.java | 17 ++ .../lod/{objects => util}/LevelPosUtil.java | 2 +- .../java/com/seibel/lod/util/LodUtil.java | 3 +- 19 files changed, 503 insertions(+), 202 deletions(-) delete mode 100644 src/main/java/com/seibel/lod/objects/DataPoint.java create mode 100644 src/main/java/com/seibel/lod/objects/SingleLevelContainer.java create mode 100644 src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java create mode 100644 src/main/java/com/seibel/lod/util/DataPointUtil.java rename src/main/java/com/seibel/lod/{objects => util}/LevelPosUtil.java (99%) diff --git a/build.gradle b/build.gradle index 860d930f6..64ad3ee48 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ compileJava { // release 8 is needed because otherwise FloatBuffer.flip() will crash // on some machines // example thread: https://github.com/eclipse/jetty.project/issues/3244 - options.compilerArgs.addAll(['--release', '8', '-Xlint:unchecked', '-Xlint:deprecation']) + options.compilerArgs.addAll(['-Xlint:unchecked', '-Xlint:deprecation']) } println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index a5be6152c..89583ff19 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -29,8 +29,8 @@ import org.lwjgl.opengl.GL11; import com.seibel.lod.builders.lodTemplates.Box; import com.seibel.lod.config.LodConfig; -import com.seibel.lod.objects.DataPoint; -import com.seibel.lod.objects.LevelPosUtil; +import com.seibel.lod.util.DataPointUtil; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.PosToRenderContainer; @@ -271,7 +271,7 @@ public class LodBufferBuilder if (lodDim.doesDataExist(detailLevel, posX, posZ)) { dataPoint = lodDim.getData(detailLevel, posX, posZ); - if(DataPoint.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPoint.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH) + if(DataPointUtil.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPointUtil.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH) continue; for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++) { diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 88d647e09..33a22d2a8 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -23,8 +23,8 @@ import java.util.concurrent.Executors; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.enums.LodDetail; -import com.seibel.lod.objects.DataPoint; -import com.seibel.lod.objects.LevelPosUtil; +import com.seibel.lod.util.DataPointUtil; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.LodWorld; @@ -200,7 +200,7 @@ public class LodBuilder posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel); posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel); boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; - data = DataPoint.createDataPoint(height, depth, ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color)); + data = DataPointUtil.createDataPoint(height, depth, ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color)); lodDim.addData(detailLevel, posX, posZ, diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 8fe0aca78..339493245 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -20,7 +20,7 @@ package com.seibel.lod.builders.lodTemplates; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.enums.ShadingMode; -import com.seibel.lod.objects.DataPoint; +import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.ColorUtil; import com.seibel.lod.util.LodUtil; @@ -53,15 +53,15 @@ public class CubicLodTemplate extends AbstractLodTemplate // add each LOD for the detail level generateBoundingBox( box, - DataPoint.getHeight(data), - DataPoint.getDepth(data), + DataPointUtil.getHeight(data), + DataPointUtil.getDepth(data), width, posX * width, 0, posZ * width, bufferCenterBlockPos); - int color = DataPoint.getColor(data); + int color = DataPointUtil.getColor(data); if (debugging != DebugMode.OFF) { color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB(); @@ -211,7 +211,7 @@ public class CubicLodTemplate extends AbstractLodTemplate }else { maxY = box.getMaxY(); - tempMaxY = DataPoint.getHeight(data); + tempMaxY = DataPointUtil.getHeight(data); if (tempMaxY < maxY) { minY = Math.max(tempMaxY, minY); @@ -220,7 +220,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); } - tempMinY = DataPoint.getDepth(data); + tempMinY = DataPointUtil.getDepth(data); minY = box.getMinY(); if (tempMinY > minY) { @@ -257,7 +257,7 @@ public class CubicLodTemplate extends AbstractLodTemplate else { maxY = box.getMaxY(); - tempMaxY = DataPoint.getHeight(data); + tempMaxY = DataPointUtil.getHeight(data); if (tempMaxY < maxY) { minY = Math.max(tempMaxY, minY); @@ -266,7 +266,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } - tempMinY = DataPoint.getDepth(data); + tempMinY = DataPointUtil.getDepth(data); minY = box.getMinY(); if (tempMinY > minY) { @@ -303,7 +303,7 @@ public class CubicLodTemplate extends AbstractLodTemplate else { maxY = box.getMaxY(); - tempMaxY = DataPoint.getHeight(data); + tempMaxY = DataPointUtil.getHeight(data); if (tempMaxY < maxY) { minY = Math.max(tempMaxY, minY); @@ -312,7 +312,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); } - tempMinY = DataPoint.getDepth(data); + tempMinY = DataPointUtil.getDepth(data); minY = box.getMinY(); if (tempMinY > minY) { @@ -349,7 +349,7 @@ public class CubicLodTemplate extends AbstractLodTemplate else { maxY = box.getMaxY(); - tempMaxY = DataPoint.getHeight(data); + tempMaxY = DataPointUtil.getHeight(data); if (tempMaxY < maxY) { minY = Math.max(tempMaxY, minY); @@ -358,7 +358,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); } - tempMinY = DataPoint.getDepth(data); + tempMinY = DataPointUtil.getDepth(data); minY = box.getMinY(); if (tempMinY > minY) { diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java index 187fe079e..7f8c991e2 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java @@ -9,7 +9,7 @@ import java.util.concurrent.atomic.AtomicInteger; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.objects.LevelPosUtil; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.PosToGenerateContainer; import com.seibel.lod.render.LodRenderer; diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 6d21d34d5..27f02c78f 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -28,7 +28,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.objects.LevelContainer; +import com.seibel.lod.objects.VerticalLevelContainer; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.RegionPos; @@ -200,7 +200,7 @@ public class LodDimensionFileHandler data = bufferedReader.readLine(); bufferedReader.close(); - region.addLevel(new LevelContainer(data)); + region.addLevel(new VerticalLevelContainer(data)); } catch (Exception e) { // the buffered reader encountered a diff --git a/src/main/java/com/seibel/lod/objects/DataPoint.java b/src/main/java/com/seibel/lod/objects/DataPoint.java deleted file mode 100644 index 397f23375..000000000 --- a/src/main/java/com/seibel/lod/objects/DataPoint.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.seibel.lod.objects; - -public class DataPoint -{ - public final static int HEIGHT_SHIFT = 54; - public final static int DEPTH_SHIFT = 44; - public final static int RED_SHIFT = 36; - public final static int GREEN_SHIFT = 28; - public final static int BLUE_SHIFT = 20; - public final static int GEN_TYPE_SHIFT = 17; - public final static int LIGHT_SHIFT = 13; - public final static int EXISTENCE_SHIFT = 0; - - public final static long HEIGHT_MASK = Long.parseUnsignedLong("1111111111", 2); - public final static long DEPTH_MASK = Long.parseUnsignedLong("1111111111", 2); - public final static long RED_MASK = Long.parseUnsignedLong("11111111", 2); - public final static long GREEN_MASK = Long.parseUnsignedLong("11111111", 2); - public final static long BLUE_MASK = Long.parseUnsignedLong("11111111", 2); - public final static long GEN_TYPE_MASK = Long.parseUnsignedLong("111", 2); - public final static long LIGHT_MASK = Long.parseUnsignedLong("1111", 2); - public final static long EXISTENCE_MASK = 1; - - public static long createDataPoint(int height, int depth, int color) - { - int red = (getRed(color) << 16) & 0x00FF0000; - int green = (getGreen(color) << 8) & 0x0000FF00; - int blue = getBlue(color)& 0x000000FF; - return createDataPoint(height, depth, red, green, blue); - } - public static long createDataPoint(int height, int depth, int red, int green, int blue) - { - long dataPoint = 0; - dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT; - dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT; - dataPoint += (red & RED_MASK) << RED_SHIFT; - dataPoint += (green & GREEN_MASK) << GREEN_SHIFT; - dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; - dataPoint += 1; - return dataPoint; - } - - public static short getHeight(long dataPoint) - { - return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK); - } - - public static short getDepth(long dataPoint) - { - - return (short) ((dataPoint >> DEPTH_SHIFT) & DEPTH_MASK); - } - - public static short getRed(long dataPoint) - { - - return (short) ((dataPoint >> RED_SHIFT) & RED_MASK); - } - - public static short getGreen(long dataPoint) - { - return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK); - } - - public static short getBlue(long dataPoint) - { - return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK); - } - - public static boolean doesItExist(long dataPoint) - { - return ((dataPoint & EXISTENCE_MASK) == 1); - } - - public static int getColor(long dataPoint) - { - int R = (getRed(dataPoint) << 16) & 0x00FF0000; - int G = (getGreen(dataPoint) << 8) & 0x0000FF00; - int B = getBlue(dataPoint)& 0x000000FF; - return 0xFF000000 | R | G | B; - } - - public static String toString(long dataPoint) - { - StringBuilder s = new StringBuilder(); - s.append(getHeight(dataPoint)); - s.append(" "); - s.append(getDepth(dataPoint)); - s.append(" "); - s.append(getRed(dataPoint)); - s.append(" "); - s.append(getBlue(dataPoint)); - s.append(" "); - s.append(getGreen(dataPoint)); - s.append('\n'); - return s.toString(); - } -} diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index ffadb459c..a5f7417ad 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -1,67 +1,16 @@ package com.seibel.lod.objects; -import java.io.Serializable; - +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; -public class LevelContainer implements Serializable +public interface LevelContainer { - - /** This is here so that Eclipse doesn't complain */ - private static final long serialVersionUID = -4930855068717998385L; - + public static final char VERTICAL_DATA_DELIMITER = ','; public static final char DATA_DELIMITER = ','; - public final byte detailLevel; - - public final long[][] data; - - public LevelContainer(byte detailLevel, long[][] data) - { - this.detailLevel = detailLevel; - this.data = data; - } - - public LevelContainer(String inputString) - { - - int index = 0; - int lastIndex = 0; - - - index = inputString.indexOf(DATA_DELIMITER, 0); - this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); - int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - - this.data = new long[size][size]; - for (int x = 0; x < size; x++) - { - for (int z = 0; z < size; z++) - { - lastIndex = index; - index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); - data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); - } - } - - } - - @Override - public String toString() - { - StringBuilder stringBuilder = new StringBuilder(); - int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - stringBuilder.append(detailLevel); - stringBuilder.append(DATA_DELIMITER); - for (int x = 0; x < size; x++) - { - for (int z = 0; z < size; z++) - { - //Converting the dataToHex - stringBuilder.append(Long.toHexString(data[x][z])); - stringBuilder.append(DATA_DELIMITER); - } - } - return stringBuilder.toString(); - } + public boolean putData(long[] data, int posX, int posZ); + public long[] getData(int posX, int posZ); + /**TODO could i use a static map from thread name to arrays to store these values?*/ + public long[] mergeData(long[][] dataArray, long[] newDataPoint, int[] indexes, long[] dataToCombine); + public String toDataString(); } diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 2343ff682..87911306b 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -26,6 +26,7 @@ import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.handlers.LodDimensionFileHandler; import com.seibel.lod.util.DetailDistanceUtil; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; import com.seibel.lod.wrappers.MinecraftWrapper; @@ -435,7 +436,7 @@ public class LodDimension * stored in the LOD. If an LOD already exists at the given * coordinates it will be overwritten. */ - public synchronized Boolean addData(byte detailLevel, int posX, int posZ, long lodDataPoint, boolean dontSave, boolean serverQuality) + public Boolean addData(byte detailLevel, int posX, int posZ, long lodDataPoint, boolean dontSave, boolean serverQuality) { // don't continue if the region can't be saved diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index c0d4fbb18..63794ce8e 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -3,7 +3,9 @@ package com.seibel.lod.objects; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.enums.DistanceGenerationMode; +import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.DetailDistanceUtil; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; /** @@ -32,17 +34,17 @@ public class LodRegion public final int regionPosX; public final int regionPosZ; - public LodRegion(LevelContainer levelContainer, RegionPos regionPos, DistanceGenerationMode generationMode) + public LodRegion(VerticalLevelContainer verticalLevelContainer, RegionPos regionPos, DistanceGenerationMode generationMode) { this.generationMode = generationMode; this.regionPosX = regionPos.x; this.regionPosZ = regionPos.z; - this.minDetailLevel = levelContainer.detailLevel; + this.minDetailLevel = verticalLevelContainer.detailLevel; //Arrays of matrices data = new long[POSSIBLE_LOD][][]; - data[minDetailLevel] = levelContainer.data; + data[minDetailLevel] = verticalLevelContainer.data; //Initialize all the different matrices for (byte lod = (byte) (minDetailLevel + 1); lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) @@ -308,16 +310,16 @@ public class LodRegion childDetailLevel = (byte) (detailLevel - 1); if (doesDataExist(childDetailLevel, childPosX, childPosZ)) { - if (!(DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT - && DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH)) + if (!(DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT + && DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH)) { numberOfChildren++; - tempRed += DataPoint.getRed(data[childDetailLevel][childPosX][childPosZ]); - tempGreen += DataPoint.getGreen(data[childDetailLevel][childPosX][childPosZ]); - tempBlue += DataPoint.getBlue(data[childDetailLevel][childPosX][childPosZ]); - tempHeight += DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]); - tempDepth += DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]); + tempRed += DataPointUtil.getRed(data[childDetailLevel][childPosX][childPosZ]); + tempGreen += DataPointUtil.getGreen(data[childDetailLevel][childPosX][childPosZ]); + tempBlue += DataPointUtil.getBlue(data[childDetailLevel][childPosX][childPosZ]); + tempHeight += DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]); + tempDepth += DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]); } else { // void children have the default height (most likely -1) @@ -342,7 +344,7 @@ public class LodRegion tempHeight = LodBuilder.DEFAULT_HEIGHT; tempDepth = LodBuilder.DEFAULT_DEPTH; } - data[detailLevel][posX][posZ] = DataPoint.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue); + data[detailLevel][posX][posZ] = DataPointUtil.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue); } @@ -354,7 +356,7 @@ public class LodRegion if(detailLevel < minDetailLevel) return false; posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return DataPoint.doesItExist(data[detailLevel][posX][posZ]); + return DataPointUtil.doesItExist(data[detailLevel][posX][posZ]); } /** @@ -376,26 +378,26 @@ public class LodRegion * @param detailLevel * @return */ - public LevelContainer getLevel(byte detailLevel) + public VerticalLevelContainer getLevel(byte detailLevel) { if (detailLevel < minDetailLevel) { throw new IllegalArgumentException("getLevel asked for a level that does not exist: minimum " + minDetailLevel + " level requested " + detailLevel); } - return new LevelContainer(detailLevel, data[detailLevel]); + return new VerticalLevelContainer(detailLevel, data[detailLevel]); } /** - * @param levelContainer + * @param verticalLevelContainer */ - public void addLevel(LevelContainer levelContainer) + public void addLevel(VerticalLevelContainer verticalLevelContainer) { - if (levelContainer.detailLevel < minDetailLevel - 1) + if (verticalLevelContainer.detailLevel < minDetailLevel - 1) { throw new IllegalArgumentException("addLevel requires a level that is at least the minimum level of the region -1 "); } - if (levelContainer.detailLevel == minDetailLevel - 1) minDetailLevel = levelContainer.detailLevel; - data[levelContainer.detailLevel] = levelContainer.data; + if (verticalLevelContainer.detailLevel == minDetailLevel - 1) minDetailLevel = verticalLevelContainer.detailLevel; + data[verticalLevelContainer.detailLevel] = verticalLevelContainer.data; } diff --git a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java index 405ee2b77..2f05f75dc 100644 --- a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java @@ -1,5 +1,7 @@ package com.seibel.lod.objects; +import com.seibel.lod.util.LevelPosUtil; + public class PosToGenerateContainer { private int playerPosX; diff --git a/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java b/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java index ef056a13d..2ec972613 100644 --- a/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java @@ -1,5 +1,6 @@ package com.seibel.lod.objects; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; public class PosToRenderContainer diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java new file mode 100644 index 000000000..589ade2b2 --- /dev/null +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -0,0 +1,134 @@ +package com.seibel.lod.objects; + +import com.seibel.lod.builders.LodBuilder; +import com.seibel.lod.util.DataPointUtil; +import com.seibel.lod.util.LevelPosUtil; +import com.seibel.lod.util.LodUtil; + +public class SingleLevelContainer implements LevelContainer +{ + public final byte detailLevel; + + public final long[][] data; + + public SingleLevelContainer(byte detailLevel, long[][] data) + { + this.detailLevel = detailLevel; + this.data = data; + } + + public boolean putData(long[] data, int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + data[posX][posZ] = data[0]; + return true; + } + + public long[] getData(int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + return data[posX][posZ]; + } + + public SingleLevelContainer(String inputString) + { + + int index = 0; + int lastIndex = 0; + + + index = inputString.indexOf(DATA_DELIMITER, 0); + this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); + int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); + + this.data = new long[size][size][1]; + for (int x = 0; x < size; x++) + { + for (int z = 0; z < size; z++) + { + lastIndex = index; + index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); + data[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); + } + } + } + + public long[] mergeData(long[][] dataArray, long[] newDataPoint, int[] indexes, long[] dataToCombine) + { + int numberOfChildren = 0; + int numberOfVoidChildren = 0; + + int tempRed = 0; + int tempGreen = 0; + int tempBlue = 0; + int tempHeight = 0; + int tempDepth = 0; + int childPosX; + int childPosZ; + byte childDetailLevel; + for (int index = 0; x <= 4; x++) + { + childDetailLevel = (byte) (detailLevel - 1); + if (doesDataExist(childDetailLevel, childPosX, childPosZ)) + { + if (!(DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT + && DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH)) + { + numberOfChildren++; + + tempRed += DataPointUtil.getRed(data[childDetailLevel][childPosX][childPosZ]); + tempGreen += DataPointUtil.getGreen(data[childDetailLevel][childPosX][childPosZ]); + tempBlue += DataPointUtil.getBlue(data[childDetailLevel][childPosX][childPosZ]); + tempHeight += DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]); + tempDepth += DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]); + } else + { + // void children have the default height (most likely -1) + // and represent a LOD with no blocks in it + numberOfVoidChildren++; + } + } + } + } + if (numberOfChildren > 0) + { + tempRed = tempRed / numberOfChildren; + tempGreen = tempGreen / numberOfChildren; + tempBlue = tempBlue / numberOfChildren; + tempHeight = tempHeight / numberOfChildren; + tempDepth = tempDepth / numberOfChildren; + } else if (numberOfVoidChildren > 0) + { + tempRed = (byte) 0; + tempGreen = (byte) 0; + tempBlue = (byte) 0; + tempHeight = LodBuilder.DEFAULT_HEIGHT; + tempDepth = LodBuilder.DEFAULT_DEPTH; + } + data[detailLevel][posX][posZ] = DataPointUtil.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue); + } + + public String toDataString() + { + return toString(); + } + + @Override + public String toString() + { + StringBuilder stringBuilder = new StringBuilder(); + int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); + stringBuilder.append(detailLevel); + stringBuilder.append(DATA_DELIMITER); + for (int x = 0; x < size; x++) + { + for (int z = 0; z < size; z++) + { + //Converting the dataToHex + stringBuilder.append(Long.toHexString(data[x][z][0])); + stringBuilder.append(DATA_DELIMITER); + } + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java new file mode 100644 index 000000000..a8da77306 --- /dev/null +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -0,0 +1,143 @@ +package com.seibel.lod.objects; + +import java.io.Serializable; + +import com.seibel.lod.util.DataPointUtil; +import com.seibel.lod.util.DetailDistanceUtil; +import com.seibel.lod.util.LevelPosUtil; +import com.seibel.lod.util.LodUtil; + +public class VerticalLevelContainer implements LevelContainer +{ + public final byte detailLevel; + + public final long[][][] data; + + public VerticalLevelContainer(byte detailLevel, long[][][] data) + { + this.detailLevel = detailLevel; + this.data = data; + } + + public boolean putData(long[] data, int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + data[posX][posZ] = data + return true; + } + + public long[] getData(int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + return data[posX][posZ]; + } + + public VerticalLevelContainer(String inputString) + { + + int index = 0; + int lastIndex = 0; + + + index = inputString.indexOf(DATA_DELIMITER, 0); + this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); + int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); + + this.data = new long[size][size][1]; + for (int x = 0; x < size; x++) + { + for (int z = 0; z < size; z++) + { + lastIndex = index; + index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); + data[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); + } + } + } + + public long[] mergeData(long[][] dataArray, long[] newDataPoint, int[] indexes, long[] dataToCombine) + { + + //int maxSize = Math.max(Math.max(Math.max(dataArray[0].length, dataArray[1].length), dataArray[2].length), dataArray[3].length); + //DetailDistanceUtil.getMaxVerticalData(detailLevel); + //we are re-using these arrays so we must reset them to 0 + int dataIndex = 0; + int i; + for (i = 0; i < newDataPoint.length; i++) + newDataPoint[i] = 0; + for (i = 0; i < 4; i++) + indexes[i] = 0; + //We continue until all the data has been read + int minDepth; + int maxHeight; + int selectedDepth; + int selectedHeight; + int startingArray; + while (indexes[0] < dataArray[0].length + && indexes[1] < dataArray[1].length + && indexes[2] < dataArray[2].length + && indexes[3] < dataArray[3].length) + { + //We select the data that at the lowest point + minDepth = Integer.MAX_VALUE; + maxHeight = Integer.MIN_VALUE; + startingArray = 0; + for (int arrayIndex = 0; arrayIndex < 4; arrayIndex++) + { + if (indexes[arrayIndex] < dataArray[arrayIndex].length) + { + if (minDepth < getDepth(dataArray[arrayIndex][indexes[arrayIndex]])) + { + minDepth = getDepth(dataArray[arrayIndex][indexes[arrayIndex]]); + startingArray = arrayIndex; + } + } + } + selectedDepth = minDepth; + //now we have selected the dataPoint that has yet to be analyzed with min depth + dataToCombine[startingArray] = dataArray[startingArray][indexes[startingArray]]; + indexes[startingArray]++; + newDataPoint[dataIndex] = minDepth; + + //now we must check if the other data can be combined with this lod + maxHeight = DataPointUtil.getHeight(dataArray[startingArray][indexes[startingArray]]); + + for (int arrayIndex = 0; arrayIndex < 4; arrayIndex++) + { + while (maxHeight >= getDepth(dataArray[arrayIndex][indexes[arrayIndex]])) + { + maxHeight = getHeight(dataArray[arrayIndex][indexes[arrayIndex]]); + dataToCombine[arrayIndex] = dataArray[arrayIndex][indexes[arrayIndex]]; + indexes[arrayIndex]++; + } + } + dataIndex++; + + } + return null; + } + + public String toDataString() + { + return toString(); + } + + @Override + public String toString() + { + StringBuilder stringBuilder = new StringBuilder(); + int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); + stringBuilder.append(detailLevel); + stringBuilder.append(DATA_DELIMITER); + for (int x = 0; x < size; x++) + { + for (int z = 0; z < size; z++) + { + //Converting the dataToHex + stringBuilder.append(Long.toHexString(data[x][z][0])); + stringBuilder.append(DATA_DELIMITER); + } + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 59e5e75da..49cab3ddf 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -38,7 +38,7 @@ import com.seibel.lod.enums.FogDistance; import com.seibel.lod.enums.FogDrawOverride; import com.seibel.lod.enums.FogQuality; import com.seibel.lod.handlers.ReflectionHandler; -import com.seibel.lod.objects.LevelPosUtil; +import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.NearFarFogSettings; import com.seibel.lod.objects.RegionPos; diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java new file mode 100644 index 000000000..554c4a835 --- /dev/null +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -0,0 +1,150 @@ +package com.seibel.lod.util; + +public class DataPointUtil +{ + + //To be used in the future for negative value + //public final static int MIN_DEPTH = -64; + //public final static int MIN_HEIGHT = -64; + + public final static int ALPHA_SHIFT = 56; + public final static int RED_SHIFT = 48; + public final static int GREEN_SHIFT = 40; + public final static int BLUE_SHIFT = 32; + public final static int COLOR_SHIFT = 32; + public final static int HEIGHT_SHIFT = 22; + public final static int DEPTH_SHIFT = 12; + public final static int LIGHT_SHIFT = 8; + public final static int GEN_TYPE_SHIFT = 2; + public final static int VOID_SHIFT = 1; + public final static int EXISTENCE_SHIFT = 0; + + public final static long ALPHA_MASK = 0b1111_1111; + public final static long RED_MASK = 0b1111_1111; + public final static long GREEN_MASK = 0b1111_1111; + public final static long BLUE_MASK = 0b1111_1111; + public final static long COLOR_MASK = 0b11111111_11111111_11111111_11111111; + public final static long HEIGHT_MASK = 0b11_1111_1111; + public final static long DEPTH_MASK = 0b11_1111_1111; + public final static long LIGHT_MASK = 0b1111; + public final static long GEN_TYPE_MASK = 0b111; + public final static long VOID_MASK = 1; + public final static long EXISTENCE_MASK = 1; + + + public static long createDataPoint(int generationMode) + { + long dataPoint = 0; + dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; + dataPoint += VOID_MASK << VOID_SHIFT; + dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT; + return dataPoint; + } + + public static long createDataPoint(int height, int depth, int color) + { + int alpha = (color >> 24) & 0xFF000000; + int red = (color >> 16) & 0x00FF0000; + int green = (color >> 8) & 0x0000FF00; + int blue = color & 0x000000FF; + return createDataPoint(height, depth, alpha, red, green, blue); + } + + public static long createDataPoint(int height, int depth, int alpha, int red, int green, int blue, int lightValue, int generationMode) + { + long dataPoint = 0; + dataPoint += (alpha & ALPHA_MASK) << ALPHA_SHIFT; + dataPoint += (red & RED_MASK) << RED_SHIFT; + dataPoint += (green & GREEN_MASK) << GREEN_SHIFT; + dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; + dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT; + dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT; + dataPoint += (depth & LIGHT_MASK) << LIGHT_SHIFT; + dataPoint += (depth & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; + dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT; + return dataPoint; + } + + public static short getHeight(long dataPoint) + { + return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK); + } + + public static short getDepth(long dataPoint) + { + + return (short) ((dataPoint >> DEPTH_SHIFT) & DEPTH_MASK); + } + + public static short getAlpha(long dataPoint) + { + return (short) ((dataPoint >> ALPHA_SHIFT) & ALPHA_MASK); + } + + public static short getRed(long dataPoint) + { + return (short) ((dataPoint >> RED_SHIFT) & RED_MASK); + } + + public static short getGreen(long dataPoint) + { + return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK); + } + + public static short getBlue(long dataPoint) + { + return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK); + } + + public static byte getLightValue(long dataPoint) + { + return (byte) ((dataPoint >> LIGHT_SHIFT) & LIGHT_MASK); + } + + public static byte getGenerationMode(long dataPoint) + { + return (byte) ((dataPoint >> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); + } + + + public static boolean isItVoid(long dataPoint) + { + return (((dataPoint >> VOID_SHIFT) & VOID_MASK) == 1); + } + + public static boolean doesItExist(long dataPoint) + { + return (((dataPoint >> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1); + } + + public static int getColor(long dataPoint) + { + int R = (getRed(dataPoint) << 16) & 0x00FF0000; + int G = (getGreen(dataPoint) << 8) & 0x0000FF00; + int B = getBlue(dataPoint) & 0x000000FF; + return 0xFF000000 | R | G | B; + } + + public static String toString(long dataPoint) + { + StringBuilder s = new StringBuilder(); + s.append(getHeight(dataPoint)); + s.append(" "); + s.append(getDepth(dataPoint)); + s.append(" "); + s.append(getRed(dataPoint)); + s.append(" "); + s.append(getBlue(dataPoint)); + s.append(" "); + s.append(getGreen(dataPoint)); + s.append('\n'); + return s.toString(); + } + + + public static long[] compress(long[] data, byte detailLevel) + { + return null; + } +} +VerticalLevelContainer \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java index 860000a17..3e631eef7 100644 --- a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java +++ b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java @@ -19,6 +19,19 @@ public class DetailDistanceUtil private static int base = 2; private static double logBase = Math.log(2); + private static int[] maxVerticalData = { + 8, + 4, + 4, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1,}; + private static LodDetail[] lodGenDetails = { LodDetail.FULL, LodDetail.HALF, @@ -176,6 +189,10 @@ public class DetailDistanceUtil } } + public static int getMaxVerticalData(int detail) + { + return maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)]; + } public static boolean regionInView(int playerPosX, int playerPosY, int playerPosZ, int xRot, int yRot, int fov, RegionPos regionPos) { diff --git a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java b/src/main/java/com/seibel/lod/util/LevelPosUtil.java similarity index 99% rename from src/main/java/com/seibel/lod/objects/LevelPosUtil.java rename to src/main/java/com/seibel/lod/util/LevelPosUtil.java index a3cf7628e..af3bc7547 100644 --- a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java +++ b/src/main/java/com/seibel/lod/util/LevelPosUtil.java @@ -1,4 +1,4 @@ -package com.seibel.lod.objects; +package com.seibel.lod.util; import com.seibel.lod.util.LodUtil; diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java index 57410a96d..fc6f02ea1 100644 --- a/src/main/java/com/seibel/lod/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/util/LodUtil.java @@ -21,7 +21,6 @@ import java.awt.Color; import java.io.File; import java.util.HashSet; -import com.seibel.lod.objects.DataPoint; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.RegionPos; import com.seibel.lod.wrappers.MinecraftWrapper; @@ -340,7 +339,7 @@ public class LodUtil long data = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z); - short lodAverageHeight = DataPoint.getHeight(data); + short lodAverageHeight = DataPointUtil.getHeight(data); if (playerPos.getY() <= lodAverageHeight) { From a9aa630aff44b1326b44e5129659e71af2f3f519 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 15:47:43 +0200 Subject: [PATCH 06/30] Started convertion for vertical data --- .../seibel/lod/objects/LevelContainer.java | 57 ++++++- .../com/seibel/lod/objects/LodRegion.java | 139 ++++++------------ .../lod/objects/SingleLevelContainer.java | 99 ++++++++++--- .../lod/objects/VerticalLevelContainer.java | 17 ++- 4 files changed, 183 insertions(+), 129 deletions(-) diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index a5f7417ad..f35de59b4 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -5,12 +5,59 @@ import com.seibel.lod.util.LodUtil; public interface LevelContainer { - public static final char VERTICAL_DATA_DELIMITER = ','; - public static final char DATA_DELIMITER = ','; + public static final char VERTICAL_DATA_DELIMITER = '\t'; + public static final char DATA_DELIMITER = '\n'; - public boolean putData(long[] data, int posX, int posZ); + /**With this you can add data to the level container + * + * @param data actual data to add in a array of long format. + * @param detailLevel just to check that it's correct + * @param posX x position in the detail level + * @param posZ z position in the detail level + * @return true if correctly added, false otherwise + */ + public boolean addData(long[] data, int posX, int posZ); + + /**With this you can get data from the level container + * + * @param detailLevel just to check that it's correct + * @param posX x position in the detail level + * @param posZ z position in the detail level + * @return the data in long array format + */ public long[] getData(int posX, int posZ); - /**TODO could i use a static map from thread name to arrays to store these values?*/ - public long[] mergeData(long[][] dataArray, long[] newDataPoint, int[] indexes, long[] dataToCombine); + + /** + * @param detailLevel just to check that it's correct + * @param posX x position in the detail level + * @param posZ z position in the detail level + * @return true only if the data exist + */ + public boolean doesItExist(int posX, int posZ); + + /** + * @return return the deatilLevel of this level container + */ + public byte getDetailLevel(); + + /**This return a level container with detail level lower than the current level. + * The new level container may use information of this level. + * @return the new level container + */ + public LevelContainer expand(); + + /** + * + * @param lowerLevelContainer lower level where we extract the data + * @param detailLevel detail level to update + * @param posX x position in the detail level to update + * @param posZ z position in the detail level to update + */ + public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ); + + /** + * This will give the data to save in the file + * @return data as a String + */ public String toDataString(); } diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index 63794ce8e..66682ea8f 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -22,55 +22,42 @@ public class LodRegion private byte minDetailLevel; private static final byte POSSIBLE_LOD = 10; //private int numberOfPoints; - private DistanceGenerationMode generationMode; //For each of the following field the first slot is for the level of detail //Important: byte have a [-128, 127] range. When converting from or to int a 128 should be added or removed //If there is a bug with color then it's probably caused by this. //in the future other fields like transparency and light level could be added - private long[][][] data; + private LevelContainer[] dataContainer; public final int regionPosX; public final int regionPosZ; - public LodRegion(VerticalLevelContainer verticalLevelContainer, RegionPos regionPos, DistanceGenerationMode generationMode) + public LodRegion(RegionPos regionPos) { - this.generationMode = generationMode; + this.minDetailLevel = LodUtil.REGION_DETAIL_LEVEL; this.regionPosX = regionPos.x; this.regionPosZ = regionPos.z; - this.minDetailLevel = verticalLevelContainer.detailLevel; - - //Arrays of matrices - data = new long[POSSIBLE_LOD][][]; - - data[minDetailLevel] = verticalLevelContainer.data; - - //Initialize all the different matrices - for (byte lod = (byte) (minDetailLevel + 1); lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) - { - int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod); - data[lod] = new long[size][size]; - } - updateArea(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ); + dataContainer = new LevelContainer[POSSIBLE_LOD]; } - public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode) + public LodRegion(byte minDetailLevel, RegionPos regionPos, boolean twoDimension) { - this.generationMode = generationMode; this.minDetailLevel = minDetailLevel; this.regionPosX = regionPos.x; this.regionPosZ = regionPos.z; - data = new long[POSSIBLE_LOD][][]; + dataContainer = new LevelContainer[POSSIBLE_LOD]; //Initialize all the different matrices for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { - int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod); - data[lod] = new long[size][size]; - + if(twoDimension){ + dataContainer[lod] = new SingleLevelContainer(lod); + }else{ + dataContainer[lod] = new VerticalLevelContainer(lod); + } } } @@ -80,7 +67,7 @@ public class LodRegion * @param dataPoint * @return */ - public boolean addData(byte detailLevel, int posX, int posZ, long dataPoint, boolean serverQuality) + public boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean serverQuality) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); @@ -91,7 +78,7 @@ public class LodRegion //if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++; //add the node data - this.data[detailLevel][posX][posZ] = dataPoint; + this.dataContainer[detailLevel].addData(dataPoint, posX, posZ); return true; } else { @@ -104,11 +91,11 @@ public class LodRegion * * @return the data at the relative pos and level */ - public long getData(byte detailLevel, int posX, int posZ) + public long[] getData(byte detailLevel, int posX, int posZ) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return data[detailLevel][posX][posZ]; + return dataContainer[detailLevel].getData(posX, posZ); } /** @@ -288,63 +275,7 @@ public class LodRegion */ private void update(byte detailLevel, int posX, int posZ) { - int numberOfChildren = 0; - int numberOfVoidChildren = 0; - - int tempRed = 0; - int tempGreen = 0; - int tempBlue = 0; - int tempHeight = 0; - int tempDepth = 0; - int childPosX; - int childPosZ; - byte childDetailLevel; - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - for (int x = 0; x <= 1; x++) - { - for (int z = 0; z <= 1; z++) - { - childPosX = 2 * posX + x; - childPosZ = 2 * posZ + z; - childDetailLevel = (byte) (detailLevel - 1); - if (doesDataExist(childDetailLevel, childPosX, childPosZ)) - { - if (!(DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT - && DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH)) - { - numberOfChildren++; - - tempRed += DataPointUtil.getRed(data[childDetailLevel][childPosX][childPosZ]); - tempGreen += DataPointUtil.getGreen(data[childDetailLevel][childPosX][childPosZ]); - tempBlue += DataPointUtil.getBlue(data[childDetailLevel][childPosX][childPosZ]); - tempHeight += DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]); - tempDepth += DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]); - } else - { - // void children have the default height (most likely -1) - // and represent a LOD with no blocks in it - numberOfVoidChildren++; - } - } - } - } - if (numberOfChildren > 0) - { - tempRed = tempRed / numberOfChildren; - tempGreen = tempGreen / numberOfChildren; - tempBlue = tempBlue / numberOfChildren; - tempHeight = tempHeight / numberOfChildren; - tempDepth = tempDepth / numberOfChildren; - } else if (numberOfVoidChildren > 0) - { - tempRed = (byte) 0; - tempGreen = (byte) 0; - tempBlue = (byte) 0; - tempHeight = LodBuilder.DEFAULT_HEIGHT; - tempDepth = LodBuilder.DEFAULT_DEPTH; - } - data[detailLevel][posX][posZ] = DataPointUtil.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue); + dataContainer[detailLevel].updateData(dataContainer[detailLevel - 1], posX, posZ); } @@ -356,15 +287,22 @@ public class LodRegion if(detailLevel < minDetailLevel) return false; posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return DataPointUtil.doesItExist(data[detailLevel][posX][posZ]); + return dataContainer[detailLevel].doesItExist(posX, posZ); } /** * @return */ - public DistanceGenerationMode getGenerationMode() + public byte getGenerationMode(byte detailLevel, int posX, int posZ) { - return generationMode; + if(dataContainer[detailLevel].doesItExist(posX,posZ)) + { + //We take the bottom information always + return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getData(posX,posZ)[0]); + }else + { + return DistanceGenerationMode.NONE.complexity; + } } public byte getMinDetailLevel() @@ -378,26 +316,26 @@ public class LodRegion * @param detailLevel * @return */ - public VerticalLevelContainer getLevel(byte detailLevel) + public LevelContainer getLevel(byte detailLevel) { if (detailLevel < minDetailLevel) { throw new IllegalArgumentException("getLevel asked for a level that does not exist: minimum " + minDetailLevel + " level requested " + detailLevel); } - return new VerticalLevelContainer(detailLevel, data[detailLevel]); + return dataContainer[detailLevel]; } /** - * @param verticalLevelContainer + * @param levelContainer */ - public void addLevel(VerticalLevelContainer verticalLevelContainer) + public void addLevel(LevelContainer levelContainer) { - if (verticalLevelContainer.detailLevel < minDetailLevel - 1) + if (levelContainer.getDetailLevel() < minDetailLevel - 1) { throw new IllegalArgumentException("addLevel requires a level that is at least the minimum level of the region -1 "); } - if (verticalLevelContainer.detailLevel == minDetailLevel - 1) minDetailLevel = verticalLevelContainer.detailLevel; - data[verticalLevelContainer.detailLevel] = verticalLevelContainer.data; + if (levelContainer.getDetailLevel() == minDetailLevel - 1) minDetailLevel = levelContainer.getDetailLevel(); + dataContainer[levelContainer.getDetailLevel()] = levelContainer; } @@ -410,7 +348,7 @@ public class LodRegion { for (byte tempLod = 0; tempLod < detailLevel; tempLod++) { - data[tempLod] = new long[0][0]; + dataContainer[tempLod] = null; } minDetailLevel = detailLevel; } @@ -423,10 +361,15 @@ public class LodRegion { if (detailLevel < minDetailLevel) { - for (byte tempLod = detailLevel; tempLod < minDetailLevel; tempLod++) + for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= minDetailLevel ; tempLod--) { int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod); - data[tempLod] = new long[size][size]; + if(dataContainer[tempLod + 1] == null) + { + /* TODO this can become either Single or Vertical*/ + dataContainer[tempLod + 1] = new SingleLevelContainer((byte) (tempLod + 1)); + } + dataContainer[tempLod] = dataContainer[tempLod+1].expand(); } minDetailLevel = detailLevel; } diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index 589ade2b2..4528c5dc9 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -1,6 +1,7 @@ package com.seibel.lod.objects; import com.seibel.lod.builders.LodBuilder; +import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; @@ -11,25 +12,53 @@ public class SingleLevelContainer implements LevelContainer public final long[][] data; + public SingleLevelContainer(byte detailLevel) + { + this.detailLevel = detailLevel; + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); + data = new long[size][size]; + } + public SingleLevelContainer(byte detailLevel, long[][] data) { this.detailLevel = detailLevel; this.data = data; } - public boolean putData(long[] data, int posX, int posZ){ + public boolean addData(long[] newData, int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - data[posX][posZ] = data[0]; + data[posX][posZ] = newData[0]; return true; } + private boolean addSingleData(long newData, int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + data[posX][posZ] = newData; + return true; + } public long[] getData(int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + //Improve this using a thread map to long[] + return new long[]{data[posX][posZ]}; + } + private long getSingleData(int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + //Improve this using a thread map to long[] return data[posX][posZ]; } + public byte getDetailLevel(){ + return detailLevel; + } + + public LevelContainer expand(){ + return new SingleLevelContainer((byte) (getDetailLevel() - 1)); + } + public SingleLevelContainer(String inputString) { @@ -41,71 +70,95 @@ public class SingleLevelContainer implements LevelContainer this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - this.data = new long[size][size][1]; + this.data = new long[size][size]; for (int x = 0; x < size; x++) { for (int z = 0; z < size; z++) { lastIndex = index; index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); - data[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); + data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); } } } - public long[] mergeData(long[][] dataArray, long[] newDataPoint, int[] indexes, long[] dataToCombine) + public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { int numberOfChildren = 0; int numberOfVoidChildren = 0; + int tempAlpha = 0; int tempRed = 0; int tempGreen = 0; int tempBlue = 0; int tempHeight = 0; int tempDepth = 0; + int tempLight = 0; + byte tempGenMode = DistanceGenerationMode.SERVER.complexity; int childPosX; int childPosZ; - byte childDetailLevel; - for (int index = 0; x <= 4; x++) + long childData; + long data = 0; + byte childDetailLevel = (byte) (detailLevel - 1); + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + for (int x = 0; x <= 1; x++) { - childDetailLevel = (byte) (detailLevel - 1); - if (doesDataExist(childDetailLevel, childPosX, childPosZ)) + for (int z = 0; z <= 1; z++) + { + childPosX = 2 * posX + x; + childPosZ = 2 * posZ + z; + childData = lowerLevelContainer.getData(childPosX, childPosZ)[0]; + + if (DataPointUtil.doesItExist(childData)) { - if (!(DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT - && DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH)) + if (!(DataPointUtil.isItVoid(childData))) { numberOfChildren++; - tempRed += DataPointUtil.getRed(data[childDetailLevel][childPosX][childPosZ]); - tempGreen += DataPointUtil.getGreen(data[childDetailLevel][childPosX][childPosZ]); - tempBlue += DataPointUtil.getBlue(data[childDetailLevel][childPosX][childPosZ]); - tempHeight += DataPointUtil.getHeight(data[childDetailLevel][childPosX][childPosZ]); - tempDepth += DataPointUtil.getDepth(data[childDetailLevel][childPosX][childPosZ]); + tempAlpha += DataPointUtil.getAlpha(childData); + tempRed += DataPointUtil.getRed(childData); + tempGreen += DataPointUtil.getGreen(childData); + tempBlue += DataPointUtil.getBlue(childData); + tempHeight += DataPointUtil.getHeight(childData); + tempDepth += DataPointUtil.getDepth(childData); } else { // void children have the default height (most likely -1) // and represent a LOD with no blocks in it numberOfVoidChildren++; } + tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(childData)); + }else + { + tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity); } } } if (numberOfChildren > 0) { + tempAlpha = tempAlpha / numberOfChildren; tempRed = tempRed / numberOfChildren; tempGreen = tempGreen / numberOfChildren; tempBlue = tempBlue / numberOfChildren; tempHeight = tempHeight / numberOfChildren; tempDepth = tempDepth / numberOfChildren; + tempLight = tempLight / numberOfChildren; + data = DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLight, tempGenMode); + addSingleData(data, posX, posZ); } else if (numberOfVoidChildren > 0) { - tempRed = (byte) 0; - tempGreen = (byte) 0; - tempBlue = (byte) 0; - tempHeight = LodBuilder.DEFAULT_HEIGHT; - tempDepth = LodBuilder.DEFAULT_DEPTH; + data = DataPointUtil.createDataPoint(tempGenMode); + addSingleData(data, posX, posZ); } - data[detailLevel][posX][posZ] = DataPointUtil.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue); + } + + + public boolean doesItExist(int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + //Improve this using a thread map to long[] + return DataPointUtil.doesItExist(getSingleData(posX, posZ)); } public String toDataString() @@ -125,7 +178,7 @@ public class SingleLevelContainer implements LevelContainer for (int z = 0; z < size; z++) { //Converting the dataToHex - stringBuilder.append(Long.toHexString(data[x][z][0])); + stringBuilder.append(Long.toHexString(data[x][z])); stringBuilder.append(DATA_DELIMITER); } } diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index a8da77306..bec1522ca 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -13,13 +13,20 @@ public class VerticalLevelContainer implements LevelContainer public final long[][][] data; + public VerticalLevelContainer(byte detailLevel) + { + this.detailLevel = detailLevel; + int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); + data = new long[size][size][]; + } + public VerticalLevelContainer(byte detailLevel, long[][][] data) { this.detailLevel = detailLevel; this.data = data; } - public boolean putData(long[] data, int posX, int posZ){ + public boolean addData(long[] data, int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); data[posX][posZ] = data @@ -55,9 +62,13 @@ public class VerticalLevelContainer implements LevelContainer } } - public long[] mergeData(long[][] dataArray, long[] newDataPoint, int[] indexes, long[] dataToCombine) - { + public void updateData(LevelContainer lowerLevelContainer, byte detailLevel, int posX, int posZ) + { + long[][] dataArray; + long[] newDataPoint; + int[] indexes; + long[] dataToCombine; //int maxSize = Math.max(Math.max(Math.max(dataArray[0].length, dataArray[1].length), dataArray[2].length), dataArray[3].length); //DetailDistanceUtil.getMaxVerticalData(detailLevel); //we are re-using these arrays so we must reset them to 0 From feebc3564ab5fb9dd2a4715be478604d3dce8505 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 16:42:21 +0200 Subject: [PATCH 07/30] Created the single level container --- .../com/seibel/lod/builders/LodBuilder.java | 4 +- .../lod/handlers/LodDimensionFileHandler.java | 6 +-- .../seibel/lod/objects/LevelContainer.java | 11 +++--- .../com/seibel/lod/objects/LodDimension.java | 11 +++++- .../com/seibel/lod/objects/LodRegion.java | 22 +++++++---- .../lod/objects/SingleLevelContainer.java | 38 +++++++++++-------- ...lContainer.java => VerticalLevelContainer} | 0 .../com/seibel/lod/util/DataPointUtil.java | 17 ++++----- 8 files changed, 65 insertions(+), 44 deletions(-) rename src/main/java/com/seibel/lod/objects/{VerticalLevelContainer.java => VerticalLevelContainer} (100%) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 33a22d2a8..e4f269062 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -126,7 +126,7 @@ public class LodBuilder generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(generationMode)); } catch (IllegalArgumentException | NullPointerException e) { - e.printStackTrace(); + //e.printStackTrace(); // if the world changes while LODs are being generated // they will throw errors as they try to access things that no longer // exist. @@ -200,7 +200,7 @@ public class LodBuilder posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel); posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel); boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; - data = DataPointUtil.createDataPoint(height, depth, ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color)); + data = DataPointUtil.createDataPoint(height, depth, color, 0 , 0); lodDim.addData(detailLevel, posX, posZ, diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 27f02c78f..1c6008dae 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -28,7 +28,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.objects.VerticalLevelContainer; +import com.seibel.lod.objects.SingleLevelContainer; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.RegionPos; @@ -200,7 +200,7 @@ public class LodDimensionFileHandler data = bufferedReader.readLine(); bufferedReader.close(); - region.addLevel(new VerticalLevelContainer(data)); + region.addLevel(new SingleLevelContainer(data)); } catch (Exception e) { // the buffered reader encountered a @@ -331,7 +331,7 @@ public class LodDimensionFileHandler fw.write(LOD_FILE_VERSION_PREFIX + " " + LOD_SAVE_FILE_VERSION + "\n"); // add each LodChunk to the file - fw.write(region.getLevel(detailLevel).toString()); + fw.write(region.getLevel(detailLevel).toDataString()); fw.close(); // overwrite the old file with the new one diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index f35de59b4..b80aca0c3 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -3,15 +3,19 @@ package com.seibel.lod.objects; import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + public interface LevelContainer { public static final char VERTICAL_DATA_DELIMITER = '\t'; - public static final char DATA_DELIMITER = '\n'; + public static final char DATA_DELIMITER = ','; + public static final ConcurrentMap threadAddDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadGetDataMap = new ConcurrentHashMap(); /**With this you can add data to the level container * * @param data actual data to add in a array of long format. - * @param detailLevel just to check that it's correct * @param posX x position in the detail level * @param posZ z position in the detail level * @return true if correctly added, false otherwise @@ -20,7 +24,6 @@ public interface LevelContainer /**With this you can get data from the level container * - * @param detailLevel just to check that it's correct * @param posX x position in the detail level * @param posZ z position in the detail level * @return the data in long array format @@ -28,7 +31,6 @@ public interface LevelContainer public long[] getData(int posX, int posZ); /** - * @param detailLevel just to check that it's correct * @param posX x position in the detail level * @param posZ z position in the detail level * @return true only if the data exist @@ -49,7 +51,6 @@ public interface LevelContainer /** * * @param lowerLevelContainer lower level where we extract the data - * @param detailLevel detail level to update * @param posX x position in the detail level to update * @param posZ z position in the detail level to update */ diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 87911306b..f4b034961 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -446,7 +446,14 @@ public class LodDimension LodRegion region = getRegion(regionPosX, regionPosZ); if (region == null) return false; - boolean nodeAdded = region.addData(detailLevel, posX, posZ, lodDataPoint, serverQuality); + ; + if(!LevelContainer.threadAddDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadAddDataMap.get(Thread.currentThread().getName()) == null)) + { + LevelContainer.threadAddDataMap.put(Thread.currentThread().getName(), new long[10]); + } + long[] dataArray = LevelContainer.threadAddDataMap.get(Thread.currentThread().getName()); + dataArray[0] = lodDataPoint; + boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataArray, serverQuality); // only save valid LODs to disk if (!dontSave && fileHandler != null) { @@ -533,7 +540,7 @@ public class LodDimension return 0; } - return region.getData(detailLevel, posX, posZ); + return region.getData(detailLevel, posX, posZ)[0]; } diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index 66682ea8f..f76a78885 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -30,6 +30,8 @@ public class LodRegion private LevelContainer[] dataContainer; + private DistanceGenerationMode generationMode; + public final int regionPosX; public final int regionPosZ; @@ -41,26 +43,32 @@ public class LodRegion dataContainer = new LevelContainer[POSSIBLE_LOD]; } - public LodRegion(byte minDetailLevel, RegionPos regionPos, boolean twoDimension) + public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode) { this.minDetailLevel = minDetailLevel; this.regionPosX = regionPos.x; this.regionPosZ = regionPos.z; - + this.generationMode = generationMode; dataContainer = new LevelContainer[POSSIBLE_LOD]; //Initialize all the different matrices for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { - if(twoDimension){ + dataContainer[lod] = new SingleLevelContainer(lod); + /*if(twoDimension){ dataContainer[lod] = new SingleLevelContainer(lod); }else{ dataContainer[lod] = new VerticalLevelContainer(lod); - } + }*/ } } + public DistanceGenerationMode getGenerationMode() + { + return generationMode; + } + /** * This method can be used to insert data into the LodRegion * @@ -287,6 +295,8 @@ public class LodRegion if(detailLevel < minDetailLevel) return false; posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + if(dataContainer == null || dataContainer[detailLevel] == null) + return false; return dataContainer[detailLevel].doesItExist(posX, posZ); } @@ -361,12 +371,10 @@ public class LodRegion { if (detailLevel < minDetailLevel) { - for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= minDetailLevel ; tempLod--) + for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= detailLevel ; tempLod--) { - int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod); if(dataContainer[tempLod + 1] == null) { - /* TODO this can become either Single or Vertical*/ dataContainer[tempLod + 1] = new SingleLevelContainer((byte) (tempLod + 1)); } dataContainer[tempLod] = dataContainer[tempLod+1].expand(); diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index 4528c5dc9..fd1975794 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -9,23 +9,19 @@ import com.seibel.lod.util.LodUtil; public class SingleLevelContainer implements LevelContainer { public final byte detailLevel; + public final int size; public final long[][] data; public SingleLevelContainer(byte detailLevel) { this.detailLevel = detailLevel; - int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); + size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); data = new long[size][size]; } - public SingleLevelContainer(byte detailLevel, long[][] data) - { - this.detailLevel = detailLevel; - this.data = data; - } - public boolean addData(long[] newData, int posX, int posZ){ + posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); data[posX][posZ] = newData[0]; @@ -39,10 +35,18 @@ public class SingleLevelContainer implements LevelContainer return true; } public long[] getData(int posX, int posZ){ + + if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) + { + LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[1]); + } + long[] dataArray = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); + posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); //Improve this using a thread map to long[] - return new long[]{data[posX][posZ]}; + dataArray[0] = data[posX][posZ]; + return dataArray; } private long getSingleData(int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); @@ -67,8 +71,8 @@ public class SingleLevelContainer implements LevelContainer index = inputString.indexOf(DATA_DELIMITER, 0); - this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); - int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); + detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); + size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); this.data = new long[size][size]; for (int x = 0; x < size; x++) @@ -162,12 +166,6 @@ public class SingleLevelContainer implements LevelContainer } public String toDataString() - { - return toString(); - } - - @Override - public String toString() { StringBuilder stringBuilder = new StringBuilder(); int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); @@ -184,4 +182,12 @@ public class SingleLevelContainer implements LevelContainer } return stringBuilder.toString(); } + + @Override + public String toString() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(detailLevel); + return stringBuilder.toString(); + } } diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer similarity index 100% rename from src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java rename to src/main/java/com/seibel/lod/objects/VerticalLevelContainer diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 554c4a835..224281e07 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -41,16 +41,16 @@ public class DataPointUtil return dataPoint; } - public static long createDataPoint(int height, int depth, int color) + public static long createDataPoint(int height, int depth, int color, int lightValue, int generationMode) { - int alpha = (color >> 24) & 0xFF000000; - int red = (color >> 16) & 0x00FF0000; - int green = (color >> 8) & 0x0000FF00; - int blue = color & 0x000000FF; - return createDataPoint(height, depth, alpha, red, green, blue); + int alpha = ColorUtil.getAlpha(color); + int red = ColorUtil.getRed(color); + int green = ColorUtil.getGreen(color); + int blue = ColorUtil.getBlue(color); + return createDataPoint(alpha, red, green, blue, height, depth, lightValue, generationMode); } - public static long createDataPoint(int height, int depth, int alpha, int red, int green, int blue, int lightValue, int generationMode) + public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightValue, int generationMode) { long dataPoint = 0; dataPoint += (alpha & ALPHA_MASK) << ALPHA_SHIFT; @@ -146,5 +146,4 @@ public class DataPointUtil { return null; } -} -VerticalLevelContainer \ No newline at end of file +} \ No newline at end of file From 5c05df0361b1920b7526948cf15a9cdb5786d16f Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 18:20:33 +0200 Subject: [PATCH 08/30] changed the thread names --- .../java/com/seibel/lod/builders/LodBufferBuilder.java | 4 +++- .../lod/builders/worldGeneration/LodNodeGenWorker.java | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index 89583ff19..ce393d0ea 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -25,6 +25,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.lwjgl.opengl.GL11; import com.seibel.lod.builders.lodTemplates.Box; @@ -61,7 +62,8 @@ public class LodBufferBuilder /** * This holds the threads used to generate buffers. */ - private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfBufferBuilderThreads.get(), new LodThreadFactory(this.getClass().getSimpleName() + " - builder")); + private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfBufferBuilderThreads.get(), new ThreadFactoryBuilder().setNameFormat("Render-Thread-%d").build()); + //private ExecutorService bufferBuilderThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfBufferBuilderThreads.get(), new LodThreadFactory(this.getClass().getSimpleName() + " - builder")); /** * The buffers that are used to create LODs using far fog diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java index 64880f35c..ffd5ea5b1 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java @@ -24,8 +24,10 @@ import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; import java.util.function.Supplier; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.builders.LodBuilderConfig; import com.seibel.lod.config.LodConfig; @@ -72,7 +74,8 @@ import net.minecraftforge.common.WorldWorkerManager.IWorker; */ public class LodNodeGenWorker implements IWorker { - public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new LodThreadFactory(LodNodeGenWorker.class.getSimpleName())); + public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build()); + //public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new LodThreadFactory(LodNodeGenWorker.class.getSimpleName())); private boolean threadStarted = false; private LodChunkGenThread thread; @@ -126,7 +129,7 @@ public class LodNodeGenWorker implements IWorker // Every other method can // be done asynchronously Thread newThread = new Thread(thread); - newThread.setPriority(3); + newThread.setPriority(5); genThreads.execute(newThread); } From 3f1cf6c305e3a141fb1ff049558943099c356d67 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 18:21:09 +0200 Subject: [PATCH 09/30] Added some new temporal data storing --- src/main/java/com/seibel/lod/objects/LevelContainer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index b80aca0c3..841863ce8 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -12,7 +12,8 @@ public interface LevelContainer public static final char DATA_DELIMITER = ','; public static final ConcurrentMap threadAddDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadGetDataMap = new ConcurrentHashMap(); - + public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); /**With this you can add data to the level container * * @param data actual data to add in a array of long format. From 59bfd739f4ac822816f75d20aa5f365340b6bb0f Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 18:21:46 +0200 Subject: [PATCH 10/30] Added max detail at FULL --- src/main/java/com/seibel/lod/objects/LodRegion.java | 8 ++++---- src/main/java/com/seibel/lod/util/DetailDistanceUtil.java | 8 +++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index f76a78885..29f5ed7a9 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -59,7 +59,7 @@ public class LodRegion /*if(twoDimension){ dataContainer[lod] = new SingleLevelContainer(lod); }else{ - dataContainer[lod] = new VerticalLevelContainer(lod); + dataContainer[lod] = new VerticalLevelContainer.java(lod); }*/ } } @@ -132,11 +132,11 @@ public class LodRegion int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel); //we have reached the target detail level - - if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) > detailLevel) + byte targetDetailLevel = DetailDistanceUtil.getLodGenDetail(DetailDistanceUtil.getDistanceGenerationInverse(maxDistance)).detailLevel; + if (targetDetailLevel > detailLevel) { return; - } else if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) == detailLevel) + } else if (targetDetailLevel == detailLevel) { if (!doesDataExist(detailLevel, posX, posZ)) { diff --git a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java index 3e631eef7..a98fc9ec5 100644 --- a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java +++ b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java @@ -160,7 +160,13 @@ public class DetailDistanceUtil public static byte getLodDrawDetail(int detail) { - return (byte) Math.max(detail, minDrawDetail); + if (detail < minGenDetail) + { + return lodGenDetails[minGenDetail].detailLevel; + } else + { + return lodGenDetails[detail].detailLevel; + } } public static LodDetail getLodGenDetail(int detail) From 99f7d70613f2579a74af5b03320e377d707b0cea Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 18:22:13 +0200 Subject: [PATCH 11/30] disabled the class until it's ready --- ...lContainer => VerticalLevelContainer.java} | 73 ++++++++++++++----- 1 file changed, 53 insertions(+), 20 deletions(-) rename src/main/java/com/seibel/lod/objects/{VerticalLevelContainer => VerticalLevelContainer.java} (62%) diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java similarity index 62% rename from src/main/java/com/seibel/lod/objects/VerticalLevelContainer rename to src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index bec1522ca..7a685d051 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -1,42 +1,51 @@ package com.seibel.lod.objects; -import java.io.Serializable; - import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; - +/* public class VerticalLevelContainer implements LevelContainer { + public final byte detailLevel; - public final long[][][] data; + public final long[][][] dataContainer; public VerticalLevelContainer(byte detailLevel) { this.detailLevel = detailLevel; int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - data = new long[size][size][]; + dataContainer = new long[size][size][]; } public VerticalLevelContainer(byte detailLevel, long[][][] data) { this.detailLevel = detailLevel; - this.data = data; + this.dataContainer = data; } - public boolean addData(long[] data, int posX, int posZ){ + @Override + public byte getDetailLevel() + { + return detailLevel; + } + + public boolean addData(long[] newData, int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - data[posX][posZ] = data + dataContainer[posX][posZ] = newData; return true; } public long[] getData(int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return data[posX][posZ]; + return dataContainer[posX][posZ]; + } + + public boolean doesItExist(int posX, int posZ){ + long[] data = getData(posX,posZ); + return (data != null && DataPointUtil.doesItExist(data[0])); } public VerticalLevelContainer(String inputString) @@ -50,25 +59,49 @@ public class VerticalLevelContainer implements LevelContainer this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - this.data = new long[size][size][1]; + this.dataContainer = new long[size][size][1]; for (int x = 0; x < size; x++) { for (int z = 0; z < size; z++) { lastIndex = index; index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); - data[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); + dataContainer[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); } } } + public LevelContainer expand(){ + return new SingleLevelContainer((byte) (getDetailLevel() - 1)); + } - public void updateData(LevelContainer lowerLevelContainer, byte detailLevel, int posX, int posZ) + public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { - long[][] dataArray; - long[] newDataPoint; + long[][][] updateTemps; int[] indexes; - long[] dataToCombine; + if(!LevelContainer.threadVerticalUpdateMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadVerticalUpdateMap.get(Thread.currentThread().getName()) == null)) + { + //To avoid the creation of multiple + updateTemps = new long[4][][]; + updateTemps[0] = new long[4][16]; + updateTemps[1] = new long[1][32]; + updateTemps[2] = new long[1][4]; + updateTemps[3] = new long[1][4]; + LevelContainer.threadVerticalUpdateMap.put(Thread.currentThread().getName(), updateTemps); + } + if(!LevelContainer.threadVerticalIndexesMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadVerticalIndexesMap.get(Thread.currentThread().getName()) == null)) + { + //To avoid the creation of multiple + indexes = new int[4]; + LevelContainer.threadVerticalIndexesMap.put(Thread.currentThread().getName(), updateTemps); + } + + updateTemps = LevelContainer.threadVerticalIndexesMap.get(Thread.currentThread().getName()); + + long[][] dataArray = updateTemps[0]; + long[] newDataPoint = updateTemps[1][1]; + long[] indexes = updateTemps[2][1]; + long[] dataToCombine = updateTemps[3][1]; //int maxSize = Math.max(Math.max(Math.max(dataArray[0].length, dataArray[1].length), dataArray[2].length), dataArray[3].length); //DetailDistanceUtil.getMaxVerticalData(detailLevel); //we are re-using these arrays so we must reset them to 0 @@ -97,9 +130,9 @@ public class VerticalLevelContainer implements LevelContainer { if (indexes[arrayIndex] < dataArray[arrayIndex].length) { - if (minDepth < getDepth(dataArray[arrayIndex][indexes[arrayIndex]])) + if (minDepth < DataPointUtil.getDepth(dataArray[arrayIndex][indexes[arrayIndex]])) { - minDepth = getDepth(dataArray[arrayIndex][indexes[arrayIndex]]); + minDepth = DataPointUtil.getDepth(dataArray[arrayIndex][indexes[arrayIndex]]); startingArray = arrayIndex; } } @@ -145,10 +178,10 @@ public class VerticalLevelContainer implements LevelContainer for (int z = 0; z < size; z++) { //Converting the dataToHex - stringBuilder.append(Long.toHexString(data[x][z][0])); + stringBuilder.append(Long.toHexString(dataContainer[x][z][0])); stringBuilder.append(DATA_DELIMITER); } } return stringBuilder.toString(); } -} +}*/ From 1395e32a5061be86d7c418305e5e8aacdc4c4e73 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sat, 11 Sep 2021 13:49:51 +0200 Subject: [PATCH 12/30] introduced the mergeSingleData function --- .../seibel/lod/objects/LevelContainer.java | 1 + .../lod/objects/SingleLevelContainer.java | 63 +++------------- .../com/seibel/lod/util/DataPointUtil.java | 74 ++++++++++++++++++- 3 files changed, 84 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index 841863ce8..c4f48eeb6 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -12,6 +12,7 @@ public interface LevelContainer public static final char DATA_DELIMITER = ','; public static final ConcurrentMap threadAddDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadGetDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); /**With this you can add data to the level container diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index fd1975794..a8c69cf32 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -3,6 +3,7 @@ package com.seibel.lod.objects; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.util.DataPointUtil; +import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; @@ -88,22 +89,16 @@ public class SingleLevelContainer implements LevelContainer public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { - int numberOfChildren = 0; - int numberOfVoidChildren = 0; + //We reset the array + if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) + { + LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[4]); + } + long[] dataToMerge = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); - int tempAlpha = 0; - int tempRed = 0; - int tempGreen = 0; - int tempBlue = 0; - int tempHeight = 0; - int tempDepth = 0; - int tempLight = 0; - byte tempGenMode = DistanceGenerationMode.SERVER.complexity; int childPosX; int childPosZ; - long childData; long data = 0; - byte childDetailLevel = (byte) (detailLevel - 1); posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); for (int x = 0; x <= 1; x++) @@ -112,49 +107,11 @@ public class SingleLevelContainer implements LevelContainer { childPosX = 2 * posX + x; childPosZ = 2 * posZ + z; - childData = lowerLevelContainer.getData(childPosX, childPosZ)[0]; - - if (DataPointUtil.doesItExist(childData)) - { - if (!(DataPointUtil.isItVoid(childData))) - { - numberOfChildren++; - - tempAlpha += DataPointUtil.getAlpha(childData); - tempRed += DataPointUtil.getRed(childData); - tempGreen += DataPointUtil.getGreen(childData); - tempBlue += DataPointUtil.getBlue(childData); - tempHeight += DataPointUtil.getHeight(childData); - tempDepth += DataPointUtil.getDepth(childData); - } else - { - // void children have the default height (most likely -1) - // and represent a LOD with no blocks in it - numberOfVoidChildren++; - } - tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(childData)); - }else - { - tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity); - } + dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ)[0]; } } - if (numberOfChildren > 0) - { - tempAlpha = tempAlpha / numberOfChildren; - tempRed = tempRed / numberOfChildren; - tempGreen = tempGreen / numberOfChildren; - tempBlue = tempBlue / numberOfChildren; - tempHeight = tempHeight / numberOfChildren; - tempDepth = tempDepth / numberOfChildren; - tempLight = tempLight / numberOfChildren; - data = DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLight, tempGenMode); - addSingleData(data, posX, posZ); - } else if (numberOfVoidChildren > 0) - { - data = DataPointUtil.createDataPoint(tempGenMode); - addSingleData(data, posX, posZ); - } + data = DataPointUtil.mergeSingleData(dataToMerge); + addSingleData(data,posX,posZ); } diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 224281e07..fe0f340d2 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -1,11 +1,14 @@ package com.seibel.lod.util; +import com.seibel.lod.enums.DistanceGenerationMode; + public class DataPointUtil { //To be used in the future for negative value //public final static int MIN_DEPTH = -64; //public final static int MIN_HEIGHT = -64; + public final static int EMPTY_DATA = 0; public final static int ALPHA_SHIFT = 56; public final static int RED_SHIFT = 48; @@ -32,7 +35,7 @@ public class DataPointUtil public final static long EXISTENCE_MASK = 1; - public static long createDataPoint(int generationMode) + public static long createVoidDataPoint(int generationMode) { long dataPoint = 0; dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; @@ -141,6 +144,75 @@ public class DataPointUtil return s.toString(); } + public static long mergeSingleData(long[] dataToMerge) + { + int numberOfChildren = 0; + int numberOfVoidChildren = 0; + + int tempAlpha = 0; + int tempRed = 0; + int tempGreen = 0; + int tempBlue = 0; + int tempHeight = 0; + int tempDepth = 0; + int tempLight = 0; + byte tempGenMode = DistanceGenerationMode.SERVER.complexity; + long newData = 0; + for(long data : dataToMerge) + { + if (DataPointUtil.doesItExist(data)) + { + if (!(DataPointUtil.isItVoid(data))) + { + numberOfChildren++; + + tempAlpha += DataPointUtil.getAlpha(data); + tempRed += DataPointUtil.getRed(data); + tempGreen += DataPointUtil.getGreen(data); + tempBlue += DataPointUtil.getBlue(data); + tempHeight += DataPointUtil.getHeight(data); + tempDepth += DataPointUtil.getDepth(data); + } else + { + // void children have the default height (most likely -1) + // and represent a LOD with no blocks in it + numberOfVoidChildren++; + } + tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(data)); + } else + { + tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity); + } + } + if (numberOfChildren > 0) + { + //we have at least 1 child + tempAlpha = tempAlpha / numberOfChildren; + tempRed = tempRed / numberOfChildren; + tempGreen = tempGreen / numberOfChildren; + tempBlue = tempBlue / numberOfChildren; + tempHeight = tempHeight / numberOfChildren; + tempDepth = tempDepth / numberOfChildren; + tempLight = tempLight / numberOfChildren; + return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLight, tempGenMode); + } else if (numberOfVoidChildren > 0) + { + //all the children are void + return DataPointUtil.createVoidDataPoint(tempGenMode); + }else + { + //no child has been initialized + return DataPointUtil.EMPTY_DATA; + } + } +/* + public static int mergeVerticalData(long dataPoint) + { + int R = (getRed(dataPoint) << 16) & 0x00FF0000; + int G = (getGreen(dataPoint) << 8) & 0x0000FF00; + int B = getBlue(dataPoint) & 0x000000FF; + return 0xFF000000 | R | G | B; + }*/ public static long[] compress(long[] data, byte detailLevel) { From bdcc4c77556bd06215cb968520e926d1b9826522 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sat, 11 Sep 2021 15:56:46 +0200 Subject: [PATCH 13/30] Introduced map util and now the Loading does not create new String object. --- .../seibel/lod/objects/LevelContainer.java | 5 -- .../com/seibel/lod/objects/LodDimension.java | 12 +-- .../lod/objects/SingleLevelContainer.java | 53 +++++++------- .../lod/objects/VerticalLevelContainer.java | 31 +++++++- .../com/seibel/lod/util/DataPointUtil.java | 39 +++++----- .../com/seibel/lod/util/ThreadMapUtil.java | 73 +++++++++++++++++++ 6 files changed, 149 insertions(+), 64 deletions(-) create mode 100644 src/main/java/com/seibel/lod/util/ThreadMapUtil.java diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index c4f48eeb6..1e2607ab8 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -10,11 +10,6 @@ public interface LevelContainer { public static final char VERTICAL_DATA_DELIMITER = '\t'; public static final char DATA_DELIMITER = ','; - public static final ConcurrentMap threadAddDataMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadGetDataMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); /**With this you can add data to the level container * * @param data actual data to add in a array of long format. diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index f4b034961..4b1db5d6f 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -25,10 +25,7 @@ import java.util.concurrent.Executors; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.handlers.LodDimensionFileHandler; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; +import com.seibel.lod.util.*; import com.seibel.lod.wrappers.MinecraftWrapper; import net.minecraft.util.math.ChunkPos; @@ -446,12 +443,7 @@ public class LodDimension LodRegion region = getRegion(regionPosX, regionPosZ); if (region == null) return false; - ; - if(!LevelContainer.threadAddDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadAddDataMap.get(Thread.currentThread().getName()) == null)) - { - LevelContainer.threadAddDataMap.put(Thread.currentThread().getName(), new long[10]); - } - long[] dataArray = LevelContainer.threadAddDataMap.get(Thread.currentThread().getName()); + long[] dataArray = ThreadMapUtil.getSingleAddDataArray(); dataArray[0] = lodDataPoint; boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataArray, serverQuality); // only save valid LODs to disk diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index a8c69cf32..66657b963 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -2,10 +2,7 @@ package com.seibel.lod.objects; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodUtil; +import com.seibel.lod.util.*; public class SingleLevelContainer implements LevelContainer { @@ -35,20 +32,16 @@ public class SingleLevelContainer implements LevelContainer data[posX][posZ] = newData; return true; } + public long[] getData(int posX, int posZ){ - - if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) - { - LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[1]); - } - long[] dataArray = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); - + long[] dataArray = ThreadMapUtil.getSingleGetDataArray(); posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); //Improve this using a thread map to long[] dataArray[0] = data[posX][posZ]; return dataArray; } + private long getSingleData(int posX, int posZ){ posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); @@ -66,23 +59,35 @@ public class SingleLevelContainer implements LevelContainer public SingleLevelContainer(String inputString) { - + int tempIndex; + int shift = 0; int index = 0; - int lastIndex = 0; - - - index = inputString.indexOf(DATA_DELIMITER, 0); - detailLevel = (byte) Integer.parseInt(inputString.substring(0, index)); + int digit; + char currentChar; + long newData; + currentChar = inputString.charAt(index); + digit = Character.digit(currentChar,16); + detailLevel = (byte) digit; size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - this.data = new long[size][size]; for (int x = 0; x < size; x++) { for (int z = 0; z < size; z++) { - lastIndex = index; - index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); - data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); + newData = 0; + for(tempIndex = 0; tempIndex < 16; tempIndex++) + { + currentChar = inputString.charAt(index+tempIndex); + if(currentChar == ','){ + break; + } + shift = (15-tempIndex)*4; + digit = Character.digit(currentChar,16); + newData += ((long) (digit & 0xf)) << shift; + } + newData = newData >>> (shift); + data[x][z] = newData; + index = index + tempIndex; } } } @@ -90,11 +95,7 @@ public class SingleLevelContainer implements LevelContainer public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { //We reset the array - if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) - { - LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[4]); - } - long[] dataToMerge = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); + long[] dataToMerge = ThreadMapUtil.getSingleUpdateArray(); int childPosX; int childPosZ; diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index 7a685d051..1c26730d6 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -1,9 +1,9 @@ package com.seibel.lod.objects; - +/* import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; -/* + public class VerticalLevelContainer implements LevelContainer { @@ -75,6 +75,33 @@ public class VerticalLevelContainer implements LevelContainer return new SingleLevelContainer((byte) (getDetailLevel() - 1)); } + public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) + { + //We reset the array + if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) + { + LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[4]); + } + long[] dataToMerge = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); + + int childPosX; + int childPosZ; + long data = 0; + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + for (int x = 0; x <= 1; x++) + { + for (int z = 0; z <= 1; z++) + { + childPosX = 2 * posX + x; + childPosZ = 2 * posZ + z; + dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ)[0]; + } + } + data = DataPointUtil.mergeSingleData(dataToMerge); + addData(data,posX,posZ); + } + public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { long[][][] updateTemps; diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index fe0f340d2..2ca05f865 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -46,11 +46,12 @@ public class DataPointUtil public static long createDataPoint(int height, int depth, int color, int lightValue, int generationMode) { - int alpha = ColorUtil.getAlpha(color); - int red = ColorUtil.getRed(color); - int green = ColorUtil.getGreen(color); - int blue = ColorUtil.getBlue(color); - return createDataPoint(alpha, red, green, blue, height, depth, lightValue, generationMode); + return createDataPoint( + ColorUtil.getAlpha(color), + ColorUtil.getRed(color), + ColorUtil.getGreen(color), + ColorUtil.getBlue(color), + height, depth, lightValue, generationMode); } public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightValue, int generationMode) @@ -62,15 +63,15 @@ public class DataPointUtil dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT; dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT; - dataPoint += (depth & LIGHT_MASK) << LIGHT_SHIFT; - dataPoint += (depth & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; + dataPoint += (lightValue & LIGHT_MASK) << LIGHT_SHIFT; + dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT; return dataPoint; } public static short getHeight(long dataPoint) { - return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK); + return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK); } public static short getDepth(long dataPoint) @@ -81,51 +82,48 @@ public class DataPointUtil public static short getAlpha(long dataPoint) { - return (short) ((dataPoint >> ALPHA_SHIFT) & ALPHA_MASK); + return (short) ((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK); } public static short getRed(long dataPoint) { - return (short) ((dataPoint >> RED_SHIFT) & RED_MASK); + return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK); } public static short getGreen(long dataPoint) { - return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK); + return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK); } public static short getBlue(long dataPoint) { - return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK); + return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK); } public static byte getLightValue(long dataPoint) { - return (byte) ((dataPoint >> LIGHT_SHIFT) & LIGHT_MASK); + return (byte) ((dataPoint >>> LIGHT_SHIFT) & LIGHT_MASK); } public static byte getGenerationMode(long dataPoint) { - return (byte) ((dataPoint >> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); + return (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); } public static boolean isItVoid(long dataPoint) { - return (((dataPoint >> VOID_SHIFT) & VOID_MASK) == 1); + return (((dataPoint >>> VOID_SHIFT) & VOID_MASK) == 1); } public static boolean doesItExist(long dataPoint) { - return (((dataPoint >> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1); + return (((dataPoint >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1); } public static int getColor(long dataPoint) { - int R = (getRed(dataPoint) << 16) & 0x00FF0000; - int G = (getGreen(dataPoint) << 8) & 0x0000FF00; - int B = getBlue(dataPoint) & 0x000000FF; - return 0xFF000000 | R | G | B; + return (int) ((dataPoint >>> COLOR_SHIFT) & COLOR_MASK); } public static String toString(long dataPoint) @@ -157,7 +155,6 @@ public class DataPointUtil int tempDepth = 0; int tempLight = 0; byte tempGenMode = DistanceGenerationMode.SERVER.complexity; - long newData = 0; for(long data : dataToMerge) { if (DataPointUtil.doesItExist(data)) diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java new file mode 100644 index 000000000..b9904276a --- /dev/null +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -0,0 +1,73 @@ +package com.seibel.lod.util; + +import com.seibel.lod.objects.LevelContainer; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class ThreadMapUtil +{ + public static final ConcurrentMap threadSingleAddDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadSingleGetDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalAddDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalGetDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); + + public static long[] getSingleAddDataArray(){ + if(!threadSingleAddDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleAddDataMap.get(Thread.currentThread().getName()) == null)) + { + threadSingleAddDataMap.put(Thread.currentThread().getName(), new long[1]); + } + return threadSingleAddDataMap.get(Thread.currentThread().getName()); + } + + public static long[] getSingleGetDataArray(){ + if(!threadSingleGetDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleGetDataMap.get(Thread.currentThread().getName()) == null)) + { + threadSingleGetDataMap.put(Thread.currentThread().getName(), new long[1]); + } + return threadSingleGetDataMap.get(Thread.currentThread().getName()); + } + + public static long[] getSingleUpdateArray(){ + if(!threadSingleUpdateMap.containsKey(Thread.currentThread().getName()) || (threadSingleUpdateMap.get(Thread.currentThread().getName()) == null)) + { + threadSingleUpdateMap.put(Thread.currentThread().getName(), new long[4]); + } + return threadSingleUpdateMap.get(Thread.currentThread().getName()); + } + + public static long[] addVerticalDataArray(){ + if(!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[16]); + } + return threadVerticalAddDataMap.get(Thread.currentThread().getName()); + } + + public static long[] getVerticalGetDataArray(){ + if(!threadVerticalGetDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalGetDataMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalGetDataMap.put(Thread.currentThread().getName(), new long[16]); + } + return threadVerticalGetDataMap.get(Thread.currentThread().getName()); + } + + public static long[][][] getVerticalUpdateArray(){ + if(!threadVerticalUpdateMap.containsKey(Thread.currentThread().getName()) || (threadVerticalUpdateMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalUpdateMap.put(Thread.currentThread().getName(), new long[4][4][16]); + } + return threadVerticalUpdateMap.get(Thread.currentThread().getName()); + } + + public static int[] getVerticalIndexesArray(){ + if(!threadVerticalIndexesMap.containsKey(Thread.currentThread().getName()) || (threadVerticalIndexesMap.get(Thread.currentThread().getName()) == null)) + { + threadVerticalIndexesMap.put(Thread.currentThread().getName(), new int[4]); + } + return threadVerticalIndexesMap.get(Thread.currentThread().getName()); + } +} From 5f1f5f0948b9041479774c3728475624c21fd09b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sat, 11 Sep 2021 16:29:20 +0200 Subject: [PATCH 14/30] Fixed some smalls bugs --- src/main/java/com/seibel/lod/objects/SingleLevelContainer.java | 2 +- src/main/java/com/seibel/lod/util/ThreadMapUtil.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index 66657b963..3d45c89e4 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -108,7 +108,7 @@ public class SingleLevelContainer implements LevelContainer { childPosX = 2 * posX + x; childPosZ = 2 * posZ + z; - dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ)[0]; + dataToMerge[2*x + z] = ((SingleLevelContainer) lowerLevelContainer).getSingleData(childPosX, childPosZ); } } data = DataPointUtil.mergeSingleData(dataToMerge); diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index b9904276a..f4e5da029 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -9,9 +9,9 @@ public class ThreadMapUtil { public static final ConcurrentMap threadSingleAddDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadSingleGetDataMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalAddDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalGetDataMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); From 7b73445f4de8cc1f102b244c13607979683587eb Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sat, 11 Sep 2021 19:59:30 +0200 Subject: [PATCH 15/30] Changed the lodBuilder to use a single function --- .../com/seibel/lod/builders/LodBuilder.java | 175 ++++++++++++++++-- .../lodTemplates/CubicLodTemplate.java | 10 +- .../com/seibel/lod/util/DataPointUtil.java | 7 + .../com/seibel/lod/util/ThreadMapUtil.java | 12 ++ 4 files changed, 191 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index e4f269062..65af14779 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -23,21 +23,20 @@ import java.util.concurrent.Executors; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.enums.LodDetail; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.LevelPosUtil; +import com.seibel.lod.util.*; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.LodWorld; -import com.seibel.lod.util.ColorUtil; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; import com.seibel.lod.wrappers.MinecraftWrapper; import net.minecraft.block.*; import net.minecraft.block.material.MaterialColor; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.DimensionType; +import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.IWorld; +import net.minecraft.world.LightType; import net.minecraft.world.biome.Biome; import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.IChunk; @@ -163,6 +162,7 @@ public class LodBuilder int endX; int endZ; int color; + byte light; short height; short depth; long data; @@ -185,7 +185,9 @@ public class LodBuilder endX = detail.endX[i]; endZ = detail.endZ[i]; + /* color = generateLodColorForArea(chunk, config, startX, startZ, endX, endZ); + light = generateLodLightForArea(chunk, config, startX, startZ, endX, endZ); if (!config.useHeightmap) { @@ -196,11 +198,12 @@ public class LodBuilder height = determineHeightPoint(chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP), startX, startZ, endX, endZ); depth = 0; - } + }*/ posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel); posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel); + long[] dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; - data = DataPointUtil.createDataPoint(height, depth, color, 0 , 0); + data = DataPointUtil.mergeSingleData(dataToMerge); lodDim.addData(detailLevel, posX, posZ, @@ -212,11 +215,99 @@ public class LodBuilder } catch (Exception e) { e.printStackTrace(); + throw e; } } + private long[] createSingleDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) + { + long[] dataToMerge = ThreadMapUtil.getBuilderArray()[detail.detailLevel]; + ChunkPos chunkPos = chunk.getPos(); + BlockState blockState; + ChunkSection[] chunkSections = chunk.getSections(); + ChunkSection section; + int size = 1 << detail.detailLevel; + int height = 0; + int depth = 0; + int color = 0; + int light = 0; + int generation = config.distanceGenerationMode.complexity; + int xRel; + int yRel; + int zRel; + int xAbs; + int zAbs; + int sectionIndex; + boolean voidData; + BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); + int index = 0; + if (dataToMerge == null) + { + dataToMerge = new long[size * size]; + } + for (index = 0; index < size * size; index++) + { + xRel = Math.floorMod(index, size) + startX; + zRel = Math.floorDiv(index, size) + startZ; + xAbs = chunkPos.getMinBlockX() + xRel; + zAbs = chunkPos.getMinBlockZ() + zRel; + voidData = true; + for (sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--) + { + for (yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) + { + if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + { + blockState = chunkSections[sectionIndex].getBlockState(xRel, yRel, zRel); + + height = sectionIndex * CHUNK_DATA_WIDTH + yRel; + color = blockState.getBlock().defaultMaterialColor().col; + + blockPos.set(xAbs, height, zAbs); + light = blockState.getLightBlock(chunk, blockPos); + + voidData = false; + break; + } + } + if (!voidData) + { + break; + } + } + + if (voidData) + { + //no valid block has been found, this column is void + dataToMerge[index] = DataPointUtil.createVoidDataPoint(generation); + continue; + } + + //A valid block has been found. Now we search the deepest one + + voidData = true; + for (sectionIndex = 0; sectionIndex < chunkSections.length; sectionIndex++) + { + for (yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++) + { + if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + { + depth = sectionIndex * CHUNK_DATA_WIDTH + yRel; + voidData = false; + break; + } + } + if (!voidData) + { + break; + } + } + dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, light, generation); + } + return dataToMerge; + } // =====================// // constructor helpers // // =====================// @@ -424,7 +515,67 @@ public class LodBuilder red /= numbOfBlocks; green /= numbOfBlocks; blue /= numbOfBlocks; - return ColorUtil.rgbToInt(red,green,blue); + return ColorUtil.rgbToInt(red, green, blue); + } + + private byte generateLodLightForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, + int endZ) + { + ChunkSection[] chunkSections = chunk.getSections(); + + int numbOfBlocks = 0; + int tempLight; + int light = 0; + BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); + for (int x = startX; x < endX; x++) + { + for (int z = startZ; z < endZ; z++) + { + boolean foundBlock = false; + + // go top down + for (int i = chunkSections.length - 1; !foundBlock && i >= 0; i--) + { + if (!foundBlock && (chunkSections[i] != null || !config.useSolidBlocksInColorGen)) + { + for (int y = CHUNK_SECTION_HEIGHT - 1; !foundBlock && y >= 0; y--) + { + tempLight = 0; + BlockState blockState = null; + if (chunkSections[i] != null) + { + blockPos.set(chunk.getPos().getMinBlockX() + x, y, chunk.getPos().getMinBlockZ() + z); + //blockState = chunkSections[i].getBlockState(x, y, z); + + tempLight += MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos); + //tempLight += MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos); + //tempLight += blockState.getLightBlock(chunk, blockPos); + } + + + light += tempLight; + + numbOfBlocks++; + + // we found a valid block, skip to the + // next x and z + foundBlock = true; + } + } + } + } + } + + if (numbOfBlocks == 0) + numbOfBlocks = 1; + + light /= numbOfBlocks; + if (light != 0) + { + System.out.println((chunk.getPos().getMinBlockX() + startX) + " " + (chunk.getPos().getMinBlockX() + endX) + " " + (chunk.getPos().getMinBlockZ() + startZ) + " " + (chunk.getPos().getMinBlockZ() + endZ)); + System.out.println(light); + } + return (byte) light; } /** @@ -435,9 +586,9 @@ public class LodBuilder int colorInt = 0; // block special cases - if (blockState == Blocks.AIR.defaultBlockState() - || blockState == Blocks.CAVE_AIR.defaultBlockState() - || blockState == Blocks.BARRIER.defaultBlockState()) + if (blockState == Blocks.AIR.defaultBlockState() + || blockState == Blocks.CAVE_AIR.defaultBlockState() + || blockState == Blocks.BARRIER.defaultBlockState()) { Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z)); tmp = tmp.darker(); diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 339493245..dd185d099 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -24,6 +24,7 @@ import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.ColorUtil; import com.seibel.lod.util.LodUtil; +import com.seibel.lod.wrappers.MinecraftWrapper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.util.Direction; @@ -60,8 +61,15 @@ public class CubicLodTemplate extends AbstractLodTemplate 0, posZ * width, bufferCenterBlockPos); + int color;/* + if(MinecraftWrapper.INSTANCE.getPlayer().level.isDay()) + { + color = DataPointUtil.getColor(data); + }else{ + color = DataPointUtil.getLightColor(data); + }*/ + color = DataPointUtil.getLightColor(data); - int color = DataPointUtil.getColor(data); if (debugging != DebugMode.OFF) { color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB(); diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 2ca05f865..9ba7d7841 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -125,6 +125,13 @@ public class DataPointUtil { return (int) ((dataPoint >>> COLOR_SHIFT) & COLOR_MASK); } + public static int getLightColor(long dataPoint) + { + int red = Math.min(getRed(dataPoint) + getLightValue(dataPoint)*8, 255); + int green = Math.min(getGreen(dataPoint) + getLightValue(dataPoint)*8, 255); + int blue = Math.min(getBlue(dataPoint) + getLightValue(dataPoint)*4, 255); + return ColorUtil.rgbToInt(red,green,blue); + } public static String toString(long dataPoint) { diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index f4e5da029..4bf2613e7 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -10,11 +10,13 @@ public class ThreadMapUtil public static final ConcurrentMap threadSingleAddDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadSingleGetDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadBuilderArrayMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalAddDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalGetDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); + public static long[] getSingleAddDataArray(){ if(!threadSingleAddDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleAddDataMap.get(Thread.currentThread().getName()) == null)) { @@ -39,6 +41,16 @@ public class ThreadMapUtil return threadSingleUpdateMap.get(Thread.currentThread().getName()); } + public static long[][] getBuilderArray(){ + if(!threadBuilderArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderArrayMap.get(Thread.currentThread().getName()) == null)) + { + long[][] array = new long[5][]; + threadBuilderArrayMap.put(Thread.currentThread().getName(), array); + } + return threadBuilderArrayMap.get(Thread.currentThread().getName()); + } + + public static long[] addVerticalDataArray(){ if(!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null)) { From 4e1e5b24ee762dc5f5e612181a4a2067dd6872b3 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sat, 11 Sep 2021 20:05:11 +0200 Subject: [PATCH 16/30] Changed the lodBuilder to use a single function --- src/main/java/com/seibel/lod/builders/LodBuilder.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 65af14779..4fe6608b5 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -263,7 +263,10 @@ public class LodBuilder blockState = chunkSections[sectionIndex].getBlockState(xRel, yRel, zRel); height = sectionIndex * CHUNK_DATA_WIDTH + yRel; - color = blockState.getBlock().defaultMaterialColor().col; + Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yRel + sectionIndex * chunkSections.length >> 2, + zRel >> 2); + color = getColorForBlock(xRel, zRel, blockState, biome); + //color = blockState.getBlock().defaultMaterialColor().col; blockPos.set(xAbs, height, zAbs); light = blockState.getLightBlock(chunk, blockPos); From c3115caa8f6819b676d85c396b5e06b423a8ed6e Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sun, 12 Sep 2021 16:29:41 +0200 Subject: [PATCH 17/30] Re-organized the LodBuilder code --- .../com/seibel/lod/builders/LodBuilder.java | 352 ++++-------------- .../lod/handlers/LodDimensionFileHandler.java | 7 +- .../seibel/lod/objects/LevelContainer.java | 2 +- 3 files changed, 81 insertions(+), 280 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 4fe6608b5..2226257f2 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -42,6 +42,8 @@ import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.IChunk; import net.minecraft.world.gen.Heightmap; +import javax.xml.crypto.Data; + /** * This object is in charge of creating Lod related objects. (specifically: Lod * World, Dimension, and Region objects) @@ -224,9 +226,7 @@ public class LodBuilder { long[] dataToMerge = ThreadMapUtil.getBuilderArray()[detail.detailLevel]; ChunkPos chunkPos = chunk.getPos(); - BlockState blockState; - ChunkSection[] chunkSections = chunk.getSections(); - ChunkSection section; + int size = 1 << detail.detailLevel; int height = 0; int depth = 0; @@ -235,12 +235,11 @@ public class LodBuilder int generation = config.distanceGenerationMode.complexity; int xRel; - int yRel; int zRel; int xAbs; + int yAbs; int zAbs; - int sectionIndex; - boolean voidData; + BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); int index = 0; if (dataToMerge == null) @@ -253,60 +252,24 @@ public class LodBuilder zRel = Math.floorDiv(index, size) + startZ; xAbs = chunkPos.getMinBlockX() + xRel; zAbs = chunkPos.getMinBlockZ() + zRel; - voidData = true; - for (sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--) + + //Calculate the height of the lod + height = determineHeightPoint(chunk, config, xRel, zRel); + + //If the lod is at default, then we set this as void data + if (height == DEFAULT_HEIGHT) { - for (yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) - { - if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) - { - blockState = chunkSections[sectionIndex].getBlockState(xRel, yRel, zRel); - - height = sectionIndex * CHUNK_DATA_WIDTH + yRel; - Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yRel + sectionIndex * chunkSections.length >> 2, - zRel >> 2); - color = getColorForBlock(xRel, zRel, blockState, biome); - //color = blockState.getBlock().defaultMaterialColor().col; - - blockPos.set(xAbs, height, zAbs); - light = blockState.getLightBlock(chunk, blockPos); - - voidData = false; - break; - } - } - if (!voidData) - { - break; - } - } - - if (voidData) - { - //no valid block has been found, this column is void dataToMerge[index] = DataPointUtil.createVoidDataPoint(generation); continue; } - //A valid block has been found. Now we search the deepest one + yAbs = height; + blockPos.set(xAbs, yAbs, zAbs); + + color = generateLodColor(chunk, config, xRel, height, zRel); + light = getLightBlockValue(chunk, blockPos, xRel, yAbs, zRel); + depth = determineBottomPoint(chunk, config, xRel, zRel); - voidData = true; - for (sectionIndex = 0; sectionIndex < chunkSections.length; sectionIndex++) - { - for (yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++) - { - if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) - { - depth = sectionIndex * CHUNK_DATA_WIDTH + yRel; - voidData = false; - break; - } - } - if (!voidData) - { - break; - } - } dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, light, generation); } return dataToMerge; @@ -318,267 +281,110 @@ public class LodBuilder /** * Find the lowest valid point from the bottom. */ - private short determineBottomPointForArea(ChunkSection[] chunkSections, int startX, int startZ, int endX, int endZ) + private short determineBottomPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel) { - int numberOfBlocksRequired = ((endX - startX) * (endZ - startZ) / 2); - - // search from the bottom up - for (int section = 0; section < CHUNK_DATA_WIDTH; section++) + ChunkSection[] chunkSections = chunk.getSections(); + short depth = DEFAULT_DEPTH; + if (config.useHeightmap) { - for (int y = 0; y < CHUNK_SECTION_HEIGHT; y++) + depth = 0; + } else + { + boolean found = false; + for (int sectionIndex = 0; sectionIndex < chunkSections.length; sectionIndex++) { - int numberOfBlocksFound = 0; - - for (int x = startX; x < endX; x++) + for (int yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++) { - for (int z = startZ; z < endZ; z++) + if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) { - if (isLayerValidLodPoint(chunkSections, section, y, x, z)) - { - numberOfBlocksFound++; - - if (numberOfBlocksFound >= numberOfBlocksRequired) - { - // we found - // enough blocks in this - // layer to count as an - // LOD point - return (short) (y + (section * CHUNK_SECTION_HEIGHT)); - } - } + depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel); + found = true; + break; } } + if (found) + { + break; + } } } - - // we never found a valid LOD point - return DEFAULT_DEPTH; + return depth; } - /** - * Find the lowest valid point from the bottom. - */ - @SuppressWarnings("unused") - private short determineBottomPoint(Heightmap heightmap) - { - // the heightmap only shows how high the blocks go, it - // doesn't have any info about how low they go - return 0; - } - /** * Find the highest valid point from the Top */ - private short determineHeightPointForArea(ChunkSection[] chunkSections, int startX, int startZ, int endX, int endZ) + private short determineHeightPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel) { - int numberOfBlocksRequired = ((endX - startX) * (endZ - startZ) / 2); - // search from the top down - for (int section = chunkSections.length - 1; section >= 0; section--) + short height = DEFAULT_HEIGHT; + if (config.useHeightmap) { - for (int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--) + height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel); + } else + { + boolean voidData = true; + ChunkSection[] chunkSections = chunk.getSections(); + for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--) { - int numberOfBlocksFound = 0; - - for (int x = startX; x < endX; x++) + for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) { - for (int z = startZ; z < endZ; z++) + if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) { - if (isLayerValidLodPoint(chunkSections, section, y, x, z)) - { - numberOfBlocksFound++; - - if (numberOfBlocksFound >= numberOfBlocksRequired) - { - // we found - // enough blocks in this - // layer to count as an - // LOD point - return (short) (y + 1 + (section * CHUNK_SECTION_HEIGHT)); - } - } + height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel); + voidData = false; + break; } } + if (!voidData) + { + break; + } } } - - // we never found a valid LOD point - return DEFAULT_HEIGHT; - } - - - /** - * Find the highest point from the Top - */ - private short determineHeightPoint(Heightmap heightmap, int startX, int startZ, int endX, int endZ) - { - short highest = 0; - for (int x = startX; x < endX; x++) - { - for (int z = startZ; z < endZ; z++) - { - short newHeight = (short) heightmap.getFirstAvailable(x, z); - if (newHeight > highest) - highest = newHeight; - } - } - - return highest; + return height; } /** * Generate the color for the given chunk using biome water color, foliage * color, and grass color. - * - * @param config_useSolidBlocksInColorGen
- * If true we look down from the top of - * the
- * chunk until we find a non-invisible - * block, and then use
- * its color. If false we generate the - * color immediately for
- * each x and z. - * @param config_useBiomeColors
- * If true use biome foliage, water, and - * grass colors,
- * otherwise only use the block's - * material color */ - private int generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, - int endZ) + private int generateLodColor(IChunk chunk, LodBuilderConfig config, int xRel, int yAbs, int zRel) { ChunkSection[] chunkSections = chunk.getSections(); - - int numbOfBlocks = 0; - int red = 0; - int green = 0; - int blue = 0; - - for (int x = startX; x < endX; x++) + int colorInt = 0; + if (config.useBiomeColors) { - for (int z = startZ; z < endZ; z++) + // I have no idea why I need to bit shift to the right, but + // if I don't the biomes don't show up correctly. + Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2); + colorInt = getColorForBiome(xRel, zRel, biome); + } else + { + int sectionIndex = Math.floorDiv(yAbs, CHUNK_SECTION_HEIGHT); + int yRel = Math.floorMod(yAbs, CHUNK_SECTION_HEIGHT); + if (chunkSections[sectionIndex] != null) { - boolean foundBlock = false; + BlockState blockState = chunkSections[sectionIndex].getBlockState(xRel, yRel, zRel); - // go top down - for (int i = chunkSections.length - 1; !foundBlock && i >= 0; i--) - { - if (!foundBlock && (chunkSections[i] != null || !config.useSolidBlocksInColorGen)) - { - for (int y = CHUNK_SECTION_HEIGHT - 1; !foundBlock && y >= 0; y--) - { - int colorInt = 0; - BlockState blockState = null; - if (chunkSections[i] != null) - { - blockState = chunkSections[i].getBlockState(x, y, z); - colorInt = blockState.getBlock().defaultMaterialColor().col; - } + // the bit shift is equivalent to dividing by 4 + Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2); - if (colorInt == 0 && config.useSolidBlocksInColorGen) - { - // skip air or invisible blocks - continue; - } - - if (config.useBiomeColors) - { - // I have no idea why I need to bit shift to the right, but - // if I don't the biomes don't show up correctly. - Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + 1 * chunkSections.length >> 2, - z >> 2); - colorInt = getColorForBiome(x, z, biome); - } else - { - - // the bit shift is equivalent to dividing by 4 - Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + i * chunkSections.length >> 2, - z >> 2); - colorInt = getColorForBlock(x, z, blockState, biome); - } - - red += ColorUtil.getRed(colorInt); - green += ColorUtil.getGreen(colorInt); - blue += ColorUtil.getBlue(colorInt); - - numbOfBlocks++; - - // we found a valid block, skip to the - // next x and z - foundBlock = true; - } - } - } + colorInt = getColorForBlock(xRel, zRel, blockState, biome); } } - - if (numbOfBlocks == 0) - numbOfBlocks = 1; - - red /= numbOfBlocks; - green /= numbOfBlocks; - blue /= numbOfBlocks; - return ColorUtil.rgbToInt(red, green, blue); + return colorInt; } - private byte generateLodLightForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, - int endZ) + private byte getLightBlockValue(IChunk chunk, BlockPos.Mutable blockPos, int xRel, int yAbs, int zRel) { - ChunkSection[] chunkSections = chunk.getSections(); + byte lightBlock; + BlockState blockState = chunk.getSections()[Math.floorDiv(yAbs, CHUNK_SECTION_HEIGHT)].getBlockState(xRel, Math.floorMod(yAbs, CHUNK_SECTION_HEIGHT), zRel); - int numbOfBlocks = 0; - int tempLight; - int light = 0; - BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); - for (int x = startX; x < endX; x++) - { - for (int z = startZ; z < endZ; z++) - { - boolean foundBlock = false; - - // go top down - for (int i = chunkSections.length - 1; !foundBlock && i >= 0; i--) - { - if (!foundBlock && (chunkSections[i] != null || !config.useSolidBlocksInColorGen)) - { - for (int y = CHUNK_SECTION_HEIGHT - 1; !foundBlock && y >= 0; y--) - { - tempLight = 0; - BlockState blockState = null; - if (chunkSections[i] != null) - { - blockPos.set(chunk.getPos().getMinBlockX() + x, y, chunk.getPos().getMinBlockZ() + z); - //blockState = chunkSections[i].getBlockState(x, y, z); - - tempLight += MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos); - //tempLight += MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos); - //tempLight += blockState.getLightBlock(chunk, blockPos); - } - - - light += tempLight; - - numbOfBlocks++; - - // we found a valid block, skip to the - // next x and z - foundBlock = true; - } - } - } - } - } - - if (numbOfBlocks == 0) - numbOfBlocks = 1; - - light /= numbOfBlocks; - if (light != 0) - { - System.out.println((chunk.getPos().getMinBlockX() + startX) + " " + (chunk.getPos().getMinBlockX() + endX) + " " + (chunk.getPos().getMinBlockZ() + startZ) + " " + (chunk.getPos().getMinBlockZ() + endZ)); - System.out.println(light); - } - return (byte) light; + //lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos); + //lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos); + lightBlock = (byte) blockState.getLightBlock(chunk, blockPos); + return lightBlock; } /** diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 1c6008dae..2a6385a41 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -46,11 +46,6 @@ import com.seibel.lod.util.LodUtil; */ public class LodDimensionFileHandler { - /** - * This is what separates each piece of data - */ - public static final char DATA_DELIMITER = ','; - private LodDimension loadedDimension = null; public long regionLastWriteTime[][]; @@ -84,7 +79,7 @@ public class LodDimensionFileHandler * file handler, older versions (smaller numbers) will be deleted and overwritten, * newer versions (larger numbers) will be ignored and won't be read. */ - public static final int LOD_SAVE_FILE_VERSION = 5; + public static final int LOD_SAVE_FILE_VERSION = 6; /** * This is the string written before the file version diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index 1e2607ab8..72006de7f 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -9,7 +9,7 @@ import java.util.concurrent.ConcurrentMap; public interface LevelContainer { public static final char VERTICAL_DATA_DELIMITER = '\t'; - public static final char DATA_DELIMITER = ','; + public static final char DATA_DELIMITER = '\n'; /**With this you can add data to the level container * * @param data actual data to add in a array of long format. From a6544d3bb6b3cf391ae6416b8576a0ad101dbe3d Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 13 Sep 2021 00:37:23 +0200 Subject: [PATCH 18/30] Introduced light and added normal in the template for future shading improvement --- .../com/seibel/lod/builders/LodBuilder.java | 22 ++++++++++--------- .../lodTemplates/AbstractLodTemplate.java | 13 ++++++++++- .../lodTemplates/CubicLodTemplate.java | 15 +++++++++---- .../com/seibel/lod/util/DataPointUtil.java | 9 +++++--- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 2226257f2..41ef198fe 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -263,11 +263,12 @@ public class LodBuilder continue; } - yAbs = height; - blockPos.set(xAbs, yAbs, zAbs); + yAbs = height - 1; + // We search light on above air block + blockPos.set(xAbs, yAbs + 1, zAbs); - color = generateLodColor(chunk, config, xRel, height, zRel); - light = getLightBlockValue(chunk, blockPos, xRel, yAbs, zRel); + color = generateLodColor(chunk, config, xRel, yAbs, zRel); + light = getLightBlockValue(chunk, blockPos); depth = determineBottomPoint(chunk, config, xRel, zRel); dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, light, generation); @@ -331,7 +332,7 @@ public class LodBuilder { if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) { - height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel); + height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); voidData = false; break; } @@ -376,14 +377,15 @@ public class LodBuilder return colorInt; } - private byte getLightBlockValue(IChunk chunk, BlockPos.Mutable blockPos, int xRel, int yAbs, int zRel) + private int getLightBlockValue(IChunk chunk, BlockPos.Mutable blockPos) { - byte lightBlock; - BlockState blockState = chunk.getSections()[Math.floorDiv(yAbs, CHUNK_SECTION_HEIGHT)].getBlockState(xRel, Math.floorMod(yAbs, CHUNK_SECTION_HEIGHT), zRel); + int lightBlock; //lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos); - //lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos); - lightBlock = (byte) blockState.getLightBlock(chunk, blockPos); + //lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos); + lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.BLOCK, blockPos); + //BlockState blockState = chunk.getBlockState(blockPos); + //lightBlock = (byte) blockState.getLightBlock(chunk, blockPos); return lightBlock; } diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java index b44d75756..584c8dd7f 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java @@ -19,7 +19,9 @@ package com.seibel.lod.builders.lodTemplates; import com.seibel.lod.enums.DebugMode; +import com.seibel.lod.enums.DistanceGenerationMode; import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; /** @@ -31,9 +33,17 @@ import net.minecraft.util.math.BlockPos; */ public abstract class AbstractLodTemplate { + + private Direction direction; + public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, byte detailLevel, int posX, int posZ, Box box, DebugMode debugging); + + protected void setDirection(Direction direction){ + this.direction = direction; + } + /** * add the given position and color to the buffer */ @@ -41,7 +51,8 @@ public abstract class AbstractLodTemplate double x, double y, double z, int red, int green, int blue, int alpha) { - buffer.vertex(x, y, z).color(red, green, blue, alpha).endVertex(); + + buffer.vertex(x, y, z).color(red, green, blue, alpha).normal(direction.getNormal().getX(), direction.getNormal().getY(), direction.getNormal().getZ()).endVertex(); } /** diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index dd185d099..17811fe72 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -61,14 +61,15 @@ public class CubicLodTemplate extends AbstractLodTemplate 0, posZ * width, bufferCenterBlockPos); - int color;/* - if(MinecraftWrapper.INSTANCE.getPlayer().level.isDay()) + int color; + int time = (int) (MinecraftWrapper.INSTANCE.getPlayer().level.getDayTime() - 13000); + if(time < 0) { color = DataPointUtil.getColor(data); }else{ + /*TODO implement a smoother transition for light from day to night */ color = DataPointUtil.getLightColor(data); - }*/ - color = DataPointUtil.getLightColor(data); + } if (debugging != DebugMode.OFF) { @@ -171,6 +172,7 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); + setDirection(Direction.UP); addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); @@ -189,6 +191,7 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); + setDirection(Direction.DOWN); addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); @@ -210,6 +213,7 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); + setDirection(Direction.WEST); if (data == 0) { addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); @@ -255,6 +259,7 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); + setDirection(Direction.EAST); if (data == 0) { addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); @@ -301,6 +306,7 @@ public class CubicLodTemplate extends AbstractLodTemplate minZ = box.getMinZ(); maxZ = box.getMaxZ(); // north (facing +Z) + setDirection(Direction.NORTH); if (data == 0) { addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); @@ -347,6 +353,7 @@ public class CubicLodTemplate extends AbstractLodTemplate minZ = box.getMinZ(); maxZ = box.getMaxZ(); // south (facing -Z) + setDirection(Direction.SOUTH); if (data == 0) { addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 9ba7d7841..68ab66ef6 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -125,11 +125,13 @@ public class DataPointUtil { return (int) ((dataPoint >>> COLOR_SHIFT) & COLOR_MASK); } + public static int getLightColor(long dataPoint) { - int red = Math.min(getRed(dataPoint) + getLightValue(dataPoint)*8, 255); - int green = Math.min(getGreen(dataPoint) + getLightValue(dataPoint)*8, 255); - int blue = Math.min(getBlue(dataPoint) + getLightValue(dataPoint)*4, 255); + int lightBlock = getLightValue(dataPoint); + int red = Math.min(getRed(dataPoint) + lightBlock*8, 255); + int green = Math.min(getGreen(dataPoint) + lightBlock*8, 255); + int blue = Math.min(getBlue(dataPoint) + lightBlock*4, 255); return ColorUtil.rgbToInt(red,green,blue); } @@ -176,6 +178,7 @@ public class DataPointUtil tempBlue += DataPointUtil.getBlue(data); tempHeight += DataPointUtil.getHeight(data); tempDepth += DataPointUtil.getDepth(data); + tempLight += DataPointUtil.getLightValue(data); } else { // void children have the default height (most likely -1) From 95d9c17e4977879947f1ad5c63a120f9e053b63b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 13 Sep 2021 01:19:39 +0200 Subject: [PATCH 19/30] Added new colors for the torches --- .../com/seibel/lod/builders/LodBuilder.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 41ef198fe..8af31d10b 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -373,6 +373,11 @@ public class LodBuilder colorInt = getColorForBlock(xRel, zRel, blockState, biome); } + if (colorInt == 0 && yAbs > 0) + { + //invisible case + colorInt = generateLodColor(chunk, config, xRel, yAbs - 1, zRel); + } } return colorInt; } @@ -381,6 +386,7 @@ public class LodBuilder { int lightBlock; + //*TODO choose the best one between those options*/ //lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos); //lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos); lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.BLOCK, blockPos); @@ -410,8 +416,21 @@ public class LodBuilder } else if (blockState == Blocks.MYCELIUM.defaultBlockState()) { colorInt = LodUtil.MYCELIUM_COLOR_INT; + } else if (blockState == Blocks.SOUL_TORCH.defaultBlockState() + || blockState == Blocks.SOUL_WALL_TORCH.defaultBlockState()) + { + colorInt = Blocks.WARPED_PLANKS.defaultMaterialColor().col; + } else if (blockState == Blocks.TORCH.defaultBlockState() + || blockState == Blocks.WALL_TORCH.defaultBlockState()) + { + colorInt = Blocks.OAK_PLANKS.defaultMaterialColor().col; + } else if (blockState == Blocks.REDSTONE_TORCH.defaultBlockState() + || blockState == Blocks.REDSTONE_WALL_TORCH.defaultBlockState()) + { + colorInt = Blocks.CRIMSON_PLANKS.defaultMaterialColor().col; } + // plant life else if (blockState.getBlock() instanceof LeavesBlock || blockState.getBlock() == Blocks.VINE) { @@ -436,7 +455,7 @@ public class LodBuilder // everything else else { - colorInt = blockState.materialColor.col; + colorInt = blockState.getBlock().defaultMaterialColor().col; } return colorInt; From 76a7baeb329d937d435a7f577c2e966490979b50 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 13 Sep 2021 01:47:04 +0200 Subject: [PATCH 20/30] Saving works again --- .../lod/builders/lodTemplates/AbstractLodTemplate.java | 2 +- src/main/java/com/seibel/lod/objects/LevelContainer.java | 2 +- .../java/com/seibel/lod/objects/SingleLevelContainer.java | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java index 584c8dd7f..185dc8740 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java @@ -51,7 +51,7 @@ public abstract class AbstractLodTemplate double x, double y, double z, int red, int green, int blue, int alpha) { - + //buffer.vertex(x, y, z).color(red, green, blue, alpha).normal(direction.getNormal().getX(), direction.getNormal().getY(), direction.getNormal().getZ()).endVertex(); buffer.vertex(x, y, z).color(red, green, blue, alpha).normal(direction.getNormal().getX(), direction.getNormal().getY(), direction.getNormal().getZ()).endVertex(); } diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index 72006de7f..94bcd2c36 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -9,7 +9,7 @@ import java.util.concurrent.ConcurrentMap; public interface LevelContainer { public static final char VERTICAL_DATA_DELIMITER = '\t'; - public static final char DATA_DELIMITER = '\n'; + public static final char DATA_DELIMITER = ' '; /**With this you can add data to the level container * * @param data actual data to add in a array of long format. diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index 3d45c89e4..88984802e 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -77,13 +77,15 @@ public class SingleLevelContainer implements LevelContainer newData = 0; for(tempIndex = 0; tempIndex < 16; tempIndex++) { + if(index+tempIndex >= inputString.length()) + break; currentChar = inputString.charAt(index+tempIndex); - if(currentChar == ','){ + if(currentChar == DATA_DELIMITER){ break; } shift = (15-tempIndex)*4; digit = Character.digit(currentChar,16); - newData += ((long) (digit & 0xf)) << shift; + newData += ((((long) digit & 0xf)) << shift); } newData = newData >>> (shift); data[x][z] = newData; From 32de70b4f01c053c146867d8a9c3d1d062a2836f Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 13 Sep 2021 01:48:11 +0200 Subject: [PATCH 21/30] Removed the normals --- .../builders/lodTemplates/AbstractLodTemplate.java | 11 ++--------- .../lod/builders/lodTemplates/CubicLodTemplate.java | 6 ------ 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java index 185dc8740..73d7e2e2d 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java @@ -19,7 +19,6 @@ package com.seibel.lod.builders.lodTemplates; import com.seibel.lod.enums.DebugMode; -import com.seibel.lod.enums.DistanceGenerationMode; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -34,16 +33,10 @@ import net.minecraft.util.math.BlockPos; public abstract class AbstractLodTemplate { - private Direction direction; public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData, byte detailLevel, int posX, int posZ, Box box, DebugMode debugging); - - protected void setDirection(Direction direction){ - this.direction = direction; - } - /** * add the given position and color to the buffer */ @@ -51,8 +44,8 @@ public abstract class AbstractLodTemplate double x, double y, double z, int red, int green, int blue, int alpha) { - //buffer.vertex(x, y, z).color(red, green, blue, alpha).normal(direction.getNormal().getX(), direction.getNormal().getY(), direction.getNormal().getZ()).endVertex(); - buffer.vertex(x, y, z).color(red, green, blue, alpha).normal(direction.getNormal().getX(), direction.getNormal().getY(), direction.getNormal().getZ()).endVertex(); + + buffer.vertex(x, y, z).color(red, green, blue, alpha).endVertex(); } /** diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 17811fe72..3aa000667 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -172,7 +172,6 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); - setDirection(Direction.UP); addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); @@ -191,7 +190,6 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); - setDirection(Direction.DOWN); addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); @@ -213,7 +211,6 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); - setDirection(Direction.WEST); if (data == 0) { addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); @@ -259,7 +256,6 @@ public class CubicLodTemplate extends AbstractLodTemplate maxY = box.getMaxY(); minZ = box.getMinZ(); maxZ = box.getMaxZ(); - setDirection(Direction.EAST); if (data == 0) { addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); @@ -306,7 +302,6 @@ public class CubicLodTemplate extends AbstractLodTemplate minZ = box.getMinZ(); maxZ = box.getMaxZ(); // north (facing +Z) - setDirection(Direction.NORTH); if (data == 0) { addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); @@ -353,7 +348,6 @@ public class CubicLodTemplate extends AbstractLodTemplate minZ = box.getMinZ(); maxZ = box.getMaxZ(); // south (facing -Z) - setDirection(Direction.SOUTH); if (data == 0) { addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha); From 34776074fdf4411c497fe26cd37950bc99827d25 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 13 Sep 2021 13:16:52 +0200 Subject: [PATCH 22/30] added the vertical merge --- .../com/seibel/lod/util/DataPointUtil.java | 136 ++++++++++++++---- 1 file changed, 108 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 68ab66ef6..e59e761b0 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -1,6 +1,10 @@ package com.seibel.lod.util; import com.seibel.lod.enums.DistanceGenerationMode; +import org.lwjgl.system.CallbackI; + +import java.lang.reflect.Array; +import java.util.Arrays; public class DataPointUtil { @@ -77,7 +81,7 @@ public class DataPointUtil public static short getDepth(long dataPoint) { - return (short) ((dataPoint >> DEPTH_SHIFT) & DEPTH_MASK); + return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK); } public static short getAlpha(long dataPoint) @@ -129,10 +133,10 @@ public class DataPointUtil public static int getLightColor(long dataPoint) { int lightBlock = getLightValue(dataPoint); - int red = Math.min(getRed(dataPoint) + lightBlock*8, 255); - int green = Math.min(getGreen(dataPoint) + lightBlock*8, 255); - int blue = Math.min(getBlue(dataPoint) + lightBlock*4, 255); - return ColorUtil.rgbToInt(red,green,blue); + int red = Math.min(getRed(dataPoint) + lightBlock * 8, 255); + int green = Math.min(getGreen(dataPoint) + lightBlock * 8, 255); + int blue = Math.min(getBlue(dataPoint) + lightBlock * 4, 255); + return ColorUtil.rgbToInt(red, green, blue); } public static String toString(long dataPoint) @@ -164,14 +168,17 @@ public class DataPointUtil int tempDepth = 0; int tempLight = 0; byte tempGenMode = DistanceGenerationMode.SERVER.complexity; - for(long data : dataToMerge) + boolean allEmpty = true; + boolean allVoid = true; + for (long data : dataToMerge) { if (DataPointUtil.doesItExist(data)) { + allEmpty = false; if (!(DataPointUtil.isItVoid(data))) { numberOfChildren++; - + allVoid = false; tempAlpha += DataPointUtil.getAlpha(data); tempRed += DataPointUtil.getRed(data); tempGreen += DataPointUtil.getGreen(data); @@ -179,11 +186,6 @@ public class DataPointUtil tempHeight += DataPointUtil.getHeight(data); tempDepth += DataPointUtil.getDepth(data); tempLight += DataPointUtil.getLightValue(data); - } else - { - // void children have the default height (most likely -1) - // and represent a LOD with no blocks in it - numberOfVoidChildren++; } tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(data)); } else @@ -191,7 +193,16 @@ public class DataPointUtil tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity); } } - if (numberOfChildren > 0) + + if (allEmpty) + { + //no child has been initialized + return DataPointUtil.EMPTY_DATA; + } else if (allVoid) + { + //all the children are void + return DataPointUtil.createVoidDataPoint(tempGenMode); + } else { //we have at least 1 child tempAlpha = tempAlpha / numberOfChildren; @@ -202,24 +213,93 @@ public class DataPointUtil tempDepth = tempDepth / numberOfChildren; tempLight = tempLight / numberOfChildren; return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLight, tempGenMode); - } else if (numberOfVoidChildren > 0) - { - //all the children are void - return DataPointUtil.createVoidDataPoint(tempGenMode); - }else - { - //no child has been initialized - return DataPointUtil.EMPTY_DATA; } } -/* - public static int mergeVerticalData(long dataPoint) + + public static long[] mergeVerticalData(long[][] dataToMerge) { - int R = (getRed(dataPoint) << 16) & 0x00FF0000; - int G = (getGreen(dataPoint) << 8) & 0x0000FF00; - int B = getBlue(dataPoint) & 0x000000FF; - return 0xFF000000 | R | G | B; - }*/ + int[][] dataCollector = new int[256][2]; + long[] singleDataToCollect = new long[256]; + int size = 0; + + int tempGenMode = DistanceGenerationMode.SERVER.complexity; + boolean allEmpty = true; + boolean allVoid = true; + long singleData; + + //We collect the indexes of the data, ordered by the depth + for (int index = 0; index < dataToMerge.length; index++) + { + for (int dataIndex = 0; dataIndex < dataToMerge.length; dataIndex++) + { + singleData = dataToMerge[index][dataIndex]; + if (doesItExist(singleData)) + { + tempGenMode = Math.min(tempGenMode, getGenerationMode(singleData)); + allEmpty = false; + if (!isItVoid(singleData)) + { + allVoid = false; + int j = size; + while (j >= 0 && (getDepth(dataToMerge[dataCollector[j][0]][dataCollector[j][1]]) > getDepth(singleData))) + { + dataCollector[j] = dataCollector[j - 1]; + j = j - 1; + } + dataCollector[j][0] = dataIndex; + dataCollector[j][1] = index; + size++; + } + } + } + } + + + //We check if there is any data that's not empty or void + if (allEmpty) + { + return new long[]{EMPTY_DATA}; + } + if (allVoid) + { + return new long[]{createVoidDataPoint(tempGenMode)}; + } + + //We merge together all the data + int minDepth; + int maxHeight = Integer.MIN_VALUE; + int tempDepth; + int tempHeight; + int index = 0; + int dataCount = 0; + long[] singleDataToMerge = new long[dataToMerge.length]; + long[] newData = new long[dataToMerge.length]; + while (index < size) + { + dataCount++; + singleData = dataToMerge[dataCollector[index][0]][dataCollector[index][1]]; + minDepth = getDepth(singleData); + maxHeight = getHeight(singleData); + index++; + while(index < size) + { + singleData = dataToMerge[dataCollector[index][0]][dataCollector[index][1]]; + tempDepth = getDepth(singleData); + tempHeight = getHeight(singleData); + if(maxHeight >= tempDepth) + { + singleDataToMerge[dataCollector[index][0]] = singleData; + maxHeight = tempHeight; + index++; + }else{ + break; + } + } + singleData = mergeSingleData(singleDataToMerge); + newData[dataCount] = createDataPoint(maxHeight, minDepth, getColor(singleData), getLightValue(singleData), getGenerationMode(singleData)); + } + return Arrays.copyOf(newData, dataCount); + } public static long[] compress(long[] data, byte detailLevel) { From 75e78d9000ab12c42dab5fdefe05685b0897f397 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 13 Sep 2021 17:34:37 +0200 Subject: [PATCH 23/30] First vertical data working --- .../seibel/lod/builders/LodBufferBuilder.java | 73 +++++----- .../com/seibel/lod/builders/LodBuilder.java | 108 +++++++++++---- .../lod/handlers/LodDimensionFileHandler.java | 8 +- .../com/seibel/lod/objects/LodDimension.java | 12 +- .../com/seibel/lod/objects/LodRegion.java | 3 +- .../lod/objects/VerticalLevelContainer.java | 125 +++--------------- .../com/seibel/lod/util/DataPointUtil.java | 122 +++++++++++++++-- .../java/com/seibel/lod/util/LodUtil.java | 3 +- .../com/seibel/lod/util/ThreadMapUtil.java | 15 ++- 9 files changed, 279 insertions(+), 190 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index ce393d0ea..bd2cd397d 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -116,11 +116,12 @@ public class LodBufferBuilder private volatile PosToRenderContainer[][] setsToRender; private volatile RegionPos center; - /** This is the ChunkPos the player was at the last time the buffers were built. - * IE the center of the buffers last time they were built */ - private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0,0); - private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0,0); - + /** + * This is the ChunkPos the player was at the last time the buffers were built. + * IE the center of the buffers last time they were built + */ + private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0, 0); + private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0, 0); public LodBufferBuilder() @@ -250,8 +251,9 @@ public class LodBufferBuilder int chunkXdist; int chunkZdist; short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length / 2 - 1); - long dataPoint; + //long dataPoint; long[] adjData = new long[NUMBER_OF_DIRECTION]; + for (int index = 0; index < posToRender.getNumberOfPos(); index++) { detailLevel = posToRender.getNthDetailLevel(index); @@ -270,39 +272,44 @@ public class LodBufferBuilder // skip any chunks that Minecraft is going to render try { - if (lodDim.doesDataExist(detailLevel, posX, posZ)) + //dataPoint = lodDim.getData(detailLevel, posX, posZ)[0]; + for(long dataPoint : lodDim.getData(detailLevel, posX, posZ)) { - dataPoint = lodDim.getData(detailLevel, posX, posZ); - if(DataPointUtil.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPointUtil.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH) - continue; - for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++) - { - xAdj = posX + ADJ_DIRECTION[direction][0]; - zAdj = posZ + ADJ_DIRECTION[direction][1]; - chunkXdist = LevelPosUtil.getChunkPos(detailLevel,xAdj) - playerChunkPos.x; - chunkZdist = LevelPosUtil.getChunkPos(detailLevel,zAdj) - playerChunkPos.z; - if (gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist)) + if (!DataPointUtil.isItVoid(dataPoint) && DataPointUtil.doesItExist(dataPoint)) + { + /* + for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++) { - if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1] - && posToRender.contains(detailLevel, xAdj, zAdj)) + xAdj = posX + ADJ_DIRECTION[direction][0]; + zAdj = posZ + ADJ_DIRECTION[direction][1]; + chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkPos.x; + chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkPos.z; + + if (gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist)) { - adjData[direction]= lodDim.getData(detailLevel, xAdj, zAdj); - }else{ - adjData[direction]= 0; - } - } else - { - if (posToRender.contains(detailLevel, xAdj, zAdj)) + if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1] + && posToRender.contains(detailLevel, xAdj, zAdj)) + { + adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj)[0]; + } else + { + adjData[direction] = 0; + } + } else { - adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj); - }else{ - adjData[direction]= 0; + if (posToRender.contains(detailLevel, xAdj, zAdj)) + { + adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj)[0]; + } else + { + adjData[direction] = 0; + } } - } + }*/ + LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData, + detailLevel, posX, posZ, boxCache[xR][zR], renderer.previousDebugMode); } - LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData, - detailLevel, posX, posZ, boxCache[xR][zR],renderer.previousDebugMode); } } catch (ArrayIndexOutOfBoundsException e) { @@ -477,7 +484,6 @@ public class LodBufferBuilder } - /** * Get the newly created VBOs */ @@ -500,6 +506,7 @@ public class LodBufferBuilder return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos); } + /** * A simple container to pass multiple objects back in the getVertexBuffers method. */ diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 8af31d10b..5d1326735 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -167,7 +167,6 @@ public class LodBuilder byte light; short height; short depth; - long data; try { LodDetail detail; @@ -187,41 +186,100 @@ public class LodBuilder endX = detail.endX[i]; endZ = detail.endZ[i]; - /* - color = generateLodColorForArea(chunk, config, startX, startZ, endX, endZ); - light = generateLodLightForArea(chunk, config, startX, startZ, endX, endZ); - - if (!config.useHeightmap) - { - height = determineHeightPointForArea(chunk.getSections(), startX, startZ, endX, endZ); - depth = determineBottomPointForArea(chunk.getSections(), startX, startZ, endX, endZ); - } else - { - height = determineHeightPoint(chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP), startX, - startZ, endX, endZ); - depth = 0; - }*/ posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel); posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel); - long[] dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; - data = DataPointUtil.mergeSingleData(dataToMerge); - lodDim.addData(detailLevel, - posX, - posZ, - data, - false, - isServer); + long[] data; + long[] dataToMerge; + //data = ThreadMapUtil.getSingleAddDataArray(); + dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + + try + { + long[][] dataToMerge2 = new long[dataToMerge.length][]; + for (int index = 0; index < dataToMerge.length; index++) + { + dataToMerge2[index] = new long[]{dataToMerge[index]}; + } + //data[0] = DataPointUtil.mergeSingleData(dataToMerge); + + //dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + data = DataPointUtil.mergeVerticalData(dataToMerge2); + + boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; + lodDim.addData(detailLevel, + posX, + posZ, + data, + false, + isServer); + }catch (Exception e) + { + e.printStackTrace(); + throw e; + } } lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); } catch (Exception e) { e.printStackTrace(); - throw e; } } + /*private long[][] createVerticalDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) + { + long[][] dataToMerge = ThreadMapUtil.getBuilderVerticalArray()[detail.detailLevel]; + ChunkPos chunkPos = chunk.getPos(); + + int size = 1 << detail.detailLevel; + int height = 0; + int depth = 0; + int color = 0; + int light = 0; + int generation = config.distanceGenerationMode.complexity; + + int xRel; + int zRel; + int xAbs; + int yAbs; + int zAbs; + + BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); + int index = 0; + if (dataToMerge == null) + { + dataToMerge = new long[size * size][256]; + } + for (index = 0; index < size * size; index++) + { + xRel = Math.floorMod(index, size) + startX; + zRel = Math.floorDiv(index, size) + startZ; + xAbs = chunkPos.getMinBlockX() + xRel; + zAbs = chunkPos.getMinBlockZ() + zRel; + + //Calculate the height of the lod + height = determineHeightPoint(chunk, config, xRel, zRel); + + //If the lod is at default, then we set this as void data + if (height == DEFAULT_HEIGHT) + { + dataToMerge[index] = DataPointUtil.createVoidDataPoint(generation); + continue; + } + + yAbs = height - 1; + // We search light on above air block + blockPos.set(xAbs, yAbs + 1, zAbs); + + color = generateLodColor(chunk, config, xRel, yAbs, zRel); + light = getLightBlockValue(chunk, blockPos); + depth = determineBottomPoint(chunk, config, xRel, zRel); + + dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, light, generation); + } + return dataToMerge; + }*/ + private long[] createSingleDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) { long[] dataToMerge = ThreadMapUtil.getBuilderArray()[detail.detailLevel]; diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 2a6385a41..0df076916 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -28,10 +28,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.objects.SingleLevelContainer; -import com.seibel.lod.objects.LodDimension; -import com.seibel.lod.objects.LodRegion; -import com.seibel.lod.objects.RegionPos; +import com.seibel.lod.objects.*; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; @@ -195,7 +192,8 @@ public class LodDimensionFileHandler data = bufferedReader.readLine(); bufferedReader.close(); - region.addLevel(new SingleLevelContainer(data)); + //region.addLevel(new SingleLevelContainer(data)); + region.addLevel(new VerticalLevelContainer(data)); } catch (Exception e) { // the buffered reader encountered a diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 4b1db5d6f..127d541f7 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -433,7 +433,7 @@ public class LodDimension * stored in the LOD. If an LOD already exists at the given * coordinates it will be overwritten. */ - public Boolean addData(byte detailLevel, int posX, int posZ, long lodDataPoint, boolean dontSave, boolean serverQuality) + public Boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean dontSave, boolean serverQuality) { // don't continue if the region can't be saved @@ -443,9 +443,7 @@ public class LodDimension LodRegion region = getRegion(regionPosX, regionPosZ); if (region == null) return false; - long[] dataArray = ThreadMapUtil.getSingleAddDataArray(); - dataArray[0] = lodDataPoint; - boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataArray, serverQuality); + boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataPoint, serverQuality); // only save valid LODs to disk if (!dontSave && fileHandler != null) { @@ -520,7 +518,7 @@ public class LodDimension * Returns null if the LodChunk doesn't exist or * is outside the loaded area. */ - public long getData(byte detailLevel, int posX, int posZ) + public long[] getData(byte detailLevel, int posX, int posZ) { if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); @@ -529,10 +527,10 @@ public class LodDimension if (region == null) { - return 0; + return new long[]{DataPointUtil.EMPTY_DATA}; } - return region.getData(detailLevel, posX, posZ)[0]; + return region.getData(detailLevel, posX, posZ); } diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index 29f5ed7a9..b21efdd06 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -55,7 +55,8 @@ public class LodRegion //Initialize all the different matrices for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { - dataContainer[lod] = new SingleLevelContainer(lod); + //dataContainer[lod] = new SingleLevelContainer(lod); + dataContainer[lod] = new VerticalLevelContainer(lod); /*if(twoDimension){ dataContainer[lod] = new SingleLevelContainer(lod); }else{ diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index 1c26730d6..f8a96d9a2 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -1,8 +1,11 @@ package com.seibel.lod.objects; -/* + import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; +import com.seibel.lod.util.ThreadMapUtil; + +import java.security.InvalidParameterException; public class VerticalLevelContainer implements LevelContainer { @@ -15,13 +18,7 @@ public class VerticalLevelContainer implements LevelContainer { this.detailLevel = detailLevel; int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - dataContainer = new long[size][size][]; - } - - public VerticalLevelContainer(byte detailLevel, long[][][] data) - { - this.detailLevel = detailLevel; - this.dataContainer = data; + dataContainer = new long[size][size][1]; } @Override @@ -45,12 +42,15 @@ public class VerticalLevelContainer implements LevelContainer public boolean doesItExist(int posX, int posZ){ long[] data = getData(posX,posZ); - return (data != null && DataPointUtil.doesItExist(data[0])); + return DataPointUtil.doesItExist(data[0]); } public VerticalLevelContainer(String inputString) { + throw new InvalidParameterException("loading not yet implemented"); + +/* int index = 0; int lastIndex = 0; @@ -68,25 +68,21 @@ public class VerticalLevelContainer implements LevelContainer index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1); dataContainer[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16); } - } + }*/ } public LevelContainer expand(){ - return new SingleLevelContainer((byte) (getDetailLevel() - 1)); + return new VerticalLevelContainer((byte) (getDetailLevel() - 1)); } public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { //We reset the array - if(!LevelContainer.threadGetDataMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()) == null)) - { - LevelContainer.threadGetDataMap.put(Thread.currentThread().getName(), new long[4]); - } - long[] dataToMerge = LevelContainer.threadGetDataMap.get(Thread.currentThread().getName()); + long[][] dataToMerge = ThreadMapUtil.getVerticalUpdateArray(); int childPosX; int childPosZ; - long data = 0; + long[] data; posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); for (int x = 0; x <= 1; x++) @@ -95,99 +91,13 @@ public class VerticalLevelContainer implements LevelContainer { childPosX = 2 * posX + x; childPosZ = 2 * posZ + z; - dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ)[0]; + dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ); } } - data = DataPointUtil.mergeSingleData(dataToMerge); + data = DataPointUtil.mergeVerticalData(dataToMerge); addData(data,posX,posZ); } - public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) - { - long[][][] updateTemps; - int[] indexes; - if(!LevelContainer.threadVerticalUpdateMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadVerticalUpdateMap.get(Thread.currentThread().getName()) == null)) - { - //To avoid the creation of multiple - updateTemps = new long[4][][]; - updateTemps[0] = new long[4][16]; - updateTemps[1] = new long[1][32]; - updateTemps[2] = new long[1][4]; - updateTemps[3] = new long[1][4]; - LevelContainer.threadVerticalUpdateMap.put(Thread.currentThread().getName(), updateTemps); - } - if(!LevelContainer.threadVerticalIndexesMap.containsKey(Thread.currentThread().getName()) || (LevelContainer.threadVerticalIndexesMap.get(Thread.currentThread().getName()) == null)) - { - //To avoid the creation of multiple - indexes = new int[4]; - LevelContainer.threadVerticalIndexesMap.put(Thread.currentThread().getName(), updateTemps); - } - - updateTemps = LevelContainer.threadVerticalIndexesMap.get(Thread.currentThread().getName()); - - long[][] dataArray = updateTemps[0]; - long[] newDataPoint = updateTemps[1][1]; - long[] indexes = updateTemps[2][1]; - long[] dataToCombine = updateTemps[3][1]; - //int maxSize = Math.max(Math.max(Math.max(dataArray[0].length, dataArray[1].length), dataArray[2].length), dataArray[3].length); - //DetailDistanceUtil.getMaxVerticalData(detailLevel); - //we are re-using these arrays so we must reset them to 0 - int dataIndex = 0; - int i; - for (i = 0; i < newDataPoint.length; i++) - newDataPoint[i] = 0; - for (i = 0; i < 4; i++) - indexes[i] = 0; - //We continue until all the data has been read - int minDepth; - int maxHeight; - int selectedDepth; - int selectedHeight; - int startingArray; - while (indexes[0] < dataArray[0].length - && indexes[1] < dataArray[1].length - && indexes[2] < dataArray[2].length - && indexes[3] < dataArray[3].length) - { - //We select the data that at the lowest point - minDepth = Integer.MAX_VALUE; - maxHeight = Integer.MIN_VALUE; - startingArray = 0; - for (int arrayIndex = 0; arrayIndex < 4; arrayIndex++) - { - if (indexes[arrayIndex] < dataArray[arrayIndex].length) - { - if (minDepth < DataPointUtil.getDepth(dataArray[arrayIndex][indexes[arrayIndex]])) - { - minDepth = DataPointUtil.getDepth(dataArray[arrayIndex][indexes[arrayIndex]]); - startingArray = arrayIndex; - } - } - } - selectedDepth = minDepth; - //now we have selected the dataPoint that has yet to be analyzed with min depth - dataToCombine[startingArray] = dataArray[startingArray][indexes[startingArray]]; - indexes[startingArray]++; - newDataPoint[dataIndex] = minDepth; - - //now we must check if the other data can be combined with this lod - maxHeight = DataPointUtil.getHeight(dataArray[startingArray][indexes[startingArray]]); - - for (int arrayIndex = 0; arrayIndex < 4; arrayIndex++) - { - while (maxHeight >= getDepth(dataArray[arrayIndex][indexes[arrayIndex]])) - { - maxHeight = getHeight(dataArray[arrayIndex][indexes[arrayIndex]]); - dataToCombine[arrayIndex] = dataArray[arrayIndex][indexes[arrayIndex]]; - indexes[arrayIndex]++; - } - } - dataIndex++; - - } - return null; - } - public String toDataString() { return toString(); @@ -196,6 +106,7 @@ public class VerticalLevelContainer implements LevelContainer @Override public String toString() { + /* StringBuilder stringBuilder = new StringBuilder(); int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); stringBuilder.append(detailLevel); @@ -210,5 +121,7 @@ public class VerticalLevelContainer implements LevelContainer } } return stringBuilder.toString(); + */ + return " "; } -}*/ +} diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index e59e761b0..d946ffe00 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -13,6 +13,7 @@ public class DataPointUtil //public final static int MIN_DEPTH = -64; //public final static int MIN_HEIGHT = -64; public final static int EMPTY_DATA = 0; + public final static int WORLD_HEIGHT = 256; public final static int ALPHA_SHIFT = 56; public final static int RED_SHIFT = 48; @@ -216,6 +217,104 @@ public class DataPointUtil } } + public static long[] mergeVerticalData(long[][] dataToMerge) + { + boolean[] projection = new boolean[WORLD_HEIGHT + 1]; + int size = 0; + + int genMode = DistanceGenerationMode.SERVER.complexity; + boolean allEmpty = true; + boolean allVoid = true; + long singleData; + + int depth = 0; + int height = 0; + //We collect the indexes of the data, ordered by the depth + for (int index = 0; index < dataToMerge.length; index++) + { + for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++) + { + singleData = dataToMerge[index][dataIndex]; + if (doesItExist(singleData)) + { + genMode = Math.min(genMode, getGenerationMode(singleData)); + allEmpty = false; + if (!isItVoid(singleData)) + { + allVoid = false; + depth = getDepth(singleData); + height = getHeight(singleData); + for (int y = depth; y <= height; y++) + { + projection[y] = true; + } + } + } + } + } + + + //We check if there is any data that's not empty or void + if (allEmpty) + { + return new long[]{EMPTY_DATA}; + } + if (allVoid) + { + return new long[]{createVoidDataPoint(genMode)}; + } + + int count = 0; + int i = 0; + int[][] heightAndDepth = new int[projection.length][2]; + while (i < projection.length) + { + while (i < projection.length && !projection[i]) + { + i++; + } + depth = i; + while (i < projection.length && projection[i]) + { + height = i; + i++; + } + if(!(i < projection.length)) + break; + heightAndDepth[count][0] = depth; + heightAndDepth[count][1] = height; + count++; + } + //As standard the vertical lods are ordered from top to bottom + long[] dataPoint = new long[count]; + for (int j = count - 1; j >= 0; j--) + { + depth = heightAndDepth[j][0]; + height = heightAndDepth[j][1]; + long[] singleDataToMerge = new long[dataToMerge.length]; + for (int index = 0; index < dataToMerge.length; index++) + { + for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++) + { + singleData = dataToMerge[index][dataIndex]; + if (doesItExist(singleData) && !isItVoid(singleData)) + { + if ((depth <= getDepth(singleData) && getDepth(singleData) <= height) + || (depth <= getHeight(singleData) && getHeight(singleData) <= height)) + { + singleDataToMerge[dataIndex] = singleData; + break; + } + } + } + } + long data = mergeSingleData(singleDataToMerge); + dataPoint[j] = createDataPoint(height, depth, getColor(data), getLightValue(data), getGenerationMode(data)); + } + + return dataPoint; + } + /* public static long[] mergeVerticalData(long[][] dataToMerge) { int[][] dataCollector = new int[256][2]; @@ -230,7 +329,7 @@ public class DataPointUtil //We collect the indexes of the data, ordered by the depth for (int index = 0; index < dataToMerge.length; index++) { - for (int dataIndex = 0; dataIndex < dataToMerge.length; dataIndex++) + for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++) { singleData = dataToMerge[index][dataIndex]; if (doesItExist(singleData)) @@ -246,11 +345,12 @@ public class DataPointUtil dataCollector[j] = dataCollector[j - 1]; j = j - 1; } - dataCollector[j][0] = dataIndex; - dataCollector[j][1] = index; + dataCollector[j][0] = index; + dataCollector[j][1] = dataIndex; size++; } } + } } @@ -273,7 +373,7 @@ public class DataPointUtil int index = 0; int dataCount = 0; long[] singleDataToMerge = new long[dataToMerge.length]; - long[] newData = new long[dataToMerge.length]; + long[] newData = new long[256]; while (index < size) { dataCount++; @@ -281,17 +381,21 @@ public class DataPointUtil minDepth = getDepth(singleData); maxHeight = getHeight(singleData); index++; - while(index < size) + while (index < size) { - singleData = dataToMerge[dataCollector[index][0]][dataCollector[index][1]]; + if(dataCollector[index][1] >= dataToMerge[dataCollector[index][0]].length) + singleData = EMPTY_DATA; + else + singleData = dataToMerge[dataCollector[index][0]][dataCollector[index][1]]; tempDepth = getDepth(singleData); tempHeight = getHeight(singleData); - if(maxHeight >= tempDepth) + if (maxHeight >= tempDepth) { singleDataToMerge[dataCollector[index][0]] = singleData; maxHeight = tempHeight; index++; - }else{ + } else + { break; } } @@ -299,7 +403,7 @@ public class DataPointUtil newData[dataCount] = createDataPoint(maxHeight, minDepth, getColor(singleData), getLightValue(singleData), getGenerationMode(singleData)); } return Arrays.copyOf(newData, dataCount); - } + }*/ public static long[] compress(long[] data, byte detailLevel) { diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java index fc6f02ea1..b6b881c3f 100644 --- a/src/main/java/com/seibel/lod/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/util/LodUtil.java @@ -337,7 +337,8 @@ public class LodUtil if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z)) continue; - long data = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z); + long[] dataVertical = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z); + long data = dataVertical[dataVertical.length - 1]; short lodAverageHeight = DataPointUtil.getHeight(data); diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index 4bf2613e7..6b9588bae 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -11,9 +11,10 @@ public class ThreadMapUtil public static final ConcurrentMap threadSingleGetDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadBuilderArrayMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadBuilderVerticalArrayMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalAddDataMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalGetDataMap = new ConcurrentHashMap(); - public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); + public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap(); public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); @@ -50,6 +51,14 @@ public class ThreadMapUtil return threadBuilderArrayMap.get(Thread.currentThread().getName()); } + public static long[][][] getBuilderVerticalArray(){ + if(!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null)) + { + long[][][] array = new long[5][][]; + threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array); + } + return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()); + } public static long[] addVerticalDataArray(){ if(!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null)) @@ -67,10 +76,10 @@ public class ThreadMapUtil return threadVerticalGetDataMap.get(Thread.currentThread().getName()); } - public static long[][][] getVerticalUpdateArray(){ + public static long[][] getVerticalUpdateArray(){ if(!threadVerticalUpdateMap.containsKey(Thread.currentThread().getName()) || (threadVerticalUpdateMap.get(Thread.currentThread().getName()) == null)) { - threadVerticalUpdateMap.put(Thread.currentThread().getName(), new long[4][4][16]); + threadVerticalUpdateMap.put(Thread.currentThread().getName(), new long[4][]); } return threadVerticalUpdateMap.get(Thread.currentThread().getName()); } From e9798ace134fc6d7c0f295bff748a075eefd08e6 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Mon, 13 Sep 2021 23:23:55 +0200 Subject: [PATCH 24/30] kinda working version --- .../com/seibel/lod/builders/LodBuilder.java | 160 +++++++++++++----- 1 file changed, 113 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 5d1326735..cbe58457d 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -127,7 +127,7 @@ public class LodBuilder generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(generationMode)); } catch (IllegalArgumentException | NullPointerException e) { - //e.printStackTrace(); + e.printStackTrace(); // if the world changes while LODs are being generated // they will throw errors as they try to access things that no longer // exist. @@ -192,31 +192,23 @@ public class LodBuilder long[] dataToMerge; //data = ThreadMapUtil.getSingleAddDataArray(); dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - - try + long[][] dataToMerge2 = new long[dataToMerge.length][]; + for (int index = 0; index < dataToMerge.length; index++) { - long[][] dataToMerge2 = new long[dataToMerge.length][]; - for (int index = 0; index < dataToMerge.length; index++) - { - dataToMerge2[index] = new long[]{dataToMerge[index]}; - } - //data[0] = DataPointUtil.mergeSingleData(dataToMerge); - - //dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - data = DataPointUtil.mergeVerticalData(dataToMerge2); - - boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; - lodDim.addData(detailLevel, - posX, - posZ, - data, - false, - isServer); - }catch (Exception e) - { - e.printStackTrace(); - throw e; + dataToMerge2[index] = new long[]{dataToMerge[index]}; } + //data[0] = DataPointUtil.mergeSingleData(dataToMerge); + + //dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + data = DataPointUtil.mergeVerticalData(dataToMerge2); + + boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; + lodDim.addData(detailLevel, + posX, + posZ, + data, + false, + isServer); } lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); } catch (Exception e) @@ -225,8 +217,7 @@ public class LodBuilder } } - - /*private long[][] createVerticalDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) + private long[][] createVerticalDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) { long[][] dataToMerge = ThreadMapUtil.getBuilderVerticalArray()[detail.detailLevel]; ChunkPos chunkPos = chunk.getPos(); @@ -246,39 +237,114 @@ public class LodBuilder BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); int index = 0; - if (dataToMerge == null) - { - dataToMerge = new long[size * size][256]; - } + dataToMerge = new long[size * size][1024]; for (index = 0; index < size * size; index++) { + xRel = Math.floorMod(index, size) + startX; zRel = Math.floorDiv(index, size) + startZ; xAbs = chunkPos.getMinBlockX() + xRel; zAbs = chunkPos.getMinBlockZ() + zRel; //Calculate the height of the lod - height = determineHeightPoint(chunk, config, xRel, zRel); + yAbs = 255; + int count = 0; + while(yAbs > 0){ + height = determineHeightPointFrom(chunk, config, xRel, zRel, yAbs); - //If the lod is at default, then we set this as void data - if (height == DEFAULT_HEIGHT) - { - dataToMerge[index] = DataPointUtil.createVoidDataPoint(generation); - continue; + //If the lod is at default, then we set this as void data + if (height == DEFAULT_HEIGHT) + { + dataToMerge[index][0] = DataPointUtil.createVoidDataPoint(generation); + break; + } + + yAbs = height - 1; + // We search light on above air block + blockPos.set(xAbs, yAbs + 1, zAbs); + + color = generateLodColor(chunk, config, xRel, yAbs, zRel); + light = getLightBlockValue(chunk, blockPos); + depth = determineBottomPointFrom(chunk, config, xRel, zRel, yAbs); + + //System.out.println(dataToMerge.length + " " + index +" " + count + " " + yAbs); + //System.out.println(dataToMerge.length + " " + dataToMerge[index].length); + dataToMerge[index][count] = DataPointUtil.createDataPoint(height, depth, color, light, generation); + yAbs = depth - 1; + count++; } - - yAbs = height - 1; - // We search light on above air block - blockPos.set(xAbs, yAbs + 1, zAbs); - - color = generateLodColor(chunk, config, xRel, yAbs, zRel); - light = getLightBlockValue(chunk, blockPos); - depth = determineBottomPoint(chunk, config, xRel, zRel); - - dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, light, generation); } return dataToMerge; - }*/ + } + + /** + * Find the lowest valid point from the bottom. + */ + private short determineBottomPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs) + { + short depth = DEFAULT_DEPTH; + if (config.useHeightmap) + { + depth = 0; + } else + { + boolean voidData = true; + ChunkSection[] chunkSections = chunk.getSections(); + for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--) + { + for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) + { + if(sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) + continue; + if (!isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + { + depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); + voidData = false; + break; + } + } + if (!voidData) + { + break; + } + } + } + return depth; + } + /** + * Find the highest valid point from the Top + */ + private short determineHeightPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs) + { + short height = DEFAULT_HEIGHT; + if (config.useHeightmap) + { + height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel); + } else + { + boolean voidData = true; + ChunkSection[] chunkSections = chunk.getSections(); + for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--) + { + for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) + { + if(sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) + continue; + if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + { + height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); + voidData = false; + break; + } + } + if (!voidData) + { + break; + } + } + } + return height; + } private long[] createSingleDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) { From 9b216fedad9d7be01e3eb5f4792ed3223f1a7bec Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 14 Sep 2021 01:05:41 +0200 Subject: [PATCH 25/30] Vertical lod now works (optimization required) --- .../com/seibel/lod/builders/LodBuilder.java | 16 +++++++------ .../lod/objects/VerticalLevelContainer.java | 2 +- .../com/seibel/lod/util/DataPointUtil.java | 24 +++++++++++++------ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index cbe58457d..30545193a 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -189,19 +189,20 @@ public class LodBuilder posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel); posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel); long[] data; - long[] dataToMerge; + long[][] dataToMerge; //data = ThreadMapUtil.getSingleAddDataArray(); - dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - long[][] dataToMerge2 = new long[dataToMerge.length][]; + //dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + /*long[][] dataToMerge2 = new long[dataToMerge.length][]; for (int index = 0; index < dataToMerge.length; index++) { dataToMerge2[index] = new long[]{dataToMerge[index]}; - } + }*/ //data[0] = DataPointUtil.mergeSingleData(dataToMerge); - //dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - data = DataPointUtil.mergeVerticalData(dataToMerge2); - + dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + data = DataPointUtil.mergeVerticalData(dataToMerge); + if(data.length == 0 || data == null) + data = new long[]{DataPointUtil.EMPTY_DATA}; boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; lodDim.addData(detailLevel, posX, @@ -209,6 +210,7 @@ public class LodBuilder data, false, isServer); + } lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); } catch (Exception e) diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index f8a96d9a2..0017b5eef 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -42,7 +42,7 @@ public class VerticalLevelContainer implements LevelContainer public boolean doesItExist(int posX, int posZ){ long[] data = getData(posX,posZ); - return DataPointUtil.doesItExist(data[0]); + return (data != null && DataPointUtil.doesItExist(data[0])); } public VerticalLevelContainer(String inputString) diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index d946ffe00..142f291ce 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -105,9 +105,9 @@ public class DataPointUtil return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK); } - public static byte getLightValue(long dataPoint) + public static int getLightValue(long dataPoint) { - return (byte) ((dataPoint >>> LIGHT_SHIFT) & LIGHT_MASK); + return (int) ((dataPoint >>> LIGHT_SHIFT) & LIGHT_MASK); } public static byte getGenerationMode(long dataPoint) @@ -128,15 +128,15 @@ public class DataPointUtil public static int getColor(long dataPoint) { - return (int) ((dataPoint >>> COLOR_SHIFT) & COLOR_MASK); + return (int) (dataPoint >>> COLOR_SHIFT); } public static int getLightColor(long dataPoint) { int lightBlock = getLightValue(dataPoint); - int red = Math.min(getRed(dataPoint) + lightBlock * 8, 255); - int green = Math.min(getGreen(dataPoint) + lightBlock * 8, 255); - int blue = Math.min(getBlue(dataPoint) + lightBlock * 4, 255); + int red = LodUtil.clamp(0, getRed(dataPoint) + lightBlock * 8, 255); + int green = LodUtil.clamp(0, getGreen(dataPoint) + lightBlock * 8, 255); + int blue = LodUtil.clamp(0, getBlue(dataPoint) + lightBlock * 4, 255); return ColorUtil.rgbToInt(red, green, blue); } @@ -147,11 +147,21 @@ public class DataPointUtil s.append(" "); s.append(getDepth(dataPoint)); s.append(" "); + s.append(getAlpha(dataPoint)); + s.append(" "); s.append(getRed(dataPoint)); s.append(" "); s.append(getBlue(dataPoint)); s.append(" "); s.append(getGreen(dataPoint)); + s.append(" "); + s.append(getLightValue(dataPoint)); + s.append(" "); + s.append(getGenerationMode(dataPoint)); + s.append(" "); + s.append(isItVoid(dataPoint)); + s.append(" "); + s.append(doesItExist(dataPoint)); s.append('\n'); return s.toString(); } @@ -302,7 +312,7 @@ public class DataPointUtil if ((depth <= getDepth(singleData) && getDepth(singleData) <= height) || (depth <= getHeight(singleData) && getHeight(singleData) <= height)) { - singleDataToMerge[dataIndex] = singleData; + singleDataToMerge[index] = singleData; break; } } From 77ccd9eec3e10ef6c651378fb11d07a5567088ed Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 14 Sep 2021 12:58:09 +0200 Subject: [PATCH 26/30] changed how the valid block is determined, and added a mask and a shift for future use --- src/main/java/com/seibel/lod/Main.java | 31 ++++++++ .../com/seibel/lod/builders/LodBuilder.java | 76 +++++++++++-------- .../com/seibel/lod/util/DataPointUtil.java | 2 + 3 files changed, 79 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/seibel/lod/Main.java diff --git a/src/main/java/com/seibel/lod/Main.java b/src/main/java/com/seibel/lod/Main.java new file mode 100644 index 000000000..da81c0be8 --- /dev/null +++ b/src/main/java/com/seibel/lod/Main.java @@ -0,0 +1,31 @@ +package com.seibel.lod; + +import com.google.common.primitives.UnsignedLong; +import com.seibel.lod.objects.PosToGenerateContainer; +import com.seibel.lod.util.DataPointUtil; + +import javax.xml.crypto.Data; +import java.math.BigInteger; + +public class Main +{ + public static void main(String[] args) + { + try + { + long[][] dataToMerge = new long[][]{ + {DataPointUtil.createDataPoint(10, 5, 0, 0, 0)}, + {DataPointUtil.createDataPoint(15, 5, 0, 0, 0)}, + {DataPointUtil.createDataPoint(40, 20, 0, 0, 0)}, + {DataPointUtil.createDataPoint(1, 0, 0, 0, 0)}}; + long[] data = DataPointUtil.mergeVerticalData(dataToMerge); + for (long dataPoint : data) + { + System.out.println("depth " + DataPointUtil.getDepth(dataPoint)); + System.out.println("height " + DataPointUtil.getHeight(dataPoint)); + } + }catch (Exception e){ + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 30545193a..91a572959 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -31,8 +31,10 @@ import com.seibel.lod.wrappers.MinecraftWrapper; import net.minecraft.block.*; import net.minecraft.block.material.MaterialColor; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.DimensionType; import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.IWorld; @@ -201,7 +203,7 @@ public class LodBuilder dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); data = DataPointUtil.mergeVerticalData(dataToMerge); - if(data.length == 0 || data == null) + if (data.length == 0 || data == null) data = new long[]{DataPointUtil.EMPTY_DATA}; boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; lodDim.addData(detailLevel, @@ -219,6 +221,7 @@ public class LodBuilder } } + private long[][] createVerticalDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ) { long[][] dataToMerge = ThreadMapUtil.getBuilderVerticalArray()[detail.detailLevel]; @@ -251,8 +254,9 @@ public class LodBuilder //Calculate the height of the lod yAbs = 255; int count = 0; - while(yAbs > 0){ - height = determineHeightPointFrom(chunk, config, xRel, zRel, yAbs); + while (yAbs > 0) + { + height = determineHeightPointFrom(chunk, config, xRel, zRel, yAbs, blockPos); //If the lod is at default, then we set this as void data if (height == DEFAULT_HEIGHT) @@ -263,11 +267,10 @@ public class LodBuilder yAbs = height - 1; // We search light on above air block - blockPos.set(xAbs, yAbs + 1, zAbs); - color = generateLodColor(chunk, config, xRel, yAbs, zRel); + depth = determineBottomPointFrom(chunk, config, xRel, zRel, yAbs, blockPos); + blockPos.set(xAbs, yAbs + 1, zAbs); light = getLightBlockValue(chunk, blockPos); - depth = determineBottomPointFrom(chunk, config, xRel, zRel, yAbs); //System.out.println(dataToMerge.length + " " + index +" " + count + " " + yAbs); //System.out.println(dataToMerge.length + " " + dataToMerge[index].length); @@ -282,7 +285,7 @@ public class LodBuilder /** * Find the lowest valid point from the bottom. */ - private short determineBottomPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs) + private short determineBottomPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos) { short depth = DEFAULT_DEPTH; if (config.useHeightmap) @@ -296,9 +299,10 @@ public class LodBuilder { for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) { - if(sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) + if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) continue; - if (!isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel); + if (!isLayerValidLodPoint(chunk, blockPos)) { depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); voidData = false; @@ -313,10 +317,11 @@ public class LodBuilder } return depth; } + /** * Find the highest valid point from the Top */ - private short determineHeightPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs) + private short determineHeightPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos) { short height = DEFAULT_HEIGHT; if (config.useHeightmap) @@ -330,9 +335,10 @@ public class LodBuilder { for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) { - if(sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) + if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) continue; - if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel); + if (isLayerValidLodPoint(chunk, blockPos)) { height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); voidData = false; @@ -380,7 +386,7 @@ public class LodBuilder zAbs = chunkPos.getMinBlockZ() + zRel; //Calculate the height of the lod - height = determineHeightPoint(chunk, config, xRel, zRel); + height = determineHeightPoint(chunk, config, xRel, zRel, blockPos); //If the lod is at default, then we set this as void data if (height == DEFAULT_HEIGHT) @@ -391,11 +397,12 @@ public class LodBuilder yAbs = height - 1; // We search light on above air block - blockPos.set(xAbs, yAbs + 1, zAbs); color = generateLodColor(chunk, config, xRel, yAbs, zRel); + depth = determineBottomPoint(chunk, config, xRel, zRel, blockPos); + + blockPos.set(xAbs, yAbs + 1, zAbs); light = getLightBlockValue(chunk, blockPos); - depth = determineBottomPoint(chunk, config, xRel, zRel); dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, light, generation); } @@ -408,7 +415,7 @@ public class LodBuilder /** * Find the lowest valid point from the bottom. */ - private short determineBottomPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel) + private short determineBottomPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, BlockPos.Mutable blockPos) { ChunkSection[] chunkSections = chunk.getSections(); short depth = DEFAULT_DEPTH; @@ -422,7 +429,7 @@ public class LodBuilder { for (int yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++) { - if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + if (isLayerValidLodPoint(chunk, blockPos)) { depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel); found = true; @@ -442,7 +449,7 @@ public class LodBuilder /** * Find the highest valid point from the Top */ - private short determineHeightPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel) + private short determineHeightPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, BlockPos.Mutable blockPos) { short height = DEFAULT_HEIGHT; if (config.useHeightmap) @@ -456,7 +463,7 @@ public class LodBuilder { for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) { - if (isLayerValidLodPoint(chunkSections, sectionIndex, yRel, xRel, zRel)) + if (isLayerValidLodPoint(chunk, blockPos)) { height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); voidData = false; @@ -652,19 +659,28 @@ public class LodBuilder /** * Is the layer between the given X, Z, and dataIndex values a valid LOD point? */ - private boolean isLayerValidLodPoint(ChunkSection[] chunkSections, int sectionIndex, int y, int x, int z) + private boolean isLayerValidLodPoint(IChunk chunk, BlockPos.Mutable blockPos) { - if (chunkSections[sectionIndex] == null) + + BlockState blockState = chunk.getBlockState(blockPos); + if (blockState != null) { - // this section doesn't have any blocks, - // it is not a valid section - return false; - } else - { - if (chunkSections[sectionIndex].getBlockState(x, y, z) != null - && chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.AIR - && chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.CAVE_AIR - && chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.BARRIER) + VoxelShape voxelShape = blockState.getShape(chunk, blockPos); + if(!voxelShape.isEmpty()){ + AxisAlignedBB bbox = voxelShape.bounds(); + int xWidth = (int) (bbox.maxX - bbox.minX); + int yWidth = (int) (bbox.maxY - bbox.minY); + int zWidth = (int) (bbox.maxZ - bbox.minZ); + if(xWidth < 0.7 && zWidth < 0.7 && yWidth < 1) + { + return false; + } + }else{ + return false; + } + if (blockState.getBlock() != Blocks.AIR + && blockState.getBlock() != Blocks.CAVE_AIR + && blockState.getBlock() != Blocks.BARRIER) { return true; } diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 142f291ce..1542a477f 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -23,6 +23,7 @@ public class DataPointUtil public final static int HEIGHT_SHIFT = 22; public final static int DEPTH_SHIFT = 12; public final static int LIGHT_SHIFT = 8; + public final static int VERTICAL_INDEX_SHIFT = 6; public final static int GEN_TYPE_SHIFT = 2; public final static int VOID_SHIFT = 1; public final static int EXISTENCE_SHIFT = 0; @@ -35,6 +36,7 @@ public class DataPointUtil public final static long HEIGHT_MASK = 0b11_1111_1111; public final static long DEPTH_MASK = 0b11_1111_1111; public final static long LIGHT_MASK = 0b1111; + public final static long VERTICAL_INDEX_SHIFT = 0b11; public final static long GEN_TYPE_MASK = 0b111; public final static long VOID_MASK = 1; public final static long EXISTENCE_MASK = 1; From 145479267dd3088fc6200eacd65905abe154f797 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 14 Sep 2021 13:15:36 +0200 Subject: [PATCH 27/30] Fixed Nether color --- .../com/seibel/lod/builders/LodBuilder.java | 22 ++++++++++++++----- .../com/seibel/lod/util/DataPointUtil.java | 2 +- .../java/com/seibel/lod/util/LodUtil.java | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 91a572959..99faf7fe3 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -546,6 +546,12 @@ public class LodBuilder } else if (blockState == Blocks.STONE.defaultBlockState()) { colorInt = LodUtil.STONE_COLOR_INT; + } else if (blockState == Blocks.NETHERRACK.defaultBlockState()) + { + colorInt = LodUtil.NETHERRACK_COLOR_INT; + } else if (blockState == Blocks.BEDROCK.defaultBlockState()) + { + colorInt = getColorForBiome(x, z, biome); } else if (blockState == Blocks.MYCELIUM.defaultBlockState()) { colorInt = LodUtil.MYCELIUM_COLOR_INT; @@ -605,7 +611,7 @@ public class LodBuilder { case NETHER: - colorInt = Blocks.BEDROCK.defaultBlockState().materialColor.col; + colorInt = LodUtil.NETHERRACK_COLOR_INT; break; case THEEND: @@ -665,17 +671,23 @@ public class LodBuilder BlockState blockState = chunk.getBlockState(blockPos); if (blockState != null) { - VoxelShape voxelShape = blockState.getShape(chunk, blockPos); - if(!voxelShape.isEmpty()){ + if (!blockState.getFluidState().isEmpty()) + { + return true; + } + VoxelShape voxelShape = blockState.getShape(chunk, blockPos); + if (!voxelShape.isEmpty()) + { AxisAlignedBB bbox = voxelShape.bounds(); int xWidth = (int) (bbox.maxX - bbox.minX); int yWidth = (int) (bbox.maxY - bbox.minY); int zWidth = (int) (bbox.maxZ - bbox.minZ); - if(xWidth < 0.7 && zWidth < 0.7 && yWidth < 1) + if (xWidth < 0.7 && zWidth < 0.7 && yWidth < 1) { return false; } - }else{ + } else + { return false; } if (blockState.getBlock() != Blocks.AIR diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 1542a477f..04f38227b 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -36,7 +36,7 @@ public class DataPointUtil public final static long HEIGHT_MASK = 0b11_1111_1111; public final static long DEPTH_MASK = 0b11_1111_1111; public final static long LIGHT_MASK = 0b1111; - public final static long VERTICAL_INDEX_SHIFT = 0b11; + public final static long VERTICAL_INDEX_MASK = 0b11; public final static long GEN_TYPE_MASK = 0b111; public final static long VOID_MASK = 1; public final static long EXISTENCE_MASK = 1; diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java index b6b881c3f..e074d0418 100644 --- a/src/main/java/com/seibel/lod/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/util/LodUtil.java @@ -63,7 +63,7 @@ public class LodUtil * and/or add a method to generate colors based on texture * issue #64 */ public static final int STONE_COLOR_INT = LodUtil.colorToInt(new Color(150, 150, 150)); - + public static final int NETHERRACK_COLOR_INT = LodUtil.colorToInt(new Color(95, 38, 38)); /** * In order of nearest to farthest:
* Red, Orange, Yellow, Green, Cyan, Blue, Magenta, white, gray, black From fe02813d1716ada22ff39974be41c51defea4787 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 14 Sep 2021 13:45:08 +0200 Subject: [PATCH 28/30] Disabled a section in the getNearbyLodChunkPosToSkip --- src/main/java/com/seibel/lod/util/LodUtil.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java index e074d0418..26e8faaf9 100644 --- a/src/main/java/com/seibel/lod/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/util/LodUtil.java @@ -334,7 +334,7 @@ public class LodUtil { for (int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++) { - if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z)) + /*if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z)) continue; long[] dataVertical = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z); @@ -347,7 +347,8 @@ public class LodUtil // don't draw Lod's that are taller than the player // to prevent LODs being drawn on top of the player posToSkip.add(new ChunkPos(x, z)); - } + }*/ + posToSkip.add(new ChunkPos(x, z)); } } From e03e09a243288a95c99b69ad74378fdd324ecc18 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 14 Sep 2021 19:02:37 +0200 Subject: [PATCH 29/30] Fixed various bugs and introduced more maps in the ThreadMapUtil --- .../com/seibel/lod/builders/LodBuilder.java | 17 ++- .../lodTemplates/CubicLodTemplate.java | 33 +++-- .../com/seibel/lod/util/DataPointUtil.java | 121 +++--------------- .../java/com/seibel/lod/util/LodUtil.java | 7 +- .../com/seibel/lod/util/ThreadMapUtil.java | 33 ++++- 5 files changed, 87 insertions(+), 124 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 99faf7fe3..9e3673fa7 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -242,10 +242,17 @@ public class LodBuilder BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); int index = 0; - dataToMerge = new long[size * size][1024]; + if(dataToMerge == null){ + dataToMerge = new long[size * size][DataPointUtil.WORLD_HEIGHT]; + } + //dataToMerge = new long[size * size][1024]; + for (index = 0; index < size * size; index++) { - + for(int i = 0; i < dataToMerge[index].length; i++) + { + dataToMerge[index][i] = 0; + } xRel = Math.floorMod(index, size) + startX; zRel = Math.floorDiv(index, size) + startZ; xAbs = chunkPos.getMinBlockX() + xRel; @@ -549,6 +556,12 @@ public class LodBuilder } else if (blockState == Blocks.NETHERRACK.defaultBlockState()) { colorInt = LodUtil.NETHERRACK_COLOR_INT; + } else if (blockState == Blocks.WARPED_NYLIUM.defaultBlockState()) + { + colorInt = LodUtil.WARPED_NYLIUM_COLOR_INT; + } else if (blockState == Blocks.CRIMSON_NYLIUM.defaultBlockState()) + { + colorInt = LodUtil.CRIMSON_NYLIUM_COLOR_INT; } else if (blockState == Blocks.BEDROCK.defaultBlockState()) { colorInt = getColorForBiome(x, z, biome); diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 3aa000667..7d590c7fb 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -62,21 +62,31 @@ public class CubicLodTemplate extends AbstractLodTemplate posZ * width, bufferCenterBlockPos); int color; - int time = (int) (MinecraftWrapper.INSTANCE.getPlayer().level.getDayTime() - 13000); - if(time < 0) + boolean hasSkyLight = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasSkyLight(); + //USE THIS IN THE boolean hasCeiling = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasCeiling(); + if (hasSkyLight) { - color = DataPointUtil.getColor(data); + int time = (int) (MinecraftWrapper.INSTANCE.getPlayer().level.getDayTime() - 13000); + if (time < 0) + { + color = DataPointUtil.getColor(data); + } else + { + /*TODO implement a smoother transition for light from day to night */ + color = DataPointUtil.getLightColor(data,4); + } }else{ - /*TODO implement a smoother transition for light from day to night */ - color = DataPointUtil.getLightColor(data); + color = DataPointUtil.getLightColor(data,1); } if (debugging != DebugMode.OFF) + { color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB(); } if (box != null) + { addBoundingBoxToBuffer(buffer, box, color, bufferCenterBlockPos, adjData); } @@ -100,7 +110,7 @@ public class CubicLodTemplate extends AbstractLodTemplate // it uses doubles to specify its location, unlike the model view matrix // which only uses floats double x = -bufferCenterBlockPos.getX(); - double z = -bufferCenterBlockPos.getZ();; + double z = -bufferCenterBlockPos.getZ(); box.set(width, height - depth, width); box.move((int) (xOffset + x), (int) (yOffset + depth), (int) (zOffset + z)); } @@ -217,7 +227,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); - }else + } else { maxY = box.getMaxY(); tempMaxY = DataPointUtil.getHeight(data); @@ -262,8 +272,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); - } - else + } else { maxY = box.getMaxY(); tempMaxY = DataPointUtil.getHeight(data); @@ -308,8 +317,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha); addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha); - } - else + } else { maxY = box.getMaxY(); tempMaxY = DataPointUtil.getHeight(data); @@ -354,8 +362,7 @@ public class CubicLodTemplate extends AbstractLodTemplate addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha); addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha); - } - else + } else { maxY = box.getMaxY(); tempMaxY = DataPointUtil.getHeight(data); diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 04f38227b..33aab8e5c 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -1,10 +1,6 @@ package com.seibel.lod.util; import com.seibel.lod.enums.DistanceGenerationMode; -import org.lwjgl.system.CallbackI; - -import java.lang.reflect.Array; -import java.util.Arrays; public class DataPointUtil { @@ -133,12 +129,12 @@ public class DataPointUtil return (int) (dataPoint >>> COLOR_SHIFT); } - public static int getLightColor(long dataPoint) + public static int getLightColor(long dataPoint, int amp) { int lightBlock = getLightValue(dataPoint); - int red = LodUtil.clamp(0, getRed(dataPoint) + lightBlock * 8, 255); - int green = LodUtil.clamp(0, getGreen(dataPoint) + lightBlock * 8, 255); - int blue = LodUtil.clamp(0, getBlue(dataPoint) + lightBlock * 4, 255); + int red = LodUtil.clamp(0, getRed(dataPoint) + lightBlock * amp, 255); + int green = LodUtil.clamp(0, getGreen(dataPoint) + lightBlock * amp, 255); + int blue = LodUtil.clamp(0, getBlue(dataPoint) + lightBlock * amp, 255); return ColorUtil.rgbToInt(red, green, blue); } @@ -231,14 +227,16 @@ public class DataPointUtil public static long[] mergeVerticalData(long[][] dataToMerge) { - boolean[] projection = new boolean[WORLD_HEIGHT + 1]; - int size = 0; - + boolean[] projection = ThreadMapUtil.getProjection(WORLD_HEIGHT + 1); + int[][] heightAndDepth = ThreadMapUtil.getHeightAndDepth(WORLD_HEIGHT + 1); + long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(dataToMerge.length); int genMode = DistanceGenerationMode.SERVER.complexity; boolean allEmpty = true; boolean allVoid = true; long singleData; + for(int k=0; k < projection.length; k++) + projection[k] = false; int depth = 0; int height = 0; //We collect the indexes of the data, ordered by the depth @@ -278,7 +276,6 @@ public class DataPointUtil int count = 0; int i = 0; - int[][] heightAndDepth = new int[projection.length][2]; while (i < projection.length) { while (i < projection.length && !projection[i]) @@ -303,7 +300,9 @@ public class DataPointUtil { depth = heightAndDepth[j][0]; height = heightAndDepth[j][1]; - long[] singleDataToMerge = new long[dataToMerge.length]; + for(int k = 0; k < dataToMerge.length; k++){ + singleDataToMerge[k] = 0; + } for (int index = 0; index < dataToMerge.length; index++) { for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++) @@ -314,8 +313,10 @@ public class DataPointUtil if ((depth <= getDepth(singleData) && getDepth(singleData) <= height) || (depth <= getHeight(singleData) && getHeight(singleData) <= height)) { - singleDataToMerge[index] = singleData; - break; + if(getHeight(singleData) > getHeight(singleDataToMerge[index])) + { + singleDataToMerge[index] = singleData; + } } } } @@ -326,96 +327,6 @@ public class DataPointUtil return dataPoint; } - /* - public static long[] mergeVerticalData(long[][] dataToMerge) - { - int[][] dataCollector = new int[256][2]; - long[] singleDataToCollect = new long[256]; - int size = 0; - - int tempGenMode = DistanceGenerationMode.SERVER.complexity; - boolean allEmpty = true; - boolean allVoid = true; - long singleData; - - //We collect the indexes of the data, ordered by the depth - for (int index = 0; index < dataToMerge.length; index++) - { - for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++) - { - singleData = dataToMerge[index][dataIndex]; - if (doesItExist(singleData)) - { - tempGenMode = Math.min(tempGenMode, getGenerationMode(singleData)); - allEmpty = false; - if (!isItVoid(singleData)) - { - allVoid = false; - int j = size; - while (j >= 0 && (getDepth(dataToMerge[dataCollector[j][0]][dataCollector[j][1]]) > getDepth(singleData))) - { - dataCollector[j] = dataCollector[j - 1]; - j = j - 1; - } - dataCollector[j][0] = index; - dataCollector[j][1] = dataIndex; - size++; - } - } - - } - } - - - //We check if there is any data that's not empty or void - if (allEmpty) - { - return new long[]{EMPTY_DATA}; - } - if (allVoid) - { - return new long[]{createVoidDataPoint(tempGenMode)}; - } - - //We merge together all the data - int minDepth; - int maxHeight = Integer.MIN_VALUE; - int tempDepth; - int tempHeight; - int index = 0; - int dataCount = 0; - long[] singleDataToMerge = new long[dataToMerge.length]; - long[] newData = new long[256]; - while (index < size) - { - dataCount++; - singleData = dataToMerge[dataCollector[index][0]][dataCollector[index][1]]; - minDepth = getDepth(singleData); - maxHeight = getHeight(singleData); - index++; - while (index < size) - { - if(dataCollector[index][1] >= dataToMerge[dataCollector[index][0]].length) - singleData = EMPTY_DATA; - else - singleData = dataToMerge[dataCollector[index][0]][dataCollector[index][1]]; - tempDepth = getDepth(singleData); - tempHeight = getHeight(singleData); - if (maxHeight >= tempDepth) - { - singleDataToMerge[dataCollector[index][0]] = singleData; - maxHeight = tempHeight; - index++; - } else - { - break; - } - } - singleData = mergeSingleData(singleDataToMerge); - newData[dataCount] = createDataPoint(maxHeight, minDepth, getColor(singleData), getLightValue(singleData), getGenerationMode(singleData)); - } - return Arrays.copyOf(newData, dataCount); - }*/ public static long[] compress(long[] data, byte detailLevel) { diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java index 26e8faaf9..915eb7bab 100644 --- a/src/main/java/com/seibel/lod/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/util/LodUtil.java @@ -64,6 +64,9 @@ public class LodUtil * issue #64 */ public static final int STONE_COLOR_INT = LodUtil.colorToInt(new Color(150, 150, 150)); public static final int NETHERRACK_COLOR_INT = LodUtil.colorToInt(new Color(95, 38, 38)); + public static final int WARPED_NYLIUM_COLOR_INT = LodUtil.colorToInt(new Color(34, 94, 85)); + public static final int CRIMSON_NYLIUM_COLOR_INT = LodUtil.colorToInt(new Color(126, 27, 27)); + /** * In order of nearest to farthest:
* Red, Orange, Yellow, Green, Cyan, Blue, Magenta, white, gray, black @@ -334,9 +337,9 @@ public class LodUtil { for (int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++) { - /*if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z)) + if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z)) continue; - + /* long[] dataVertical = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z); long data = dataVertical[dataVertical.length - 1]; diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index 6b9588bae..39ea8f798 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -1,7 +1,5 @@ package com.seibel.lod.util; -import com.seibel.lod.objects.LevelContainer; - import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -18,6 +16,11 @@ public class ThreadMapUtil public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap(); + public static final ConcurrentMap projectionMap = new ConcurrentHashMap(); + public static final ConcurrentMap heightAndDepthMap = new ConcurrentHashMap(); + public static final ConcurrentMap singleDataToMergeMap = new ConcurrentHashMap(); + + public static long[] getSingleAddDataArray(){ if(!threadSingleAddDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleAddDataMap.get(Thread.currentThread().getName()) == null)) { @@ -91,4 +94,30 @@ public class ThreadMapUtil } return threadVerticalIndexesMap.get(Thread.currentThread().getName()); } + + + + public static boolean[] getProjection(int size){ + if(!projectionMap.containsKey(Thread.currentThread().getName()) || (projectionMap.get(Thread.currentThread().getName()) == null) || (projectionMap.get(Thread.currentThread().getName()).length != size)) + { + projectionMap.put(Thread.currentThread().getName(), new boolean[size]); + } + return projectionMap.get(Thread.currentThread().getName()); + } + + public static int[][] getHeightAndDepth(int size){ + if(!heightAndDepthMap.containsKey(Thread.currentThread().getName()) || (heightAndDepthMap.get(Thread.currentThread().getName()) == null) || (heightAndDepthMap.get(Thread.currentThread().getName()).length != size)) + { + heightAndDepthMap.put(Thread.currentThread().getName(), new int[size][2]); + } + return heightAndDepthMap.get(Thread.currentThread().getName()); + } + + public static long[] getSingleAddDataToMerge(int size){ + if(!singleDataToMergeMap.containsKey(Thread.currentThread().getName()) || (singleDataToMergeMap.get(Thread.currentThread().getName()) == null) || (singleDataToMergeMap.get(Thread.currentThread().getName()).length != size)) + { + singleDataToMergeMap.put(Thread.currentThread().getName(), new long[size]); + } + return singleDataToMergeMap.get(Thread.currentThread().getName()); + } } From f9cf27a2c7c0a4bcb265ca3838bdc2e0a30864e4 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 14 Sep 2021 23:21:48 +0200 Subject: [PATCH 30/30] Changed the dataPoint, started the introduction of the lightmap use --- src/main/java/com/seibel/lod/Main.java | 3 +- .../seibel/lod/builders/LodBufferBuilder.java | 21 +++- .../com/seibel/lod/builders/LodBuilder.java | 20 ++- .../lodTemplates/CubicLodTemplate.java | 18 +-- .../lod/objects/VerticalLevelContainer.java | 4 +- .../com/seibel/lod/util/DataPointUtil.java | 115 +++++++++++++----- 6 files changed, 120 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/seibel/lod/Main.java b/src/main/java/com/seibel/lod/Main.java index da81c0be8..e51463c7b 100644 --- a/src/main/java/com/seibel/lod/Main.java +++ b/src/main/java/com/seibel/lod/Main.java @@ -11,6 +11,7 @@ public class Main { public static void main(String[] args) { + /* try { long[][] dataToMerge = new long[][]{ @@ -26,6 +27,6 @@ public class Main } }catch (Exception e){ e.printStackTrace(); - } + }*/ } } diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index bd2cd397d..4ff3eb99b 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -17,6 +17,7 @@ */ package com.seibel.lod.builders; +import java.awt.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; @@ -26,20 +27,18 @@ import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.seibel.lod.util.*; +import net.minecraft.client.renderer.LightTexture; import org.lwjgl.opengl.GL11; import com.seibel.lod.builders.lodTemplates.Box; import com.seibel.lod.config.LodConfig; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.PosToRenderContainer; import com.seibel.lod.objects.RegionPos; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.render.LodRenderer; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.vertex.VertexBuffer; @@ -142,6 +141,20 @@ public class LodBufferBuilder public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim, BlockPos playerBlockPos, boolean fullRegen) { + + + for(int i = 0; i<16; i++) + { + for(int j = 0; j<16; j++) + { + int lightTint = LightTexture.pack(i,j); + //System.out.print(ColorUtil.getRed(lightTint) + " " + ColorUtil.getGreen(lightTint) + " " + ColorUtil.getBlue(lightTint) + " "); + System.out.print(Integer.toHexString(lightTint) + " "); + } + System.out.println(); + } + + // only allow one generation process to happen at a time if (generatingBuffers) return; diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 9e3673fa7..d025f84b3 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -36,7 +36,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.DimensionType; -import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.IWorld; import net.minecraft.world.LightType; import net.minecraft.world.biome.Biome; @@ -44,8 +43,6 @@ import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.chunk.IChunk; import net.minecraft.world.gen.Heightmap; -import javax.xml.crypto.Data; - /** * This object is in charge of creating Lod related objects. (specifically: Lod * World, Dimension, and Region objects) @@ -277,11 +274,11 @@ public class LodBuilder color = generateLodColor(chunk, config, xRel, yAbs, zRel); depth = determineBottomPointFrom(chunk, config, xRel, zRel, yAbs, blockPos); blockPos.set(xAbs, yAbs + 1, zAbs); - light = getLightBlockValue(chunk, blockPos); + light = getLightValue(chunk, blockPos); //System.out.println(dataToMerge.length + " " + index +" " + count + " " + yAbs); //System.out.println(dataToMerge.length + " " + dataToMerge[index].length); - dataToMerge[index][count] = DataPointUtil.createDataPoint(height, depth, color, light, generation); + dataToMerge[index][count] = DataPointUtil.createDataPoint(height, depth, color, (light >> 4) & 0b1111, light & 0b1111, generation); yAbs = depth - 1; count++; } @@ -409,9 +406,9 @@ public class LodBuilder depth = determineBottomPoint(chunk, config, xRel, zRel, blockPos); blockPos.set(xAbs, yAbs + 1, zAbs); - light = getLightBlockValue(chunk, blockPos); + light = getLightValue(chunk, blockPos); - dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, light, generation); + dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, (light >> 4) & 0b1111, light & 0b1111, generation); } return dataToMerge; } @@ -522,17 +519,18 @@ public class LodBuilder return colorInt; } - private int getLightBlockValue(IChunk chunk, BlockPos.Mutable blockPos) + private int getLightValue(IChunk chunk, BlockPos.Mutable blockPos) { - int lightBlock; + int light; //*TODO choose the best one between those options*/ //lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos); //lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos); - lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.BLOCK, blockPos); + light = MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.BLOCK, blockPos); + light += MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.SKY, blockPos) << 4; //BlockState blockState = chunk.getBlockState(blockPos); //lightBlock = (byte) blockState.getLightBlock(chunk, blockPos); - return lightBlock; + return light; } /** diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java index 7d590c7fb..441ddb1a6 100644 --- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java @@ -63,21 +63,11 @@ public class CubicLodTemplate extends AbstractLodTemplate bufferCenterBlockPos); int color; boolean hasSkyLight = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasSkyLight(); + boolean hasRoof = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasSkyLight(); + int time = (int) (MinecraftWrapper.INSTANCE.getPlayer().level.getDayTime() - 13000); + boolean isDay = time < 0; //USE THIS IN THE boolean hasCeiling = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasCeiling(); - if (hasSkyLight) - { - int time = (int) (MinecraftWrapper.INSTANCE.getPlayer().level.getDayTime() - 13000); - if (time < 0) - { - color = DataPointUtil.getColor(data); - } else - { - /*TODO implement a smoother transition for light from day to night */ - color = DataPointUtil.getLightColor(data,4); - } - }else{ - color = DataPointUtil.getLightColor(data,1); - } + color = DataPointUtil.getLightColor(data, (hasRoof & hasSkyLight), isDay); if (debugging != DebugMode.OFF) diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index 0017b5eef..3de5e291b 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -42,7 +42,9 @@ public class VerticalLevelContainer implements LevelContainer public boolean doesItExist(int posX, int posZ){ long[] data = getData(posX,posZ); - return (data != null && DataPointUtil.doesItExist(data[0])); + if(data == null) + return false; + return DataPointUtil.doesItExist(data[0]); } public VerticalLevelContainer(String inputString) diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 33aab8e5c..7df1df24c 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -1,38 +1,72 @@ package com.seibel.lod.util; import com.seibel.lod.enums.DistanceGenerationMode; +import net.minecraft.client.renderer.LightTexture; public class DataPointUtil { + /* + |a |a |a |a |r |r |r |r | + |r |r |r |r |g |g |g |g | + + |g |g |g |g |b |b |b |b | + + |b |b |b |b |h |h |h |h | + + |h |h |h |h |h |h |d |d | + + |d |d |d |d |d |d |d |d | + + |bl |bl |bl |bl |sl |sl |sl |sl | + + |l |l |f |g |g |g |v |e | + + + */ //To be used in the future for negative value //public final static int MIN_DEPTH = -64; //public final static int MIN_HEIGHT = -64; public final static int EMPTY_DATA = 0; public final static int WORLD_HEIGHT = 256; - public final static int ALPHA_SHIFT = 56; - public final static int RED_SHIFT = 48; - public final static int GREEN_SHIFT = 40; - public final static int BLUE_SHIFT = 32; - public final static int COLOR_SHIFT = 32; - public final static int HEIGHT_SHIFT = 22; - public final static int DEPTH_SHIFT = 12; - public final static int LIGHT_SHIFT = 8; + public final static int ALPHA_DOWNSIZE_SHIFT = 4; + + public final static int BLUE_COLOR_SHIFT = 0; + public final static int GREEN_COLOR_SHIFT = 8; + public final static int RED_COLOR_SHIFT = 16; + public final static int ALPHA_COLOR_SHIFT = 24; + + public final static int BLUE_SHIFT = 36; + public final static int GREEN_SHIFT = BLUE_SHIFT + 8; + public final static int RED_SHIFT = BLUE_SHIFT + 16 ; + public final static int ALPHA_SHIFT = BLUE_SHIFT + 24; + + public final static int COLOR_SHIFT = 36; + + public final static int HEIGHT_SHIFT = 26; + public final static int DEPTH_SHIFT = 16; + public final static int BLOCK_LIGHT_SHIFT = 12; + public final static int SKY_LIGHT_SHIFT = 8; + public final static int LIGHTS_SHIFT = SKY_LIGHT_SHIFT; public final static int VERTICAL_INDEX_SHIFT = 6; + public final static int FLAG_SHIFT = 5; public final static int GEN_TYPE_SHIFT = 2; public final static int VOID_SHIFT = 1; public final static int EXISTENCE_SHIFT = 0; - public final static long ALPHA_MASK = 0b1111_1111; + public final static long ALPHA_MASK = 0b1111; public final static long RED_MASK = 0b1111_1111; public final static long GREEN_MASK = 0b1111_1111; public final static long BLUE_MASK = 0b1111_1111; - public final static long COLOR_MASK = 0b11111111_11111111_11111111_11111111; + public final static long COLOR_MASK = 0b11111111_11111111_11111111; public final static long HEIGHT_MASK = 0b11_1111_1111; public final static long DEPTH_MASK = 0b11_1111_1111; - public final static long LIGHT_MASK = 0b1111; + public final static long LIGHTS_MASK = 0b1111_1111; + public final static long BLOCK_LIGHT_MASK = 0b1111; + public final static long SKY_LIGHT_MASK = 0b1111; public final static long VERTICAL_INDEX_MASK = 0b11; + public final static long FLAG_MASK = 0b1; public final static long GEN_TYPE_MASK = 0b111; public final static long VOID_MASK = 1; public final static long EXISTENCE_MASK = 1; @@ -47,26 +81,27 @@ public class DataPointUtil return dataPoint; } - public static long createDataPoint(int height, int depth, int color, int lightValue, int generationMode) + public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode) { return createDataPoint( ColorUtil.getAlpha(color), ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color), - height, depth, lightValue, generationMode); + height, depth, lightSky, lightBlock, generationMode); } - public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightValue, int generationMode) + public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode) { long dataPoint = 0; - dataPoint += (alpha & ALPHA_MASK) << ALPHA_SHIFT; + dataPoint += ((alpha & ALPHA_MASK) >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT; dataPoint += (red & RED_MASK) << RED_SHIFT; dataPoint += (green & GREEN_MASK) << GREEN_SHIFT; dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT; dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT; - dataPoint += (lightValue & LIGHT_MASK) << LIGHT_SHIFT; + dataPoint += (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT; + dataPoint += (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT; dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT; return dataPoint; @@ -85,7 +120,7 @@ public class DataPointUtil public static short getAlpha(long dataPoint) { - return (short) ((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK); + return (short) (((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT); } public static short getRed(long dataPoint) @@ -103,9 +138,14 @@ public class DataPointUtil return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK); } - public static int getLightValue(long dataPoint) + public static int getLightSky(long dataPoint) { - return (int) ((dataPoint >>> LIGHT_SHIFT) & LIGHT_MASK); + return (int) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); + } + + public static int getLightBlock(long dataPoint) + { + return (int) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK); } public static byte getGenerationMode(long dataPoint) @@ -126,15 +166,25 @@ public class DataPointUtil public static int getColor(long dataPoint) { + int color = getBlue(dataPoint) << BLUE_COLOR_SHIFT; + color += getRed(dataPoint) << BLUE_COLOR_SHIFT; return (int) (dataPoint >>> COLOR_SHIFT); } - public static int getLightColor(long dataPoint, int amp) + public static int getLightColor(long dataPoint, boolean roof, boolean day) { - int lightBlock = getLightValue(dataPoint); - int red = LodUtil.clamp(0, getRed(dataPoint) + lightBlock * amp, 255); - int green = LodUtil.clamp(0, getGreen(dataPoint) + lightBlock * amp, 255); - int blue = LodUtil.clamp(0, getBlue(dataPoint) + lightBlock * amp, 255); + int lightBlock = getLightBlock(dataPoint); + int lightSky = getLightSky(dataPoint); + int lightTint = LightTexture.pack(lightSky,lightBlock); + + int red = (ColorUtil.getRed(lightTint) + getRed(dataPoint))/2; + int green = (ColorUtil.getGreen(lightTint) + getGreen(dataPoint))/2; + int blue = (ColorUtil.getBlue(lightTint) + getBlue(dataPoint))/2; + /* + red = LodUtil.clamp(0, getRed(dataPoint) + red, 255); + green = LodUtil.clamp(0, getGreen(dataPoint) + green, 255); + blue = LodUtil.clamp(0, getBlue(dataPoint) + blue, 255);*/ + return ColorUtil.rgbToInt(red, green, blue); } @@ -153,7 +203,9 @@ public class DataPointUtil s.append(" "); s.append(getGreen(dataPoint)); s.append(" "); - s.append(getLightValue(dataPoint)); + s.append(getLightBlock(dataPoint)); + s.append(" "); + s.append(getLightSky(dataPoint)); s.append(" "); s.append(getGenerationMode(dataPoint)); s.append(" "); @@ -175,7 +227,8 @@ public class DataPointUtil int tempBlue = 0; int tempHeight = 0; int tempDepth = 0; - int tempLight = 0; + int tempLightBlock = 0; + int tempLightSky = 0; byte tempGenMode = DistanceGenerationMode.SERVER.complexity; boolean allEmpty = true; boolean allVoid = true; @@ -194,7 +247,8 @@ public class DataPointUtil tempBlue += DataPointUtil.getBlue(data); tempHeight += DataPointUtil.getHeight(data); tempDepth += DataPointUtil.getDepth(data); - tempLight += DataPointUtil.getLightValue(data); + tempLightBlock += DataPointUtil.getLightBlock(data); + tempLightSky += DataPointUtil.getLightSky(data); } tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(data)); } else @@ -220,8 +274,9 @@ public class DataPointUtil tempBlue = tempBlue / numberOfChildren; tempHeight = tempHeight / numberOfChildren; tempDepth = tempDepth / numberOfChildren; - tempLight = tempLight / numberOfChildren; - return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLight, tempGenMode); + tempLightBlock = tempLightBlock / numberOfChildren; + tempLightSky = tempLightSky / numberOfChildren; + return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLightSky, tempLightBlock, tempGenMode); } } @@ -322,7 +377,7 @@ public class DataPointUtil } } long data = mergeSingleData(singleDataToMerge); - dataPoint[j] = createDataPoint(height, depth, getColor(data), getLightValue(data), getGenerationMode(data)); + dataPoint[j] = createDataPoint(height, depth, getColor(data), getLightSky(data), getLightBlock(data), getGenerationMode(data)); } return dataPoint;