Start impl the dynamic section data detail offset
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
package com.seibel.lod.core.objects.a7;
|
||||
|
||||
import com.seibel.lod.core.objects.a7.datatype.column.ColumnDatatype;
|
||||
import com.seibel.lod.core.objects.a7.pos.DhBlockPos2D;
|
||||
import com.seibel.lod.core.objects.a7.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.gridList.MovableGridRingList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
// QuadTree built from several layers of 2d ring buffers
|
||||
|
||||
/**
|
||||
@@ -30,6 +35,37 @@ public abstract class LodQuadTree {
|
||||
|
||||
public final int numbersOfDetailLevels;
|
||||
private final MovableGridRingList<LodSection>[] ringLists;
|
||||
|
||||
static class ContainerTypeConfigEntry {
|
||||
final Class<?> containerType;
|
||||
final int levelOffset;
|
||||
public ContainerTypeConfigEntry(Class<?> containerType, int levelOffset) {
|
||||
this.containerType = containerType;
|
||||
this.levelOffset = levelOffset;
|
||||
}
|
||||
}
|
||||
|
||||
static final ArrayList<ContainerTypeConfigEntry> containerTypeConfig = new ArrayList<>();
|
||||
static {
|
||||
Collections.addAll(containerTypeConfig,
|
||||
null,
|
||||
null, //1
|
||||
null, //2
|
||||
null, //3
|
||||
new ContainerTypeConfigEntry(FullDatatype.class, 4), //4 -> 0
|
||||
null, //5 breaks down to 4
|
||||
null, //6 breaks down to 4
|
||||
new ContainerTypeConfigEntry(ColumnDatatype.class, ColumnDatatype.SECTION_SIZE_OFFSET), //7 -> 1
|
||||
new ContainerTypeConfigEntry(ColumnDatatype.class, ColumnDatatype.SECTION_SIZE_OFFSET), //8 -> 2
|
||||
new ContainerTypeConfigEntry(ColumnDatatype.class, ColumnDatatype.SECTION_SIZE_OFFSET), //9 -> 3
|
||||
new ContainerTypeConfigEntry(ColumnDatatype.class, ColumnDatatype.SECTION_SIZE_OFFSET), //10 -> 4
|
||||
new ContainerTypeConfigEntry(ColumnDatatype.class, ColumnDatatype.SECTION_SIZE_OFFSET) //11 -> 5...
|
||||
);
|
||||
}
|
||||
|
||||
final ContainerTypeConfigEntry[] containerTypeConfigs;
|
||||
|
||||
//public static final
|
||||
|
||||
/**
|
||||
* Constructor of the quadTree
|
||||
@@ -38,13 +74,35 @@ public abstract class LodQuadTree {
|
||||
* @param initialPlayerZ player z coordinate
|
||||
*/
|
||||
public LodQuadTree(int viewDistance, int initialPlayerX, int initialPlayerZ) {
|
||||
numbersOfDetailLevels = DetailDistanceUtil.getDetailLevelFromDistance(viewDistance*Math.sqrt(2));
|
||||
byte maxDetailLevel = DetailDistanceUtil.getDetailLevelFromDistance(viewDistance*Math.sqrt(2));
|
||||
ContainerTypeConfigEntry finalEntry = null;
|
||||
byte topSectionLevel = 0;
|
||||
for (; topSectionLevel < containerTypeConfig.size(); topSectionLevel++) {
|
||||
if (containerTypeConfig.get(topSectionLevel) == null) continue;
|
||||
finalEntry = containerTypeConfig.get(topSectionLevel);
|
||||
if (topSectionLevel - finalEntry.levelOffset >= maxDetailLevel) break;
|
||||
}
|
||||
if (finalEntry == null) throw new RuntimeException("No container type found!");
|
||||
if (topSectionLevel == containerTypeConfig.size())
|
||||
topSectionLevel = (byte) (maxDetailLevel - finalEntry.levelOffset);
|
||||
numbersOfDetailLevels = topSectionLevel + 1;
|
||||
containerTypeConfigs = new ContainerTypeConfigEntry[numbersOfDetailLevels];
|
||||
finalEntry = null;
|
||||
for (byte i = 0; i < numbersOfDetailLevels; i++) {
|
||||
if (containerTypeConfig.get(i) == null) continue; //TODO: Next here
|
||||
|
||||
}
|
||||
|
||||
ringLists = new MovableGridRingList[numbersOfDetailLevels];
|
||||
int size;
|
||||
for (byte detailLevel = 0; detailLevel < numbersOfDetailLevels; detailLevel++) {
|
||||
double distance = DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel);
|
||||
int sectionCount = LodUtil.ceilDiv((int) Math.ceil(distance),
|
||||
DhSectionPos.getWidth(detailLevel).toBlock()) + 1; // +1 for the border during move
|
||||
int distance = getFurthestPoint(detailLevel);
|
||||
ContainerTypeConfigEntry configEntry = containerTypeConfig.get(detailLevel);
|
||||
if (configEntry == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int sectionCount = LodUtil.ceilDiv(distance, DhSectionPos.getWidth(detailLevel).toBlock()) + 1; // +1 for the border during move
|
||||
ringLists[detailLevel] = new MovableGridRingList<LodSection>(sectionCount,
|
||||
initialPlayerX >> detailLevel, initialPlayerZ >> detailLevel);
|
||||
}
|
||||
@@ -88,10 +146,10 @@ public abstract class LodQuadTree {
|
||||
return ringLists[detailLevel].get(x, z);
|
||||
}
|
||||
|
||||
// Overridable
|
||||
|
||||
/**
|
||||
* This method will compute the detail level based on player position and section pos
|
||||
* Override this method if you want to use a different algorithm
|
||||
* @param playerPos player position as a reference for calculating the detail level
|
||||
* @param sectionPos section position
|
||||
* @return detail level of this section pos
|
||||
@@ -101,6 +159,17 @@ public abstract class LodQuadTree {
|
||||
playerPos.dist(sectionPos.getCenter().getCenter()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The method will return the furthest distance to the center for the given detail level
|
||||
* Override this method if you want to use a different algorithm
|
||||
* Note: the returned distance should always be the ceiling estimation of the distance
|
||||
* @param detailLevel detail level
|
||||
* @return the furthest distance to the center, in blocks
|
||||
*/
|
||||
public int getFurthestPoint(byte detailLevel) {
|
||||
return (int)Math.ceil(DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel));
|
||||
}
|
||||
|
||||
public abstract RenderDataProvider getRenderDataProvider();
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,8 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class ColumnDatatype implements LodDataSource, RenderDataSource {
|
||||
public static final boolean DO_SAFETY_CHECKS = true;
|
||||
public static final int SECTION_SIZE = DhSectionPos.DATA_WIDTH_PER_SECTION;
|
||||
public static final int SECTION_SIZE_OFFSET = 6;
|
||||
public static final int SECTION_SIZE = 1 << SECTION_SIZE_OFFSET;
|
||||
public static final int LATEST_VERSION = 9;
|
||||
public final int AIR_LODS_SIZE = 16;
|
||||
public final int AIR_SECTION_SIZE = SECTION_SIZE/AIR_LODS_SIZE;
|
||||
|
||||
@@ -5,52 +5,48 @@ import com.seibel.lod.core.enums.LodDirection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class DhSectionPos {
|
||||
public static final byte SECTION_DETAIL_LEVEL_OFFSET = 6;
|
||||
public static final int DATA_WIDTH_PER_SECTION = 1 << SECTION_DETAIL_LEVEL_OFFSET;
|
||||
|
||||
public final byte detail;
|
||||
public final int x;
|
||||
public final int z;
|
||||
public final int yOffset;
|
||||
public final byte dataDetailOffset;
|
||||
|
||||
public DhSectionPos(byte detail, int x, int z) {
|
||||
this.detail = detail;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.yOffset = 0;
|
||||
}
|
||||
public DhSectionPos(byte detail, int x, int z, int yOffset) {
|
||||
public DhSectionPos(byte detail, int x, int z, int yOffset, byte dataDetailOffset) {
|
||||
this.detail = detail;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.yOffset = yOffset;
|
||||
this.dataDetailOffset = dataDetailOffset;
|
||||
}
|
||||
|
||||
public DhSectionPos withOffset(int yOffset) {
|
||||
return new DhSectionPos(detail, x, z, yOffset);
|
||||
public DhSectionPos withYOffset(int yOffset) {
|
||||
return new DhSectionPos(detail, x, z, yOffset, dataDetailOffset);
|
||||
}
|
||||
public DhSectionPos withDataOffset(byte dataDetailOffset) {
|
||||
return new DhSectionPos(detail, x, z, yOffset, dataDetailOffset);
|
||||
}
|
||||
|
||||
|
||||
public DhLodPos getCenter() {
|
||||
return new DhLodPos(detail, x * DATA_WIDTH_PER_SECTION + DATA_WIDTH_PER_SECTION / 2, z * DATA_WIDTH_PER_SECTION + DATA_WIDTH_PER_SECTION / 2);
|
||||
if (dataDetailOffset == 0) return new DhLodPos(detail, x, z);
|
||||
return new DhLodPos(detail, (x << dataDetailOffset)+(1 << (dataDetailOffset-1)), (z << dataDetailOffset)+(1 << (dataDetailOffset-1)));
|
||||
}
|
||||
|
||||
public DhLodPos getCorner() {
|
||||
return new DhLodPos(detail, x * DATA_WIDTH_PER_SECTION, z * DATA_WIDTH_PER_SECTION);
|
||||
return new DhLodPos(detail, x << dataDetailOffset, z << dataDetailOffset);
|
||||
}
|
||||
|
||||
public DhLodUnit getWidth() {
|
||||
return new DhLodUnit(detail, DATA_WIDTH_PER_SECTION);
|
||||
return new DhLodUnit(detail, 1 << dataDetailOffset);
|
||||
}
|
||||
|
||||
public static DhLodUnit getWidth(byte detail) {
|
||||
return new DhLodUnit(detail, DATA_WIDTH_PER_SECTION);
|
||||
public static DhLodUnit getWidth(byte detail, byte dataDetailOffset){
|
||||
return new DhLodUnit(detail, 1 << dataDetailOffset);
|
||||
}
|
||||
|
||||
public DhSectionPos 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 DhSectionPos((byte) (detail - 1), x * 2 + (child0to3 & 1), z * 2 + (child0to3 & 2) / 2, yOffset);
|
||||
if (detail-dataDetailOffset <= 0) throw new IllegalStateException("detail or data detail must be greater than 0");
|
||||
return new DhSectionPos((byte) (detail - 1), x * 2 + (child0to3 & 1), z * 2 + (child0to3 & 2) / 2, yOffset, dataDetailOffset);
|
||||
}
|
||||
|
||||
public void forEachChild(Consumer<DhSectionPos> callback){
|
||||
@@ -60,21 +56,22 @@ public class DhSectionPos {
|
||||
}
|
||||
|
||||
public DhSectionPos getParent(){
|
||||
return new DhSectionPos((byte) (detail + 1), x / 2, z / 2, yOffset);
|
||||
return new DhSectionPos((byte) (detail + 1), x / 2, z / 2, yOffset, dataDetailOffset);
|
||||
}
|
||||
|
||||
public DhSectionPos getAdjacent(LodDirection dir) {
|
||||
return new DhSectionPos(detail, x + dir.getNormal().x, z + dir.getNormal().z, yOffset);
|
||||
return new DhSectionPos(detail, x + dir.getNormal().x, z + dir.getNormal().z, yOffset, dataDetailOffset);
|
||||
}
|
||||
|
||||
public DhSectionPos convertUpwardsTo(byte newDetail){
|
||||
if (detail == newDetail) return this;
|
||||
if (detail > newDetail) return new DhSectionPos(newDetail, x >> (detail - newDetail), z >> (detail - newDetail), yOffset);
|
||||
if (detail > newDetail) return
|
||||
new DhSectionPos(newDetail, x >> (detail - newDetail), z >> (detail - newDetail), yOffset, dataDetailOffset);
|
||||
throw new IllegalArgumentException("newDetail must be greater than detail");
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: This equals() does not consider yOffset!
|
||||
* NOTE: This equals() does not consider yOffset or dataDetailOffset!
|
||||
*/
|
||||
|
||||
public boolean equals(Object o){
|
||||
@@ -85,7 +82,7 @@ public class DhSectionPos {
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: This does not consider yOffset!
|
||||
* NOTE: This does not consider yOffset! (dataDetailOffset is also ignored since, well, it doesn't effect the outcome)
|
||||
*/
|
||||
public boolean overlaps(DhSectionPos other){
|
||||
if (this.equals(other))
|
||||
|
||||
Reference in New Issue
Block a user