Cleanup debug logging and get rid of unused functions in vertContainer

This commit is contained in:
tom lee
2022-02-11 12:38:35 +08:00
parent 14d3418651
commit f422df6280
4 changed files with 73 additions and 813 deletions
@@ -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
@@ -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 {
@@ -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
@@ -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;
}