From 21140593e26269db142749b269b12e75f175e25b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 10 Sep 2021 01:05:12 +0200 Subject: [PATCH] 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) {