Refactor/comment DhSectionPos, DhLodPos, and DhLodUnit
Also add BitShiftUtil to hold bit shift operation aliases for easier reading
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
/**
|
||||
* A list of helper methods to make code easier to read. <br>
|
||||
* Specifically written because bit shifts short circuit James' brain.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2022-11-6
|
||||
*/
|
||||
public class BitShiftUtil
|
||||
{
|
||||
/**
|
||||
* Equivalent to: <br>
|
||||
* 1 << value, <br>
|
||||
* 2^value, <br>
|
||||
* Math.pow(2, value) <br><br>
|
||||
*
|
||||
* Note: Math.pow() isn't identical for large values where bits would be lost in the shift, however for medium to small values they function the same. <br><br>
|
||||
*
|
||||
* Can also be used to replace bit shifts in the format: <br>
|
||||
* multiplier << value; <br>
|
||||
* multiplier * powerOfTwo(value);
|
||||
*/
|
||||
public static int powerOfTwo(int value) { return 1 << value; }
|
||||
|
||||
/**
|
||||
* Equivalent to: <br>
|
||||
* value >> 1, <br>
|
||||
* value / 2 <br><br>
|
||||
*
|
||||
* Note: value / 2 isn't identical for negative values
|
||||
*/
|
||||
public static int half(int value) { return value >> 1; }
|
||||
|
||||
}
|
||||
@@ -6,43 +6,28 @@ public class MathUtil
|
||||
* Clamps the given value between the min and max values.
|
||||
* May behave strangely if min > max.
|
||||
*/
|
||||
public static int clamp(int min, int value, int max)
|
||||
{
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
public static int clamp(int min, int value, int max) { return Math.min(max, Math.max(value, min)); }
|
||||
|
||||
/**
|
||||
* Clamps the given value between the min and max values.
|
||||
* May behave strangely if min > max.
|
||||
*/
|
||||
public static float clamp(float min, float value, float max)
|
||||
{
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
public static float clamp(float min, float value, float max) { return Math.min(max, Math.max(value, min)); }
|
||||
|
||||
/**
|
||||
* Clamps the given value between the min and max values.
|
||||
* May behave strangely if min > max.
|
||||
*/
|
||||
public static double clamp(double min, double value, double max)
|
||||
{
|
||||
return Math.min(max, Math.max(value, min));
|
||||
}
|
||||
public static double clamp(double min, double value, double max) { return Math.min(max, Math.max(value, min)); }
|
||||
|
||||
/**
|
||||
* Like Math.floorDiv, but reverse in that it is a ceilDiv
|
||||
*/
|
||||
public static int ceilDiv(int value, int divider) {
|
||||
return -Math.floorDiv(-value, divider);
|
||||
}
|
||||
public static int ceilDiv(int value, int divider) { return -Math.floorDiv(-value, divider); }
|
||||
|
||||
// Why is this not in the standard library?! Come on Java!
|
||||
public static byte min(byte a, byte b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
public static byte max(byte a, byte b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
public static byte min(byte a, byte b) { return a < b ? a : b; }
|
||||
public static byte max(byte a, byte b) { return a > b ? a : b; }
|
||||
|
||||
|
||||
/** This is copied from Minecraft's MathHelper class */
|
||||
@@ -54,11 +39,10 @@ public class MathUtil
|
||||
numb = Float.intBitsToFloat(i);
|
||||
return numb * (1.5F - half * numb * numb);
|
||||
}
|
||||
public static float pow2(float x) {return x*x;}
|
||||
public static double pow2(double x) {return x*x;}
|
||||
public static int pow2(int x) {return x*x;}
|
||||
|
||||
public static long pow2(long x) {return x*x;}
|
||||
public static float pow2(float x) { return x * x; }
|
||||
public static double pow2(double x) { return x * x; }
|
||||
public static int pow2(int x) { return x * x; }
|
||||
|
||||
public static long pow2(long x) { return x * x; }
|
||||
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
|
||||
ColumnRenderSource[] data = new ColumnRenderSource[ELodDirection.ADJ_DIRECTIONS.length];
|
||||
for (ELodDirection direction : ELodDirection.ADJ_DIRECTIONS)
|
||||
{
|
||||
LodRenderSection section = quadTree.getSection(this.sectionPos.getAdjacent(direction)); //FIXME: Handle traveling through different detail levels
|
||||
LodRenderSection section = quadTree.getSection(this.sectionPos.getAdjacentPos(direction)); //FIXME: Handle traveling through different detail levels
|
||||
if (section != null && section.getRenderSource() != null && section.getRenderSource() instanceof ColumnRenderSource)
|
||||
{
|
||||
data[direction.ordinal() - 2] = ((ColumnRenderSource) section.getRenderSource());
|
||||
@@ -503,7 +503,7 @@ public class ColumnRenderSource implements ILodRenderSource, IColumnDatatype
|
||||
stringBuilder.append(sectionPos);
|
||||
stringBuilder.append(LINE_DELIMITER);
|
||||
|
||||
int size = sectionPos.getWidth().value;
|
||||
int size = sectionPos.getWidth().numberOfLodSectionsWide;
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
for (int x = 0; x < size; x++)
|
||||
|
||||
@@ -156,7 +156,7 @@ public class SparseDataSource implements IIncompleteDataSource
|
||||
|
||||
DhLodPos basePos = sectionPos.getCorner(SPARSE_UNIT_DETAIL);
|
||||
DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL);
|
||||
int coveredChunks = pos.getWidth(SPARSE_UNIT_DETAIL).value;
|
||||
int coveredChunks = pos.getWidth(SPARSE_UNIT_DETAIL).numberOfLodSectionsWide;
|
||||
int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> fullSource.getDataDetail();
|
||||
LodUtil.assertTrue(coveredChunks*sourceDataPerChunk == FullDataSource.SECTION_SIZE);
|
||||
int offsetX = dataPos.x-basePos.x;
|
||||
|
||||
@@ -214,7 +214,7 @@ public class SpottyDataSource extends FullArrayView implements IIncompleteDataSo
|
||||
int offsetZ = dataPos.z - basePos.z;
|
||||
LodUtil.assertTrue(offsetX >= 0 && offsetX < SECTION_SIZE && offsetZ >= 0 && offsetZ < SECTION_SIZE);
|
||||
int chunksPerData = 1 << (getDataDetail() - SparseDataSource.SPARSE_UNIT_DETAIL);
|
||||
int dataSpan = sectionPos.getWidth(getDataDetail()).value;
|
||||
int dataSpan = sectionPos.getWidth(getDataDetail()).numberOfLodSectionsWide;
|
||||
|
||||
for (int ox = 0; ox < dataSpan; ox++) {
|
||||
for (int oz = 0; oz < dataSpan; oz++) {
|
||||
@@ -229,7 +229,7 @@ public class SpottyDataSource extends FullArrayView implements IIncompleteDataSo
|
||||
}
|
||||
} else {
|
||||
DhLodPos dataPos = pos.getSectionBBoxPos();
|
||||
int lowerSectionsPerData = sectionPos.getWidth(dataPos.detail).value;
|
||||
int lowerSectionsPerData = sectionPos.getWidth(dataPos.detailLevel).numberOfLodSectionsWide;
|
||||
if (dataPos.x % lowerSectionsPerData != 0 || dataPos.z % lowerSectionsPerData != 0) return;
|
||||
|
||||
DhLodPos basePos = sectionPos.getCorner(getDataDetail());
|
||||
@@ -254,7 +254,7 @@ public class SpottyDataSource extends FullArrayView implements IIncompleteDataSo
|
||||
DhLodPos dataPos = pos.getCorner(getDataDetail());
|
||||
int offsetX = dataPos.x - basePos.x;
|
||||
int offsetZ = dataPos.z - basePos.z;
|
||||
int dataSpan = sectionPos.getWidth(getDataDetail()).value;
|
||||
int dataSpan = sectionPos.getWidth(getDataDetail()).numberOfLodSectionsWide;
|
||||
for (int ox = 0; ox < dataSpan; ox++) {
|
||||
for (int oz = 0; oz < dataSpan; oz++) {
|
||||
isColumnNotEmpty.set((offsetX + ox) * SECTION_SIZE + offsetZ + oz, true);
|
||||
@@ -262,7 +262,7 @@ public class SpottyDataSource extends FullArrayView implements IIncompleteDataSo
|
||||
}
|
||||
} else {
|
||||
DhLodPos dataPos = pos.getSectionBBoxPos();
|
||||
int lowerSectionsPerData = sectionPos.getWidth(dataPos.detail).value;
|
||||
int lowerSectionsPerData = sectionPos.getWidth(dataPos.detailLevel).numberOfLodSectionsWide;
|
||||
if (dataPos.x % lowerSectionsPerData != 0 || dataPos.z % lowerSectionsPerData != 0) return;
|
||||
DhLodPos basePos = sectionPos.getCorner(getDataDetail());
|
||||
dataPos = dataPos.convertUpwardsTo(getDataDetail());
|
||||
|
||||
+4
-4
@@ -37,8 +37,8 @@ public class FullToColumnTransformer {
|
||||
if (dataDetail == columnSource.getDataDetail()) {
|
||||
int baseX = pos.getCorner().getCorner().x;
|
||||
int baseZ = pos.getCorner().getCorner().z;
|
||||
for (int x = 0; x < pos.getWidth(dataDetail).value; x++) {
|
||||
for (int z = 0; z < pos.getWidth(dataDetail).value; z++) {
|
||||
for (int x = 0; x < pos.getWidth(dataDetail).numberOfLodSectionsWide; x++) {
|
||||
for (int z = 0; z < pos.getWidth(dataDetail).numberOfLodSectionsWide; z++) {
|
||||
ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z);
|
||||
SingleFullArrayView fullArrayView = data.get(x, z);
|
||||
convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView, 1);
|
||||
@@ -77,8 +77,8 @@ public class FullToColumnTransformer {
|
||||
if (dataDetail == columnSource.getDataDetail()) {
|
||||
int baseX = pos.getCorner().getCorner().x;
|
||||
int baseZ = pos.getCorner().getCorner().z;
|
||||
for (int x = 0; x < pos.getWidth(dataDetail).value; x++) {
|
||||
for (int z = 0; z < pos.getWidth(dataDetail).value; z++) {
|
||||
for (int x = 0; x < pos.getWidth(dataDetail).numberOfLodSectionsWide; x++) {
|
||||
for (int z = 0; z < pos.getWidth(dataDetail).numberOfLodSectionsWide; z++) {
|
||||
SingleFullArrayView fullArrayView = data.tryGet(x, z);
|
||||
if (fullArrayView == null) continue;
|
||||
ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z);
|
||||
|
||||
@@ -136,7 +136,7 @@ public class DataFileHandler implements IDataSourceProvider {
|
||||
outerLoop:
|
||||
while (--detail >= minDetailLevel) {
|
||||
DhLodPos min = pos.getCorner().getCorner(detail);
|
||||
int count = pos.getSectionBBoxPos().getWidth(detail);
|
||||
int count = pos.getSectionBBoxPos().getBlockWidth(detail);
|
||||
for (int ox = 0; ox<count; ox++) {
|
||||
for (int oz = 0; oz<count; oz++) {
|
||||
DhSectionPos subPos = new DhSectionPos(detail, ox+min.x, oz+min.z);
|
||||
@@ -158,7 +158,7 @@ public class DataFileHandler implements IDataSourceProvider {
|
||||
missing.add(pos);
|
||||
} else {
|
||||
{
|
||||
DhSectionPos childPos = pos.getChild(0);
|
||||
DhSectionPos childPos = pos.getChildByIndex(0);
|
||||
if (FullDataSource.neededForPosition(basePos, childPos)) {
|
||||
DataMetaFile metaFile = files.get(childPos);
|
||||
if (metaFile != null) {
|
||||
@@ -171,7 +171,7 @@ public class DataFileHandler implements IDataSourceProvider {
|
||||
}
|
||||
}
|
||||
{
|
||||
DhSectionPos childPos = pos.getChild(1);
|
||||
DhSectionPos childPos = pos.getChildByIndex(1);
|
||||
if (FullDataSource.neededForPosition(basePos, childPos)) {
|
||||
DataMetaFile metaFile = files.get(childPos);
|
||||
if (metaFile != null) {
|
||||
@@ -184,7 +184,7 @@ public class DataFileHandler implements IDataSourceProvider {
|
||||
}
|
||||
}
|
||||
{
|
||||
DhSectionPos childPos = pos.getChild(2);
|
||||
DhSectionPos childPos = pos.getChildByIndex(2);
|
||||
if (FullDataSource.neededForPosition(basePos, childPos)) {
|
||||
DataMetaFile metaFile = files.get(childPos);
|
||||
if (metaFile != null) {
|
||||
@@ -197,7 +197,7 @@ public class DataFileHandler implements IDataSourceProvider {
|
||||
}
|
||||
}
|
||||
{
|
||||
DhSectionPos childPos = pos.getChild(3);
|
||||
DhSectionPos childPos = pos.getChildByIndex(3);
|
||||
if (FullDataSource.neededForPosition(basePos, childPos)) {
|
||||
DataMetaFile metaFile = files.get(childPos);
|
||||
if (metaFile != null) {
|
||||
@@ -232,7 +232,7 @@ public class DataFileHandler implements IDataSourceProvider {
|
||||
DhLodPos chunkPos = new DhLodPos((byte) (chunkData.dataDetail+4), chunkData.x, chunkData.z);
|
||||
LodUtil.assertTrue(chunkPos.overlaps(sectionPos.getSectionBBoxPos()), "Chunk {} does not overlap section {}", chunkPos, sectionPos);
|
||||
chunkPos = chunkPos.convertUpwardsTo((byte) minDetailLevel); // TODO: Handle if chunkData has higher detail than lowestDetail.
|
||||
recursiveWrite(new DhSectionPos(chunkPos.detail, chunkPos.x, chunkPos.z), chunkData);
|
||||
recursiveWrite(new DhSectionPos(chunkPos.detailLevel, chunkPos.x, chunkPos.z), chunkData);
|
||||
}
|
||||
private void recursiveWrite(DhSectionPos sectionPos, ChunkSizedData chunkData) {
|
||||
DataMetaFile metaFile = files.get(sectionPos);
|
||||
@@ -240,7 +240,7 @@ public class DataFileHandler implements IDataSourceProvider {
|
||||
metaFile.addToWriteQueue(chunkData);
|
||||
}
|
||||
if (sectionPos.sectionDetail <= topDetailLevel.get()) {
|
||||
recursiveWrite(sectionPos.getParent(), chunkData);
|
||||
recursiveWrite(sectionPos.getParentPos(), chunkData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,10 +151,10 @@ public class RenderFileHandler implements IRenderSourceProvider {
|
||||
private void recursive_write(DhSectionPos sectPos, ChunkSizedData chunkData) {
|
||||
if (!sectPos.getSectionBBoxPos().overlaps(new DhLodPos((byte) (4 + chunkData.dataDetail), chunkData.x, chunkData.z))) return;
|
||||
if (sectPos.sectionDetail > ColumnRenderSource.SECTION_SIZE_OFFSET) {
|
||||
recursive_write(sectPos.getChild(0), chunkData);
|
||||
recursive_write(sectPos.getChild(1), chunkData);
|
||||
recursive_write(sectPos.getChild(2), chunkData);
|
||||
recursive_write(sectPos.getChild(3), chunkData);
|
||||
recursive_write(sectPos.getChildByIndex(0), chunkData);
|
||||
recursive_write(sectPos.getChildByIndex(1), chunkData);
|
||||
recursive_write(sectPos.getChildByIndex(2), chunkData);
|
||||
recursive_write(sectPos.getChildByIndex(3), chunkData);
|
||||
}
|
||||
RenderMetaFile metaFile = files.get(sectPos);
|
||||
if (metaFile != null) { // Fast path: if there is a file for this section, just write to it.
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.seibel.lod.core.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.pos.DhBlockPos2D;
|
||||
import com.seibel.lod.core.pos.DhLodPos;
|
||||
import com.seibel.lod.core.pos.Pos2D;
|
||||
import com.seibel.lod.core.util.MathUtil;
|
||||
import com.seibel.lod.core.util.objects.UncheckedInterruptedException;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.pos.DhChunkPos;
|
||||
@@ -120,7 +119,7 @@ public class GenerationQueue implements Closeable {
|
||||
// FIXME: This is using up a TONS of time to process!
|
||||
private final ConcurrentSkipListMap<DhLodPos, TaskGroup> taskGroups = new ConcurrentSkipListMap<>(
|
||||
(a, b) -> {
|
||||
if (a.detail != b.detail) return a.detail - b.detail;
|
||||
if (a.detailLevel != b.detailLevel) return a.detailLevel - b.detailLevel;
|
||||
int aDist = a.getCenter().toPos2D().chebyshevDist(Pos2D.ZERO);
|
||||
int bDist = b.getCenter().toPos2D().chebyshevDist(Pos2D.ZERO);
|
||||
if (aDist != bDist) return aDist - bDist;
|
||||
@@ -154,13 +153,13 @@ public class GenerationQueue implements Closeable {
|
||||
}
|
||||
if (requiredDataDetail > maxDataDetail) requiredDataDetail = maxDataDetail;
|
||||
|
||||
LodUtil.assertTrue(pos.detail > requiredDataDetail+4);
|
||||
byte granularity = (byte) (pos.detail - requiredDataDetail);
|
||||
LodUtil.assertTrue(pos.detailLevel > requiredDataDetail+4);
|
||||
byte granularity = (byte) (pos.detailLevel - requiredDataDetail);
|
||||
|
||||
if (granularity > maxGranularity) {
|
||||
// Too big of a chunk. We need to split it up
|
||||
byte subDetail = (byte) (maxGranularity + requiredDataDetail);
|
||||
int subPosCount = pos.getWidth(subDetail);
|
||||
int subPosCount = pos.getBlockWidth(subDetail);
|
||||
DhLodPos cornerSubPos = pos.getCorner(subDetail);
|
||||
CompletableFuture<Boolean>[] subFutures = new CompletableFuture[subPosCount*subPosCount];
|
||||
ArrayList<GenTask> subTasks = new ArrayList<>(subPosCount*subPosCount);
|
||||
@@ -171,7 +170,7 @@ public class GenerationQueue implements Closeable {
|
||||
for (int oz = 0; oz < subPosCount; oz++) {
|
||||
CompletableFuture<Boolean> subFuture = new CompletableFuture<>();
|
||||
subFutures[i++] = subFuture;
|
||||
subTasks.add(new GenTask(cornerSubPos.offset(ox, oz), requiredDataDetail, splitTask, subFuture));
|
||||
subTasks.add(new GenTask(cornerSubPos.addOffset(ox, oz), requiredDataDetail, splitTask, subFuture));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,7 +206,7 @@ public class GenerationQueue implements Closeable {
|
||||
}
|
||||
|
||||
private void addAndCombineGroup(TaskGroup target) {
|
||||
byte granularity = (byte) (target.pos.detail - target.dataDetail);
|
||||
byte granularity = (byte) (target.pos.detailLevel - target.dataDetail);
|
||||
LodUtil.assertTrue(granularity <= maxGranularity && granularity >= minGranularity);
|
||||
LodUtil.assertTrue(!taskGroups.containsKey(target.pos));
|
||||
|
||||
@@ -221,7 +220,7 @@ public class GenerationQueue implements Closeable {
|
||||
if (!group.pos.overlaps(target.pos)) continue;
|
||||
|
||||
// We should have already ALWAYS selected the higher granularity.
|
||||
LodUtil.assertTrue(group.pos.detail < target.pos.detail);
|
||||
LodUtil.assertTrue(group.pos.detailLevel < target.pos.detailLevel);
|
||||
groupIter.remove(); // Remove and consume all from that lower granularity request
|
||||
target.members.addAll(group.members);
|
||||
}
|
||||
@@ -231,12 +230,12 @@ public class GenerationQueue implements Closeable {
|
||||
if (granularity < maxGranularity) { // Obviously, only do so if we aren't at the maxGranularity already
|
||||
// Check for merging and upping the granularity
|
||||
DhLodPos corePos = target.pos;
|
||||
DhLodPos parentPos = corePos.convertUpwardsTo((byte) (corePos.detail+1));
|
||||
DhLodPos parentPos = corePos.convertUpwardsTo((byte) (corePos.detailLevel +1));
|
||||
int targetChildId = target.pos.getChildIndexOfParent();
|
||||
boolean allPassed = true;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (i == targetChildId) continue;
|
||||
TaskGroup group = taskGroups.get(parentPos.getChild(i));
|
||||
TaskGroup group = taskGroups.get(parentPos.getChildByIndex(i));
|
||||
if (group == null || group.dataDetail != target.dataDetail) {
|
||||
allPassed = false;
|
||||
break;
|
||||
@@ -247,7 +246,7 @@ public class GenerationQueue implements Closeable {
|
||||
TaskGroup[] groups = new TaskGroup[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (i==targetChildId) groups[i] = target;
|
||||
else groups[i] = taskGroups.remove(parentPos.getChild(i));
|
||||
else groups[i] = taskGroups.remove(parentPos.getChildByIndex(i));
|
||||
LodUtil.assertTrue(groups[i] != null && groups[i].dataDetail == target.dataDetail);
|
||||
}
|
||||
|
||||
@@ -286,7 +285,7 @@ public class GenerationQueue implements Closeable {
|
||||
GenTask task = looseTasks.poll();
|
||||
taskProcessed++;
|
||||
byte taskDataDetail = task.dataDetail;
|
||||
byte taskGranularity = (byte) (task.pos.detail - taskDataDetail);
|
||||
byte taskGranularity = (byte) (task.pos.detailLevel - taskDataDetail);
|
||||
LodUtil.assertTrue(taskGranularity >= 4 && taskGranularity >= minGranularity && taskGranularity <= maxGranularity);
|
||||
|
||||
// Check existing one
|
||||
@@ -401,7 +400,7 @@ public class GenerationQueue implements Closeable {
|
||||
private void startTaskGroup(InProgressTask task) {
|
||||
byte dataDetail = task.group.dataDetail;
|
||||
DhLodPos pos = task.group.pos;
|
||||
byte granularity = (byte) (pos.detail - dataDetail);
|
||||
byte granularity = (byte) (pos.detailLevel - dataDetail);
|
||||
LodUtil.assertTrue(granularity >= minGranularity && granularity <= maxGranularity);
|
||||
LodUtil.assertTrue(dataDetail >= minDataDetail && dataDetail <= maxDataDetail);
|
||||
|
||||
|
||||
@@ -141,9 +141,9 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
|
||||
RenderState rs = renderState.get();
|
||||
DhLodPos pos = data.getBBoxLodPos().convertUpwardsTo(FullDataSource.SECTION_SIZE_OFFSET);
|
||||
if (rs != null) {
|
||||
rs.renderFileHandler.write(new DhSectionPos(pos.detail, pos.x, pos.z), data);
|
||||
rs.renderFileHandler.write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
|
||||
} else {
|
||||
dataFileHandler.write(new DhSectionPos(pos.detail, pos.x, pos.z), data);
|
||||
dataFileHandler.write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,105 +1,165 @@
|
||||
package com.seibel.lod.core.pos;
|
||||
|
||||
import com.seibel.lod.core.util.BitShiftUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class DhLodPos implements Comparable<DhLodPos> {
|
||||
public final byte detail;
|
||||
public final int x;
|
||||
public final int z;
|
||||
|
||||
public DhLodPos(byte detail, int x, int z) {
|
||||
this.detail = detail;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[" + detail + "*" + x + "," + z + "]";
|
||||
}
|
||||
|
||||
public DhLodUnit getX() {
|
||||
return new DhLodUnit(detail, x);
|
||||
}
|
||||
|
||||
public DhLodUnit getZ() {
|
||||
return new DhLodUnit(detail, z);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return 1 << detail;
|
||||
}
|
||||
public int getWidth(byte detail) {
|
||||
LodUtil.assertTrue(detail <= this.detail);
|
||||
return 1 << (this.detail - detail);
|
||||
}
|
||||
|
||||
public static int blockWidth(byte detail) {
|
||||
return 1 << detail;
|
||||
}
|
||||
|
||||
public DhBlockPos2D getCenter() {
|
||||
return new DhBlockPos2D(getX().toBlock() + (getWidth() >> 1), getZ().toBlock() + (getWidth() >> 1));
|
||||
}
|
||||
public DhBlockPos2D getCorner() {
|
||||
return new DhBlockPos2D(getX().toBlock(), getZ().toBlock());
|
||||
}
|
||||
|
||||
public DhLodPos getCorner(byte newDetail) {
|
||||
LodUtil.assertTrue(newDetail <= detail);
|
||||
return new DhLodPos(newDetail, x << (detail-newDetail), z << (detail-newDetail));
|
||||
}
|
||||
|
||||
public DhLodPos convertUpwardsTo(byte newDetail) {
|
||||
LodUtil.assertTrue(newDetail >= detail);
|
||||
return new DhLodPos(newDetail, Math.floorDiv(x, 1<<(newDetail-detail)), Math.floorDiv(z, 1<<(newDetail-detail)));
|
||||
}
|
||||
public DhLodPos getChild(int child0to3) {
|
||||
if (child0to3 < 0 || child0to3 > 3) throw new IllegalArgumentException("child0to3 must be between 0 and 3");
|
||||
if (detail <= 0) throw new IllegalStateException("detail must be greater than 0");
|
||||
return new DhLodPos((byte) (detail - 1),
|
||||
x * 2 + (child0to3 & 1),
|
||||
z * 2 + ((child0to3 & 2) >> 1));
|
||||
}
|
||||
public int getChildIndexOfParent() {
|
||||
return (x & 1) + ((z & 1) << 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* A MC world position that is relative to a given detail level.
|
||||
*
|
||||
* @author Leetom
|
||||
* @version 2022-11-6
|
||||
*/
|
||||
public class DhLodPos implements Comparable<DhLodPos>
|
||||
{
|
||||
public final byte detailLevel;
|
||||
public final int x;
|
||||
public final int z;
|
||||
|
||||
|
||||
|
||||
public DhLodPos(byte detailLevel, int x, int z)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public DhLodUnit getX() { return new DhLodUnit(this.detailLevel, this.x); }
|
||||
public DhLodUnit getZ() { return new DhLodUnit(this.detailLevel, this.z); }
|
||||
|
||||
public int getBlockWidth() { return this.getBlockWidth(this.detailLevel); }
|
||||
public int getBlockWidth(byte detailLevel)
|
||||
{
|
||||
LodUtil.assertTrue(detailLevel <= this.detailLevel);
|
||||
return BitShiftUtil.powerOfTwo(this.detailLevel - detailLevel);
|
||||
}
|
||||
|
||||
public DhBlockPos2D getCenter()
|
||||
{
|
||||
return new DhBlockPos2D(
|
||||
this.getX().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()),
|
||||
this.getZ().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()));
|
||||
}
|
||||
public DhBlockPos2D getCorner() { return new DhBlockPos2D(this.getX().toBlockWidth(), this.getZ().toBlockWidth()); }
|
||||
|
||||
public DhLodPos getCorner(byte newDetail)
|
||||
{
|
||||
LodUtil.assertTrue(newDetail <= this.detailLevel);
|
||||
return new DhLodPos(newDetail,
|
||||
this.x * BitShiftUtil.powerOfTwo(this.detailLevel - newDetail),
|
||||
this.z * BitShiftUtil.powerOfTwo(this.detailLevel - newDetail));
|
||||
}
|
||||
|
||||
public DhLodPos convertUpwardsTo(byte newDetail)
|
||||
{
|
||||
LodUtil.assertTrue(newDetail >= this.detailLevel);
|
||||
return new DhLodPos(newDetail,
|
||||
Math.floorDiv(this.x, BitShiftUtil.powerOfTwo(newDetail - this.detailLevel)),
|
||||
Math.floorDiv(this.z, BitShiftUtil.powerOfTwo(newDetail - this.detailLevel)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DhLodPos 1 detail level lower <br><br>
|
||||
*
|
||||
* Relative child positions returned for each index: <br>
|
||||
* 0 = (0,0) <br>
|
||||
* 1 = (1,0) <br>
|
||||
* 2 = (0,1) <br>
|
||||
* 3 = (1,1) <br>
|
||||
*
|
||||
* @param child0to3 must be an int between 0 and 3
|
||||
*/
|
||||
public DhLodPos getChildByIndex(int child0to3) throws IllegalArgumentException, IllegalStateException
|
||||
{
|
||||
if (child0to3 < 0 || child0to3 > 3)
|
||||
throw new IllegalArgumentException("child0to3 must be between 0 and 3");
|
||||
if (this.detailLevel <= 0)
|
||||
throw new IllegalStateException("detailLevel must be greater than 0");
|
||||
|
||||
return new DhLodPos((byte) (this.detailLevel - 1),
|
||||
this.x * 2 + (child0to3 & 1),
|
||||
this.z * 2 + BitShiftUtil.half(child0to3 & 2));
|
||||
}
|
||||
/** Returns this position's child index in its parent */
|
||||
public int getChildIndexOfParent() { return (this.x & 1) + ((this.z & 1) << 1); }
|
||||
|
||||
public boolean overlaps(DhLodPos other)
|
||||
{
|
||||
if (this.equals(other))
|
||||
return true;
|
||||
if (this.detailLevel == other.detailLevel)
|
||||
return false;
|
||||
|
||||
if (this.detailLevel > other.detailLevel)
|
||||
{
|
||||
return this.equals(other.convertUpwardsTo(this.detailLevel));
|
||||
}
|
||||
else
|
||||
{
|
||||
return other.equals(this.convertUpwardsTo(other.detailLevel));
|
||||
}
|
||||
}
|
||||
|
||||
/** Only valid for DhLodUnits for an equal or greater detail level */
|
||||
public DhLodPos addLodUnit(DhLodUnit width)
|
||||
{
|
||||
if (width.detailLevel < this.detailLevel)
|
||||
throw new IllegalArgumentException("add called with width.detailLevel < pos detail");
|
||||
|
||||
return new DhLodPos(this.detailLevel,
|
||||
x + width.createFromDetailLevel(this.detailLevel).numberOfLodSectionsWide,
|
||||
z + width.createFromDetailLevel(this.detailLevel).numberOfLodSectionsWide);
|
||||
}
|
||||
|
||||
/** Equivalent to adding a DhLodUnit with the same detail level as this DhLodPos */
|
||||
public DhLodPos addOffset(int xOffset, int zOffset) { return new DhLodPos(this.detailLevel, this.x + xOffset, this.z + zOffset); }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj == null || this.getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DhLodPos otherPos = (DhLodPos) obj;
|
||||
return this.detailLevel == otherPos.detailLevel && this.x == otherPos.x && this.z == otherPos.z;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
DhLodPos dhLodPos = (DhLodPos) o;
|
||||
return detail == dhLodPos.detail && x == dhLodPos.x && z == dhLodPos.z;
|
||||
}
|
||||
|
||||
public int hashCode() { return Objects.hash(detailLevel, x, z); }
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(detail, x, z);
|
||||
}
|
||||
|
||||
public boolean overlaps(DhLodPos other) {
|
||||
if (equals(other)) return true;
|
||||
if (detail == other.detail) return false;
|
||||
if (detail > other.detail) {
|
||||
return this.equals(other.convertUpwardsTo(this.detail));
|
||||
} else {
|
||||
return other.equals(this.convertUpwardsTo(other.detail));
|
||||
}
|
||||
}
|
||||
|
||||
public DhLodPos add(DhLodUnit width) {
|
||||
if (width.detail < detail) throw new IllegalArgumentException("add called with width.detail < pos detail");
|
||||
return new DhLodPos(detail, x + width.convertTo(detail).value, z + width.convertTo(detail).value);
|
||||
}
|
||||
public DhLodPos offset(int ox, int oz) {
|
||||
return new DhLodPos(detail, x+ox, z+oz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull DhLodPos o) {
|
||||
return detail != o.detail ? Integer.compare(detail, o.detail) : x != o.x ? Integer.compare(x, o.x) : Integer.compare(z, o.z);
|
||||
}
|
||||
public int compareTo(@NotNull DhLodPos obj)
|
||||
{
|
||||
if (this.detailLevel != obj.detailLevel)
|
||||
{
|
||||
return Integer.compare(this.detailLevel, obj.detailLevel);
|
||||
}
|
||||
else if (this.x != obj.x)
|
||||
{
|
||||
return Integer.compare(this.x, obj.x);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Integer.compare(this.z, obj.z);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return "[" + this.detailLevel + "*" + this.x + "," + this.z + "]"; }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +1,54 @@
|
||||
package com.seibel.lod.core.pos;
|
||||
|
||||
public class DhLodUnit {
|
||||
public final byte detail;
|
||||
public final int value;
|
||||
import com.seibel.lod.core.util.BitShiftUtil;
|
||||
|
||||
public DhLodUnit(byte detail, int value) {
|
||||
this.detail = detail;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int toBlock() {
|
||||
return value << detail;
|
||||
}
|
||||
|
||||
public static DhLodUnit fromBlock(int block, byte targetDetail) {
|
||||
return new DhLodUnit(targetDetail, Math.floorDiv(block, 1<<targetDetail));
|
||||
}
|
||||
|
||||
public DhLodUnit convertTo(byte targetDetail) {
|
||||
if (detail == targetDetail) {
|
||||
return this;
|
||||
}
|
||||
if (detail > targetDetail) { //TODO check if this is correct
|
||||
return new DhLodUnit(targetDetail, value << (detail - targetDetail));
|
||||
}
|
||||
return new DhLodUnit(targetDetail, Math.floorDiv(value, 1<<(targetDetail-detail)));
|
||||
/**
|
||||
* Often used to measure LOD widths
|
||||
*
|
||||
* @author Leetom
|
||||
* @version 2022-11-6
|
||||
*/
|
||||
public class DhLodUnit
|
||||
{
|
||||
/** The detail level of this LOD Unit */
|
||||
public final byte detailLevel;
|
||||
/** How many LOD columns wide this LOD Unit represents */
|
||||
public final int numberOfLodSectionsWide;
|
||||
|
||||
|
||||
|
||||
public DhLodUnit(byte detailLevel, int numberOfLodSectionsWide)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
this.numberOfLodSectionsWide = numberOfLodSectionsWide;
|
||||
}
|
||||
|
||||
|
||||
/** @return the size of this LOD unit in Minecraft blocks */
|
||||
public int toBlockWidth() { return this.numberOfLodSectionsWide << this.detailLevel; }
|
||||
/** @return the LOD Unit relative to the given block width and detail level */
|
||||
public static DhLodUnit fromBlockWidth(int blockWidth, byte targetDetailLevel) { return new DhLodUnit(targetDetailLevel, Math.floorDiv(blockWidth, BitShiftUtil.powerOfTwo(targetDetailLevel))); }
|
||||
|
||||
/**
|
||||
* if the targetDetailLevel and this object's detail are the same,
|
||||
* this will be returned instead of creating a new object
|
||||
*/
|
||||
public DhLodUnit createFromDetailLevel(byte targetDetailLevel)
|
||||
{
|
||||
if (this.detailLevel == targetDetailLevel)
|
||||
{
|
||||
// no need to create a new object, this one is already the right detail level
|
||||
return this;
|
||||
}
|
||||
else if (this.detailLevel > targetDetailLevel)
|
||||
{
|
||||
//TODO check if this is correct
|
||||
return new DhLodUnit(targetDetailLevel, this.numberOfLodSectionsWide * BitShiftUtil.powerOfTwo(this.detailLevel - targetDetailLevel));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new DhLodUnit(targetDetailLevel, Math.floorDiv(this.numberOfLodSectionsWide, BitShiftUtil.powerOfTwo(targetDetailLevel - this.detailLevel)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,112 +1,150 @@
|
||||
package com.seibel.lod.core.pos;
|
||||
|
||||
import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.util.BitShiftUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.MathUtil;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class DhSectionPos {
|
||||
public final byte sectionDetail;
|
||||
public final int sectionX; // in sectionDetail level grid
|
||||
public final int sectionZ; // in sectionDetail level grid
|
||||
|
||||
public DhSectionPos(byte sectionDetail, int sectionX, int sectionZ) {
|
||||
this.sectionDetail = sectionDetail;
|
||||
this.sectionX = sectionX;
|
||||
this.sectionZ = sectionZ;
|
||||
}
|
||||
|
||||
public DhLodPos getCenter(byte returnDetailLevel) {
|
||||
LodUtil.assertTrue(returnDetailLevel <= sectionDetail, "returnDetailLevel must be less than sectionDetail");
|
||||
if (returnDetailLevel == sectionDetail)
|
||||
return new DhLodPos(sectionDetail, sectionX, sectionZ);
|
||||
byte offset = (byte) (sectionDetail - returnDetailLevel);
|
||||
return new DhLodPos(returnDetailLevel, (sectionX << offset)+(1 << (offset -1)),
|
||||
(sectionZ << offset)+(1 << (offset -1)));
|
||||
}
|
||||
public DhLodPos getCorner(byte returnDetailLevel) {
|
||||
LodUtil.assertTrue(returnDetailLevel <= sectionDetail, "returnDetailLevel must be less than sectionDetail");
|
||||
byte offset = (byte) (sectionDetail - returnDetailLevel);
|
||||
return new DhLodPos(returnDetailLevel, sectionX << offset, sectionZ << offset);
|
||||
}
|
||||
public DhLodUnit getWidth(byte returnDetailLevel) {
|
||||
LodUtil.assertTrue(returnDetailLevel <= sectionDetail, "returnDetailLevel must be less than sectionDetail");
|
||||
byte offset = (byte) (sectionDetail - returnDetailLevel);
|
||||
return new DhLodUnit(sectionDetail, 1 << offset);
|
||||
}
|
||||
public DhLodPos getCenter() {
|
||||
return getCenter((byte)0);
|
||||
}
|
||||
public DhLodPos getCorner() {
|
||||
return getCorner((byte) (sectionDetail-1));
|
||||
}
|
||||
public DhLodUnit getWidth() {
|
||||
return getWidth(sectionDetail);
|
||||
}
|
||||
|
||||
public DhSectionPos getChild(int child0to3){
|
||||
if (child0to3 < 0 || child0to3 > 3) throw new IllegalArgumentException("child0to3 must be between 0 and 3");
|
||||
if (sectionDetail <= 0) throw new IllegalStateException("section detail must be greater than 0");
|
||||
return new DhSectionPos((byte) (sectionDetail - 1),
|
||||
sectionX * 2 + (child0to3 & 1),
|
||||
sectionZ * 2 + ((child0to3 & 2) >> 1));
|
||||
}
|
||||
public int getChildIndexOfParent() {
|
||||
return (sectionX & 1) + ((sectionZ & 1) << 1);
|
||||
}
|
||||
|
||||
public void forEachChild(Consumer<DhSectionPos> callback){
|
||||
for (int i = 0; i < 4; i++) {
|
||||
callback.accept(getChild(i));
|
||||
}
|
||||
}
|
||||
|
||||
public DhSectionPos getParent(){
|
||||
return new DhSectionPos((byte) (sectionDetail + 1), sectionX >> 1, sectionZ >> 1);
|
||||
}
|
||||
|
||||
public DhSectionPos getAdjacent(ELodDirection dir) {
|
||||
return new DhSectionPos(sectionDetail, sectionX + dir.getNormal().x, sectionZ + dir.getNormal().z);
|
||||
}
|
||||
|
||||
public DhLodPos getSectionBBoxPos() {
|
||||
return new DhLodPos(sectionDetail, sectionX, sectionZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: This does not consider yOffset!
|
||||
*/
|
||||
public boolean overlaps(DhSectionPos other){
|
||||
return getSectionBBoxPos().overlaps(other.getSectionBBoxPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + sectionDetail +
|
||||
"*" + sectionX +
|
||||
"," + sectionZ +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
DhSectionPos that = (DhSectionPos) o;
|
||||
return sectionDetail == that.sectionDetail &&
|
||||
sectionX == that.sectionX &&
|
||||
sectionZ == that.sectionZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Integer.hashCode(sectionDetail) ^
|
||||
Integer.hashCode(sectionX) ^
|
||||
Integer.hashCode(sectionZ);
|
||||
}
|
||||
|
||||
// Serialize() is different from toString() as this requires it to NEVER be changed, and should be in a short format
|
||||
public String serialize() {
|
||||
return "[" + sectionDetail + ',' + sectionX + ',' + sectionZ + ']';
|
||||
}
|
||||
/**
|
||||
* The position object used to define LOD objects in the quad trees.
|
||||
*
|
||||
* @author Leetom
|
||||
* @version 2022-11-6
|
||||
*/
|
||||
public class DhSectionPos
|
||||
{
|
||||
public final byte sectionDetail;
|
||||
|
||||
/** in sectionDetail level grid */
|
||||
public final int sectionX;
|
||||
/** in sectionDetail level grid */
|
||||
public final int sectionZ;
|
||||
|
||||
|
||||
|
||||
public DhSectionPos(byte sectionDetail, int sectionX, int sectionZ)
|
||||
{
|
||||
this.sectionDetail = sectionDetail;
|
||||
this.sectionX = sectionX;
|
||||
this.sectionZ = sectionZ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Returns the center for the highest detail level (0) */
|
||||
public DhLodPos getCenter() { return this.getCenter((byte) 0); }
|
||||
public DhLodPos getCenter(byte returnDetailLevel)
|
||||
{
|
||||
LodUtil.assertTrue(returnDetailLevel <= this.sectionDetail, "returnDetailLevel must be less than sectionDetail");
|
||||
|
||||
if (returnDetailLevel == this.sectionDetail)
|
||||
return new DhLodPos(this.sectionDetail, this.sectionX, this.sectionZ);
|
||||
|
||||
byte offset = (byte) (this.sectionDetail - returnDetailLevel);
|
||||
return new DhLodPos(returnDetailLevel,
|
||||
(this.sectionX * BitShiftUtil.powerOfTwo(offset)) + BitShiftUtil.powerOfTwo(offset - 1),
|
||||
(this.sectionZ * BitShiftUtil.powerOfTwo(offset)) + BitShiftUtil.powerOfTwo(offset - 1));
|
||||
}
|
||||
|
||||
/** @return the corner with the smallest X and Z coordinate */
|
||||
public DhLodPos getCorner() { return this.getCorner((byte) (this.sectionDetail - 1)); }
|
||||
/** @return the corner with the smallest X and Z coordinate */
|
||||
public DhLodPos getCorner(byte returnDetailLevel)
|
||||
{
|
||||
LodUtil.assertTrue(returnDetailLevel <= this.sectionDetail, "returnDetailLevel must be less than sectionDetail");
|
||||
byte offset = (byte) (this.sectionDetail - returnDetailLevel);
|
||||
return new DhLodPos(returnDetailLevel,
|
||||
this.sectionX * BitShiftUtil.powerOfTwo(offset),
|
||||
this.sectionZ * BitShiftUtil.powerOfTwo(offset));
|
||||
}
|
||||
|
||||
public DhLodUnit getWidth() { return this.getWidth(this.sectionDetail); }
|
||||
public DhLodUnit getWidth(byte returnDetailLevel)
|
||||
{
|
||||
LodUtil.assertTrue(returnDetailLevel <= this.sectionDetail, "returnDetailLevel must be less than sectionDetail");
|
||||
byte offset = (byte) (this.sectionDetail - returnDetailLevel);
|
||||
return new DhLodUnit(this.sectionDetail, BitShiftUtil.powerOfTwo(offset));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the DhLodPos 1 detail level lower <br><br>
|
||||
*
|
||||
* Relative child positions returned for each index: <br>
|
||||
* 0 = (0,0) <br>
|
||||
* 1 = (1,0) <br>
|
||||
* 2 = (0,1) <br>
|
||||
* 3 = (1,1) <br>
|
||||
*
|
||||
* @param child0to3 must be an int between 0 and 3
|
||||
*/
|
||||
public DhSectionPos getChildByIndex(int child0to3) throws IllegalArgumentException, IllegalStateException
|
||||
{
|
||||
if (child0to3 < 0 || child0to3 > 3)
|
||||
throw new IllegalArgumentException("child0to3 must be between 0 and 3");
|
||||
if (this.sectionDetail <= 0)
|
||||
throw new IllegalStateException("section detail must be greater than 0");
|
||||
|
||||
return new DhSectionPos((byte) (this.sectionDetail - 1),
|
||||
this.sectionX * 2 + (child0to3 & 1),
|
||||
this.sectionZ * 2 + BitShiftUtil.half(child0to3 & 2));
|
||||
}
|
||||
/** Returns this position's child index in its parent */
|
||||
public int getChildIndexOfParent() { return (this.sectionX & 1) + ((this.sectionZ & 1) << 1); }
|
||||
|
||||
/** Applies the given consumer to all 4 of this position's children. */
|
||||
public void forEachChild(Consumer<DhSectionPos> callback)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
callback.accept(this.getChildByIndex(i));
|
||||
}
|
||||
}
|
||||
|
||||
public DhSectionPos getParentPos() { return new DhSectionPos((byte) (this.sectionDetail + 1), BitShiftUtil.half(this.sectionX), BitShiftUtil.half(this.sectionZ)); }
|
||||
|
||||
public DhSectionPos getAdjacentPos(ELodDirection dir)
|
||||
{
|
||||
return new DhSectionPos(this.sectionDetail,
|
||||
this.sectionX + dir.getNormal().x,
|
||||
this.sectionZ + dir.getNormal().z);
|
||||
}
|
||||
|
||||
public DhLodPos getSectionBBoxPos() { return new DhLodPos(this.sectionDetail, this.sectionX, this.sectionZ); }
|
||||
|
||||
/** NOTE: This does not consider yOffset! */
|
||||
public boolean overlaps(DhSectionPos other) { return this.getSectionBBoxPos().overlaps(other.getSectionBBoxPos()); }
|
||||
|
||||
/** Serialize() is different from toString() as it must NEVER be changed, and should be in a short format */
|
||||
public String serialize() { return "[" + this.sectionDetail + ',' + this.sectionX + ',' + this.sectionZ + ']'; }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() { return "{" + this.sectionDetail + "*" + this.sectionX + "," + this.sectionZ + "}"; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || this.getClass() != obj.getClass())
|
||||
return false;
|
||||
|
||||
DhSectionPos that = (DhSectionPos) obj;
|
||||
return this.sectionDetail == that.sectionDetail &&
|
||||
this.sectionX == that.sectionX &&
|
||||
this.sectionZ == that.sectionZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Integer.hashCode(this.sectionDetail) ^ // XOR
|
||||
Integer.hashCode(this.sectionX) ^ // XOR
|
||||
Integer.hashCode(this.sectionZ);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ public class LodQuadTree implements AutoCloseable {
|
||||
* @return the parent LodSection
|
||||
*/
|
||||
public LodRenderSection getParentSection(DhSectionPos pos) {
|
||||
return getSection(pos.getParent());
|
||||
return getSection(pos.getParentPos());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,7 +192,7 @@ public class LodQuadTree implements AutoCloseable {
|
||||
* @return one of the child LodSection
|
||||
*/
|
||||
public LodRenderSection getChildSection(DhSectionPos pos, int child0to3) {
|
||||
return getSection(pos.getChild(child0to3));
|
||||
return getSection(pos.getChildByIndex(child0to3));
|
||||
}
|
||||
|
||||
private LodRenderSection _set(MovableGridRingList<LodRenderSection> list, int x, int z, LodRenderSection t) {
|
||||
@@ -280,15 +280,15 @@ public class LodQuadTree implements AutoCloseable {
|
||||
if (parentRingList != null) {
|
||||
LodRenderSection parent = _get(parentRingList, pos.x >> 1, pos.y >> 1);
|
||||
if (parent == null) {
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("sect {} missing parent. Creating at {}", section.pos, section.pos.getParent());
|
||||
parent = _set(parentRingList, pos.x >> 1, pos.y >> 1, new LodRenderSection(section.pos.getParent()));
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("sect {} missing parent. Creating at {}", section.pos, section.pos.getParentPos());
|
||||
parent = _set(parentRingList, pos.x >> 1, pos.y >> 1, new LodRenderSection(section.pos.getParentPos()));
|
||||
parent.childCount++;
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("parent sect {} now has {} childs.", section.pos.getParent(), parent.childCount);
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("parent sect {} now has {} childs.", section.pos.getParentPos(), parent.childCount);
|
||||
}
|
||||
LodUtil.assertTrue(parent.childCount <= 4 && parent.childCount > 0);
|
||||
}
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
DhSectionPos childPos = section.pos.getChild(i);
|
||||
DhSectionPos childPos = section.pos.getChildByIndex(i);
|
||||
LodUtil.assertTrue(childRingList != null);
|
||||
LodRenderSection child = _get(childRingList, childPos.sectionX, childPos.sectionZ);
|
||||
if (child == null) {
|
||||
@@ -338,11 +338,11 @@ public class LodQuadTree implements AutoCloseable {
|
||||
LodUtil.assertTrue(parentRingList != null);
|
||||
LodRenderSection parent = _get(parentRingList, pos.x >> 1, pos.y >> 1);
|
||||
if (parent == null) {
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("sect {} missing parent. Creating at {}", sectPos, sectPos.getParent());
|
||||
parent = _set(parentRingList, pos.x >> 1, pos.y >> 1, new LodRenderSection(sectPos.getParent()));
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("sect {} missing parent. Creating at {}", sectPos, sectPos.getParentPos());
|
||||
parent = _set(parentRingList, pos.x >> 1, pos.y >> 1, new LodRenderSection(sectPos.getParentPos()));
|
||||
}
|
||||
parent.childCount++;
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("parent sect {} now has {} childs.", sectPos.getParent(), parent.childCount);
|
||||
if (SUPER_VERBOSE_LOGGING) LOGGER.info("parent sect {} now has {} childs.", sectPos.getParentPos(), parent.childCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ public class RenderBufferHandler {
|
||||
if (children == null) {
|
||||
RenderBufferNode[] childs = new RenderBufferNode[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
childs[i] = new RenderBufferNode(pos.getChild(i));
|
||||
childs[i] = new RenderBufferNode(pos.getChildByIndex(i));
|
||||
}
|
||||
children = childs;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user