From 69a72312e47ead50ca90eff9a5b1ec3120a3a806 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 27 Sep 2021 21:43:16 -0500 Subject: [PATCH] Refactor and comment LodRegion --- .../lod/handlers/LodDimensionFileHandler.java | 6 +- .../com/seibel/lod/objects/LodDimension.java | 22 +- .../com/seibel/lod/objects/LodRegion.java | 345 ++++++++++-------- .../lod/objects/SingleLevelContainer.java | 1 + 4 files changed, 216 insertions(+), 158 deletions(-) diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index a5cad24c9..ce5e0bff2 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -188,10 +188,10 @@ public class LodDimensionFileHandler { default: case HEIGHTMAP: - region.addLevel(new SingleLevelContainer(data)); + region.addLevelContainer(new SingleLevelContainer(data)); break; case VOXEL: - region.addLevel(new VerticalLevelContainer(data)); + region.addLevelContainer(new VerticalLevelContainer(data)); break; } } @@ -212,7 +212,7 @@ public class LodDimensionFileHandler }// for each detail level if (region.getMinDetailLevel() >= detailLevel) - region.expand(detailLevel); + region.growTree(detailLevel); return region; } diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index f4fd0ccb7..ec4ece352 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -43,8 +43,12 @@ import net.minecraft.world.server.ServerWorld; /** * This object holds all loaded LOD regions - * for a given dimension. - * + * for a given dimension.

+ * + * Coordinate Standard:
+ * Coordinate called posX or posZ are relative LevelPos coordinates
+ * unless stated otherwise.
+ * * @author Leonardo Amato * @author James Seibel * @version 9-27-2021 @@ -442,7 +446,7 @@ public class LodDimension // Second case, the region exists at a higher detail level. // Expand the region by introducing the missing layer - region.expand(levelToGen); + region.growTree(levelToGen); recreateRegionBuffer[x][z] = true; } } @@ -506,7 +510,7 @@ public class LodDimension /** * Returns every position that need to be generated based on the position of the player */ - public PosToGenerateContainer getDataToGenerate(int maxDataToGenerate, int playerPosX, int playerPosZ) + public PosToGenerateContainer getDataToGenerate(int maxDataToGenerate, int playerBlockPosX, int playerBlockPosZ) { PosToGenerateContainer posToGenerate; LodRegion region; @@ -522,10 +526,10 @@ public class LodDimension { default: case NEAR_FIRST: - posToGenerate = new PosToGenerateContainer((byte) 10, maxDataToGenerate, 0, playerPosX, playerPosZ); + posToGenerate = new PosToGenerateContainer((byte) 10, maxDataToGenerate, 0, playerBlockPosX, playerBlockPosZ); - int playerChunkX = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerPosX); - int playerChunkZ = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerPosZ); + int playerChunkX = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerBlockPosX); + int playerChunkZ = LevelPosUtil.getChunkPos(LodUtil.BLOCK_DETAIL_LEVEL, playerBlockPosZ); int xChunkToCheck; int zChunkToCheck; @@ -583,7 +587,7 @@ public class LodDimension case FAR_FIRST: - posToGenerate = new PosToGenerateContainer((byte) 8, maxDataToGenerate, (int) (maxDataToGenerate * 0.25), playerPosX, playerPosZ); + posToGenerate = new PosToGenerateContainer((byte) 8, maxDataToGenerate, (int) (maxDataToGenerate * 0.25), playerBlockPosX, playerBlockPosZ); int xRegion; int zRegion; @@ -595,7 +599,7 @@ public class LodDimension region = getRegion(xRegion, zRegion); if (region != null) - region.getDataToGenerate(posToGenerate, playerPosX, playerPosZ); + region.getDataToGenerate(posToGenerate, playerBlockPosX, playerBlockPosZ); if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z))) diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index 9331e7779..3b63bf1a6 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -11,17 +11,21 @@ import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; /** - * STANDARD TO FOLLOW - * every coordinate called posX or posZ is a relative coordinate and not and absolute coordinate - * if an array contain coordinate the order is the following - * 0 for x, 1 for z in 2D - * 0 for x, 1 for y, 2 for z in 3D + * This object holds all loaded LevelContainers + * for a given region.

+ * + * Coordinate Standard:
+ * Coordinate called posX or posZ are relative LevelPos coordinates
+ * unless stated otherwise.
+ * * * @author Leonardo Amato * @version 9-27-2021 */ public class LodRegion { + /** Holds the lowest (least detailed) detail level in this region + * TODO is that correct? */ private byte minDetailLevel; private static final byte POSSIBLE_LOD = 10; @@ -34,6 +38,9 @@ public class LodRegion public final int regionPosX; public final int regionPosZ; + + + public LodRegion(RegionPos regionPos) { this.minDetailLevel = LodUtil.REGION_DETAIL_LEVEL; @@ -68,6 +75,8 @@ public class LodRegion } } + + public VerticalQuality getLodQualityMode() { return verticalQuality; @@ -84,16 +93,18 @@ public class LodRegion } /** - * This method can be used to insert data into the LodRegion - * - * @return if the data was added successfully + * Inserts the data point into the region. + * + * TODO this will always return true unless it has + * @return true if the data was added successfully */ public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - // For some reason the dataContainer can contain null entries + // The dataContainer could have null entries if the + // detailLevel changes. if (this.dataContainer[detailLevel] == null) { if (verticalQuality == VerticalQuality.HEIGHTMAP) @@ -108,9 +119,10 @@ public class LodRegion } /** - * This method will return the data in the position relative to the level of detail + * Get the dataPoint at the given relative position. * - * @return the data at the relative pos and level + * @return the data at the relative pos and detail level, + * 0 if the data doesn't exist. */ public long getData(byte detailLevel, int posX, int posZ, int verticalIndex) { @@ -118,99 +130,110 @@ public class LodRegion } /** - * This method will return the data in the position relative to the level of detail + * Get the dataPoint at the given relative position. * - * @return the data at the relative pos and level + * @return the data at the relative pos and detail level, + * 0 if the data doesn't exist. */ public long getSingleData(byte detailLevel, int posX, int posZ) { return dataContainer[detailLevel].getSingleData(posX, posZ); } + /** Clears the datapoint at the given relative position */ public void clear(byte detailLevel, int posX, int posZ) { dataContainer[detailLevel].clear(posX, posZ); } /** - * This method will return all the levelPos that are renderable according to the requisite given in input - * - * @return + * This method will fill the posToGenerate array with all levelPos that + * are render-able. + * + * TODO why don't we return the posToGenerate, it would make this easier to understand */ - public void getDataToGenerate(PosToGenerateContainer posToGenerate, int playerPosX, int playerPosZ) + public void getDataToGenerate(PosToGenerateContainer posToGenerate, + int playerBlockPosX, int playerBlockPosZ) { - getDataToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ); + getDataToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerBlockPosX, playerBlockPosZ); } - private void getDataToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ) + /** + * A recursive method that fills the posToGenerate array with all levelPos that + * need to be generated. + * + * TODO why don't we return the posToGenerate, it would make this easier to understand + */ + private void getDataToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel, + int childOffsetPosX, int childOffsetPosZ, int playerPosX, int playerPosZ) { + // equivalent to 2^(...) int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - //here i calculate the the LevelPos is in range - //This is important to avoid any kind of hole in the generation - //nt minDistance = LevelPosUtil.minDistance(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size, playerPosX, playerPosZ); - int maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ); + // calculate what LevelPos are in range to generate + int maxDistance = LevelPosUtil.maxDistance(detailLevel, childOffsetPosX, childOffsetPosZ, playerPosX, playerPosZ, regionPosX, regionPosZ); + // determine this child's levelPos byte childDetailLevel = (byte) (detailLevel - 1); - int childPosX = posX * 2; - int childPosZ = posZ * 2; + int childPosX = childOffsetPosX * 2; + int childPosZ = childOffsetPosZ * 2; int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel); - //we have reached the target detail level + byte targetDetailLevel = DetailDistanceUtil.getLodGenDetail(DetailDistanceUtil.getGenerationDetailFromDistance(maxDistance)).detailLevel; if (targetDetailLevel > detailLevel) { + // we have gone beyond the target Detail level + // we can stop generating return; - } else if (targetDetailLevel == detailLevel) + } + else if (targetDetailLevel == detailLevel) { - if (!doesDataExist(detailLevel, posX, posZ)) - { - posToGenerate.addPosToGenerate(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); - } - } else + if (!doesDataExist(detailLevel, childOffsetPosX, childOffsetPosZ)) + posToGenerate.addPosToGenerate(detailLevel, childOffsetPosX + regionPosX * size, childOffsetPosZ + regionPosZ * size); + } + else { - //we want max a request per chunk. So for lod smaller than chunk we explore only the top rigth child + // we want at max one request per chunk (since the world generator creates chunks). + // So for lod smaller than a chunk, only recurse down + // the top right child + if (detailLevel > LodUtil.CHUNK_DETAIL_LEVEL) { - int num = 0; - //We take all the children that are not generated to at least the generation level taken in input + int ungeneratedChildren = 0; + + // make sure all children are generated to this detailLevel for (int x = 0; x <= 1; x++) { for (int z = 0; z <= 1; z++) { - if (!doesDataExist(childDetailLevel, childPosX + x, childPosZ + z)) { - num++; + ungeneratedChildren++; posToGenerate.addPosToGenerate(childDetailLevel, childPosX + x + regionPosX * childSize, childPosZ + z + regionPosZ * childSize); } } } - //only if all the children are correctly generated we go deeper - if (num == 0) - { + // only if all the children are correctly generated + // should we go deeper + if (ungeneratedChildren == 0) for (int x = 0; x <= 1; x++) - { for (int z = 0; z <= 1; z++) - { getDataToGenerate(posToGenerate, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ); - } - } - } - } else - //now we keep exploring the top right child + } + else { + // The detail Level is smaller than a chunk. + // Only recurse down the top right child. + if (DetailDistanceUtil.getLodGenDetail(childDetailLevel).detailLevel <= (childDetailLevel)) { if (!doesDataExist(childDetailLevel, childPosX, childPosZ)) - { posToGenerate.addPosToGenerate(childDetailLevel, childPosX + regionPosX * childSize, childPosZ + regionPosZ * childSize); - } else - { + else getDataToGenerate(posToGenerate, childDetailLevel, childPosX, childPosZ, playerPosX, playerPosZ); - } } } } @@ -218,78 +241,99 @@ public class LodRegion /** - * @return + * This method will fill the posToRender array with all levelPos that + * are render-able. + * + * TODO why don't we return the posToRender, it would make this easier to understand */ - public void getDataToRender(PosToRenderContainer posToRender, int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) + public void getDataToRender(PosToRenderContainer posToRender, + int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) { getDataToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, requireCorrectDetailLevel); } /** - * @return + * This method will fill the posToRender array with all levelPos that + * are render-able. + * + * TODO why don't we return the posToRender, it would make this easier to understand + * TODO this needs some more comments, James was only able to figure out part of it */ - private void getDataToRender(PosToRenderContainer posToRender, byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) + private void getDataToRender(PosToRenderContainer posToRender, + byte detailLevel, int posX, int posZ, + int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) { + // equivalent to 2^(...) int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); - //here i calculate the the LevelPos is in range - //This is important to avoid any kind of hole in the rendering - byte supposedLevel; + byte desiredLevel; int maxDistance; boolean stopNow = false; int minDistance; int childLevel; + + + // calculate the LevelPos that are in range switch (LodConfig.CLIENT.graphics.detailDropOff.get()) { default: case BY_CHUNK: maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ); - supposedLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance)); + desiredLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance)); minDistance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ); childLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(minDistance)); stopNow = detailLevel == childLevel - 1; + break; - break; case BY_REGION_FANCY: - supposedLevel = minDetailLevel; + desiredLevel = minDetailLevel; break; + case BY_REGION_FAST: int playerRegionX = LevelPosUtil.getRegion(LodUtil.BLOCK_DETAIL_LEVEL, playerPosX); int playerRegionZ = LevelPosUtil.getRegion(LodUtil.BLOCK_DETAIL_LEVEL, playerPosZ); if (playerRegionX == regionPosX && playerRegionZ == regionPosZ) { maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ); - supposedLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance)); + desiredLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance)); minDistance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ); childLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(minDistance)); stopNow = detailLevel == childLevel - 1; - } else + } + else { maxDistance = LevelPosUtil.maxDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ, playerRegionX * 512 + 256, playerRegionZ * 512 + 256); - supposedLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance)); + desiredLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDrawDetailFromDistance(maxDistance)); } break; } + if (stopNow) { posToRender.addPosToRender(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); - } else if (supposedLevel > detailLevel) + } + else if (desiredLevel > detailLevel) { + // we have gone beyond the target Detail level + // we can stop generating return; - } else if (supposedLevel == detailLevel) + } + else if (desiredLevel == detailLevel) { posToRender.addPosToRender(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size); - } else //case where (detailLevel > supposedLevel) + } + else //case where (detailLevel > desiredLevel) { int childPosX = posX * 2; int childPosZ = posZ * 2; byte childDetailLevel = (byte) (detailLevel - 1); int childrenCount = 0; + for (int x = 0; x <= 1; x++) { for (int z = 0; z <= 1; z++) @@ -297,30 +341,24 @@ public class LodRegion if (doesDataExist(childDetailLevel, childPosX + x, childPosZ + z)) { if (!requireCorrectDetailLevel) - { childrenCount++; - } else - { + else getDataToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ, requireCorrectDetailLevel); - } } } } - //If all the four children exist we go deeper if (!requireCorrectDetailLevel) { + // If all the four children exist go deeper if (childrenCount == 4) { for (int x = 0; x <= 1; x++) - { for (int z = 0; z <= 1; z++) - { getDataToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ, requireCorrectDetailLevel); - } - } - } else + } + else { posToRender.addPosToRender(detailLevel, posX + regionPosX * size, @@ -330,27 +368,31 @@ public class LodRegion } } + /** - * + * Updates all children. + * + * TODO could this be renamed mergeArea? */ public void updateArea(byte detailLevel, int posX, int posZ) { int width; int startX; int startZ; - for (byte bottom = (byte) (minDetailLevel + 1); bottom <= detailLevel; bottom++) + + // TODO what are each of these loops updating? + for (byte down = (byte) (minDetailLevel + 1); down <= detailLevel; down++) { - startX = LevelPosUtil.convert(detailLevel, posX, bottom); - startZ = LevelPosUtil.convert(detailLevel, posZ, bottom); - width = 1 << (detailLevel - bottom); + startX = LevelPosUtil.convert(detailLevel, posX, down); + startZ = LevelPosUtil.convert(detailLevel, posZ, down); + width = 1 << (detailLevel - down); + for (int x = 0; x < width; x++) - { for (int z = 0; z < width; z++) - { - update(bottom, startX + x, startZ + z); - } - } + update(down, startX + x, startZ + z); } + + for (byte up = (byte) (detailLevel + 1); up <= LodUtil.REGION_DETAIL_LEVEL; up++) { update(up, @@ -360,7 +402,9 @@ public class LodRegion } /** - * + * Update the child at the given relative Pos + * + * TODO could this be renamed mergeChildData? */ private void update(byte detailLevel, int posX, int posZ) { @@ -369,126 +413,143 @@ public class LodRegion /** - * @return + * Returns if data exists at the given relative Pos. */ public boolean doesDataExist(byte detailLevel, int posX, int posZ) { - if (detailLevel < minDetailLevel) return false; + if (detailLevel < minDetailLevel) + return false; + posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); + if (dataContainer == null || dataContainer[detailLevel] == null) return false; + return dataContainer[detailLevel].doesItExist(posX, posZ); } /** - * @return + * Gets the generation mode for the data point at the given relative pos. */ public byte getGenerationMode(byte detailLevel, int posX, int posZ) { if (dataContainer[detailLevel].doesItExist(posX, posZ)) - { - //We take the bottom information always + // We take the bottom information always + // TODO what does that mean? bottom of what? return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleData(posX, posZ)); - } else - { + else return DistanceGenerationMode.NONE.complexity; - } } + /** Returns the lowest detail level in this region + * TODO is that right? */ public byte getMinDetailLevel() { return minDetailLevel; } /** - * This will be used to save a level - * - * @param detailLevel - * @return + * Returns the LevelContainer for the detailLevel + * + * @throws IllegalArgumentException if the detailLevel is less than minDetailLevel */ public LevelContainer getLevel(byte detailLevel) { if (detailLevel < minDetailLevel) - { - throw new IllegalArgumentException("getLevel asked for a level that does not exist: minimum " + minDetailLevel + " level requested " + detailLevel); - } + throw new IllegalArgumentException("getLevel asked for a detail level that does not exist: minimum: [" + minDetailLevel + "] level requested: [" + detailLevel + "]"); + return dataContainer[detailLevel]; } /** - * @param levelContainer + * Add the levelContainer to this Region, updating the minDetailLevel + * if necessary. + * + * @throws IllegalArgumentException if the LevelContainer's detailLevel + * is 2 or more detail levels lower than the + * minDetailLevel of this region. */ - public void addLevel(LevelContainer levelContainer) + public void addLevelContainer(LevelContainer levelContainer) { if (levelContainer.getDetailLevel() < minDetailLevel - 1) { - throw new IllegalArgumentException("addLevel requires a level that is at least the minimum level of the region -1 "); + throw new IllegalArgumentException( + "the LevelContainer's detailLevel was " + + "[" + levelContainer.getDetailLevel() + "] but this region " + + "only allows adding LevelContainers with a " + + "detail level of [" + (minDetailLevel - 1) + "]"); } - if (levelContainer.getDetailLevel() == minDetailLevel - 1) minDetailLevel = levelContainer.getDetailLevel(); - dataContainer[levelContainer.getDetailLevel()] = levelContainer; + if (levelContainer.getDetailLevel() == minDetailLevel - 1) + minDetailLevel = levelContainer.getDetailLevel(); + + dataContainer[levelContainer.getDetailLevel()] = levelContainer; } + // TODO James thinks cutTree and growTree (which he renamed to match cutTree) + // should have more descriptive names, to make sure the "Tree" portion isn't + // confused with Minecraft trees (the plant). + /** - * @param detailLevel + * Removes any dataContainers that are higher than + * the given detailLevel */ public void cutTree(byte detailLevel) { - if (minDetailLevel < detailLevel) + if (detailLevel > minDetailLevel) { - for (byte tempLod = 0; tempLod < detailLevel; tempLod++) - { - dataContainer[tempLod] = null; - } + for (byte detailLevelIndex = 0; detailLevelIndex < detailLevel; detailLevelIndex++) + dataContainer[detailLevelIndex] = null; + minDetailLevel = detailLevel; } } /** - * TODO what does this do? - * @param detailLevel + * Make this region more detailed to the detailLevel given. + * TODO is that correct? */ - public void expand(byte detailLevel) + public void growTree(byte detailLevel) { if (detailLevel < minDetailLevel) { - for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= detailLevel; tempLod--) + for (byte detailLevelIndex = (byte) (minDetailLevel - 1); detailLevelIndex >= detailLevel; detailLevelIndex--) { - if (dataContainer[tempLod + 1] == null) - { - dataContainer[tempLod + 1] = new SingleLevelContainer((byte) (tempLod + 1)); - } - dataContainer[tempLod] = dataContainer[tempLod + 1].expand(); + if (dataContainer[detailLevelIndex + 1] == null) + dataContainer[detailLevelIndex + 1] = new SingleLevelContainer((byte) (detailLevelIndex + 1)); + + dataContainer[detailLevelIndex] = dataContainer[detailLevelIndex + 1].expand(); } minDetailLevel = detailLevel; } } - /** - * return RegionPos of this lod region - */ + /** return RegionPos of this lod region */ public RegionPos getRegionPos() { return new RegionPos(regionPosX, regionPosZ); } - /** - * return needed memory in byte - * - * @param template - */ + /** Returns the minimum memory needed in bytes */ public int getMinMemoryNeeded(LodTemplate template) { - int count = 0; - for (byte tempLod = LodUtil.REGION_DETAIL_LEVEL; tempLod > minDetailLevel; tempLod--) + int memory = 0; + for (byte detailLevelIndex = LodUtil.REGION_DETAIL_LEVEL; detailLevelIndex > minDetailLevel; detailLevelIndex--) { - //i'm doing a upper limit of the minimum - //Color should be just 3 byte but i'm gonna calculate as 12 byte - //Height and depth should be just 4 byte but i'm gonna calculate as 8 byte - count += dataContainer[tempLod].getMaxMemoryUse() * template.getBufferMemoryForSingleLod(dataContainer[tempLod].getMaxVerticalData()); - //count += Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod) * (24 + 8 + 8 + 8 + 8); + // TODO why are we multiplying the dataContainer's memory by the template's memory? + memory += dataContainer[detailLevelIndex].getMaxMemoryUse() * template.getBufferMemoryForSingleLod(dataContainer[detailLevelIndex].getMaxVerticalData()); } + return memory; + } + + /** Returns how many LODs are in this region */ + public int getNumberOfLods() + { + int count = 0; + for (LevelContainer container : dataContainer) + count += container.getMaxNumberOfLods(); + return count; } @@ -497,12 +558,4 @@ public class LodRegion { return getLevel(LodUtil.REGION_DETAIL_LEVEL).toString(); } - - public int getNumberOfLods() - { - int count = 0; - for (LevelContainer container : dataContainer) - count += container.getMaxNumberOfLods(); - return count; - } } diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java index b242bf1f7..1798deeec 100644 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java @@ -111,6 +111,7 @@ public class SingleLevelContainer implements LevelContainer } } + /** TODO could this be renamed mergeData? */ @Override public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) {