From 30cc294a0486d812daef269389eaa2f11f4baea7 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Sat, 4 Dec 2021 14:03:01 +0100 Subject: [PATCH] reworked it back to primitive arrays --- .../LodBufferBuilderFactory.java | 61 +++-- .../lodTemplates/AbstractLodTemplate.java | 4 +- .../lodTemplates/CubicLodTemplate.java | 17 +- .../lodTemplates/DynamicLodTemplate.java | 4 +- .../lodTemplates/TriangularLodTemplate.java | 4 +- .../core/builders/lodBuilding/LodBuilder.java | 179 +++++++------- .../java/com/seibel/lod/core/objects/Box.java | 54 ++-- .../lod/core/objects/lod/DataPoint.java | 39 --- .../lod/core/objects/lod/LevelContainer.java | 21 +- .../lod/core/objects/lod/LodDimension.java | 75 ++++-- .../lod/core/objects/lod/LodRegion.java | 39 ++- .../objects/lod/VerticalLevelContainer.java | 152 ++++++++---- .../seibel/lod/core/util/DataPointUtil.java | 234 ++++++++++-------- .../seibel/lod/core/util/ThreadMapUtil.java | 216 ++++++++++++---- 14 files changed, 683 insertions(+), 416 deletions(-) delete mode 100644 src/main/java/com/seibel/lod/core/objects/lod/DataPoint.java diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java index f7bfdc8e1..054be59bd 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/LodBufferBuilderFactory.java @@ -30,7 +30,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; -import com.seibel.lod.core.objects.lod.DataPoint; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL30; @@ -288,7 +287,9 @@ public class LodBufferBuilderFactory int maxVerticalData = DetailDistanceUtil.getMaxVerticalData((byte) 0); //we get or create the map that will contain the adj data - Map adjData = ThreadMapUtil.getAdjDataArray(maxVerticalData); + + Map adjData = ThreadMapUtil.getAdjDataArray(maxVerticalData); + Map adjFlags = ThreadMapUtil.getAdjFlagsArray(maxVerticalData); //previous setToRender cache if (setsToRender[xR][zR] == null) @@ -348,7 +349,9 @@ public class LodBufferBuilderFactory xAdj = posX + Box.DIRECTION_NORMAL_MAP.get(lodDirection).x; zAdj = posZ + Box.DIRECTION_NORMAL_MAP.get(lodDirection).z; - DataPoint data; + int color; + int data; + byte flags; chunkXdist = LevelPosUtil.getChunkPos(detailLevel, xAdj) - playerChunkPos.getX(); chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkPos.getZ(); adjPosInPlayerChunk = (chunkXdist == 0 && chunkZdist == 0); @@ -364,20 +367,26 @@ public class LodBufferBuilderFactory { for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, xAdj, zAdj); verticalIndex++) { - data = lodDim.getData(detailLevel, xAdj, zAdj, verticalIndex); + lodDim.getDataPoint(detailLevel, xAdj, zAdj, verticalIndex); + data = ThreadMapUtil.dataPointData; + flags = ThreadMapUtil.dataPointFlags; adjShadeDisabled[Box.DIRECTION_INDEX.get(lodDirection)] = false; adjData.get(lodDirection)[verticalIndex] = data; + adjFlags.get(lodDirection)[verticalIndex] = flags; } } else { //Otherwise, we check if this position is - data = lodDim.getSingleData(detailLevel, xAdj, zAdj); + lodDim.getSingleDataPoint(detailLevel, xAdj, zAdj); + data = ThreadMapUtil.dataPointData; + flags = ThreadMapUtil.dataPointFlags; - adjData.get(lodDirection)[0] = DataPointUtil.EMPTY_DATA; + adjData.get(lodDirection)[0] = 0; + adjFlags.get(lodDirection)[0] = 0; if ((isThisPositionGoingToBeRendered(detailLevel, xAdj, zAdj, playerChunkPos, vanillaRenderedChunks, gameChunkRenderDistance) || (posNotInPlayerChunk && adjPosInPlayerChunk)) - && DataPointUtil.doesItExist(data) && !DataPointUtil.isVoid(data)) + && DataPointUtil.doesItExist(flags) && !DataPointUtil.isVoid(flags)) { adjShadeDisabled[Box.DIRECTION_INDEX.get(lodDirection)] = DataPointUtil.getAlpha(data) < 255; } @@ -387,32 +396,50 @@ public class LodBufferBuilderFactory // We render every vertical lod present in this position // We only stop when we find a block that is void or non-existing block - DataPoint data; + int color; + int data; + byte flags; for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++) { //we get the above block as adj UP if (verticalIndex > 0) - adjData.get(LodDirection.UP)[0] = lodDim.getData(detailLevel, posX, posZ, verticalIndex - 1); + { + lodDim.getDataPoint(detailLevel, posX, posZ, verticalIndex - 1); + adjData.get(LodDirection.UP)[0] = ThreadMapUtil.dataPointData; + adjFlags.get(LodDirection.UP)[0] = ThreadMapUtil.dataPointFlags; + } else - adjData.get(LodDirection.UP)[0] = DataPointUtil.EMPTY_DATA; - + { + adjData.get(LodDirection.UP)[0] = 0; + adjFlags.get(LodDirection.UP)[0] = 0; + } //we get the below block as adj DOWN if (verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ) - 1) - adjData.get(LodDirection.DOWN)[0] = lodDim.getData(detailLevel, posX, posZ, verticalIndex + 1); + { + lodDim.getDataPoint(detailLevel, posX, posZ, verticalIndex + 1); + adjData.get(LodDirection.DOWN)[0] = ThreadMapUtil.dataPointData; + adjFlags.get(LodDirection.DOWN)[0] = ThreadMapUtil.dataPointFlags; + } else - adjData.get(LodDirection.DOWN)[0] = DataPointUtil.EMPTY_DATA; + { + adjData.get(LodDirection.DOWN)[0] = 0; + adjFlags.get(LodDirection.DOWN)[0] = 0; + } //We extract the data to render - data = lodDim.getData(detailLevel, posX, posZ, verticalIndex); + lodDim.getDataPoint(detailLevel, posX, posZ, verticalIndex); + color = ThreadMapUtil.dataPointColor; + data = ThreadMapUtil.dataPointData; + flags = ThreadMapUtil.dataPointFlags; //If the data is not renderable (Void or non-existing) we stop since there is no data left in this position - if (!DataPointUtil.doesItExist(data) || DataPointUtil.isVoid(data)) + if (!DataPointUtil.doesItExist(flags) || DataPointUtil.isVoid(flags)) break; //We send the call to create the vertices - CONFIG.client().graphics().advancedGraphics().getLodTemplate().template.addLodToBuffer(currentBuffers[bufferIndex], playerBlockPosRounded, data, adjData, + CONFIG.client().graphics().advancedGraphics().getLodTemplate().template.addLodToBuffer(currentBuffers[bufferIndex], playerBlockPosRounded, color, data, flags, adjData, adjFlags, detailLevel, posX, posZ, box, renderer.previousDebugMode, adjShadeDisabled); } @@ -420,9 +447,7 @@ public class LodBufferBuilderFactory // the thread executed successfully return true; }; - nodeToRenderThreads.add(dataToRenderThread); - } } // region z } // region z diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java index 44a549079..37982ed9c 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java @@ -24,7 +24,6 @@ import java.util.Map; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.rendering.DebugMode; import com.seibel.lod.core.objects.Box; -import com.seibel.lod.core.objects.lod.DataPoint; import com.seibel.lod.core.objects.opengl.LodBufferBuilder; import com.seibel.lod.core.util.ColorUtil; import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; @@ -38,7 +37,8 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; public abstract class AbstractLodTemplate { /** Uploads the given LOD to the buffer. */ - public abstract void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, DataPoint data, Map adjData, + public abstract void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, int color, int data, byte flags, + Map adjData, Map adjFlags, byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled); /** add the given position and color to the buffer */ diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java index 124500966..a5cc055dc 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java @@ -24,7 +24,6 @@ import java.util.Map; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.rendering.DebugMode; import com.seibel.lod.core.objects.Box; -import com.seibel.lod.core.objects.lod.DataPoint; import com.seibel.lod.core.objects.opengl.LodBufferBuilder; import com.seibel.lod.core.util.ColorUtil; import com.seibel.lod.core.util.DataPointUtil; @@ -45,7 +44,9 @@ public class CubicLodTemplate extends AbstractLodTemplate } @Override - public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, DataPoint data, Map adjData, + public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, + int color, int data, byte flags, + Map adjData, Map adjFlags, byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled) { if (box == null) @@ -54,12 +55,8 @@ public class CubicLodTemplate extends AbstractLodTemplate // equivalent to 2^detailLevel int blockWidth = 1 << detailLevel; - int color; if (debugging != DebugMode.OFF) color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB(); - else - color = DataPointUtil.getColor(data); - generateBoundingBox( box, @@ -69,8 +66,9 @@ public class CubicLodTemplate extends AbstractLodTemplate posX * blockWidth, 0, posZ * blockWidth, // x, y, z offset bufferCenterBlockPos, adjData, + adjFlags, color, - DataPointUtil.getLightSkyAlt(data), + DataPointUtil.getLightSkyAlt(data, flags), DataPointUtil.getLightBlock(data), adjShadeDisabled); @@ -81,7 +79,8 @@ public class CubicLodTemplate extends AbstractLodTemplate int height, int depth, int width, double xOffset, double yOffset, double zOffset, AbstractBlockPosWrapper bufferCenterBlockPos, - Map adjData, + Map adjData, + Map adjFlags, int color, int skyLight, int blockLight, @@ -107,7 +106,7 @@ public class CubicLodTemplate extends AbstractLodTemplate box.setWidth(width, height - depth, width); box.setOffset((int) (xOffset + x), (int) (depth + yOffset), (int) (zOffset + z)); box.setUpCulling(32, bufferCenterBlockPos); - box.setAdjData(adjData); + box.setAdjData(adjData, adjFlags); } private void addBoundingBoxToBuffer(LodBufferBuilder buffer, Box box) diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java index a9f70e551..b40e8fee3 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java @@ -25,7 +25,6 @@ import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.rendering.DebugMode; import com.seibel.lod.core.objects.Box; -import com.seibel.lod.core.objects.lod.DataPoint; import com.seibel.lod.core.objects.opengl.LodBufferBuilder; import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; @@ -40,7 +39,8 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; public class DynamicLodTemplate extends AbstractLodTemplate { @Override - public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, DataPoint data, Map adjData, + public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, int color, int data, byte flags, + Map adjData, Map adjFlags, byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled) { ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!"); diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java index c1869d312..21e44005c 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java @@ -25,7 +25,6 @@ import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.rendering.DebugMode; import com.seibel.lod.core.objects.Box; -import com.seibel.lod.core.objects.lod.DataPoint; import com.seibel.lod.core.objects.opengl.LodBufferBuilder; import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; @@ -38,7 +37,8 @@ import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; public class TriangularLodTemplate extends AbstractLodTemplate { @Override - public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, DataPoint data, Map adjData, + public void addLodToBuffer(LodBufferBuilder buffer, AbstractBlockPosWrapper bufferCenterBlockPos, int color, int data, byte flags, + Map adjData, Map adjFlags, byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, boolean[] adjShadeDisabled) { ClientApi.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!"); diff --git a/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java index 22bfbd9a1..e45c4c279 100644 --- a/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java @@ -24,7 +24,6 @@ import java.util.concurrent.Executors; import com.seibel.lod.core.enums.config.DistanceGenerationMode; import com.seibel.lod.core.enums.config.HorizontalResolution; -import com.seibel.lod.core.objects.lod.DataPoint; import com.seibel.lod.core.objects.lod.LodDimension; import com.seibel.lod.core.objects.lod.LodRegion; import com.seibel.lod.core.objects.lod.LodWorld; @@ -196,105 +195,107 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper; startX = detail.startX[i]; startZ = detail.startZ[i]; - DataPoint[] data; - DataPoint[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ); - data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.WORLD_HEIGHT / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel)); + // creates a vertical DataPoint + // equivalent to 2^detailLevel + int size = 1 << detail.detailLevel; + int[] dataToMergeColor = ThreadMapUtil.getBuilderVerticalArrayColor(detail.detailLevel); + int[] dataToMergeData = ThreadMapUtil.getBuilderVerticalArrayData(detail.detailLevel); + byte[] dataToMergeFlags = ThreadMapUtil.getBuilderVerticalArrayFlags(detail.detailLevel); + int verticalData = DataPointUtil.WORLD_HEIGHT / 2 + 1; + + AbstractChunkPosWrapper chunkPos = chunk.getPos(); + int height; + int depth; + int color; + int light; + int lightSky; + int lightBlock; + byte generation = config.distanceGenerationMode.complexity; + + int xRel; + int zRel; + int xAbs; + int yAbs; + int zAbs; + boolean hasCeiling = MC.getWrappedClientWorld().getDimensionType().hasCeiling(); + boolean hasSkyLight = MC.getWrappedClientWorld().getDimensionType().hasSkyLight(); + boolean isDefault; + AbstractBlockPosWrapper blockPos = FACTORY.createBlockPos(); + int index; + + for (index = 0; index < size * size; index++) + { + xRel = startX + index % size; + zRel = startZ + index / size; + xAbs = chunkPos.getMinBlockX() + xRel; + zAbs = chunkPos.getMinBlockZ() + zRel; + + //Calculate the height of the lod + yAbs = DataPointUtil.WORLD_HEIGHT - DataPointUtil.VERTICAL_OFFSET + 1; + int count = 0; + boolean topBlock = true; + while (yAbs > 0) + { + height = determineHeightPointFrom(chunk, config, xRel, yAbs, zRel, blockPos); + + // If the lod is at the default height, it must be void data + if (height == DEFAULT_HEIGHT) + { + if (topBlock) + dataToMergeFlags[index * verticalData] = DataPointUtil.createVoidDataPoint(generation); + break; + } + + yAbs = height - 1; + // We search light on above air block + depth = determineBottomPointFrom(chunk, config, xRel, yAbs, zRel, blockPos); + if (hasCeiling && topBlock) + { + yAbs = depth; + blockPos.set(xAbs, yAbs, zAbs); + light = getLightValue(chunk, blockPos, true, hasSkyLight, true); + color = generateLodColor(chunk, config, xAbs, yAbs, zAbs, blockPos); + blockPos.set(xAbs, yAbs - 1, zAbs); + } + else + { + blockPos.set(xAbs, yAbs, zAbs); + light = getLightValue(chunk, blockPos, hasCeiling, hasSkyLight, topBlock); + color = generateLodColor(chunk, config, xRel, yAbs, zRel, blockPos); + blockPos.set(xAbs, yAbs + 1, zAbs); + } + lightBlock = light & 0b1111; + lightSky = (light >> 4) & 0b1111; + isDefault = ((light >> 8)) == 1; + DataPointUtil.createDataPoint(height - DataPointUtil.VERTICAL_OFFSET, depth - DataPointUtil.VERTICAL_OFFSET, color, lightSky, lightBlock, generation, isDefault); + dataToMergeColor[index * verticalData + count] = ThreadMapUtil.dataPointColor; + dataToMergeData[index * verticalData + count] = ThreadMapUtil.dataPointData; + dataToMergeFlags[index * verticalData + count] = ThreadMapUtil.dataPointFlags; + + topBlock = false; + yAbs = depth - 1; + count++; + } + } + + + DataPointUtil.mergeMultiData(dataToMergeColor, dataToMergeData, dataToMergeFlags, DataPointUtil.WORLD_HEIGHT / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel)); + int[] mergedColor = ThreadMapUtil.getRawVerticalDataArrayColor(); + int[] mergedData = ThreadMapUtil.getRawVerticalDataArrayData(); + byte[] mergedFlags = ThreadMapUtil.getRawVerticalDataArrayFlags(); //lodDim.clear(detailLevel, posX, posZ); - if (data != null && data.length != 0) + if (mergedFlags.length != 0) { posX = LevelPosUtil.convert((byte) 0, chunk.getPos().getX() * 16 + startX, detail.detailLevel); posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().getZ() * 16 + startZ, detail.detailLevel); - lodDim.addVerticalData(detailLevel, posX, posZ, data, false); + lodDim.addVerticalData(detailLevel, posX, posZ, mergedColor, mergedData, mergedFlags, false); } } lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().getX(), chunk.getPos().getZ()); } - /** creates a vertical DataPoint */ - private DataPoint[] createVerticalDataToMerge(HorizontalResolution detail, IChunkWrapper chunk, LodBuilderConfig config, int startX, int startZ) - { - // equivalent to 2^detailLevel - int size = 1 << detail.detailLevel; - - DataPoint[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray(detail.detailLevel); - int verticalData = DataPointUtil.WORLD_HEIGHT / 2 + 1; - - AbstractChunkPosWrapper chunkPos = chunk.getPos(); - int height; - int depth; - int color; - int light; - int lightSky; - int lightBlock; - int generation = config.distanceGenerationMode.complexity; - - int xRel; - int zRel; - int xAbs; - int yAbs; - int zAbs; - boolean hasCeiling = MC.getWrappedClientWorld().getDimensionType().hasCeiling(); - boolean hasSkyLight = MC.getWrappedClientWorld().getDimensionType().hasSkyLight(); - boolean isDefault; - AbstractBlockPosWrapper blockPos = FACTORY.createBlockPos(); - int index; - - for (index = 0; index < size * size; index++) - { - xRel = startX + index % size; - zRel = startZ + index / size; - xAbs = chunkPos.getMinBlockX() + xRel; - zAbs = chunkPos.getMinBlockZ() + zRel; - - //Calculate the height of the lod - yAbs = DataPointUtil.WORLD_HEIGHT - DataPointUtil.VERTICAL_OFFSET + 1; - int count = 0; - boolean topBlock = true; - while (yAbs > 0) - { - height = determineHeightPointFrom(chunk, config, xRel, yAbs, zRel, blockPos); - - // If the lod is at the default height, it must be void data - if (height == DEFAULT_HEIGHT) - { - if (topBlock) - dataToMerge[index * verticalData] = DataPointUtil.createVoidDataPoint(generation); - break; - } - - yAbs = height - 1; - // We search light on above air block - depth = determineBottomPointFrom(chunk, config, xRel, yAbs, zRel, blockPos); - if (hasCeiling && topBlock) - { - yAbs = depth; - blockPos.set(xAbs, yAbs, zAbs); - light = getLightValue(chunk, blockPos, true, hasSkyLight, true); - color = generateLodColor(chunk, config, xAbs, yAbs, zAbs, blockPos); - blockPos.set(xAbs, yAbs - 1, zAbs); - } - else - { - blockPos.set(xAbs, yAbs, zAbs); - light = getLightValue(chunk, blockPos, hasCeiling, hasSkyLight, topBlock); - color = generateLodColor(chunk, config, xRel, yAbs, zRel, blockPos); - blockPos.set(xAbs, yAbs + 1, zAbs); - } - lightBlock = light & 0b1111; - lightSky = (light >> 4) & 0b1111; - isDefault = ((light >> 8)) == 1; - - dataToMerge[index * verticalData + count] = DataPointUtil.createDataPoint(height - DataPointUtil.VERTICAL_OFFSET, depth - DataPointUtil.VERTICAL_OFFSET, color, lightSky, lightBlock, generation, isDefault); - topBlock = false; - yAbs = depth - 1; - count++; - } - } - return dataToMerge; - } - /** * Find the lowest valid point from the bottom. * Used when creating a vertical LOD. diff --git a/src/main/java/com/seibel/lod/core/objects/Box.java b/src/main/java/com/seibel/lod/core/objects/Box.java index 9af37bda1..4b85e7154 100644 --- a/src/main/java/com/seibel/lod/core/objects/Box.java +++ b/src/main/java/com/seibel/lod/core/objects/Box.java @@ -25,7 +25,6 @@ import java.util.Map; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.rendering.DebugMode; -import com.seibel.lod.core.objects.lod.DataPoint; import com.seibel.lod.core.objects.math.Vec3i; import com.seibel.lod.core.util.ColorUtil; import com.seibel.lod.core.util.DataPointUtil; @@ -340,25 +339,27 @@ public class Box * This method create all the shared face culling based on the adjacent data * @param adjData data adjacent to the column we are going to render */ - public void setAdjData(Map adjData) + public void setAdjData(Map adjData, Map adjFlags) { int height; int depth; int minY = getMinY(); int maxY = getMaxY(); - DataPoint singleAdjDataPoint; + int singleAdjData; + byte singleAdjFlags; /* TODO implement attached vertical face culling //Up direction case if(DataPointUtil.doesItExist(adjData.get(Direction.UP))) { - height = DataPointUtil.getHeight(singleAdjDataPoint); - depth = DataPointUtil.getDepth(singleAdjDataPoint); + height = DataPointUtil.getHeight(singleAdjData); + depth = DataPointUtil.getDepth(singleAdjData); }*/ //Down direction case - singleAdjDataPoint = adjData.get(LodDirection.DOWN)[0]; - if(DataPointUtil.doesItExist(singleAdjDataPoint)) - skyLights.get(LodDirection.DOWN)[0] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); + singleAdjData = adjData.get(LodDirection.DOWN)[0]; + singleAdjFlags = adjFlags.get(LodDirection.DOWN)[0]; + if(DataPointUtil.doesItExist(singleAdjFlags)) + skyLights.get(LodDirection.DOWN)[0] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); else skyLights.get(LodDirection.DOWN)[0] = skyLights.get(LodDirection.UP)[0]; //other sided @@ -368,8 +369,9 @@ public class Box if (isCulled(lodDirection)) continue; - DataPoint[] dataPoint = adjData.get(lodDirection); - if (DataPointUtil.isVoid(dataPoint[0])) + int[] data = adjData.get(lodDirection); + byte[] flags = adjFlags.get(lodDirection); + if (DataPointUtil.isVoid(flags[0])) { adjHeight.get(lodDirection)[0] = maxY; adjDepth.get(lodDirection)[0] = minY; @@ -385,15 +387,16 @@ public class Box boolean toFinish = false; int toFinishIndex = 0; boolean allAbove = true; - for (i = 0; i < dataPoint.length; i++) + for (i = 0; i < flags.length; i++) { - singleAdjDataPoint = dataPoint[i]; + singleAdjData = data[i]; + singleAdjFlags = flags[i]; - if (DataPointUtil.isVoid(singleAdjDataPoint) || !DataPointUtil.doesItExist(singleAdjDataPoint)) + if (DataPointUtil.isVoid(singleAdjFlags) || !DataPointUtil.doesItExist(singleAdjFlags)) break; - height = DataPointUtil.getHeight(singleAdjDataPoint); - depth = DataPointUtil.getDepth(singleAdjDataPoint); + height = DataPointUtil.getHeight(singleAdjData); + depth = DataPointUtil.getDepth(singleAdjData); if (depth <= maxY) { @@ -406,12 +409,12 @@ public class Box { adjHeight.get(lodDirection)[0] = getMaxY(); adjDepth.get(lodDirection)[0] = getMinY(); - skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); //skyLights.get(Direction.UP)[0]; + skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); //skyLights.get(Direction.UP)[0]; } else { adjDepth.get(lodDirection)[faceToDraw] = getMinY(); - skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); + skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); } faceToDraw++; toFinish = false; @@ -437,12 +440,12 @@ public class Box { adjHeight.get(lodDirection)[0] = getMaxY(); adjDepth.get(lodDirection)[0] = height; - skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); //skyLights.get(Direction.UP)[0]; + skyLights.get(lodDirection)[0] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); //skyLights.get(Direction.UP)[0]; } else { adjDepth.get(lodDirection)[faceToDraw] = height; - skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); + skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); } toFinish = false; faceToDraw++; @@ -454,7 +457,7 @@ public class Box // the adj data intersects the higher part of the current data // we start the creation of a new face adjHeight.get(lodDirection)[faceToDraw] = depth; - //skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSkyAlt(singleAdjDataPoint); + //skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSkyAlt(singleAdjData); firstFace = false; toFinish = true; toFinishIndex = i + 1; @@ -470,7 +473,7 @@ public class Box } adjDepth.get(lodDirection)[faceToDraw] = height; - skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); + skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); faceToDraw++; adjHeight.get(lodDirection)[faceToDraw] = depth; firstFace = false; @@ -490,11 +493,12 @@ public class Box else if (toFinish) { adjDepth.get(lodDirection)[faceToDraw] = minY; - if(toFinishIndex < dataPoint.length) + if(toFinishIndex < flags.length) { - singleAdjDataPoint = dataPoint[toFinishIndex]; - if (DataPointUtil.doesItExist(singleAdjDataPoint)) - skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjDataPoint); + singleAdjData = data[toFinishIndex]; + singleAdjFlags = flags[toFinishIndex]; + if (DataPointUtil.doesItExist(singleAdjFlags)) + skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSkyAlt(singleAdjData, singleAdjFlags); else skyLights.get(lodDirection)[faceToDraw] = skyLights.get(LodDirection.UP)[0]; } diff --git a/src/main/java/com/seibel/lod/core/objects/lod/DataPoint.java b/src/main/java/com/seibel/lod/core/objects/lod/DataPoint.java deleted file mode 100644 index 4ce109f3a..000000000 --- a/src/main/java/com/seibel/lod/core/objects/lod/DataPoint.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.seibel.lod.core.objects.lod; - -public class DataPoint -{ - public int color; - // |a |a |a |a |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 | - public int data; - // |h |h |h |h |h |h |h |h | - // |h |h |h |h |d |d |d |d | - // |d |d |d |d |d |d |d |d | - // |bl |bl |bl |bl |sl |sl |sl |sl | - public byte flags; - // |l |l |f |g |g |g |v |e | - - - public DataPoint() - { - color = 0; - data = 0; - flags = 0; - } - - public DataPoint(int newColor, int newData, byte newFlags) - { - color = newColor; - data = newData; - flags = newFlags; - } - - public void clear() - { - color = 0; - data = 0; - flags = 0; - } -} diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java b/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java index 2fb2c553d..fbeb81d8d 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LevelContainer.java @@ -32,7 +32,7 @@ public interface LevelContainer * @param index z position in the detail level * @return true if correctly added, false otherwise */ - boolean addData(DataPoint data, int posX, int posZ, int index); + boolean addData(int color, int data, byte flags, int posX, int posZ, int index); /** * With this you can add data to the level container @@ -41,7 +41,7 @@ public interface LevelContainer * @param posZ z position in the detail level * @return true if correctly added, false otherwise */ - boolean addVerticalData(DataPoint[] data, int posX, int posZ); + boolean addVerticalData(int[] color, int[] data, byte[] flags, int posX, int posZ); /** * With this you can add data to the level container @@ -50,25 +50,32 @@ public interface LevelContainer * @param posZ z position in the detail level * @return true if correctly added, false otherwise */ - boolean addSingleData(DataPoint data, int posX, int posZ); + boolean addSingleData(int color, int data, byte flags, int posX, int posZ); /** * With this you can get data from the level container + * data is returned to ThreadMapUtil variables * @param posX x position in the detail level * @param posZ z position in the detail level - * @return the data in long array format */ - DataPoint getData(int posX, int posZ, int index); + void getDataPoint(int posX, int posZ, int index); /** * With this you can get data from the level container + * data is returned to ThreadMapUtil variables * @param posX x position in the detail level * @param posZ z position in the detail level - * @return the data in long array format */ - DataPoint getSingleData(int posX, int posZ); + void getSingleDataPoint(int posX, int posZ); + + int getData(int posX, int posZ, int index); + + byte getFlags(int posX, int posZ, int index); + + byte getSingleFlags(int posX, int posZ); /** + * data is returned to ThreadMapUtil variables * @param posX x position in the detail level * @param posZ z position in the detail level * @return true only if the data exist diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java b/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java index 994075b84..9ae7683c0 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java @@ -30,12 +30,7 @@ import com.seibel.lod.core.enums.config.VerticalQuality; import com.seibel.lod.core.handlers.LodDimensionFileHandler; import com.seibel.lod.core.objects.PosToGenerateContainer; import com.seibel.lod.core.objects.PosToRenderContainer; -import com.seibel.lod.core.util.DataPointUtil; -import com.seibel.lod.core.util.DetailDistanceUtil; -import com.seibel.lod.core.util.LevelPosUtil; -import com.seibel.lod.core.util.LodThreadFactory; -import com.seibel.lod.core.util.LodUtil; -import com.seibel.lod.core.util.SingletonHandler; +import com.seibel.lod.core.util.*; import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory; import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; @@ -445,7 +440,7 @@ public class LodDimension * stored in the LOD. If an LOD already exists at the given * coordinate it will be overwritten. */ - public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, DataPoint data, boolean dontSave) + public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, int color, int data, byte flags, boolean dontSave) { int regionPosX = LevelPosUtil.getRegion(detailLevel, posX); int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ); @@ -455,7 +450,7 @@ public class LodDimension if (region == null) return false; - boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, data); + boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, color, data, flags); // only save valid LODs to disk if (!dontSave && fileHandler != null) @@ -487,7 +482,7 @@ public class LodDimension * stored in the LOD. If an LOD already exists at the given * coordinate it will be overwritten. */ - public Boolean addVerticalData(byte detailLevel, int posX, int posZ, DataPoint[] data, boolean dontSave) + public Boolean addVerticalData(byte detailLevel, int posX, int posZ, int[] color, int[] data, byte[] flags, boolean dontSave) { int regionPosX = LevelPosUtil.getRegion(detailLevel, posX); int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ); @@ -497,7 +492,7 @@ public class LodDimension if (region == null) return false; - boolean nodeAdded = region.addVerticalData(detailLevel, posX, posZ, data); + boolean nodeAdded = region.addVerticalData(detailLevel, posX, posZ, color, data, flags); // only save valid LODs to disk if (!dontSave && fileHandler != null) @@ -566,7 +561,9 @@ public class LodDimension byte detailLevel; int posX; int posZ; - DataPoint data; + int color; + int data; + byte flags; int numbChunksWide = (width) * 32; int circleLimit = Integer.MAX_VALUE; @@ -614,11 +611,12 @@ public class LodDimension posX = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, xChunkToCheck, detailLevel); posZ = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, zChunkToCheck, detailLevel); - data = getSingleData(detailLevel, posX, posZ); + getSingleDataPoint(detailLevel, posX, posZ); + flags = ThreadMapUtil.dataPointFlags; //we will generate the position only if the current generation complexity is lower than the target one. //an un-generated area will always have 0 generation - if (data != null && DataPointUtil.getGenerationMode(data) < complexity) + if (DataPointUtil.getGenerationMode(flags) < complexity) { posToGenerate.addPosToGenerate(detailLevel, posX, posZ); if (maxDataToGenerate >= 0) @@ -712,18 +710,41 @@ public class LodDimension * Returns null if the LodChunk doesn't exist or * is outside the loaded area. */ - public DataPoint getData(byte detailLevel, int posX, int posZ, int verticalIndex) + public void getDataPoint(byte detailLevel, int posX, int posZ, int verticalIndex) { if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); LodRegion region = getRegion(detailLevel, posX, posZ); if (region == null) - return DataPointUtil.EMPTY_DATA; - - return region.getData(detailLevel, posX, posZ, verticalIndex); + ThreadMapUtil.saveDataPoint(0,0, (byte) 0); + else + region.getDataPoint(detailLevel, posX, posZ, verticalIndex); } + public int getData(byte detailLevel, int posX, int posZ, int verticalIndex) + { + if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) + throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); + + LodRegion region = getRegion(detailLevel, posX, posZ); + if (region == null) + return 0; + else + return region.getData(detailLevel, posX, posZ, verticalIndex); + } + + public byte getFlags(byte detailLevel, int posX, int posZ, int verticalIndex) + { + if (detailLevel > LodUtil.REGION_DETAIL_LEVEL) + throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max."); + + LodRegion region = getRegion(detailLevel, posX, posZ); + if (region == null) + return 0; + else + return region.getFlags(detailLevel, posX, posZ, verticalIndex); + } /** * Get the data point at the given X and Z coordinates @@ -732,16 +753,28 @@ public class LodDimension * Returns null if the LodChunk doesn't exist or * is outside the loaded area. */ - public DataPoint getSingleData(byte detailLevel, int posX, int posZ) + public void getSingleDataPoint(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."); LodRegion region = getRegion(detailLevel, posX, posZ); if (region == null) - return DataPointUtil.EMPTY_DATA; - - return region.getSingleData(detailLevel, posX, posZ); + ThreadMapUtil.saveDataPoint(0, 0, (byte) 0); + else + region.getSingleDataPoint(detailLevel, posX, posZ); + } + + public byte getSingleFlags(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."); + + LodRegion region = getRegion(detailLevel, posX, posZ); + if (region == null) + return (byte) 0; + else + return region.getSingleFlags(detailLevel, posX, posZ); } /** Clears the given region */ diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java index a97ce2325..51e1da6f9 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java @@ -154,7 +154,7 @@ public class LodRegion * TODO this will always return true unless it has * @return true if the data was added successfully */ - public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, DataPoint data) + public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, int color, int data, byte flags) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); @@ -166,7 +166,7 @@ public class LodRegion this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel); } - this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex); + this.dataContainer[detailLevel].addData(color, data, flags, posX, posZ, verticalIndex); return true; } @@ -177,7 +177,7 @@ public class LodRegion * TODO this will always return true unless it has * @return true if the data was added successfully */ - public boolean addVerticalData(byte detailLevel, int posX, int posZ, DataPoint[] data) + public boolean addVerticalData(byte detailLevel, int posX, int posZ, int[] color, int[] data, byte[] flags) { //position is already relative //posX = LevelPosUtil.getRegionModule(detailLevel, posX); @@ -188,7 +188,7 @@ public class LodRegion if (this.dataContainer[detailLevel] == null) this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel); - return this.dataContainer[detailLevel].addVerticalData(data, posX, posZ); + return this.dataContainer[detailLevel].addVerticalData(color, data, flags, posX, posZ); } /** @@ -196,21 +196,42 @@ public class LodRegion * @return the data at the relative pos and detail level, * 0 if the data doesn't exist. */ - public DataPoint getData(byte detailLevel, int posX, int posZ, int verticalIndex) + public void getDataPoint(byte detailLevel, int posX, int posZ, int verticalIndex) + { + dataContainer[detailLevel].getDataPoint(posX, posZ, verticalIndex); + } + + public int getData(byte detailLevel, int posX, int posZ, int verticalIndex) { return dataContainer[detailLevel].getData(posX, posZ, verticalIndex); } + public byte getFlags(byte detailLevel, int posX, int posZ, int verticalIndex) + { + return dataContainer[detailLevel].getFlags(posX, posZ, verticalIndex); + } + /** * Get the dataPoint at the given relative position. * @return the data at the relative pos and detail level, * 0 if the data doesn't exist. */ - public DataPoint getSingleData(byte detailLevel, int posX, int posZ) + public void getSingleDataPoint(byte detailLevel, int posX, int posZ) { - return dataContainer[detailLevel].getSingleData(posX, posZ); + dataContainer[detailLevel].getSingleDataPoint(posX, posZ); } + /** + * Get the flags at the given relative position. + * @return the data at the relative pos and detail level, + * 0 if the data doesn't exist. + */ + public byte getSingleFlags(byte detailLevel, int posX, int posZ) + { + return dataContainer[detailLevel].getSingleFlags(posX, posZ); + } + + /** * Clears the datapoint at the given relative position */ @@ -358,6 +379,7 @@ public class LodRegion posZ + regionPosZ * size); } else + { //if (desiredLevel > detailLevel) //{ // we have gone beyond the target Detail level @@ -408,6 +430,7 @@ public class LodRegion } } } + } } @@ -479,7 +502,7 @@ public class LodRegion if (dataContainer[detailLevel].doesItExist(posX, posZ)) // We take the bottom information always // TODO what does that mean? bottom of what? - return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleData(posX, posZ)); + return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleFlags(posX, posZ)); else return DistanceGenerationMode.NONE.complexity; } diff --git a/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java index 9fad8ae7c..b3fcec794 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/VerticalLevelContainer.java @@ -37,14 +37,19 @@ public class VerticalLevelContainer implements LevelContainer public final int size; public final int maxVerticalData; - public final DataPoint[] dataContainer; + public final int[] dataContainerColor; + public final int[] dataContainerData; + public final byte[] dataContainerFlags; public VerticalLevelContainer(byte detailLevel) { this.detailLevel = detailLevel; size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); maxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel); - dataContainer = new DataPoint[size * size * DetailDistanceUtil.getMaxVerticalData(detailLevel)]; + final int i = size * size * maxVerticalData; + dataContainerColor = new int[i]; + dataContainerData = new int[i]; + dataContainerFlags = new byte[i]; } @Override @@ -60,47 +65,79 @@ public class VerticalLevelContainer implements LevelContainer posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); for (int verticalIndex = 0; verticalIndex < maxVerticalData; verticalIndex++) { - dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex] = DataPointUtil.EMPTY_DATA; + final int i = (posX * size + posZ) * maxVerticalData + verticalIndex; + dataContainerColor[i] = 0; + dataContainerData[i] = 0; + dataContainerFlags[i] = 0; } } @Override - public boolean addData(DataPoint data, int posX, int posZ, int verticalIndex) + public boolean addData(int color, int data, byte flags, int posX, int posZ, int verticalIndex) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex] = data; + final int i = (posX * size + posZ) * maxVerticalData + verticalIndex; + dataContainerColor[i] = color; + dataContainerData[i] = data; + dataContainerFlags[i] = flags; return true; } @Override - public boolean addVerticalData(DataPoint[] data, int posX, int posZ) + public boolean addVerticalData(int[] color, int[] data, byte[] flags, int posX, int posZ) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); for (int verticalIndex = 0; verticalIndex < maxVerticalData; verticalIndex++) - dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex] = data[verticalIndex]; + { + final int i = (posX * size + posZ) * maxVerticalData + verticalIndex; + dataContainerColor[i] = color[verticalIndex]; + dataContainerData[i] = data[verticalIndex]; + dataContainerFlags[i] = flags[verticalIndex]; + } return true; } @Override - public boolean addSingleData(DataPoint data, int posX, int posZ) + public boolean addSingleData(int color, int data, byte flags, int posX, int posZ) { - return addData(data, posX, posZ, 0); + return addData(color, data, flags, posX, posZ, 0); } @Override - public DataPoint getData(int posX, int posZ, int verticalIndex) + public void getDataPoint(int posX, int posZ, int verticalIndex) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return dataContainer[posX * size * maxVerticalData + posZ * maxVerticalData + verticalIndex]; + final int i = (posX * size + posZ) * maxVerticalData + verticalIndex; + ThreadMapUtil.saveDataPoint(dataContainerColor[i], dataContainerData[i], dataContainerFlags[i]); } @Override - public DataPoint getSingleData(int posX, int posZ) + public void getSingleDataPoint(int posX, int posZ) { - return getData(posX, posZ, 0); + getDataPoint(posX, posZ, 0); + } + + @Override + public int getData(int posX, int posZ, int verticalIndex) + { + return dataContainerData[(posX * size + posZ) * maxVerticalData + verticalIndex]; + } + + @Override + public byte getFlags(int posX, int posZ, int verticalIndex) + { + return dataContainerFlags[(posX * size + posZ) * maxVerticalData + verticalIndex]; + } + + @Override + public byte getSingleFlags(int posX, int posZ) + { + posX = LevelPosUtil.getRegionModule(detailLevel, posX); + posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + return dataContainerFlags[(posX * size + posZ) * maxVerticalData]; } @Override @@ -119,7 +156,7 @@ public class VerticalLevelContainer implements LevelContainer { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - return DataPointUtil.doesItExist(getSingleData(posX, posZ)); + return DataPointUtil.doesItExist(dataContainerFlags[(posX * size + posZ) * maxVerticalData]); } public VerticalLevelContainer(byte[] inputData, int version) @@ -133,7 +170,9 @@ public class VerticalLevelContainer implements LevelContainer index++; size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); int x = size * size * tempMaxVerticalData; - DataPoint[] tempDataContainer = new DataPoint[x]; + int[] tempDataContainerColor = new int[x]; + int[] tempDataContainerData = new int[x]; + byte[] tempDataContainerFlags = new byte[x]; if (version == 6) { @@ -154,7 +193,7 @@ public class VerticalLevelContainer implements LevelContainer |bl |bl |bl |bl |sl |sl |sl |sl | |l |l |f |g |g |g |v |e | */ - DataPoint newData = DataPointUtil.createDataPoint( + DataPointUtil.createDataPoint( (int)((oldData >> 60) << 4) + 15, (int)(oldData >> 52) & 0xFF, (int)(oldData >> 44) & 0xFF, @@ -166,7 +205,9 @@ public class VerticalLevelContainer implements LevelContainer (int)(oldData >> 5) & 0x1, ((oldData >> 5) & 0x1) == 1 ); - tempDataContainer[i] = newData; + tempDataContainerColor[i] = ThreadMapUtil.dataPointColor; + tempDataContainerData[i] = ThreadMapUtil.dataPointData; + tempDataContainerFlags[i] = ThreadMapUtil.dataPointFlags; } } else if (version == 7) @@ -178,7 +219,7 @@ public class VerticalLevelContainer implements LevelContainer for (tempIndex = 0; tempIndex < 8; tempIndex++) oldData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex); index += 8; - DataPoint newData = DataPointUtil.createDataPoint( + DataPointUtil.createDataPoint( (int)((oldData >> 60) << 4) + 15, (int)(oldData >> 52) & 0xFF, (int)(oldData >> 44) & 0xFF, @@ -190,7 +231,9 @@ public class VerticalLevelContainer implements LevelContainer (int)(oldData >> 5) & 0x1, ((oldData >> 5) & 0x1) == 1 ); - tempDataContainer[i] = newData; + tempDataContainerColor[i] = ThreadMapUtil.dataPointColor; + tempDataContainerData[i] = ThreadMapUtil.dataPointData; + tempDataContainerFlags[i] = ThreadMapUtil.dataPointFlags; } } else //if (version == 8) @@ -210,28 +253,42 @@ public class VerticalLevelContainer implements LevelContainer } index += 8; - tempDataContainer[i] = new DataPoint(color, data, flags); + tempDataContainerColor[i] = color; + tempDataContainerData[i] = data; + tempDataContainerFlags[i] = flags; } } if (tempMaxVerticalData > DetailDistanceUtil.getMaxVerticalData(detailLevel)) { int tempMaxVerticalData2 = DetailDistanceUtil.getMaxVerticalData(detailLevel); - DataPoint[] dataToMerge = new DataPoint[tempMaxVerticalData]; - DataPoint[] tempDataContainer2 = new DataPoint[size * size * tempMaxVerticalData2]; + int[] dataToMergeColor = new int[tempMaxVerticalData]; + int[] dataToMergeData = new int[tempMaxVerticalData]; + byte[] dataToMergeFlags = new byte[tempMaxVerticalData]; + int[] tempDataContainer2Color = new int[size * size * tempMaxVerticalData2]; + int[] tempDataContainer2Data = new int[size * size * tempMaxVerticalData2]; + byte[] tempDataContainer2Flags = new byte[size * size * tempMaxVerticalData2]; for (int i = 0; i < size * size; i++) { - System.arraycopy(tempDataContainer, i * tempMaxVerticalData, dataToMerge, 0, tempMaxVerticalData); - dataToMerge = DataPointUtil.mergeMultiData(dataToMerge, tempMaxVerticalData, tempMaxVerticalData2); - System.arraycopy(dataToMerge, 0, tempDataContainer2, i * tempMaxVerticalData2, tempMaxVerticalData2); + System.arraycopy(tempDataContainerColor, i * tempMaxVerticalData, dataToMergeColor, 0, tempMaxVerticalData); + System.arraycopy(tempDataContainerData, i * tempMaxVerticalData, dataToMergeData, 0, tempMaxVerticalData); + System.arraycopy(tempDataContainerFlags, i * tempMaxVerticalData, dataToMergeFlags, 0, tempMaxVerticalData); + DataPointUtil.mergeMultiData(dataToMergeColor, dataToMergeData, dataToMergeFlags, tempMaxVerticalData, tempMaxVerticalData2); + System.arraycopy(ThreadMapUtil.getRawVerticalDataArrayColor(), 0, tempDataContainer2Color, i * tempMaxVerticalData2, tempMaxVerticalData2); + System.arraycopy(ThreadMapUtil.getRawVerticalDataArrayData(), 0, tempDataContainer2Data, i * tempMaxVerticalData2, tempMaxVerticalData2); + System.arraycopy(ThreadMapUtil.getRawVerticalDataArrayFlags(), 0, tempDataContainer2Flags, i * tempMaxVerticalData2, tempMaxVerticalData2); } maxVerticalData = tempMaxVerticalData2; - this.dataContainer = tempDataContainer2; + this.dataContainerColor = tempDataContainer2Color; + this.dataContainerData = tempDataContainer2Data; + this.dataContainerFlags = tempDataContainer2Flags; } else { maxVerticalData = tempMaxVerticalData; - this.dataContainer = tempDataContainer; + this.dataContainerColor = tempDataContainerColor; + this.dataContainerData = tempDataContainerData; + this.dataContainerFlags = tempDataContainerFlags; } } @@ -245,12 +302,13 @@ public class VerticalLevelContainer implements LevelContainer public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) { //We reset the array - DataPoint[] dataToMerge = ThreadMapUtil.getVerticalUpdateArray(detailLevel); + int[] dataToMergeColor = ThreadMapUtil.getVerticalUpdateArrayColor(detailLevel); + int[] dataToMergeData = ThreadMapUtil.getVerticalUpdateArrayData(detailLevel); + byte[] dataToMergeFlags = ThreadMapUtil.getVerticalUpdateArrayFlags(detailLevel); - int lowerMaxVertical = dataToMerge.length / 4; + int lowerMaxVertical = dataToMergeFlags.length / 4; int childPosX; int childPosZ; - DataPoint[] data; posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); for (int x = 0; x <= 1; x++) @@ -260,12 +318,17 @@ public class VerticalLevelContainer implements LevelContainer childPosX = 2 * posX + x; childPosZ = 2 * posZ + z; for (int verticalIndex = 0; verticalIndex < lowerMaxVertical; verticalIndex++) - dataToMerge[(z * 2 + x) * lowerMaxVertical + verticalIndex] = lowerLevelContainer.getData(childPosX, childPosZ, verticalIndex); + { + lowerLevelContainer.getDataPoint(childPosX, childPosZ, verticalIndex); + final int i = (z * 2 + x) * lowerMaxVertical + verticalIndex; + dataToMergeColor[i] = ThreadMapUtil.dataPointColor; + dataToMergeData[i] = ThreadMapUtil.dataPointData; + dataToMergeFlags[i] = ThreadMapUtil.dataPointFlags; + } } } - data = DataPointUtil.mergeMultiData(dataToMerge, lowerMaxVertical, getMaxVerticalData()); - - addVerticalData(data, posX, posZ); + DataPointUtil.mergeMultiData(dataToMergeColor, dataToMergeData, dataToMergeFlags, lowerMaxVertical, getMaxVerticalData()); + addVerticalData(ThreadMapUtil.getRawVerticalDataArrayColor(), ThreadMapUtil.getRawVerticalDataArrayData(), ThreadMapUtil.getRawVerticalDataArrayFlags(), posX, posZ); } @Override @@ -274,7 +337,8 @@ public class VerticalLevelContainer implements LevelContainer int index = 0; int x = size * size; int tempIndex; - DataPoint current; + int currentColor; + int currentData; boolean allGenerated = true; byte[] tempData = ThreadMapUtil.getSaveContainer(detailLevel); @@ -287,20 +351,18 @@ public class VerticalLevelContainer implements LevelContainer { for (j = 0; j < maxVerticalData; j++) { - current = dataContainer[i * maxVerticalData + j]; - if (current != null) + currentColor = dataContainerColor[i * maxVerticalData + j]; + currentData = dataContainerData[i * maxVerticalData + j]; + tempData[index] = dataContainerFlags[i * maxVerticalData + j]; + index++; + for (tempIndex = 0; tempIndex < 4; tempIndex++) { - tempData[index] = current.flags; - index++; - for (tempIndex = 0; tempIndex < 4; tempIndex++) - { - tempData[index + tempIndex] = (byte) (current.data >>> (8 * tempIndex)); - tempData[index + tempIndex + 4] = (byte) (current.color >>> (8 * tempIndex)); - } + tempData[index + tempIndex] = (byte) (currentData >>> (8 * tempIndex)); + tempData[index + tempIndex + 4] = (byte) (currentColor >>> (8 * tempIndex)); } index += 8; } - if(dataContainer[i] == null || !DataPointUtil.doesItExist(dataContainer[i])) + if(!DataPointUtil.doesItExist(dataContainerFlags[i])) allGenerated = false; } if (allGenerated) diff --git a/src/main/java/com/seibel/lod/core/util/DataPointUtil.java b/src/main/java/com/seibel/lod/core/util/DataPointUtil.java index e39707ce7..c6e304966 100644 --- a/src/main/java/com/seibel/lod/core/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/core/util/DataPointUtil.java @@ -22,7 +22,6 @@ package com.seibel.lod.core.util; import static com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory.skyLightPlayer; import com.seibel.lod.core.enums.config.DistanceGenerationMode; -import com.seibel.lod.core.objects.lod.DataPoint; /** * @@ -58,7 +57,7 @@ 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 DataPoint EMPTY_DATA = new DataPoint(); + public final static byte EMPTY_DATA = 0; public static final short VERTICAL_OFFSET = -2048; public static int WORLD_HEIGHT = 4096; @@ -103,16 +102,17 @@ public class DataPointUtil public final static byte VOID_MASK = 1; public final static byte EXISTENCE_MASK = 1; - - public static DataPoint createVoidDataPoint(int generationMode) + /** Returns the Flags byte */ + public static byte createVoidDataPoint(byte generationMode) { - byte flags = (byte) ((generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT); - flags += VOID_MASK << VOID_SHIFT; - flags += EXISTENCE_MASK << EXISTENCE_SHIFT; - return new DataPoint(0, 0, flags); + generationMode = (byte) ((generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT); + generationMode |= VOID_MASK << VOID_SHIFT; + generationMode |= EXISTENCE_MASK << EXISTENCE_SHIFT; + return generationMode; } - public static DataPoint createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode, boolean flag) + /** Returned datapoint is in ThreadMapUtil */ + public static void createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode, boolean flag) { int data = (height & HEIGHT_MASK) << HEIGHT_SHIFT; data += (depth & DEPTH_MASK) << DEPTH_SHIFT; @@ -121,105 +121,106 @@ public class DataPointUtil byte flags = (byte) ((generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT); if (flag) flags += FLAG_MASK << FLAG_SHIFT; flags += EXISTENCE_MASK << EXISTENCE_SHIFT; - return new DataPoint(color, data, flags); + ThreadMapUtil.saveDataPoint(color, data, flags); } - public static DataPoint createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode, boolean flag) + public static void createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode, boolean flag) { - return createDataPoint( + createDataPoint( height, depth, (alpha << ALPHA_SHIFT) | (red << RED_SHIFT) | (green << GREEN_SHIFT) | blue, lightSky, lightBlock, generationMode, flag); } - public static short getHeight(DataPoint dataPoint) + public static short getHeight(int data) { - return (short) ((dataPoint.data >>> HEIGHT_SHIFT) & HEIGHT_MASK); + return (short) ((data >>> HEIGHT_SHIFT) & HEIGHT_MASK); } - public static short getDepth(DataPoint dataPoint) + public static short getDepth(int data) { - return (short) ((dataPoint.data >>> DEPTH_SHIFT) & DEPTH_MASK); + return (short) ((data >>> DEPTH_SHIFT) & DEPTH_MASK); } - public static short getAlpha(DataPoint dataPoint) + public static short getAlpha(int color) { - return (short) ((dataPoint.color >>> ALPHA_SHIFT) & ALPHA_MASK); + return (short) ((color >>> ALPHA_SHIFT) & ALPHA_MASK); } - public static short getRed(DataPoint dataPoint) + public static short getRed(int color) { - return (short) ((dataPoint.color >>> RED_SHIFT) & RED_MASK); + return (short) ((color >>> RED_SHIFT) & RED_MASK); } - public static short getGreen(DataPoint dataPoint) + public static short getGreen(int color) { - return (short) ((dataPoint.color >>> GREEN_SHIFT) & GREEN_MASK); + return (short) ((color >>> GREEN_SHIFT) & GREEN_MASK); } - public static short getBlue(DataPoint dataPoint) + public static short getBlue(int color) { - return (short) ((dataPoint.color >>> BLUE_SHIFT) & BLUE_MASK); + return (short) ((color >>> BLUE_SHIFT) & BLUE_MASK); } - public static byte getLightSky(DataPoint dataPoint) + public static byte getLightSky(int data) { - return (byte) ((dataPoint.data >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); + return (byte) ((data >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); } - public static byte getLightSkyAlt(DataPoint dataPoint) + public static byte getLightSkyAlt(int data, byte flags) { - if (skyLightPlayer == 0 && ((dataPoint.flags >>> FLAG_SHIFT) & FLAG_MASK) == 1) + if (skyLightPlayer == 0 && ((flags >>> FLAG_SHIFT) & FLAG_MASK) == 1) return 0; else - return (byte) ((dataPoint.data >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); + return (byte) ((data >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK); } - public static byte getLightBlock(DataPoint dataPoint) + public static byte getLightBlock(int data) { - return (byte) ((dataPoint.data >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK); + return (byte) ((data >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK); } - public static boolean getFlag(DataPoint dataPoint) + public static boolean getFlag(byte flags) { - return ((dataPoint.flags >>> FLAG_SHIFT) & FLAG_MASK) == 1; + return ((flags >>> FLAG_SHIFT) & FLAG_MASK) == 1; } - public static byte getGenerationMode(DataPoint dataPoint) + public static byte getGenerationMode(byte flags) { - return (byte) ((dataPoint.flags >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); + return (byte) ((flags >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK); } - public static boolean isVoid(DataPoint dataPoint) + public static boolean isVoid(byte flags) { - return (((dataPoint.flags >>> VOID_SHIFT) & VOID_MASK) == 1); + return (((flags >>> VOID_SHIFT) & VOID_MASK) == 1); } - public static boolean doesItExist(DataPoint dataPoint) + public static boolean doesItExist(byte flags) { - return (dataPoint != null) && (((dataPoint.flags >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1); + return ((flags >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1; } - public static int getColor(DataPoint dataPoint) + @Deprecated + public static int getColor(int color) { - return dataPoint.color; + return color; } /** This is used to convert a dataPoint to string (useful for the print function) */ @SuppressWarnings("unused") - public static String toString(DataPoint dataPoint) + public static String toString(int color, int data, byte flags) { - return getHeight(dataPoint) + " " + - getDepth(dataPoint) + " " + - getAlpha(dataPoint) + " " + - getRed(dataPoint) + " " + - getBlue(dataPoint) + " " + - getGreen(dataPoint) + " " + - getLightBlock(dataPoint) + " " + - getLightSky(dataPoint) + " " + - getGenerationMode(dataPoint) + " " + - isVoid(dataPoint) + " " + - doesItExist(dataPoint) + '\n'; + return getHeight(data) + " " + + getDepth(data) + " " + + getAlpha(color) + " " + + getRed(color) + " " + + getBlue(color) + " " + + getGreen(color) + " " + + getLightBlock(data) + " " + + getLightSky(data) + " " + + getGenerationMode(flags) + " " + + isVoid(flags) + " " + + doesItExist(flags) + '\n'; } public static void shrinkArray(short[] array, int packetSize, int start, int length, int arraySize) @@ -249,25 +250,30 @@ public class DataPointUtil /** * This method merge column of multiple data together - * @param dataToMerge one or more columns of data + * Returned datapoint is in ThreadMapUtil + * @param dataToMergeColor colors of one or more columns of data + * @param dataToMergeData data of one or more columns of data + * @param dataToMergeFlags flags of one or more columns of data * @param inputVerticalData vertical size of an input data * @param maxVerticalData max vertical size of the merged data - * @return one column of correctly parsed data */ - public static DataPoint[] mergeMultiData(DataPoint[] dataToMerge, int inputVerticalData, int maxVerticalData) + public static void mergeMultiData(int[] dataToMergeColor, int[] dataToMergeData, byte[] dataToMergeFlags, int inputVerticalData, int maxVerticalData) { - int size = dataToMerge.length / inputVerticalData; + int size = dataToMergeData.length / inputVerticalData; // We initialize the arrays that are going to be used short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((WORLD_HEIGHT / 2 + 1) * 2); - DataPoint[] dataPoint = ThreadMapUtil.getVerticalDataArray(DetailDistanceUtil.getMaxVerticalData(0)); + int[] dataPointColor = ThreadMapUtil.getVerticalDataArrayColor(DetailDistanceUtil.getMaxVerticalData(0)); + int[] dataPointData = ThreadMapUtil.getVerticalDataArrayData(DetailDistanceUtil.getMaxVerticalData(0)); + byte[] dataPointFlags = ThreadMapUtil.getVerticalDataArrayFlags(DetailDistanceUtil.getMaxVerticalData(0)); - int genMode = DistanceGenerationMode.FULL.complexity; + byte genMode = DistanceGenerationMode.FULL.complexity; boolean allEmpty = true; boolean allVoid = true; boolean allDefault; - DataPoint singleData; + int singleDataData; + byte singleDataFlags; short depth; @@ -281,16 +287,17 @@ public class DataPointUtil { for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++) { - singleData = dataToMerge[index * inputVerticalData + dataIndex]; - if (singleData != null && doesItExist(singleData)) + singleDataData = dataToMergeData[index * inputVerticalData + dataIndex]; + singleDataFlags = dataToMergeFlags[index * inputVerticalData + dataIndex]; + if (doesItExist(singleDataFlags)) { - genMode = Math.min(genMode, getGenerationMode(singleData)); + genMode = (byte) Math.min(genMode, getGenerationMode(singleDataFlags)); allEmpty = false; - if (!isVoid(singleData)) + if (!isVoid(singleDataFlags)) { allVoid = false; - depth = getDepth(singleData); - height = getHeight(singleData); + depth = getDepth(singleDataData); + height = getHeight(singleDataData); int botPos = -1; int topPos = -1; @@ -393,11 +400,11 @@ public class DataPointUtil //We check if there is any data that's not empty or void if (allEmpty) - return dataPoint; + return; if (allVoid) { - dataPoint[0] = createVoidDataPoint(genMode); - return dataPoint; + dataPointFlags[0] = createVoidDataPoint(genMode); + return; } //we limit the vertical portion to maxVerticalData @@ -442,73 +449,90 @@ public class DataPointUtil allEmpty = true; allVoid = true; allDefault = true; - DataPoint data = EMPTY_DATA; + int singleDataColor; + int data = EMPTY_DATA; + int color = EMPTY_DATA; + byte flags = EMPTY_DATA; for (int index = 0; index < size; index++) { for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++) { - singleData = dataToMerge[index * inputVerticalData + dataIndex]; - if (doesItExist(singleData) && !isVoid(singleData)) + singleDataColor = dataToMergeColor[index * inputVerticalData + dataIndex]; + singleDataData = dataToMergeData[index * inputVerticalData + dataIndex]; + singleDataFlags = dataToMergeFlags[index * inputVerticalData + dataIndex]; + if (doesItExist(singleDataFlags) && !isVoid(singleDataFlags)) { - if ((depth <= getDepth(singleData) && getDepth(singleData) <= height) - || (depth <= getHeight(singleData) && getHeight(singleData) <= height)) + if ((depth <= getDepth(singleDataData) && getDepth(singleDataData) <= height) + || (depth <= getHeight(singleDataData) && getHeight(singleDataData) <= height)) { - if (getHeight(singleData) > getHeight(data)) - data = singleData; + if (getHeight(singleDataData) > getHeight(data)) + { + color = singleDataColor; + data = singleDataData; + flags = singleDataFlags; + } } } else break; } - if (!doesItExist(data)) + if (!doesItExist(flags)) { - singleData = dataToMerge[index * inputVerticalData]; - if (doesItExist(singleData)) - data = createVoidDataPoint(getGenerationMode(singleData)); + singleDataFlags = dataToMergeFlags[index * inputVerticalData]; + if (doesItExist(singleDataFlags)) + flags = createVoidDataPoint(getGenerationMode(singleDataFlags)); else - data = createVoidDataPoint(0); + flags = createVoidDataPoint((byte) 0); + data = EMPTY_DATA; + color = EMPTY_DATA; } - if (doesItExist(data)) + if (doesItExist(flags)) { allEmpty = false; - if (!isVoid(data)) + if (!isVoid(flags)) { numberOfChildren++; allVoid = false; - tempAlpha += getAlpha(data); - tempRed += getRed(data); - tempGreen += getGreen(data); - tempBlue += getBlue(data); + tempAlpha += getAlpha(color); + tempRed += getRed(color); + tempGreen += getGreen(color); + tempBlue += getBlue(color); tempLightBlock += getLightBlock(data); tempLightSky += getLightSky(data); - if (!getFlag(data)) allDefault = false; + if (!getFlag(flags)) + allDefault = false; } - tempGenMode = (byte) Math.min(tempGenMode, getGenerationMode(data)); + tempGenMode = (byte) Math.min(tempGenMode, getGenerationMode(flags)); } else tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity); } - if (allEmpty) - //no child has been initialized - dataPoint[j] = EMPTY_DATA; - else if (allVoid) - //all the children are void - dataPoint[j] = createVoidDataPoint(tempGenMode); - else + if (!allEmpty) { - //we have at least 1 child - tempAlpha = tempAlpha / numberOfChildren; - tempRed = tempRed / numberOfChildren; - tempGreen = tempGreen / numberOfChildren; - tempBlue = tempBlue / numberOfChildren; - tempLightBlock = tempLightBlock / numberOfChildren; - tempLightSky = tempLightSky / numberOfChildren; - dataPoint[j] = createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, height, depth, tempLightSky, tempLightBlock, tempGenMode, allDefault); + //child has been initialized + if (allVoid) + { + //all the children are void + dataPointFlags[j] = createVoidDataPoint(tempGenMode); + } + else + { + //we have at least 1 child + tempAlpha = tempAlpha / numberOfChildren; + tempRed = tempRed / numberOfChildren; + tempGreen = tempGreen / numberOfChildren; + tempBlue = tempBlue / numberOfChildren; + tempLightBlock = tempLightBlock / numberOfChildren; + tempLightSky = tempLightSky / numberOfChildren; + createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, height, depth, tempLightSky, tempLightBlock, tempGenMode, allDefault); + dataPointColor[j] = ThreadMapUtil.dataPointColor; + dataPointData[j] = ThreadMapUtil.dataPointData; + dataPointFlags[j] = ThreadMapUtil.dataPointFlags; + } } } - return dataPoint; } } \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java index daf4a7785..fa50fdc52 100644 --- a/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java @@ -27,7 +27,6 @@ import java.util.concurrent.ConcurrentMap; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.objects.Box; -import com.seibel.lod.core.objects.lod.DataPoint; /** * Holds data used by specific threads so @@ -39,15 +38,18 @@ import com.seibel.lod.core.objects.lod.DataPoint; */ public class ThreadMapUtil { - 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 threadBuilderVerticalArrayMapColor = new ConcurrentHashMap<>(); + public static final ConcurrentMap threadBuilderVerticalArrayMapData = new ConcurrentHashMap<>(); + public static final ConcurrentMap threadBuilderVerticalArrayMapFlags = new ConcurrentHashMap<>(); + public static final ConcurrentMap threadVerticalAddDataMapColor = new ConcurrentHashMap<>(); + public static final ConcurrentMap threadVerticalAddDataMapData = new ConcurrentHashMap<>(); + public static final ConcurrentMap threadVerticalAddDataMapFlags = new ConcurrentHashMap<>(); public static final ConcurrentMap saveContainer = new ConcurrentHashMap<>(); public static final ConcurrentMap projectionArrayMap = new ConcurrentHashMap<>(); public static final ConcurrentMap heightAndDepthMap = new ConcurrentHashMap<>(); - public static final ConcurrentMap singleDataToMergeMap = new ConcurrentHashMap<>(); - public static final ConcurrentMap verticalUpdate = new ConcurrentHashMap<>(); + public static final ConcurrentMap verticalUpdateColor = new ConcurrentHashMap<>(); + public static final ConcurrentMap verticalUpdateData = new ConcurrentHashMap<>(); + public static final ConcurrentMap verticalUpdateFlags = new ConcurrentHashMap<>(); //________________________// @@ -55,9 +57,14 @@ public class ThreadMapUtil //________________________// public static final ConcurrentMap adjShadeDisabled = new ConcurrentHashMap<>(); - public static final ConcurrentMap> adjDataMap = new ConcurrentHashMap<>(); + public static final ConcurrentMap> adjDataMap = new ConcurrentHashMap<>(); + public static final ConcurrentMap> adjFlagsMap = new ConcurrentHashMap<>(); public static final ConcurrentMap boxMap = new ConcurrentHashMap<>(); + public static int dataPointColor = 0; + public static int dataPointData = 0; + public static byte dataPointFlags = 0; + /** returns the array NOT cleared every time */ @@ -73,7 +80,7 @@ public class ThreadMapUtil } /** returns the array NOT cleared every time */ - public static Map getAdjDataArray(int verticalData) + public static Map getAdjDataArray(int verticalData) { if (!adjDataMap.containsKey(Thread.currentThread().getName()) || (adjDataMap.get(Thread.currentThread().getName()) == null) @@ -81,20 +88,41 @@ public class ThreadMapUtil || (adjDataMap.get(Thread.currentThread().getName()).get(LodDirection.NORTH).length != verticalData)) { adjDataMap.put(Thread.currentThread().getName(), new HashMap<>()); - adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.UP, new DataPoint[1]); - adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.DOWN, new DataPoint[1]); + adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.UP, new int[1]); + adjDataMap.get(Thread.currentThread().getName()).put(LodDirection.DOWN, new int[1]); for (LodDirection lodDirection : Box.ADJ_DIRECTIONS) - adjDataMap.get(Thread.currentThread().getName()).put(lodDirection, new DataPoint[verticalData]); + adjDataMap.get(Thread.currentThread().getName()).put(lodDirection, new int[verticalData]); } else { - for (LodDirection lodDirection : Box.ADJ_DIRECTIONS) - Arrays.fill(adjDataMap.get(Thread.currentThread().getName()).get(lodDirection), DataPointUtil.EMPTY_DATA); + Arrays.fill(adjDataMap.get(Thread.currentThread().getName()).get(lodDirection), 0); } return adjDataMap.get(Thread.currentThread().getName()); } + /** returns the array NOT cleared every time */ + public static Map getAdjFlagsArray(int verticalData) + { + if (!adjFlagsMap.containsKey(Thread.currentThread().getName()) + || (adjFlagsMap.get(Thread.currentThread().getName()) == null) + || (adjFlagsMap.get(Thread.currentThread().getName()).get(LodDirection.NORTH) == null) + || (adjFlagsMap.get(Thread.currentThread().getName()).get(LodDirection.NORTH).length != verticalData)) + { + adjFlagsMap.put(Thread.currentThread().getName(), new HashMap<>()); + adjFlagsMap.get(Thread.currentThread().getName()).put(LodDirection.UP, new byte[1]); + adjFlagsMap.get(Thread.currentThread().getName()).put(LodDirection.DOWN, new byte[1]); + for (LodDirection lodDirection : Box.ADJ_DIRECTIONS) + adjFlagsMap.get(Thread.currentThread().getName()).put(lodDirection, new byte[verticalData]); + } + else + { + for (LodDirection lodDirection : Box.ADJ_DIRECTIONS) + Arrays.fill(adjFlagsMap.get(Thread.currentThread().getName()).get(lodDirection), (byte) 0); + } + return adjFlagsMap.get(Thread.currentThread().getName()); + } + public static Box getBox() { if (!boxMap.containsKey(Thread.currentThread().getName()) @@ -120,21 +148,57 @@ public class ThreadMapUtil /** returns the array filled with 0's */ - public static DataPoint[] getBuilderVerticalArray(int detailLevel) + public static int[] getBuilderVerticalArrayColor(int detailLevel) { - if (!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null)) + if (!threadBuilderVerticalArrayMapColor.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMapColor.get(Thread.currentThread().getName()) == null)) { - DataPoint[][] array = new DataPoint[5][]; + int[][] array = new int[5][]; int size; for (int i = 0; i < 5; i++) { size = 1 << i; - array[i] = new DataPoint[size * size * (DataPointUtil.WORLD_HEIGHT / 2 + 1)]; + array[i] = new int[size * size * (DataPointUtil.WORLD_HEIGHT / 2 + 1)]; } - threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array); + threadBuilderVerticalArrayMapColor.put(Thread.currentThread().getName(), array); } - Arrays.fill(threadBuilderVerticalArrayMap.get(Thread.currentThread().getName())[detailLevel], DataPointUtil.EMPTY_DATA); - return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName())[detailLevel]; + Arrays.fill(threadBuilderVerticalArrayMapColor.get(Thread.currentThread().getName())[detailLevel], 0); + return threadBuilderVerticalArrayMapColor.get(Thread.currentThread().getName())[detailLevel]; + } + + /** returns the array filled with 0's */ + public static int[] getBuilderVerticalArrayData(int detailLevel) + { + if (!threadBuilderVerticalArrayMapData.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMapData.get(Thread.currentThread().getName()) == null)) + { + int[][] array = new int[5][]; + int size; + for (int i = 0; i < 5; i++) + { + size = 1 << i; + array[i] = new int[size * size * (DataPointUtil.WORLD_HEIGHT / 2 + 1)]; + } + threadBuilderVerticalArrayMapData.put(Thread.currentThread().getName(), array); + } + Arrays.fill(threadBuilderVerticalArrayMapData.get(Thread.currentThread().getName())[detailLevel], 0); + return threadBuilderVerticalArrayMapData.get(Thread.currentThread().getName())[detailLevel]; + } + + /** returns the array filled with 0's */ + public static byte[] getBuilderVerticalArrayFlags(int detailLevel) + { + if (!threadBuilderVerticalArrayMapFlags.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMapFlags.get(Thread.currentThread().getName()) == null)) + { + byte[][] array = new byte[5][]; + int size; + for (int i = 0; i < 5; i++) + { + size = 1 << i; + array[i] = new byte[size * size * (DataPointUtil.WORLD_HEIGHT / 2 + 1)]; + } + threadBuilderVerticalArrayMapFlags.put(Thread.currentThread().getName(), array); + } + Arrays.fill(threadBuilderVerticalArrayMapFlags.get(Thread.currentThread().getName())[detailLevel], (byte) 0); + return threadBuilderVerticalArrayMapFlags.get(Thread.currentThread().getName())[detailLevel]; } /** returns the array NOT cleared every time */ @@ -157,19 +221,46 @@ public class ThreadMapUtil /** returns the array filled with 0's */ - public static DataPoint[] getVerticalDataArray(int arrayLength) + public static int[] getVerticalDataArrayColor(int arrayLength) { - if (!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null)) - { - threadVerticalAddDataMap.put(Thread.currentThread().getName(), new DataPoint[arrayLength]); - } + if (!threadVerticalAddDataMapColor.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMapColor.get(Thread.currentThread().getName()) == null)) + threadVerticalAddDataMapColor.put(Thread.currentThread().getName(), new int[arrayLength]); else - { - Arrays.fill(threadVerticalAddDataMap.get(Thread.currentThread().getName()), DataPointUtil.EMPTY_DATA); - } - return threadVerticalAddDataMap.get(Thread.currentThread().getName()); + Arrays.fill(threadVerticalAddDataMapColor.get(Thread.currentThread().getName()), 0); + return threadVerticalAddDataMapColor.get(Thread.currentThread().getName()); + } + public static int[] getRawVerticalDataArrayColor() + { + return threadVerticalAddDataMapColor.get(Thread.currentThread().getName()); } + /** returns the array filled with 0's */ + public static int[] getVerticalDataArrayData(int arrayLength) + { + if (!threadVerticalAddDataMapData.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMapData.get(Thread.currentThread().getName()) == null)) + threadVerticalAddDataMapData.put(Thread.currentThread().getName(), new int[arrayLength]); + else + Arrays.fill(threadVerticalAddDataMapData.get(Thread.currentThread().getName()), 0); + return threadVerticalAddDataMapData.get(Thread.currentThread().getName()); + } + public static int[] getRawVerticalDataArrayData() + { + return threadVerticalAddDataMapData.get(Thread.currentThread().getName()); + } + + /** returns the array filled with 0's */ + public static byte[] getVerticalDataArrayFlags(int arrayLength) + { + if (!threadVerticalAddDataMapFlags.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMapFlags.get(Thread.currentThread().getName()) == null)) + threadVerticalAddDataMapFlags.put(Thread.currentThread().getName(), new byte[arrayLength]); + else + Arrays.fill(threadVerticalAddDataMapFlags.get(Thread.currentThread().getName()), (byte) 0); + return threadVerticalAddDataMapFlags.get(Thread.currentThread().getName()); + } + public static byte[] getRawVerticalDataArrayFlags() + { + return threadVerticalAddDataMapFlags.get(Thread.currentThread().getName()); + } /** returns the array NOT cleared every time */ @@ -182,22 +273,49 @@ public class ThreadMapUtil return heightAndDepthMap.get(Thread.currentThread().getName()); } - /** returns the array filled with 0's */ - public static DataPoint[] getVerticalUpdateArray(int detailLevel) + public static int[] getVerticalUpdateArrayColor(int detailLevel) { - if (!verticalUpdate.containsKey(Thread.currentThread().getName()) || (verticalUpdate.get(Thread.currentThread().getName()) == null)) + if (!verticalUpdateColor.containsKey(Thread.currentThread().getName()) || (verticalUpdateColor.get(Thread.currentThread().getName()) == null)) { - DataPoint[][] array = new DataPoint[LodUtil.DETAIL_OPTIONS][]; + int[][] array = new int[LodUtil.DETAIL_OPTIONS][]; for (int i = 1; i < LodUtil.DETAIL_OPTIONS; i++) - array[i] = new DataPoint[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4]; - verticalUpdate.put(Thread.currentThread().getName(), array); + array[i] = new int[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4]; + verticalUpdateColor.put(Thread.currentThread().getName(), array); } else + Arrays.fill(verticalUpdateColor.get(Thread.currentThread().getName())[detailLevel], 0); + return verticalUpdateColor.get(Thread.currentThread().getName())[detailLevel]; + } + + /** returns the array filled with 0's */ + public static int[] getVerticalUpdateArrayData(int detailLevel) + { + if (!verticalUpdateData.containsKey(Thread.currentThread().getName()) || (verticalUpdateData.get(Thread.currentThread().getName()) == null)) { - Arrays.fill(verticalUpdate.get(Thread.currentThread().getName())[detailLevel], DataPointUtil.EMPTY_DATA); + int[][] array = new int[LodUtil.DETAIL_OPTIONS][]; + for (int i = 1; i < LodUtil.DETAIL_OPTIONS; i++) + array[i] = new int[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4]; + verticalUpdateData.put(Thread.currentThread().getName(), array); } - return verticalUpdate.get(Thread.currentThread().getName())[detailLevel]; + else + Arrays.fill(verticalUpdateData.get(Thread.currentThread().getName())[detailLevel], 0); + return verticalUpdateData.get(Thread.currentThread().getName())[detailLevel]; + } + + /** returns the array filled with 0's */ + public static byte[] getVerticalUpdateArrayFlags(int detailLevel) + { + if (!verticalUpdateFlags.containsKey(Thread.currentThread().getName()) || (verticalUpdateFlags.get(Thread.currentThread().getName()) == null)) + { + byte[][] array = new byte[LodUtil.DETAIL_OPTIONS][]; + for (int i = 1; i < LodUtil.DETAIL_OPTIONS; i++) + array[i] = new byte[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4]; + verticalUpdateFlags.put(Thread.currentThread().getName(), array); + } + else + Arrays.fill(verticalUpdateFlags.get(Thread.currentThread().getName())[detailLevel], (byte) 0); + return verticalUpdateFlags.get(Thread.currentThread().getName())[detailLevel]; } /** clears all arrays so they will have to be rebuilt */ @@ -206,14 +324,24 @@ public class ThreadMapUtil adjShadeDisabled.clear(); adjDataMap.clear(); boxMap.clear(); - threadSingleUpdateMap.clear(); - threadBuilderArrayMap.clear(); - threadBuilderVerticalArrayMap.clear(); - threadVerticalAddDataMap.clear(); + threadBuilderVerticalArrayMapColor.clear(); + threadBuilderVerticalArrayMapData.clear(); + threadBuilderVerticalArrayMapFlags.clear(); + threadVerticalAddDataMapColor.clear(); + threadVerticalAddDataMapData.clear(); + threadVerticalAddDataMapFlags.clear(); saveContainer.clear(); projectionArrayMap.clear(); heightAndDepthMap.clear(); - singleDataToMergeMap.clear(); - verticalUpdate.clear(); + verticalUpdateColor.clear(); + verticalUpdateData.clear(); + verticalUpdateFlags.clear(); + } + + public static void saveDataPoint(int color, int data, byte flags) + { + dataPointColor = color; + dataPointData = data; + dataPointFlags = flags; } }