Cleanup debug logging and get rid of unused functions in vertContainer
This commit is contained in:
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user