From f422df628046e077d1dffcf2e6abe337ed06575a Mon Sep 17 00:00:00 2001 From: tom lee Date: Fri, 11 Feb 2022 12:38:35 +0800 Subject: [PATCH] Cleanup debug logging and get rid of unused functions in vertContainer --- .../LodBufferBuilderFactory.java | 2 +- .../core/builders/lodBuilding/LodBuilder.java | 89 +- .../objects/lod/VerticalLevelContainer.java | 766 +----------------- .../seibel/lod/core/util/DataPointUtil.java | 29 +- 4 files changed, 73 insertions(+), 813 deletions(-) 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 6e162b75b..066bef8da 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 @@ -911,7 +911,7 @@ public class LodBufferBuilderFactory private boolean swapBuffers() { bufferLock.lock(); if (ENABLE_BUFFER_SWAP_LOGGING) - ClientApi.LOGGER.info("Lod Swap Buffers"); + ClientApi.LOGGER.debug("Lod Swap Buffers"); { boolean shouldRegenBuff = true; try 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 573b6b8bc..0ca124d09 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 @@ -19,7 +19,6 @@ package com.seibel.lod.core.builders.lodBuilding; -import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -39,7 +38,6 @@ import com.seibel.lod.core.util.SingletonHandler; import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper; import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper; import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper; -import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper; @@ -158,46 +156,51 @@ public class LodBuilder */ public boolean generateLodNodeFromChunk(LodDimension lodDim, IChunkWrapper chunk, LodBuilderConfig config, boolean override, boolean genAll) { - if (chunk == null) - throw new IllegalArgumentException("generateLodFromChunk given a null chunk"); - LodRegion region = lodDim.getRegion(chunk.getRegionPosX(), chunk.getRegionPosZ()); - if (region == null) - return false; - // this happens if a LOD is generated after the user leaves the world. - if (MC.getWrappedClientWorld() == null) - return false; - if (!chunk.isLightCorrect()) return false; - - - // generate the LODs - int maxVerticalData = DetailDistanceUtil.getMaxVerticalData((byte)0); - long[] data = new long[maxVerticalData*16*16]; - - if (!config.quickFillWithVoid) { - for (int i = 0; i < 16*16; i++) - { - int subX = i/16; - int subZ = i%16; - writeVerticalData(data, i*maxVerticalData, maxVerticalData, chunk, config, subX, subZ); - //if (DataPointUtil.isVoid(data[i*maxVerticalData])) - // ClientApi.LOGGER.debug("Datapoint is Void: {}, {}", chunk.getMinX()+subX, chunk.getMinZ()+subZ); - if (!DataPointUtil.doesItExist(data[i*maxVerticalData])) - throw new RuntimeException("Datapoint does not exist at "+ chunk.getMinX()+subX +", "+ chunk.getMinZ()+subZ); - if (DataPointUtil.getGenerationMode(data[i*maxVerticalData]) != config.distanceGenerationMode.complexity) - throw new RuntimeException("Datapoint invalid at "+ chunk.getMinX()+subX +", "+ chunk.getMinZ()+subZ); + try { + if (chunk == null) + throw new IllegalArgumentException("generateLodFromChunk given a null chunk"); + LodRegion region = lodDim.getRegion(chunk.getRegionPosX(), chunk.getRegionPosZ()); + if (region == null) + return false; + // this happens if a LOD is generated after the user leaves the world. + if (MC.getWrappedClientWorld() == null) + return false; + if (!chunk.isLightCorrect()) return false; + + + // generate the LODs + int maxVerticalData = DetailDistanceUtil.getMaxVerticalData((byte)0); + long[] data = new long[maxVerticalData*16*16]; + + if (!config.quickFillWithVoid) { + for (int i = 0; i < 16*16; i++) + { + int subX = i/16; + int subZ = i%16; + writeVerticalData(data, i*maxVerticalData, maxVerticalData, chunk, config, subX, subZ); + //if (DataPointUtil.isVoid(data[i*maxVerticalData])) + // ClientApi.LOGGER.debug("Datapoint is Void: {}, {}", chunk.getMinX()+subX, chunk.getMinZ()+subZ); + if (!DataPointUtil.doesItExist(data[i*maxVerticalData])) + throw new RuntimeException("writeVerticalData result: Datapoint does not exist at "+ chunk.getMinX()+subX +", "+ chunk.getMinZ()+subZ); + if (DataPointUtil.getGenerationMode(data[i*maxVerticalData]) != config.distanceGenerationMode.complexity) + throw new RuntimeException("writeVerticalData result: Datapoint invalid at "+ chunk.getMinX()+subX +", "+ chunk.getMinZ()+subZ); + } + } else { + for (int i = 0; i < 16*16; i++) + { + data[i*maxVerticalData] = DataPointUtil.createVoidDataPoint(config.distanceGenerationMode.complexity); + } } - } else { - for (int i = 0; i < 16*16; i++) - { - data[i*maxVerticalData] = DataPointUtil.createVoidDataPoint(config.distanceGenerationMode.complexity); + if (!chunk.isLightCorrect()) return false; + + if (genAll) { + return writeAllLodNodeData(lodDim, region, chunk.getChunkPosX(), chunk.getChunkPosZ(), data, config, override); + } else { + return writePartialLodNodeData(lodDim, region, chunk.getChunkPosX(), chunk.getChunkPosZ(), data, config, override); } - } - if (!chunk.isLightCorrect()) return false; - - if (genAll) { - return writeAllLodNodeData(lodDim, region, chunk.getChunkPosX(), chunk.getChunkPosZ(), data, config, override); - } else { - return writePartialLodNodeData(lodDim, region, chunk.getChunkPosX(), chunk.getChunkPosZ(), data, config, override); + } catch (RuntimeException e) { + ClientApi.LOGGER.error("LodBuilder encountered an error on building lod for chunk {}: {}", chunk ,e); + return false; } } @@ -209,7 +212,7 @@ public class LodBuilder try { if (region.getMinDetailLevel()!= 0) { if (!LodUtil.checkRamUsage(0.05, 16)) { - ClientApi.LOGGER.warn("LodBuilder: Not enough RAM avalible for building lods! Skipping..."); + ClientApi.LOGGER.debug("LodBuilder: Not enough RAM avalible for loading files to build lods! Returning..."); return false; } @@ -227,8 +230,6 @@ public class LodBuilder throw new RuntimeException("data at detail 0 is still null after writes to it!"); if (!region.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ, config.distanceGenerationMode)) throw new RuntimeException("data at chunk detail level is still null after writes to it!"); - } catch (Exception e) { - e.printStackTrace(); } finally { region.isWriting.decrementAndGet(); } @@ -291,7 +292,7 @@ public class LodBuilder LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, targetLevel), LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkZ, targetLevel), config.distanceGenerationMode)) - throw new RuntimeException("data at detail 0 is still null after writes to it!"); + throw new RuntimeException("data at detail "+ targetLevel+" is still null after writes to it!"); } catch (Exception e) { e.printStackTrace(); } finally { 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 254c89348..5a066aff5 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 @@ -276,717 +276,6 @@ public class VerticalLevelContainer implements LevelContainer dataContainer = DataPointUtil.changeMaxVertSize(tempDataContainer, fileMaxVerticalData, verticalSize); } - /** - * This method merge column of multiple data together - * @return one column of correctly parsed data - */ - public void mergeAndAddData(int posZ, int posX, short[] inputPositionDataToMerge, int[] inputVerticalData, int[] inputColorData, byte[] inputLightData, byte inputDetailLevel, int inputVerticalSize) - { - mergeAndAddData(0, inputPositionDataToMerge.length, posZ, posX, inputPositionDataToMerge, inputVerticalData, inputColorData, inputLightData, inputDetailLevel, inputVerticalSize); - } - - /** - * This method merge column of multiple data together - * @return one column of correctly parsed data - */ - public void mergeAndAddData(int sliceStart, int sliceEnd, int posZ, int posX, short[] inputPositionData, int[] inputVerticalData, int[] inputColorData, byte[] inputLightData, byte inputDetailLevel, int inputVerticalSize) - { - - - //STEP 1// - //We initially reset this position of the data container - final int indexA = posX * size + posZ; - positionDataContainer[indexA] = PositionDataFormat.EMPTY_DATA; - for (int verticalIndex = 0; verticalIndex < verticalSize; verticalIndex++) - { - final int indexB = indexA * verticalSize + verticalIndex; - verticalDataContainer[indexB] = VerticalDataFormat.EMPTY_LOD; - lightDataContainer[indexB] = 0; - colorDataContainer[indexB] = 0; - } - - - - //STEP 2// - //We start by populating the PositionDataToMerge - byte genMode = DistanceGenerationMode.FULL.complexity; - boolean correctLight = true; - boolean allEmpty = true; - boolean allVoid = true; - - short tempPositionData; - //we combine every position in the slice of the input - //I THINK YOU CAN SEE HOW TO USE THE SLICE FROM HERE - for (int positionIndex = sliceStart; positionIndex <= sliceEnd; positionIndex++) - { - tempPositionData = inputPositionData[positionIndex]; - genMode = (byte) Math.min(genMode, PositionDataFormat.getGenerationMode(tempPositionData)); - correctLight &= PositionDataFormat.getFlag(tempPositionData); - allVoid &= PositionDataFormat.isVoid(tempPositionData); - allEmpty &= PositionDataFormat.doesItExist(tempPositionData); - } - - //Case 1: should never happen but we use this just in case - //if all the data is empty (maybe a bug) then we simply return - if (allEmpty) - { - return; - } - - //Case 2: if all the data is void - //if all the data is empty (maybe a bug) then we simply return - if (allVoid) - { - positionDataContainer[posX * size + posZ] = PositionDataFormat.createVoidPositionData(genMode); - return; - } - - //Case 3: data is non void and non empty, we continue - positionDataContainer[posX * size + posZ] = PositionDataFormat.createPositionData(0, correctLight, genMode); - - - //STEP 3// - //now we firstly merge the height and depth values of the input data - //in this process we do a sort of "projection" of the data on a single column - - /* simple visualization of the process - input: -> projection: - | | | | - | | | - | | - - - | | - - | | - | | - */ - - int inputSize = 1 << inputDetailLevel; - // I'll disable the ThreadMap array for the initial testing //ThreadMapUtil.getHeightAndDepth(inputVerticalSize * 2 * 4) - short[] heightAndDepth = new short[inputVerticalSize * 2 * 4]; - - int tempVerticalData; - short depth; - short height; - int count = 0; - int i; - int ii; - //We collect the indexes of the data, ordered by the depth - for (int positionIndex = sliceStart; positionIndex <= sliceEnd; positionIndex++) - { - tempPositionData = inputPositionData[positionIndex]; - if (!PositionDataFormat.doesItExist(tempPositionData) || PositionDataFormat.isVoid(tempPositionData)) - continue; - for (int verticalIndex = 0; verticalIndex < inputVerticalSize; verticalIndex++) - { - tempVerticalData = inputVerticalData[positionIndex * inputVerticalSize + verticalIndex]; - if (VerticalDataFormat.doesItExist(tempVerticalData)) - { - depth = VerticalDataFormat.getDepth(tempVerticalData); - height = VerticalDataFormat.getDepth(tempVerticalData); - - int botPos = -1; - int topPos = -1; - //values fall in between and possibly require extension of array - boolean botExtend = false; - boolean topExtend = false; - for (i = 0; i < count; i++) - { - if (depth <= heightAndDepth[i * 2] && depth >= heightAndDepth[i * 2 + 1]) - { - botPos = i; - break; - } - else if (depth < heightAndDepth[i * 2 + 1] && ((i + 1 < count && depth > heightAndDepth[(i + 1) * 2]) || i + 1 == count)) - { - botPos = i; - botExtend = true; - break; - } - } - for (i = 0; i < count; i++) - { - if (height <= heightAndDepth[i * 2] && height >= heightAndDepth[i * 2 + 1]) - { - topPos = i; - break; - } - else if (height < heightAndDepth[i * 2 + 1] && ((i + 1 < count && height > heightAndDepth[(i + 1) * 2]) || i + 1 == count)) - { - topPos = i; - topExtend = true; - break; - } - } - if (topPos == -1) - { - if (botPos == -1) - { - //whole block falls above - DataMergeUtil.extendArray(heightAndDepth, 2, 0, 1, count); - heightAndDepth[0] = height; - heightAndDepth[1] = depth; - count++; - } - else if (!botExtend) - { - //only top falls above extending it there, while bottom is inside existing - DataMergeUtil.shrinkArray(heightAndDepth, 2, 0, botPos, count); - heightAndDepth[0] = height; - count -= botPos; - } - else - { - //top falls between some blocks, extending those as well - DataMergeUtil.shrinkArray(heightAndDepth, 2, 0, botPos, count); - heightAndDepth[0] = height; - heightAndDepth[1] = depth; - count -= botPos; - } - } - else if (!topExtend) - { - if (!botExtend) - //both top and bottom are within some exiting blocks, possibly merging them - heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1]; - else - //top falls between some blocks, extending it there - heightAndDepth[topPos * 2 + 1] = depth; - DataMergeUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count); - count -= botPos - topPos; - } - else - { - if (!botExtend) - { - //only top is within some exiting block, extending it - topPos++; //to make it easier - heightAndDepth[topPos * 2] = height; - heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1]; - DataMergeUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count); - count -= botPos - topPos; - } - else - { - //both top and bottom are outside existing blocks - DataMergeUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count); - count -= botPos - topPos; - DataMergeUtil.extendArray(heightAndDepth, 2, topPos + 1, 1, count); - count++; - heightAndDepth[topPos * 2 + 2] = height; - heightAndDepth[topPos * 2 + 3] = depth; - } - } - } - else - break; - } - } - - - - //STEP 4// - //we merge height and depth to respect the verticalSize of this LevelContainer - //and we save the values directly in the VerticalDataContainer - //In this process we can easily compute the count of this position to be inserted in the positionDataContainer - //if the size of the array heightAndDepth is over the maxVerticalSize, then we use that - //otherwise we use the size of the heightAndDepth - /* simple visualization of the process - before: after: - | | - | | - | | - - - | | - we fill--> | - | | - | | - - this way we reduce from verticalSize 3 to verticalSize 2 - */ - - //we limit the vertical portion to maxVerticalData - int j = 0; - while (count > verticalSize) - { - ii = DataPointUtil.WORLD_HEIGHT; - for (i = 0; i < count - 1; i++) - { - if (heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2] <= ii) - { - ii = heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2]; - j = i; - } - } - heightAndDepth[j * 2 + 1] = heightAndDepth[(j + 1) * 2 + 1]; - for (i = j + 1; i < count - 1; i++) - { - heightAndDepth[i * 2] = heightAndDepth[(i + 1) * 2]; - heightAndDepth[i * 2 + 1] = heightAndDepth[(i + 1) * 2 + 1]; - } - //System.arraycopy(heightAndDepth, j + 1, heightAndDepth, j, count - j - 1); - count--; - } - - short lodCount = 0; - for (j = 0; j < count; j--) - { - height = heightAndDepth[j * 2]; - depth = heightAndDepth[j * 2 + 1]; - - if ((depth == 0 && height == 0) || j >= heightAndDepth.length / 2) - break; - - setVerticalData( - VerticalDataFormat.createVerticalData(height, depth, 0, false, false), - posX, - posZ, - lodCount); - lodCount++; - } - - //we update the count - setPositionData( - PositionDataFormat.setLodCount( - getPositionData(posX,posZ), - lodCount), - posX, - posZ); - - //STEP 5// - //we now get the top lods on each vertical index and we merge - //the color, the data and ligth of all of them - - boolean allDefault; - int tempColorData; - byte tempLightData; - int storedVerticalData; - int newVerticalData = 0; - int newColorData = 0; - byte newLightData = 0; - //As standard the vertical lods are ordered from top to bottom - for (int verticalIndex = lodCount; verticalIndex >= 0; verticalIndex--) - { - storedVerticalData = getVerticalData(posX, posZ, verticalIndex); - height = VerticalDataFormat.getHeight(storedVerticalData); - depth = VerticalDataFormat.getDepth(storedVerticalData); - - if ((depth == 0 && height == 0) || verticalIndex >= heightAndDepth.length / 2) - break; - - int numberOfChildren = 0; - int tempAlpha = 0; - int tempRed = 0; - int tempGreen = 0; - int tempBlue = 0; - int tempLightBlock = 0; - int tempLightSky = 0; - - for (int positionIndex = sliceStart; positionIndex <= sliceEnd; positionIndex++) - { - tempPositionData = inputPositionData[positionIndex]; - - if (!PositionDataFormat.doesItExist(tempPositionData) || PositionDataFormat.isVoid(tempPositionData)) - continue; - for (int inputVerticalIndex = 0; inputVerticalIndex < inputVerticalSize; inputVerticalIndex++) - { - tempVerticalData = inputVerticalData[positionIndex * inputVerticalSize + inputVerticalIndex]; - tempColorData = inputColorData[positionIndex * inputVerticalSize + inputVerticalIndex]; - tempLightData = inputLightData[positionIndex * inputVerticalSize + inputVerticalIndex]; - if (VerticalDataFormat.doesItExist(tempVerticalData)) - { - if ((depth <= VerticalDataFormat.getDepth(tempVerticalData) && VerticalDataFormat.getDepth(tempVerticalData) <= height) - || (depth <= VerticalDataFormat.getHeight(tempVerticalData) && VerticalDataFormat.getHeight(tempVerticalData) <= height)) - { - if (VerticalDataFormat.getHeight(tempVerticalData) > VerticalDataFormat.getHeight(newVerticalData)) - { - newVerticalData = tempColorData; - newColorData = tempVerticalData; - newLightData = tempLightData; - } - } - } - else - break; - } - - numberOfChildren++; - tempAlpha += ColorFormat.getAlpha(newColorData); - tempRed += ColorFormat.getRed(newColorData); - tempGreen += ColorFormat.getGreen(newColorData); - tempBlue += ColorFormat.getBlue(newColorData); - tempLightBlock += LightFormat.getBlockLight(newLightData); - tempLightSky += LightFormat.getSkyLight(newLightData); - } - - //we have at least 1 child - tempAlpha = tempAlpha / numberOfChildren; - tempRed = tempRed / numberOfChildren; - tempGreen = tempGreen / numberOfChildren; - tempBlue = tempBlue / numberOfChildren; - tempLightBlock = tempLightBlock / numberOfChildren; - tempLightSky = tempLightSky / numberOfChildren; - setColorData(ColorFormat.createColorData(tempAlpha, tempRed, tempGreen, tempBlue), posX, posZ, verticalIndex); - setLightData(LightFormat.formatLightAsByte((byte) tempLightSky, (byte) tempLightBlock), posX, posZ, verticalIndex); - } - } - - //SPLITTED VERSION OF THE MERGE AND ADD - private void resetPosition(int posX, int posZ) - { - final int indexA = posX * size + posZ; - positionDataContainer[indexA] = PositionDataFormat.EMPTY_DATA; - for (int verticalIndex = 0; verticalIndex < verticalSize; verticalIndex++) - { - final int indexB = indexA * verticalSize + verticalIndex; - verticalDataContainer[indexB] = VerticalDataFormat.EMPTY_LOD; - lightDataContainer[indexB] = 0; - colorDataContainer[indexB] = 0; - } - } - - private boolean mergeAndAddPositionData(int sliceStart, int sliceEnd, int posZ, int posX, short[] inputPositionData) - { - - //We start by populating the PositionDataToMerge - byte genMode = DistanceGenerationMode.FULL.complexity; - boolean correctLight = true; - boolean allEmpty = true; - boolean allVoid = true; - - short tempPositionData; - //we combine every position in the slice of the input - //I THINK YOU CAN SEE HOW TO USE THE SLICE FROM HERE - for (int positionIndex = sliceStart; positionIndex <= sliceEnd; positionIndex++) - { - tempPositionData = inputPositionData[positionIndex]; - genMode = (byte) Math.min(genMode, PositionDataFormat.getGenerationMode(tempPositionData)); - correctLight &= PositionDataFormat.getFlag(tempPositionData); - allVoid &= PositionDataFormat.isVoid(tempPositionData); - allEmpty &= PositionDataFormat.doesItExist(tempPositionData); - } - - //Case 1: should never happen but we use this just in case - //if all the data is empty (maybe a bug) then we simply return - if (allEmpty) - { - return false; - } - - //Case 2: if all the data is void - //if all the data is empty (maybe a bug) then we simply return - if (allVoid) - { - positionDataContainer[posX * size + posZ] = PositionDataFormat.createVoidPositionData(genMode); - return false; - } - - //Case 3: data is non void and non empty, we continue - positionDataContainer[posX * size + posZ] = PositionDataFormat.createPositionData(0, correctLight, genMode); - return true; - } - - private void mergeAndAddVerticalData(int sliceStart, int sliceEnd, int posZ, int posX, short[] inputPositionData, int[] inputVerticalData, int[] inputColorData, byte[] inputLightData, byte inputDetailLevel, int inputVerticalSize) - { - //STEP 3// - //now we firstly merge the height and depth values of the input data - //in this process we do a sort of "projection" of the data on a single column - - /* simple visualization of the process - input: -> projection: - | | | | - | | | - | | - - - | | - - | | - | | - */ - - int inputSize = 1 << inputDetailLevel; - // I'll disable the ThreadMap array for the initial testing //ThreadMapUtil.getHeightAndDepth(inputVerticalSize * 2 * 4) - short[] heightAndDepth = new short[inputVerticalSize * 2 * 4]; - short tempPositionData; - int tempVerticalData; - short depth; - short height; - int count = 0; - int i; - int ii; - //We collect the indexes of the data, ordered by the depth - for (int positionIndex = sliceStart; positionIndex < sliceEnd; positionIndex++) - { - tempPositionData = inputPositionData[positionIndex]; - if (!PositionDataFormat.doesItExist(tempPositionData) || PositionDataFormat.isVoid(tempPositionData)) - continue; - for (int verticalIndex = 0; verticalIndex < inputVerticalSize; verticalIndex++) - { - tempVerticalData = inputVerticalData[positionIndex * inputVerticalSize + verticalIndex]; - if (VerticalDataFormat.doesItExist(tempVerticalData)) - { - depth = VerticalDataFormat.getDepth(tempVerticalData); - height = VerticalDataFormat.getDepth(tempVerticalData); - - int botPos = -1; - int topPos = -1; - //values fall in between and possibly require extension of array - boolean botExtend = false; - boolean topExtend = false; - for (i = 0; i < count; i++) - { - if (depth <= heightAndDepth[i * 2] && depth >= heightAndDepth[i * 2 + 1]) - { - botPos = i; - break; - } - else if (depth < heightAndDepth[i * 2 + 1] && ((i + 1 < count && depth > heightAndDepth[(i + 1) * 2]) || i + 1 == count)) - { - botPos = i; - botExtend = true; - break; - } - } - for (i = 0; i < count; i++) - { - if (height <= heightAndDepth[i * 2] && height >= heightAndDepth[i * 2 + 1]) - { - topPos = i; - break; - } - else if (height < heightAndDepth[i * 2 + 1] && ((i + 1 < count && height > heightAndDepth[(i + 1) * 2]) || i + 1 == count)) - { - topPos = i; - topExtend = true; - break; - } - } - if (topPos == -1) - { - if (botPos == -1) - { - //whole block falls above - DataMergeUtil.extendArray(heightAndDepth, 2, 0, 1, count); - heightAndDepth[0] = height; - heightAndDepth[1] = depth; - count++; - } - else if (!botExtend) - { - //only top falls above extending it there, while bottom is inside existing - DataMergeUtil.shrinkArray(heightAndDepth, 2, 0, botPos, count); - heightAndDepth[0] = height; - count -= botPos; - } - else - { - //top falls between some blocks, extending those as well - DataMergeUtil.shrinkArray(heightAndDepth, 2, 0, botPos, count); - heightAndDepth[0] = height; - heightAndDepth[1] = depth; - count -= botPos; - } - } - else if (!topExtend) - { - if (!botExtend) - //both top and bottom are within some exiting blocks, possibly merging them - heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1]; - else - //top falls between some blocks, extending it there - heightAndDepth[topPos * 2 + 1] = depth; - DataMergeUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count); - count -= botPos - topPos; - } - else - { - if (!botExtend) - { - //only top is within some exiting block, extending it - topPos++; //to make it easier - heightAndDepth[topPos * 2] = height; - heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1]; - DataMergeUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count); - count -= botPos - topPos; - } - else - { - //both top and bottom are outside existing blocks - DataMergeUtil.shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count); - count -= botPos - topPos; - DataMergeUtil.extendArray(heightAndDepth, 2, topPos + 1, 1, count); - count++; - heightAndDepth[topPos * 2 + 2] = height; - heightAndDepth[topPos * 2 + 3] = depth; - } - } - } - else - break; - } - } - - - - //STEP 4// - //we merge height and depth to respect the verticalSize of this LevelContainer - //and we save the values directly in the VerticalDataContainer - //In this process we can easily compute the count of this position to be inserted in the positionDataContainer - //if the size of the array heightAndDepth is over the maxVerticalSize, then we use that - //otherwise we use the size of the heightAndDepth - /* simple visualization of the process - before: after: - | | - | | - | | - - - | | - we fill--> | - | | - | | - - this way we reduce from verticalSize 3 to verticalSize 2 - */ - - //we limit the vertical portion to maxVerticalData - int j = 0; - while (count > verticalSize) - { - ii = DataPointUtil.WORLD_HEIGHT; - for (i = 0; i < count - 1; i++) - { - if (heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2] <= ii) - { - ii = heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2]; - j = i; - } - } - heightAndDepth[j * 2 + 1] = heightAndDepth[(j + 1) * 2 + 1]; - for (i = j + 1; i < count - 1; i++) - { - heightAndDepth[i * 2] = heightAndDepth[(i + 1) * 2]; - heightAndDepth[i * 2 + 1] = heightAndDepth[(i + 1) * 2 + 1]; - } - //System.arraycopy(heightAndDepth, j + 1, heightAndDepth, j, count - j - 1); - count--; - } - - short lodCount = 0; - for (j = 0; j < count; j--) - { - height = heightAndDepth[j * 2]; - depth = heightAndDepth[j * 2 + 1]; - - if ((depth == 0 && height == 0) || j >= heightAndDepth.length / 2) - break; - - setVerticalData( - VerticalDataFormat.createVerticalData(height, depth, 0, false, false), - posX, - posZ, - lodCount); - lodCount++; - } - - //we update the count - setPositionData( - PositionDataFormat.setLodCount( - getPositionData(posX,posZ), - lodCount), - posX, - posZ); - } - - private void mergeAndAddColorLightData(int sliceStart, int sliceEnd, int posZ, int posX, short[] inputPositionData, int[] inputVerticalData, int[] inputColorData, byte[] inputLightData, byte inputDetailLevel, int inputVerticalSize) - { - //STEP 5// - //we now get the top lods on each vertical index and we merge - //the color, the data and ligth of all of them - - short tempPositionData; - int tempVerticalData; - int tempColorData; - byte tempLightData; - - int storedVerticalData; - - int newVerticalData = 0; - int newColorData = 0; - byte newLightData = 0; - - int height; - int depth; - - short lodCount = PositionDataFormat.getLodCount(getPositionData(posX,posZ)); - - //As standard the vertical lods are ordered from top to bottom - for (int verticalIndex = lodCount; verticalIndex >= 0; verticalIndex--) - { - storedVerticalData = getVerticalData(posX, posZ, verticalIndex); - height = VerticalDataFormat.getHeight(storedVerticalData); - depth = VerticalDataFormat.getDepth(storedVerticalData); - - int numberOfChildren = 0; - int tempAlpha = 0; - int tempRed = 0; - int tempGreen = 0; - int tempBlue = 0; - int tempLightBlock = 0; - int tempLightSky = 0; - - for (int positionIndex = sliceStart; positionIndex <= sliceEnd; positionIndex++) - { - tempPositionData = inputPositionData[positionIndex]; - - if (!PositionDataFormat.doesItExist(tempPositionData) || PositionDataFormat.isVoid(tempPositionData)) - continue; - for (int inputVerticalIndex = 0; inputVerticalIndex < inputVerticalSize; inputVerticalIndex++) - { - tempVerticalData = inputVerticalData[positionIndex * inputVerticalSize + inputVerticalIndex]; - tempColorData = inputColorData[positionIndex * inputVerticalSize + inputVerticalIndex]; - tempLightData = inputLightData[positionIndex * inputVerticalSize + inputVerticalIndex]; - if (VerticalDataFormat.doesItExist(tempVerticalData)) - { - if ((depth <= VerticalDataFormat.getDepth(tempVerticalData) && VerticalDataFormat.getDepth(tempVerticalData) <= height) - || (depth <= VerticalDataFormat.getHeight(tempVerticalData) && VerticalDataFormat.getHeight(tempVerticalData) <= height)) - { - if (VerticalDataFormat.getHeight(tempVerticalData) > VerticalDataFormat.getHeight(newVerticalData)) - { - newVerticalData = tempColorData; - newColorData = tempVerticalData; - newLightData = tempLightData; - } - } - } - else - break; - } - - numberOfChildren++; - tempAlpha += ColorFormat.getAlpha(newColorData); - tempRed += ColorFormat.getRed(newColorData); - tempGreen += ColorFormat.getGreen(newColorData); - tempBlue += ColorFormat.getBlue(newColorData); - tempLightBlock += LightFormat.getBlockLight(newLightData); - tempLightSky += LightFormat.getSkyLight(newLightData); - } - - //we have at least 1 child - tempAlpha = tempAlpha / numberOfChildren; - tempRed = tempRed / numberOfChildren; - tempGreen = tempGreen / numberOfChildren; - tempBlue = tempBlue / numberOfChildren; - tempLightBlock = tempLightBlock / numberOfChildren; - tempLightSky = tempLightSky / numberOfChildren; - setColorData(ColorFormat.createColorData(tempAlpha, tempRed, tempGreen, tempBlue), posX, posZ, verticalIndex); - setLightData(LightFormat.formatLightAsByte((byte) tempLightSky, (byte) tempLightBlock), posX, posZ, verticalIndex); - } - } - @Override public LevelContainer expand() { @@ -1036,41 +325,9 @@ public class VerticalLevelContainer implements LevelContainer if (DataPointUtil.getGenerationMode(data[0]) != DataPointUtil.getGenerationMode(lowerLevelContainer.getSingleData(posX*2, posZ*2))) throw new RuntimeException("Update data called but higher level datapoint does not have the same GenerationMode as the top left corner child datapoint!"); - forceWriteVerticalData(data, posX, posZ); } - - public void newUpdateData(VerticalLevelContainer lowerLevelContainer, int posX, int posZ) - { - //We reset the array - int lowerVerticalSize = lowerLevelContainer.getVerticalSize(); - short[] positionDataToMerge = new short[4]; - int[] verticalDataToMerge = new int[4 * lowerVerticalSize]; - int[] colorDataToMerge = new int[4 * lowerVerticalSize]; - byte[] ligthDataToMerge = new byte[4 * lowerVerticalSize]; - - int childPosX; - int childPosZ; - for (int x = 0; x <= 1; x++) - { - for (int z = 0; z <= 1; z++) - { - childPosX = 2 * posX + x; - childPosZ = 2 * posZ + z; - positionDataToMerge[z * 2 + x] = lowerLevelContainer.getPositionData(childPosX, childPosZ); - for (int verticalIndex = 0; verticalIndex < lowerVerticalSize; verticalIndex++) - { - final int i = (z * 2 + x) * lowerVerticalSize + verticalIndex; - verticalDataToMerge[i] = lowerLevelContainer.getVerticalData(childPosX, childPosZ, verticalIndex); - colorDataToMerge[i] = lowerLevelContainer.getColorData(childPosX, childPosZ, verticalIndex); - ligthDataToMerge[i] = lowerLevelContainer.getLightData(childPosX, childPosZ, verticalIndex); - } - } - } - mergeAndAddData(posX,posZ, positionDataToMerge, verticalDataToMerge, colorDataToMerge, ligthDataToMerge, lowerLevelContainer.detailLevel, lowerVerticalSize); - } - @Override public boolean writeData(DataOutputStream output) throws IOException { output.writeByte(detailLevel); @@ -1093,26 +350,29 @@ public class VerticalLevelContainer implements LevelContainer } @Override - @SuppressWarnings("unused") public String toString() { - /* + String LINE_DELIMITER = "\n"; + String DATA_DELIMITER = " "; + String SUBDATA_DELIMITER = ","; StringBuilder stringBuilder = new StringBuilder(); int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); stringBuilder.append(detailLevel); - stringBuilder.append(DATA_DELIMITER); - for (int x = 0; x < size; x++) + stringBuilder.append(LINE_DELIMITER); + for (int z = 0; z < size; z++) { - for (int z = 0; z < size; z++) + for (int x = 0; x < size; x++) { - //Converting the dataToHex - stringBuilder.append(Long.toHexString(dataContainer[x][z][0])); - stringBuilder.append(DATA_DELIMITER); + for (int y = 0; y < verticalSize; y++) { + //Converting the dataToHex + stringBuilder.append(Long.toHexString(getData(x,z,y))); + if (y != verticalSize) stringBuilder.append(SUBDATA_DELIMITER); + } + if (x != size) stringBuilder.append(DATA_DELIMITER); } + if (z != size) stringBuilder.append(LINE_DELIMITER); } return stringBuilder.toString(); - */ - return " "; } @Override 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 3a73de663..6ee44faa9 100644 --- a/src/main/java/com/seibel/lod/core/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/core/util/DataPointUtil.java @@ -110,9 +110,9 @@ public class DataPointUtil public static long createVoidDataPoint(int generationMode) { long dataPoint = 0; - dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; - dataPoint += VOID_MASK << VOID_SHIFT; - dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT; + dataPoint |= (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; + dataPoint |= VOID_MASK << VOID_SHIFT; + dataPoint |= EXISTENCE_MASK << EXISTENCE_SHIFT; return dataPoint; } @@ -129,18 +129,17 @@ public class DataPointUtil public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode, boolean flag) { long dataPoint = 0; - dataPoint += (long) (alpha >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT; - dataPoint += (red & RED_MASK) << RED_SHIFT; - dataPoint += (green & GREEN_MASK) << GREEN_SHIFT; - dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; - dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT; - dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT; - dataPoint += (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT; - dataPoint += (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT; - dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; - if (flag) dataPoint += FLAG_MASK << FLAG_SHIFT; - dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT; - + dataPoint |= (long) (alpha >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT; + dataPoint |= (red & RED_MASK) << RED_SHIFT; + dataPoint |= (green & GREEN_MASK) << GREEN_SHIFT; + dataPoint |= (blue & BLUE_MASK) << BLUE_SHIFT; + dataPoint |= (height & HEIGHT_MASK) << HEIGHT_SHIFT; + dataPoint |= (depth & DEPTH_MASK) << DEPTH_SHIFT; + dataPoint |= (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT; + dataPoint |= (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT; + dataPoint |= (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT; + if (flag) dataPoint |= FLAG_MASK << FLAG_SHIFT; + dataPoint |= EXISTENCE_MASK << EXISTENCE_SHIFT; return dataPoint; }