WorldOctTree small updates
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
This commit is contained in:
parent
4f2fcc62c9
commit
183c98367c
@ -14,7 +14,7 @@ import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.util.ds.octree.WorldOctTree;
|
||||
import electrosphere.util.ds.octree.WorldOctTree.FloatingChunkTreeNode;
|
||||
import electrosphere.util.ds.octree.WorldOctTree.WorldOctTreeNode;
|
||||
import electrosphere.util.math.GeomUtils;
|
||||
|
||||
/**
|
||||
@ -95,7 +95,7 @@ public class ClientDrawCellManager {
|
||||
/**
|
||||
* Tracks what nodes have been evaluated this frame -- used to deduplicate evaluation calls
|
||||
*/
|
||||
Map<FloatingChunkTreeNode<DrawCell>,Boolean> evaluationMap = new HashMap<FloatingChunkTreeNode<DrawCell>,Boolean>();
|
||||
Map<WorldOctTreeNode<DrawCell>,Boolean> evaluationMap = new HashMap<WorldOctTreeNode<DrawCell>,Boolean>();
|
||||
|
||||
/**
|
||||
* The last recorded player world position
|
||||
@ -173,7 +173,7 @@ public class ClientDrawCellManager {
|
||||
validCellCount = 0;
|
||||
evaluationMap.clear();
|
||||
//update all full res cells
|
||||
FloatingChunkTreeNode<DrawCell> rootNode = this.chunkTree.getRoot();
|
||||
WorldOctTreeNode<DrawCell> rootNode = this.chunkTree.getRoot();
|
||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.update - full res cells");
|
||||
updatedLastFrame = this.recursivelyUpdateCells(rootNode, playerWorldPos, evaluationMap, SIXTEENTH_RES_LOD, distCache);
|
||||
Globals.profiler.endCpuSample();
|
||||
@ -217,7 +217,7 @@ public class ClientDrawCellManager {
|
||||
* @param evaluationMap Map of leaf nodes that have been evaluated this frame
|
||||
* @return true if there is work remaining to be done, false otherwise
|
||||
*/
|
||||
private boolean recursivelyUpdateCells(FloatingChunkTreeNode<DrawCell> node, Vector3i playerPos, Map<FloatingChunkTreeNode<DrawCell>,Boolean> evaluationMap, int minLeafLod, int distCache){
|
||||
private boolean recursivelyUpdateCells(WorldOctTreeNode<DrawCell> node, Vector3i playerPos, Map<WorldOctTreeNode<DrawCell>,Boolean> evaluationMap, int minLeafLod, int distCache){
|
||||
boolean updated = false;
|
||||
if(evaluationMap.containsKey(node)){
|
||||
return false;
|
||||
@ -229,7 +229,7 @@ public class ClientDrawCellManager {
|
||||
if(this.shouldSplit(playerPos, node, distCache)){
|
||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.split");
|
||||
//perform op
|
||||
FloatingChunkTreeNode<DrawCell> container = chunkTree.split(node);
|
||||
WorldOctTreeNode<DrawCell> container = chunkTree.split(node);
|
||||
|
||||
//do deletions
|
||||
this.twoLayerDestroy(node);
|
||||
@ -300,7 +300,7 @@ public class ClientDrawCellManager {
|
||||
if(this.shouldJoin(playerPos, node, distCache)) {
|
||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.join");
|
||||
//perform op
|
||||
FloatingChunkTreeNode<DrawCell> newLeaf = chunkTree.join(node);
|
||||
WorldOctTreeNode<DrawCell> newLeaf = chunkTree.join(node);
|
||||
|
||||
//do deletions
|
||||
this.twoLayerDestroy(node);
|
||||
@ -317,9 +317,9 @@ public class ClientDrawCellManager {
|
||||
updated = true;
|
||||
} else {
|
||||
this.validCellCount++;
|
||||
List<FloatingChunkTreeNode<DrawCell>> children = node.getChildren();
|
||||
List<WorldOctTreeNode<DrawCell>> children = node.getChildren();
|
||||
for(int i = 0; i < 8; i++){
|
||||
FloatingChunkTreeNode<DrawCell> child = children.get(i);
|
||||
WorldOctTreeNode<DrawCell> child = children.get(i);
|
||||
boolean childUpdate = recursivelyUpdateCells(child, playerPos, evaluationMap, minLeafLod, distCache);
|
||||
if(childUpdate == true){
|
||||
updated = true;
|
||||
@ -339,7 +339,7 @@ public class ClientDrawCellManager {
|
||||
* @param node the node
|
||||
* @return the distance
|
||||
*/
|
||||
public double getMinDistance(Vector3i worldPos, FloatingChunkTreeNode<DrawCell> node, int distCache){
|
||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<DrawCell> node, int distCache){
|
||||
if(node.getData() == null){
|
||||
return GeomUtils.getMinSquaredDistanceAABB(worldPos, node.getMinBound(), node.getMaxBound());
|
||||
} else {
|
||||
@ -388,7 +388,7 @@ public class ClientDrawCellManager {
|
||||
* @param node The node
|
||||
* @return true if should split, false otherwise
|
||||
*/
|
||||
public boolean shouldSplit(Vector3i pos, FloatingChunkTreeNode<DrawCell> node, int distCache){
|
||||
public boolean shouldSplit(Vector3i pos, WorldOctTreeNode<DrawCell> node, int distCache){
|
||||
//breaking out into dedicated function so can add case handling ie if we want
|
||||
//to combine fullres nodes into larger nodes to conserve on draw calls
|
||||
return
|
||||
@ -430,7 +430,7 @@ public class ClientDrawCellManager {
|
||||
* @param node The node to consider
|
||||
* @return -1 if outside of render range, -1 if the node is not a valid draw cell leaf, otherwise returns the LOD level
|
||||
*/
|
||||
private int getLODLevel(FloatingChunkTreeNode<DrawCell> node){
|
||||
private int getLODLevel(WorldOctTreeNode<DrawCell> node){
|
||||
return this.chunkTree.getMaxLevel() - node.getLevel();
|
||||
}
|
||||
|
||||
@ -440,7 +440,7 @@ public class ClientDrawCellManager {
|
||||
* @param playerWorldPos The player's world position
|
||||
* @return true if should solve for high res faces, false otherwise
|
||||
*/
|
||||
private boolean shouldSolveFaces(FloatingChunkTreeNode<DrawCell> node, Vector3i playerWorldPos, int distCache){
|
||||
private boolean shouldSolveFaces(WorldOctTreeNode<DrawCell> node, Vector3i playerWorldPos, int distCache){
|
||||
if(node.getLevel() == this.chunkTree.getMaxLevel()){
|
||||
return false;
|
||||
}
|
||||
@ -472,7 +472,7 @@ public class ClientDrawCellManager {
|
||||
* @param node The node for the chunk
|
||||
* @return The face if there is a higher resolution face, null otherwise
|
||||
*/
|
||||
private List<DrawCellFace> solveHighResFace(FloatingChunkTreeNode<DrawCell> node){
|
||||
private List<DrawCellFace> solveHighResFace(WorldOctTreeNode<DrawCell> node){
|
||||
//don't bother to check if it's a full res chunk
|
||||
if(node.getLevel() == this.chunkTree.getMaxLevel()){
|
||||
return null;
|
||||
@ -484,37 +484,37 @@ public class ClientDrawCellManager {
|
||||
int spacing = (int)Math.pow(2,lodMultiplitier);
|
||||
List<DrawCellFace> faces = new LinkedList<DrawCellFace>();
|
||||
if(node.getMinBound().x - 1 >= 0){
|
||||
FloatingChunkTreeNode<DrawCell> xNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(-1,1,1), false);
|
||||
WorldOctTreeNode<DrawCell> xNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(-1,1,1), false);
|
||||
if(xNegNode != null && xNegNode.getLevel() > node.getLevel()){
|
||||
faces.add(DrawCellFace.X_NEGATIVE);
|
||||
}
|
||||
}
|
||||
if(node.getMinBound().y - 1 >= 0){
|
||||
FloatingChunkTreeNode<DrawCell> yNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,-1,1), false);
|
||||
WorldOctTreeNode<DrawCell> yNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,-1,1), false);
|
||||
if(yNegNode != null && yNegNode.getLevel() > node.getLevel()){
|
||||
faces.add(DrawCellFace.Y_NEGATIVE);
|
||||
}
|
||||
}
|
||||
if(node.getMinBound().z - 1 >= 0){
|
||||
FloatingChunkTreeNode<DrawCell> zNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,1,-1), false);
|
||||
WorldOctTreeNode<DrawCell> zNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,1,-1), false);
|
||||
if(zNegNode != null && zNegNode.getLevel() > node.getLevel()){
|
||||
faces.add(DrawCellFace.Z_NEGATIVE);
|
||||
}
|
||||
}
|
||||
if(node.getMaxBound().x + spacing + 1 < this.worldDim){
|
||||
FloatingChunkTreeNode<DrawCell> xPosNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(spacing + 1,1,1), false);
|
||||
WorldOctTreeNode<DrawCell> xPosNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(spacing + 1,1,1), false);
|
||||
if(xPosNode != null && xPosNode.getLevel() > node.getLevel()){
|
||||
faces.add(DrawCellFace.X_POSITIVE);
|
||||
}
|
||||
}
|
||||
if(node.getMaxBound().y + spacing + 1 < this.worldDim){
|
||||
FloatingChunkTreeNode<DrawCell> yPosNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,spacing + 1,1), false);
|
||||
WorldOctTreeNode<DrawCell> yPosNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,spacing + 1,1), false);
|
||||
if(yPosNode != null && yPosNode.getLevel() > node.getLevel()){
|
||||
faces.add(DrawCellFace.Y_POSITIVE);
|
||||
}
|
||||
}
|
||||
if(node.getMaxBound().z + spacing + 1 < this.worldDim){
|
||||
FloatingChunkTreeNode<DrawCell> zPosNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,1,spacing + 1), false);
|
||||
WorldOctTreeNode<DrawCell> zPosNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(1,1,spacing + 1), false);
|
||||
if(zPosNode != null && zPosNode.getLevel() > node.getLevel()){
|
||||
faces.add(DrawCellFace.Z_POSITIVE);
|
||||
}
|
||||
@ -530,43 +530,43 @@ public class ClientDrawCellManager {
|
||||
* @param node The node to search from adjacencies from
|
||||
* @param level The level to check against
|
||||
*/
|
||||
private void conditionalUpdateAdjacentNodes(FloatingChunkTreeNode<DrawCell> node, int level){
|
||||
private void conditionalUpdateAdjacentNodes(WorldOctTreeNode<DrawCell> node, int level){
|
||||
//don't bother to check if it's a lowest-res chunk
|
||||
if(this.chunkTree.getMaxLevel() - level > ClientDrawCellManager.FULL_RES_LOD){
|
||||
return;
|
||||
}
|
||||
if(node.getMinBound().x - 1 >= 0){
|
||||
FloatingChunkTreeNode<DrawCell> xNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(-1,0,0), false);
|
||||
WorldOctTreeNode<DrawCell> xNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(-1,0,0), false);
|
||||
if(xNegNode != null && xNegNode.getLevel() < level){
|
||||
xNegNode.getData().setHasGenerated(false);
|
||||
}
|
||||
}
|
||||
if(node.getMinBound().y - 1 >= 0){
|
||||
FloatingChunkTreeNode<DrawCell> yNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(0,-1,0), false);
|
||||
WorldOctTreeNode<DrawCell> yNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(0,-1,0), false);
|
||||
if(yNegNode != null && yNegNode.getLevel() < level){
|
||||
yNegNode.getData().setHasGenerated(false);
|
||||
}
|
||||
}
|
||||
if(node.getMinBound().z - 1 >= 0){
|
||||
FloatingChunkTreeNode<DrawCell> zNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(0,0,-1), false);
|
||||
WorldOctTreeNode<DrawCell> zNegNode = this.chunkTree.search(new Vector3i(node.getMinBound()).add(0,0,-1), false);
|
||||
if(zNegNode != null && zNegNode.getLevel() < level){
|
||||
zNegNode.getData().setHasGenerated(false);
|
||||
}
|
||||
}
|
||||
if(node.getMaxBound().x + 1 < this.worldDim){
|
||||
FloatingChunkTreeNode<DrawCell> xPosNode = this.chunkTree.search(new Vector3i(node.getMaxBound()).add(1,-1,-1), false);
|
||||
WorldOctTreeNode<DrawCell> xPosNode = this.chunkTree.search(new Vector3i(node.getMaxBound()).add(1,-1,-1), false);
|
||||
if(xPosNode != null && xPosNode.getLevel() < level){
|
||||
xPosNode.getData().setHasGenerated(false);
|
||||
}
|
||||
}
|
||||
if(node.getMaxBound().y + 1 < this.worldDim){
|
||||
FloatingChunkTreeNode<DrawCell> yPosNode = this.chunkTree.search(new Vector3i(node.getMaxBound()).add(-1,1,-1), false);
|
||||
WorldOctTreeNode<DrawCell> yPosNode = this.chunkTree.search(new Vector3i(node.getMaxBound()).add(-1,1,-1), false);
|
||||
if(yPosNode != null && yPosNode.getLevel() < level){
|
||||
yPosNode.getData().setHasGenerated(false);
|
||||
}
|
||||
}
|
||||
if(node.getMaxBound().z + 1 < this.worldDim){
|
||||
FloatingChunkTreeNode<DrawCell> zPosNode = this.chunkTree.search(new Vector3i(node.getMaxBound()).add(-1,-1,1), false);
|
||||
WorldOctTreeNode<DrawCell> zPosNode = this.chunkTree.search(new Vector3i(node.getMaxBound()).add(-1,-1,1), false);
|
||||
if(zPosNode != null && zPosNode.getLevel() < level){
|
||||
zPosNode.getData().setHasGenerated(false);
|
||||
}
|
||||
@ -579,7 +579,7 @@ public class ClientDrawCellManager {
|
||||
* @param node The node
|
||||
* @return true if should be joined, false otherwise
|
||||
*/
|
||||
public boolean shouldJoin(Vector3i pos, FloatingChunkTreeNode<DrawCell> node, int distCache){
|
||||
public boolean shouldJoin(Vector3i pos, WorldOctTreeNode<DrawCell> node, int distCache){
|
||||
//breaking out into dedicated function so can add case handling ie if we want
|
||||
//to combine fullres nodes into larger nodes to conserve on draw calls
|
||||
return
|
||||
@ -620,7 +620,7 @@ public class ClientDrawCellManager {
|
||||
* @param minLeafLod The minimum LOD required to evaluate a leaf
|
||||
* @return true if should request chunk data, false otherwise
|
||||
*/
|
||||
public boolean shouldRequest(Vector3i pos, FloatingChunkTreeNode<DrawCell> node, int minLeafLod, int distCache){
|
||||
public boolean shouldRequest(Vector3i pos, WorldOctTreeNode<DrawCell> node, int minLeafLod, int distCache){
|
||||
return
|
||||
node.getData() != null &&
|
||||
!node.getData().hasRequested() &&
|
||||
@ -666,7 +666,7 @@ public class ClientDrawCellManager {
|
||||
* @param minLeafLod The minimum LOD required to evaluate a leaf
|
||||
* @return true if should generate, false otherwise
|
||||
*/
|
||||
public boolean shouldGenerate(Vector3i pos, FloatingChunkTreeNode<DrawCell> node, int minLeafLod, int distCache){
|
||||
public boolean shouldGenerate(Vector3i pos, WorldOctTreeNode<DrawCell> node, int minLeafLod, int distCache){
|
||||
return
|
||||
node.getData() != null &&
|
||||
!node.getData().hasGenerated() &&
|
||||
@ -710,7 +710,7 @@ public class ClientDrawCellManager {
|
||||
* @param node The node
|
||||
* @return true if should destroy, false otherwise
|
||||
*/
|
||||
public boolean shouldDestroy(FloatingChunkTreeNode<DrawCell> node){
|
||||
public boolean shouldDestroy(WorldOctTreeNode<DrawCell> node){
|
||||
return
|
||||
node.getData() != null &&
|
||||
node.getData().getEntity() != null
|
||||
@ -728,7 +728,7 @@ public class ClientDrawCellManager {
|
||||
* Recursively destroy a tree
|
||||
* @param node The root of the tree
|
||||
*/
|
||||
private void recursivelyDestroy(FloatingChunkTreeNode<DrawCell> node){
|
||||
private void recursivelyDestroy(WorldOctTreeNode<DrawCell> node){
|
||||
if(node.getChildren().size() > 0){
|
||||
node.getChildren().forEach(child -> recursivelyDestroy(child));
|
||||
}
|
||||
@ -741,9 +741,9 @@ public class ClientDrawCellManager {
|
||||
* Destroys two layers of nodes
|
||||
* @param node The top node
|
||||
*/
|
||||
private void twoLayerDestroy(FloatingChunkTreeNode<DrawCell> node){
|
||||
private void twoLayerDestroy(WorldOctTreeNode<DrawCell> node){
|
||||
if(node.getData() == null){
|
||||
for(FloatingChunkTreeNode<DrawCell> child : node.getChildren()){
|
||||
for(WorldOctTreeNode<DrawCell> child : node.getChildren()){
|
||||
if(child.getData() != null){
|
||||
child.getData().destroy();
|
||||
}
|
||||
@ -797,7 +797,7 @@ public class ClientDrawCellManager {
|
||||
* @param cell The cell
|
||||
* @return true if all cells were successfully requested, false otherwise
|
||||
*/
|
||||
private boolean requestChunks(WorldOctTree.FloatingChunkTreeNode<DrawCell> node, List<DrawCellFace> highResFaces){
|
||||
private boolean requestChunks(WorldOctTree.WorldOctTreeNode<DrawCell> node, List<DrawCellFace> highResFaces){
|
||||
DrawCell cell = node.getData();
|
||||
int lod = this.chunkTree.getMaxLevel() - node.getLevel();
|
||||
int spacingFactor = (int)Math.pow(2,lod);
|
||||
@ -873,7 +873,7 @@ public class ClientDrawCellManager {
|
||||
* @param highResFace The higher resolution face of a not-full-resolution chunk. Null if the chunk is max resolution or there is no higher resolution face for the current chunk
|
||||
* @return true if all data is available, false otherwise
|
||||
*/
|
||||
private boolean containsDataToGenerate(WorldOctTree.FloatingChunkTreeNode<DrawCell> node, List<DrawCellFace> highResFaces){
|
||||
private boolean containsDataToGenerate(WorldOctTree.WorldOctTreeNode<DrawCell> node, List<DrawCellFace> highResFaces){
|
||||
DrawCell cell = node.getData();
|
||||
int lod = this.chunkTree.getMaxLevel() - node.getLevel();
|
||||
int spacingFactor = (int)Math.pow(2,lod);
|
||||
@ -966,7 +966,7 @@ public class ClientDrawCellManager {
|
||||
* Recursively calculates the status of the manager
|
||||
* @param node The root node
|
||||
*/
|
||||
private void recursivelyCalculateStatus(FloatingChunkTreeNode<DrawCell> node){
|
||||
private void recursivelyCalculateStatus(WorldOctTreeNode<DrawCell> node){
|
||||
if(node.getLevel() == this.chunkTree.getMaxLevel() - 1){
|
||||
halfResCount++;
|
||||
}
|
||||
@ -977,8 +977,8 @@ public class ClientDrawCellManager {
|
||||
generated++;
|
||||
}
|
||||
if(node.getChildren() != null && node.getChildren().size() > 0){
|
||||
List<FloatingChunkTreeNode<DrawCell>> children = new LinkedList<FloatingChunkTreeNode<DrawCell>>(node.getChildren());
|
||||
for(FloatingChunkTreeNode<DrawCell> child : children){
|
||||
List<WorldOctTreeNode<DrawCell>> children = new LinkedList<WorldOctTreeNode<DrawCell>>(node.getChildren());
|
||||
for(WorldOctTreeNode<DrawCell> child : children){
|
||||
recursivelyCalculateStatus(child);
|
||||
}
|
||||
}
|
||||
@ -1024,7 +1024,7 @@ public class ClientDrawCellManager {
|
||||
* @return The draw cell if it exists, null otherwise
|
||||
*/
|
||||
public DrawCell getDrawCell(int worldX, int worldY, int worldZ){
|
||||
FloatingChunkTreeNode<DrawCell> node = this.chunkTree.search(new Vector3i(worldX,worldY,worldZ), false);
|
||||
WorldOctTreeNode<DrawCell> node = this.chunkTree.search(new Vector3i(worldX,worldY,worldZ), false);
|
||||
if(node != null){
|
||||
return node.getData();
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ import electrosphere.entity.types.terrain.TerrainChunk;
|
||||
import electrosphere.renderer.meshgen.TransvoxelModelGeneration;
|
||||
import electrosphere.renderer.meshgen.TransvoxelModelGeneration.TransvoxelChunkData;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.util.ds.octree.WorldOctTree.FloatingChunkTreeNode;
|
||||
import electrosphere.util.ds.octree.WorldOctTree.WorldOctTreeNode;
|
||||
import electrosphere.util.math.GeomUtils;
|
||||
|
||||
/**
|
||||
@ -536,7 +536,7 @@ public class DrawCell {
|
||||
* @param distCache the lod value under which distance caches are invalidated
|
||||
* @return the distance
|
||||
*/
|
||||
public double getMinDistance(Vector3i worldPos, FloatingChunkTreeNode<DrawCell> node, int distCache){
|
||||
public double getMinDistance(Vector3i worldPos, WorldOctTreeNode<DrawCell> node, int distCache){
|
||||
if(cachedMinDistance != INVALID_DIST_CACHE && distCache < lod){
|
||||
return cachedMinDistance;
|
||||
} else {
|
||||
|
||||
@ -21,12 +21,12 @@ public class WorldOctTree <T> {
|
||||
/**
|
||||
* The root node
|
||||
*/
|
||||
private FloatingChunkTreeNode<T> root = null;
|
||||
private WorldOctTreeNode<T> root = null;
|
||||
|
||||
/**
|
||||
* The list of all nodes in the tree
|
||||
*/
|
||||
List<FloatingChunkTreeNode<T>> nodes = null;
|
||||
List<WorldOctTreeNode<T>> nodes = null;
|
||||
|
||||
/**
|
||||
* The minimum position
|
||||
@ -60,8 +60,8 @@ public class WorldOctTree <T> {
|
||||
//calculate max level
|
||||
int dimRaw = max.x - min.x;
|
||||
this.maxLevel = (int)MathUtils.log2(dimRaw);
|
||||
this.nodes = new ArrayList<FloatingChunkTreeNode<T>>();
|
||||
this.root = new FloatingChunkTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max));
|
||||
this.nodes = new ArrayList<WorldOctTreeNode<T>>();
|
||||
this.root = new WorldOctTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max));
|
||||
this.root.isLeaf = true;
|
||||
this.nodes.add(this.root);
|
||||
}
|
||||
@ -71,7 +71,7 @@ public class WorldOctTree <T> {
|
||||
* @param parent The parent
|
||||
* @return The new non-leaf node
|
||||
*/
|
||||
public FloatingChunkTreeNode<T> split(FloatingChunkTreeNode<T> existing){
|
||||
public WorldOctTreeNode<T> split(WorldOctTreeNode<T> existing){
|
||||
if(!existing.isLeaf()){
|
||||
throw new IllegalArgumentException("Tried to split non-leaf!");
|
||||
}
|
||||
@ -81,20 +81,20 @@ public class WorldOctTree <T> {
|
||||
int midY = (max.y - min.y) / 2 + min.y;
|
||||
int midZ = (max.z - min.z) / 2 + min.z;
|
||||
int currentLevel = existing.getLevel();
|
||||
FloatingChunkTreeNode<T> newContainer = new FloatingChunkTreeNode<>(this, currentLevel, min, max);
|
||||
WorldOctTreeNode<T> newContainer = new WorldOctTreeNode<>(this, currentLevel, min, max);
|
||||
//add children
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,min.y,min.z), new Vector3i(midX,midY,midZ)));
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,min.y,min.z), new Vector3i(max.x,midY,midZ)));
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,midY,min.z), new Vector3i(midX,max.y,midZ)));
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,midY,min.z), new Vector3i(max.x,max.y,midZ)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,min.y,min.z), new Vector3i(midX,midY,midZ)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,min.y,min.z), new Vector3i(max.x,midY,midZ)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,midY,min.z), new Vector3i(midX,max.y,midZ)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,midY,min.z), new Vector3i(max.x,max.y,midZ)));
|
||||
//
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,min.y,midZ), new Vector3i(midX,midY,max.z)));
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,min.y,midZ), new Vector3i(max.x,midY,max.z)));
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,midY,midZ), new Vector3i(midX,max.y,max.z)));
|
||||
newContainer.addChild(new FloatingChunkTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,midY,midZ), new Vector3i(max.x,max.y,max.z)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,min.y,midZ), new Vector3i(midX,midY,max.z)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,min.y,midZ), new Vector3i(max.x,midY,max.z)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(min.x,midY,midZ), new Vector3i(midX,max.y,max.z)));
|
||||
newContainer.addChild(new WorldOctTreeNode<T>(this, currentLevel + 1, new Vector3i(midX,midY,midZ), new Vector3i(max.x,max.y,max.z)));
|
||||
|
||||
boolean foundMin = false;
|
||||
for(FloatingChunkTreeNode<T> child : newContainer.getChildren()){
|
||||
for(WorldOctTreeNode<T> child : newContainer.getChildren()){
|
||||
if(child.getMinBound().distance(newContainer.getMinBound()) == 0){
|
||||
foundMin = true;
|
||||
}
|
||||
@ -104,7 +104,7 @@ public class WorldOctTree <T> {
|
||||
message = message + min + " " + max + "\n";
|
||||
message = message + midX + " " + midY + " " + midZ + "\n";
|
||||
message = message + "container mid: " + newContainer.getMinBound();
|
||||
for(FloatingChunkTreeNode<T> child : newContainer.getChildren()){
|
||||
for(WorldOctTreeNode<T> child : newContainer.getChildren()){
|
||||
message = message + "child min: " + child.getMinBound() + "\n";
|
||||
}
|
||||
throw new Error(message);
|
||||
@ -126,14 +126,14 @@ public class WorldOctTree <T> {
|
||||
* @param parent The non-leaf
|
||||
* @return The new leaf node
|
||||
*/
|
||||
public FloatingChunkTreeNode<T> join(FloatingChunkTreeNode<T> existing){
|
||||
public WorldOctTreeNode<T> join(WorldOctTreeNode<T> existing){
|
||||
if(existing.isLeaf()){
|
||||
throw new IllegalArgumentException("Tried to split non-leaf!");
|
||||
}
|
||||
Vector3i min = existing.getMinBound();
|
||||
Vector3i max = existing.getMaxBound();
|
||||
int currentLevel = existing.getLevel();
|
||||
FloatingChunkTreeNode<T> newContainer = new FloatingChunkTreeNode<>(this, currentLevel, min, max);
|
||||
WorldOctTreeNode<T> newContainer = new WorldOctTreeNode<>(this, currentLevel, min, max);
|
||||
|
||||
//replace existing node
|
||||
this.replaceNode(existing,newContainer);
|
||||
@ -151,11 +151,11 @@ public class WorldOctTree <T> {
|
||||
* @param existing the existing node
|
||||
* @param newNode the new node
|
||||
*/
|
||||
private void replaceNode(FloatingChunkTreeNode<T> existing, FloatingChunkTreeNode<T> newNode){
|
||||
private void replaceNode(WorldOctTreeNode<T> existing, WorldOctTreeNode<T> newNode){
|
||||
if(existing == this.root){
|
||||
this.root = newNode;
|
||||
} else {
|
||||
FloatingChunkTreeNode<T> parent = existing.getParent();
|
||||
WorldOctTreeNode<T> parent = existing.getParent();
|
||||
int index = parent.children.indexOf(existing);
|
||||
parent.removeChild(existing);
|
||||
parent.addChild(index, newNode);
|
||||
@ -165,7 +165,7 @@ public class WorldOctTree <T> {
|
||||
/**
|
||||
* Gets the root node of the tree
|
||||
*/
|
||||
public FloatingChunkTreeNode<T> getRoot() {
|
||||
public WorldOctTreeNode<T> getRoot() {
|
||||
return this.root;
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ public class WorldOctTree <T> {
|
||||
*/
|
||||
public void clear(){
|
||||
this.nodes.clear();
|
||||
this.root = new FloatingChunkTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max));
|
||||
this.root = new WorldOctTreeNode<T>(this, 0, new Vector3i(min), new Vector3i(max));
|
||||
this.root.isLeaf = true;
|
||||
this.nodes.add(this.root);
|
||||
}
|
||||
@ -201,7 +201,7 @@ public class WorldOctTree <T> {
|
||||
* @param returnNonLeaf If true, the function can return non-leaf nodes, otherwise will only return leaf nodes
|
||||
* @return The leaf if it exists, null otherwise
|
||||
*/
|
||||
public FloatingChunkTreeNode<T> search(Vector3i position, boolean returnNonLeaf){
|
||||
public WorldOctTreeNode<T> search(Vector3i position, boolean returnNonLeaf){
|
||||
return this.search(position,returnNonLeaf,this.maxLevel);
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ public class WorldOctTree <T> {
|
||||
* @param maxLevel The maximum level to search for
|
||||
* @return The leaf if it exists, null otherwise
|
||||
*/
|
||||
public FloatingChunkTreeNode<T> search(Vector3i position, boolean returnNonLeaf, int maxLevel){
|
||||
public WorldOctTreeNode<T> search(Vector3i position, boolean returnNonLeaf, int maxLevel){
|
||||
//out of bounds check
|
||||
if(
|
||||
position.x < min.x || position.x > max.x ||
|
||||
@ -221,7 +221,7 @@ public class WorldOctTree <T> {
|
||||
){
|
||||
throw new Error("Trying to search for node outside tree range!");
|
||||
}
|
||||
FloatingChunkTreeNode<T> searchResult = recursiveSearchUnsafe(root,position,maxLevel);
|
||||
WorldOctTreeNode<T> searchResult = recursiveSearchUnsafe(root,position,maxLevel);
|
||||
if(!returnNonLeaf && !searchResult.isLeaf()){
|
||||
return null;
|
||||
}
|
||||
@ -235,7 +235,7 @@ public class WorldOctTree <T> {
|
||||
* @param maxLevel The maximum level to search for
|
||||
* @return The found node
|
||||
*/
|
||||
private FloatingChunkTreeNode<T> recursiveSearchUnsafe(FloatingChunkTreeNode<T> currentNode, Vector3i position, int maxLevel){
|
||||
private WorldOctTreeNode<T> recursiveSearchUnsafe(WorldOctTreeNode<T> currentNode, Vector3i position, int maxLevel){
|
||||
if(maxLevel < 0){
|
||||
throw new Error("Provided invalid max level! Must be created than 0! " + maxLevel);
|
||||
}
|
||||
@ -246,7 +246,7 @@ public class WorldOctTree <T> {
|
||||
return currentNode;
|
||||
}
|
||||
if(currentNode.getChildren().size() > 0){
|
||||
for(FloatingChunkTreeNode<T> child : currentNode.getChildren()){
|
||||
for(WorldOctTreeNode<T> child : currentNode.getChildren()){
|
||||
if(
|
||||
position.x < child.getMaxBound().x && position.x >= child.getMinBound().x &&
|
||||
position.y < child.getMaxBound().y && position.y >= child.getMinBound().y &&
|
||||
@ -258,7 +258,7 @@ public class WorldOctTree <T> {
|
||||
String message = "Current node is within range, but no children are! This does not make any sense.\n";
|
||||
|
||||
message = message + " current pos: " + currentNode.getMinBound() + " " + currentNode.getMaxBound() + "\n";
|
||||
for(FloatingChunkTreeNode<T> child : currentNode.getChildren()){
|
||||
for(WorldOctTreeNode<T> child : currentNode.getChildren()){
|
||||
message = message + " child " + child + " pos: " + child.getMinBound() + " " + child.getMaxBound() + "\n";
|
||||
}
|
||||
message = message + "position to search: " + position + "\n";
|
||||
@ -272,13 +272,13 @@ public class WorldOctTree <T> {
|
||||
/**
|
||||
* A node in a chunk tree
|
||||
*/
|
||||
public static class FloatingChunkTreeNode<T> {
|
||||
public static class WorldOctTreeNode<T> {
|
||||
|
||||
//True if this is a leaf node, false otherwise
|
||||
private boolean isLeaf;
|
||||
|
||||
//the parent node
|
||||
private FloatingChunkTreeNode<T> parent;
|
||||
private WorldOctTreeNode<T> parent;
|
||||
|
||||
/**
|
||||
* The tree containing this node
|
||||
@ -286,7 +286,7 @@ public class WorldOctTree <T> {
|
||||
private WorldOctTree<T> containingTree;
|
||||
|
||||
//the children of this node
|
||||
private List<FloatingChunkTreeNode<T>> children = new LinkedList<FloatingChunkTreeNode<T>>();
|
||||
private List<WorldOctTreeNode<T>> children = new LinkedList<WorldOctTreeNode<T>>();
|
||||
|
||||
//The data at the node
|
||||
private T data;
|
||||
@ -314,7 +314,7 @@ public class WorldOctTree <T> {
|
||||
* @param min The minimum position of the node
|
||||
* @param max The maximum position of then ode
|
||||
*/
|
||||
private FloatingChunkTreeNode(WorldOctTree<T> tree, int level, Vector3i min, Vector3i max){
|
||||
private WorldOctTreeNode(WorldOctTree<T> tree, int level, Vector3i min, Vector3i max){
|
||||
if(tree == null){
|
||||
throw new Error("Invalid tree provided " + tree);
|
||||
}
|
||||
@ -340,8 +340,8 @@ public class WorldOctTree <T> {
|
||||
* @param max The max point
|
||||
* @return The node
|
||||
*/
|
||||
public static <T> FloatingChunkTreeNode<T> constructorForTests(WorldOctTree<T> tree, int level, Vector3i min, Vector3i max){
|
||||
return new FloatingChunkTreeNode<T>(tree, level, min, max);
|
||||
public static <T> WorldOctTreeNode<T> constructorForTests(WorldOctTree<T> tree, int level, Vector3i min, Vector3i max){
|
||||
return new WorldOctTreeNode<T>(tree, level, min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -353,6 +353,22 @@ public class WorldOctTree <T> {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this node is a leaf or not
|
||||
* @param isLeaf true if it is a leaf, false otherwise
|
||||
*/
|
||||
public void setLeaf(boolean isLeaf){
|
||||
this.isLeaf = isLeaf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data of the node
|
||||
* @param data The data
|
||||
*/
|
||||
public void setData(T data){
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data associated with this node
|
||||
*/
|
||||
@ -363,14 +379,14 @@ public class WorldOctTree <T> {
|
||||
/**
|
||||
* Gets the parent of this node
|
||||
*/
|
||||
public FloatingChunkTreeNode<T> getParent() {
|
||||
public WorldOctTreeNode<T> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the children of this node
|
||||
*/
|
||||
public List<FloatingChunkTreeNode<T>> getChildren() {
|
||||
public List<WorldOctTreeNode<T>> getChildren() {
|
||||
return Collections.unmodifiableList(this.children);
|
||||
}
|
||||
|
||||
@ -418,7 +434,7 @@ public class WorldOctTree <T> {
|
||||
* Adds a child to this node
|
||||
* @param child The child
|
||||
*/
|
||||
private void addChild(FloatingChunkTreeNode<T> child){
|
||||
private void addChild(WorldOctTreeNode<T> child){
|
||||
this.children.add(child);
|
||||
child.parent = this;
|
||||
}
|
||||
@ -428,7 +444,7 @@ public class WorldOctTree <T> {
|
||||
* @param index The index of the child
|
||||
* @param child The child
|
||||
*/
|
||||
private void addChild(int index, FloatingChunkTreeNode<T> child){
|
||||
private void addChild(int index, WorldOctTreeNode<T> child){
|
||||
this.children.add(index, child);
|
||||
child.parent = this;
|
||||
}
|
||||
@ -437,7 +453,7 @@ public class WorldOctTree <T> {
|
||||
* Removes a child node
|
||||
* @param child the child
|
||||
*/
|
||||
private void removeChild(FloatingChunkTreeNode<T> child){
|
||||
private void removeChild(WorldOctTreeNode<T> child){
|
||||
this.children.remove(child);
|
||||
child.parent = null;
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import electrosphere.engine.Main;
|
||||
import electrosphere.server.terrain.manager.ServerTerrainChunk;
|
||||
import electrosphere.test.annotations.UnitTest;
|
||||
import electrosphere.test.template.extensions.StateCleanupCheckerExtension;
|
||||
import electrosphere.util.ds.octree.WorldOctTree.FloatingChunkTreeNode;
|
||||
import electrosphere.util.ds.octree.WorldOctTree.WorldOctTreeNode;
|
||||
|
||||
/**
|
||||
* Tests for the client draw cell manager
|
||||
@ -39,7 +39,7 @@ public class ClientDrawCellManagerTests {
|
||||
ClientDrawCellManager manager = new ClientDrawCellManager(null, 64);
|
||||
double precomputedMidDist = 0;
|
||||
Vector3i playerPos = new Vector3i(0,0,0);
|
||||
FloatingChunkTreeNode<DrawCell> node = FloatingChunkTreeNode.constructorForTests(manager.chunkTree, 1, new Vector3i(16,0,0), new Vector3i(32,16,16));
|
||||
WorldOctTreeNode<DrawCell> node = WorldOctTreeNode.constructorForTests(manager.chunkTree, 1, new Vector3i(16,0,0), new Vector3i(32,16,16));
|
||||
node.convertToLeaf(DrawCell.generateTerrainCell(new Vector3i(0,0,0),3));
|
||||
|
||||
assertTrue(manager.shouldSplit(playerPos, node, 0));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user