Added LevelPosUtil, now the node are added using it and not with the LevelPos object

This commit is contained in:
Leonardo
2021-09-01 15:15:23 +02:00
parent 4c7ca395c6
commit 1360edb459
6 changed files with 274 additions and 69 deletions
@@ -25,6 +25,7 @@ import com.seibel.lod.enums.DistanceGenerationMode;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.DataPoint;
import com.seibel.lod.objects.LevelPosUtil;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.LodWorld;
import com.seibel.lod.objects.LevelPos.LevelPos;
@@ -163,7 +164,7 @@ public class LodBuilder
short[] color;
short height;
short depth;
LevelPos levelPos = new LevelPos((byte) 0, 0, 0);
int[] levelPos;
short[] data;
try
{
@@ -186,20 +187,23 @@ public class LodBuilder
startZ, endX, endZ);
depth = 0;
}
levelPos.changeParameters((byte) 0,
chunk.getPos().x * 16 + startX,
chunk.getPos().z * 16 + startZ);
levelPos.convert(detail.detailLevel);
levelPos = LevelPosUtil.convert(
LevelPosUtil.createLevelPos((byte) 0,
chunk.getPos().x * 16 + startX,
chunk.getPos().z * 16 + startZ),
detail.detailLevel
);
boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER;
data = DataPoint.createDataPoint(height, depth, color[0], color[1], color[2]);
lodDim.addData(levelPos,
boolean added = lodDim.addData(levelPos,
data,
false,
isServer);
System.out.println(added);
}
//levelPos.changeParameters(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
lodDim.updateData(new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z));
lodDim.updateData(LevelPosUtil.createLevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z));
} catch (Exception e)
{
//e.printStackTrace();
@@ -432,12 +436,10 @@ public class LodBuilder
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
tmp = tmp.darker();
colorInt = LodUtil.colorToInt(tmp);
}
else if (blockState == Blocks.STONE.defaultBlockState())
} else if (blockState == Blocks.STONE.defaultBlockState())
{
colorInt = LodUtil.STONE_COLOR_INT;
}
else if (blockState == Blocks.MYCELIUM.defaultBlockState())
} else if (blockState == Blocks.MYCELIUM.defaultBlockState())
{
colorInt = LodUtil.MYCELIUM_COLOR_INT;
}
@@ -0,0 +1,184 @@
package com.seibel.lod.objects;
import com.seibel.lod.objects.LevelPos.ImmutableLevelPos;
import com.seibel.lod.objects.LevelPos.MutableLevelPos;
import com.seibel.lod.util.LodUtil;
import net.minecraft.util.math.ChunkPos;
import java.util.Comparator;
public class LevelPosUtil
{
public static int[] convert(int[] levelPos, byte newDetailLevel)
{
return convert(getDetailLevel(levelPos), getPosX(levelPos), getPosZ(levelPos), newDetailLevel);
}
public static int[] convert(byte detailLevel, int posX, int posZ, byte newDetailLevel)
{
int width;
if (newDetailLevel >= detailLevel)
{
width = 1 << (newDetailLevel - detailLevel);
return createLevelPos(
newDetailLevel,
Math.floorDiv(posX, width),
Math.floorDiv(posZ, width));
} else
{
width = 1 << (detailLevel - newDetailLevel);
return createLevelPos(
newDetailLevel,
posX * width,
posZ * width);
}
}
public static int[] createLevelPos(byte detailLevel, int posX, int posZ)
{
return new int[]{detailLevel, posX, posZ};
}
public static byte getDetailLevel(int[] levelPos)
{
return (byte) levelPos[0];
}
public static int getPosX(int[] levelPos)
{
return levelPos[1];
}
public static int getPosZ(int[] levelPos)
{
return levelPos[2];
}
public static int[] getRegionModule(int[] levelPos)
{
return getRegionModule(getDetailLevel(levelPos), getPosX(levelPos), getPosZ(levelPos));
}
public static int[] getRegionModule(byte detailLevel, int posX, int posZ)
{
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
return createLevelPos(
detailLevel,
Math.floorMod(posX, width),
Math.floorMod(posZ, width));
}
public static int[] applyOffset(int[] levelPos, int xOffset, int zOffset)
{
return createLevelPos(
getDetailLevel(levelPos),
getPosX(levelPos) + xOffset,
getPosZ(levelPos) + zOffset);
}
public static int[] applyLevelOffset(int[] levelPos, byte detailOffset, int xOffset, int zOffset)
{
return createLevelPos(
getDetailLevel(levelPos),
getPosX(levelPos) + xOffset * (1 << detailOffset),
getPosZ(levelPos) + zOffset * (1 << detailOffset));
}
public static int getRegionPosX(int[] levelPos)
{
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - getDetailLevel(levelPos));
return Math.floorDiv(getPosX(levelPos), width);
}
public static int getRegionPosZ(int[] levelPos)
{
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - getDetailLevel(levelPos));
return Math.floorDiv(getPosZ(levelPos), width);
}
public static ChunkPos getChunkPos(int[] levelPos)
{
levelPos = convert(levelPos, LodUtil.CHUNK_DETAIL_LEVEL);
return new ChunkPos(
getPosX(levelPos),
getPosZ(levelPos));
}
public static int maxDistance(int[] levelPos, int playerPosX, int playerPosZ)
{
int width = 1 << getDetailLevel(levelPos);
int startPosX = getPosX(levelPos) * width;
int startPosZ = getPosX(levelPos) * width;
int endPosX = startPosX + width;
int endPosZ = startPosZ + width;
int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
return maxDistance;
}
public static int minDistance(int[] levelPos, int playerPosX, int playerPosZ)
{
int width = 1 << getDetailLevel(levelPos);
int startPosX = getPosX(levelPos) * width;
int startPosZ = getPosX(levelPos) * width;
int endPosX = startPosX + width;
int endPosZ = startPosZ + width;
boolean inXArea = playerPosX >= startPosX && playerPosX <= endPosX;
boolean inZArea = playerPosZ >= startPosZ && playerPosZ <= endPosZ;
if (inXArea && inZArea)
{
return 0;
} else if (inXArea)
{
return Math.min(
Math.abs(playerPosZ - startPosZ),
Math.abs(playerPosZ - endPosZ)
);
} else if (inZArea)
{
return Math.min(
Math.abs(playerPosX - startPosX),
Math.abs(playerPosX - endPosX)
);
} else
{
int minDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
return minDistance;
}
}
public static int compareDistance(int posX, int posZ, int[] first, int[] second)
{
return Integer.compare(
minDistance(first, posX, posZ),
minDistance(second, posX, posZ));
}
public static int compareLevelAndDistance(int posX, int posZ, int[] first, int[] second)
{
int compareResult = Integer.compare(getDetailLevel(second), getDetailLevel(first));
if (compareResult == 0)
{
compareResult = Integer.compare(
minDistance(first, posX, posZ),
minDistance(second, posX, posZ));
}
return compareResult;
}
public static String toString(int[] levelPos)
{
return (getDetailLevel(levelPos) + " " + getPosX(levelPos) + " " + getPosZ(levelPos));
}
}
@@ -23,6 +23,7 @@ import java.security.InvalidParameterException;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import org.apache.commons.lang3.mutable.MutableBoolean;
@@ -284,6 +285,27 @@ public class LodDimension
return regions[xIndex][zIndex];
}
/**
* Gets the region at the given X and Z
* <br>
* Returns null if the region doesn't exist
* or is outside the loaded area.
*/
public LodRegion getRegion(int[] levelPos)
{
int xIndex = (LevelPosUtil.getRegionPosX(levelPos) - center.x) + halfWidth;
int zIndex = (LevelPosUtil.getRegionPosZ(levelPos) - center.z) + halfWidth;
if (!regionIsInRange(LevelPosUtil.getRegionPosX(levelPos), LevelPosUtil.getRegionPosZ(levelPos)))
throw new ArrayIndexOutOfBoundsException("Region for level pos " + levelPos + " out of range");
else if (regions[xIndex][zIndex] == null)
throw new InvalidParameterException("Region for level pos " + levelPos + " not currently initialized");
else if (regions[xIndex][zIndex].getMinDetailLevel() > LevelPosUtil.getDetailLevel(levelPos))
throw new InvalidParameterException("Region for level pos " + levelPos + " currently only reach level " + regions[xIndex][zIndex].getMinDetailLevel());
return regions[xIndex][zIndex];
}
/**
* Gets the region at the given X and Z
* <br>
@@ -439,12 +461,13 @@ public class LodDimension
* stored in the LOD. If an LOD already exists at the given
* coordinates it will be overwritten.
*/
public synchronized Boolean addData(LevelPos levelPos, short[] lodDataPoint, boolean dontSave, boolean serverQuality)
public synchronized Boolean addData(int[] levelPos, short[] lodDataPoint, boolean dontSave, boolean serverQuality)
{
// don't continue if the region can't be saved
RegionPos regionPos = levelPos.getRegionPos();
if (!regionIsInRange(regionPos.x, regionPos.z))
int xRegion = LevelPosUtil.getRegionPosX(levelPos);
int zRegion = LevelPosUtil.getRegionPosZ(levelPos);
if (!regionIsInRange(xRegion, zRegion))
{
return false;
}
@@ -458,8 +481,8 @@ public class LodDimension
try
{
// mark the region as dirty so it will be saved to disk
int xIndex = (regionPos.x - center.x) + halfWidth;
int zIndex = (regionPos.z - center.z) + halfWidth;
int xIndex = (xRegion - center.x) + halfWidth;
int zIndex = (zRegion - center.z) + halfWidth;
isRegionDirty[xIndex][zIndex] = true;
regen[xIndex][zIndex] = true;
regenDimension = true;
@@ -582,10 +605,10 @@ public class LodDimension
* Returns null if the LodChunk doesn't exist or
* is outside the loaded area.
*/
public void updateData(LevelPos levelPos)
public void updateData(int[] levelPos)
{
if (levelPos.detailLevel > LodUtil.REGION_DETAIL_LEVEL)
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + levelPos.detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
if (LevelPosUtil.getDetailLevel(levelPos) > LodUtil.REGION_DETAIL_LEVEL)
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + LevelPosUtil.getDetailLevel(levelPos) + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
LodRegion region = getRegion(levelPos);
@@ -611,7 +634,7 @@ public class LodDimension
return false;
}
return region.doesDataExist(levelPos.clone());
return region.doesDataExist(LevelPosUtil.createLevelPos(levelPos.detailLevel,levelPos.posX,levelPos.posZ));
} catch (Exception e)
{
return false;
@@ -77,7 +77,6 @@ public class LodRegion implements Serializable
dataExistence[lod] = new boolean[size][size];
}
int width;
LevelPos levelPos = new LevelPos();
for (byte tempLod = (byte) (minDetailLevel + 1); tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++)
{
width = 1 << (LodUtil.REGION_DETAIL_LEVEL - tempLod);
@@ -85,8 +84,7 @@ public class LodRegion implements Serializable
{
for (int z = 0; z < width; z++)
{
levelPos.changeParameters(tempLod, x, z);
update(levelPos);
update(LevelPosUtil.createLevelPos(tempLod, x, z));
}
}
}
@@ -127,22 +125,25 @@ public class LodRegion implements Serializable
* @param dataPoint
* @return
*/
public boolean addData(LevelPos levelPos, short[] dataPoint, boolean serverQuality)
public boolean addData(int[] levelPos, short[] dataPoint, boolean serverQuality)
{
levelPos.performRegionModule();
levelPos = LevelPosUtil.getRegionModule(levelPos);
byte detailLevel = LevelPosUtil.getDetailLevel(levelPos);
int posX = LevelPosUtil.getPosX(levelPos);
int posZ = LevelPosUtil.getPosZ(levelPos);
if (!doesDataExist(levelPos) || serverQuality)
{
//update the number of node present
if (this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ]) numberOfPoints++;
if (this.dataExistence[detailLevel][posX][posZ]) numberOfPoints++;
//add the node data
this.height[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = DataPoint.getHeight(dataPoint);
this.depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = DataPoint.getDepth(dataPoint);
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] = (byte) (DataPoint.getRed(dataPoint) - 128);
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] = (byte) (DataPoint.getGreen(dataPoint) - 128);
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] = (byte) (DataPoint.getBlue(dataPoint) - 128);
this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = true;
this.height[detailLevel][posX][posZ] = DataPoint.getHeight(dataPoint);
this.depth[detailLevel][posX][posZ] = DataPoint.getDepth(dataPoint);
this.colors[detailLevel][posX][posZ][0] = (byte) (DataPoint.getRed(dataPoint) - 128);
this.colors[detailLevel][posX][posZ][1] = (byte) (DataPoint.getGreen(dataPoint) - 128);
this.colors[detailLevel][posX][posZ][2] = (byte) (DataPoint.getBlue(dataPoint) - 128);
this.dataExistence[detailLevel][posX][posZ] = true;
return true;
} else
{
@@ -203,7 +204,7 @@ public class LodRegion implements Serializable
return;
} else if (DetailDistanceUtil.getDistanceGenerationInverse(minDistance) == detailLevel)
{
if (!doesDataExist(levelPos))
if (!doesDataExist(LevelPosUtil.createLevelPos(levelPos.detailLevel, levelPos.posX, levelPos.posZ)))
{
levelPos.changeParameters(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size);
if (dataToGenerate.containsKey(levelPos))
@@ -227,7 +228,7 @@ public class LodRegion implements Serializable
{
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z);
if (!doesDataExist(levelPos))
if (!doesDataExist(LevelPosUtil.createLevelPos(levelPos.detailLevel, levelPos.posX, levelPos.posZ)))
{
num++;
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x + regionPosX * childSize, childPosZ + z + regionPosZ * childSize);
@@ -261,7 +262,7 @@ public class LodRegion implements Serializable
{
levelPos.changeParameters(detailLevel, posX, posZ);
levelPos.convert(childDetailLevel);
if (!doesDataExist(levelPos))
if (!doesDataExist(LevelPosUtil.createLevelPos(levelPos.detailLevel, levelPos.posX, levelPos.posZ)))
{
levelPos.changeParameters(levelPos.detailLevel, levelPos.posX + regionPosX * childSize, levelPos.posZ + regionPosZ * childSize);
if (dataToGenerate.containsKey(levelPos))
@@ -335,7 +336,7 @@ public class LodRegion implements Serializable
for (int z = 0; z <= 1; z++)
{
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z);
if (doesDataExist(levelPos)) childrenCount++;
if (doesDataExist(LevelPosUtil.createLevelPos(levelPos.detailLevel, levelPos.posX, levelPos.posZ))) childrenCount++;
}
}
@@ -371,43 +372,36 @@ public class LodRegion implements Serializable
/**
* @param levelPos
*/
public void updateArea(LevelPos levelPos)
public void updateArea(int[] levelPos)
{
int width;
int startX;
int startZ;
byte detailLevel = levelPos.detailLevel;
int posX = levelPos.posX;
int posZ = levelPos.posZ;
levelPos = LevelPosUtil.getRegionModule(levelPos);
int detailLevel = LevelPosUtil.getDetailLevel(levelPos);
int[] bottomLevelPos;
for (byte bottom = (byte) (minDetailLevel + 1); bottom <= detailLevel; bottom++)
{
levelPos.convert(bottom);
startX = levelPos.posX;
startZ = levelPos.posZ;
bottomLevelPos = LevelPosUtil.convert(levelPos, bottom);
width = 1 << (detailLevel - bottom);
for (int x = 0; x < width; x++)
{
for (int z = 0; z < width; z++)
{
levelPos.changeParameters(bottom, startX + x, startZ + z);
update(levelPos);
update(LevelPosUtil.applyOffset(bottomLevelPos, x, z));
}
}
levelPos.changeParameters(detailLevel, posX, posZ);
}
for (byte tempLod = (byte) (detailLevel + 1); tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++)
for (byte up = (byte) (detailLevel + 1); up <= LodUtil.REGION_DETAIL_LEVEL; up++)
{
levelPos.convert(tempLod);
update(levelPos);
update(LevelPosUtil.convert(levelPos, up));
}
}
/**
* @param levelPos
*/
private void update(LevelPos levelPos)
private void update(int[] levelPos)
{
levelPos.performRegionModule();
levelPos = LevelPosUtil.getRegionModule(levelPos);
int numberOfChildren = 0;
int numberOfVoidChildren = 0;
@@ -419,9 +413,9 @@ public class LodRegion implements Serializable
int newPosX;
int newPosZ;
byte newDetailLevel;
int detailLevel = levelPos.detailLevel;
int posX = levelPos.posX;
int posZ = levelPos.posZ;
int detailLevel = LevelPosUtil.getDetailLevel(levelPos);
int posX = LevelPosUtil.getPosX(levelPos);
int posZ = LevelPosUtil.getPosZ(levelPos);
for (int x = 0; x <= 1; x++)
{
for (int z = 0; z <= 1; z++)
@@ -429,7 +423,7 @@ public class LodRegion implements Serializable
newPosX = 2 * posX + x;
newPosZ = 2 * posZ + z;
newDetailLevel = (byte) (detailLevel - 1);
levelPos.changeParameters(newDetailLevel, newPosX, newPosZ);
levelPos = LevelPosUtil.createLevelPos(newDetailLevel, newPosX, newPosZ);
if (doesDataExist(levelPos))
{
if (height[newDetailLevel][newPosX][newPosZ] != LodBuilder.DEFAULT_HEIGHT
@@ -477,12 +471,12 @@ public class LodRegion implements Serializable
* @param levelPos
* @return
*/
public boolean doesDataExist(LevelPos levelPos)
public boolean doesDataExist(int[] levelPos)
{
try
{
levelPos = levelPos.getRegionModuleLevelPos();
return dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ];
levelPos = LevelPosUtil.getRegionModule(levelPos);
return dataExistence[LevelPosUtil.getDetailLevel(levelPos)][LevelPosUtil.getPosX(levelPos)][LevelPosUtil.getPosZ(levelPos)];
} catch (NullPointerException e)
{
return false;
@@ -773,7 +773,7 @@ public class LodRenderer
//=============//
// full regens //
//=============//
// check if the view distance changed
if (ClientProxy.previousLodRenderDistance != LodConfig.CLIENT.lodChunkRenderDistance.get()
|| mc.options.renderDistance != prevRenderDistance
@@ -787,13 +787,7 @@ public class LodRenderer
//vanillaRenderedChunks.stream().filter(pos -> ((Math.abs(pos.x - player.xChunk) > mc.options.renderDistance) || (Math.abs(pos.z - player.zChunk) > mc.options.renderDistance)));
vanillaRenderedChunks.clear();
}
// did the user change the debug setting?
if (LodConfig.CLIENT.debugMode.get() != previousDebugMode)
{
previousDebugMode = LodConfig.CLIENT.debugMode.get();
fullRegen = true;
}
long newTime = System.currentTimeMillis();
@@ -868,6 +862,14 @@ public class LodRenderer
{
vanillaRenderedChunks.clear();
}
// did the user change the debug setting?
if (LodConfig.CLIENT.debugMode.get() != previousDebugMode)
{
previousDebugMode = LodConfig.CLIENT.debugMode.get();
fullRegen = true;
}
}
}
@@ -121,7 +121,7 @@ public class RenderUtil
{
// convert the vbo position into a direction vector
// starting from the player's position
Vector3d vboVec = new Vector3d(vboCenterPos.getX(), 0, vboCenterPos.getZ());
Vector3d vboVec = new Vector3d(vboCenterPos.getX(), 64, vboCenterPos.getZ());
Vector3d playerVec = new Vector3d(playerBlockPos.getX(), playerBlockPos.getY(), playerBlockPos.getZ());
Vector3d vboCenterVec = vboVec.subtract(playerVec);