foliage manager fixes
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
742c606540
commit
8430439509
@ -61,15 +61,19 @@ public class ClientFoliageManager {
|
|||||||
for(int x = -chunkRadius; x < chunkRadius+1; x++){
|
for(int x = -chunkRadius; x < chunkRadius+1; x++){
|
||||||
for(int y = -chunkRadius; y < chunkRadius+1; y++){
|
for(int y = -chunkRadius; y < chunkRadius+1; y++){
|
||||||
for(int z = -chunkRadius; z < chunkRadius+1; z++){
|
for(int z = -chunkRadius; z < chunkRadius+1; z++){
|
||||||
Vector3i worldPos = Globals.clientWorldData.convertRealToWorldSpace(EntityUtils.getPosition(Globals.playerEntity));
|
Vector3i worldPos = Globals.clientWorldData.convertRealToWorldSpace(EntityUtils.getPosition(Globals.playerEntity)).add(x,y,z);
|
||||||
updatePosition(worldPos);
|
if(Globals.clientWorldData.worldPosInBounds(worldPos)){
|
||||||
|
this.updatePosition(worldPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Globals.profiler.beginCpuSample("ClientFoliageManager.update - destroy chunks");
|
||||||
for(FoliageChunk chunk : this.chunkUpdateCache){
|
for(FoliageChunk chunk : this.chunkUpdateCache){
|
||||||
chunk.destroy();
|
chunk.destroy();
|
||||||
}
|
}
|
||||||
this.chunkUpdateCache.clear();
|
this.chunkUpdateCache.clear();
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,8 +22,6 @@ import electrosphere.client.terrain.cache.ChunkData;
|
|||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityCreationUtils;
|
import electrosphere.entity.EntityCreationUtils;
|
||||||
import electrosphere.entity.EntityDataStrings;
|
|
||||||
import electrosphere.entity.EntityTags;
|
|
||||||
import electrosphere.entity.EntityUtils;
|
import electrosphere.entity.EntityUtils;
|
||||||
import electrosphere.entity.state.foliage.AmbientFoliage;
|
import electrosphere.entity.state.foliage.AmbientFoliage;
|
||||||
import electrosphere.entity.types.camera.CameraEntityUtils;
|
import electrosphere.entity.types.camera.CameraEntityUtils;
|
||||||
@ -344,7 +342,7 @@ public class FoliageCell {
|
|||||||
EntityUtils.getRotation(grassEntity).set(0,0,0,1);
|
EntityUtils.getRotation(grassEntity).set(0,0,0,1);
|
||||||
EntityUtils.getScale(grassEntity).set(1,1,1);
|
EntityUtils.getScale(grassEntity).set(1,1,1);
|
||||||
//add ambient foliage behavior tree
|
//add ambient foliage behavior tree
|
||||||
AmbientFoliage.attachAmbientFoliageTree(grassEntity, 0.0f, foliageType.getGrowthModel().getGrowthRate());
|
AmbientFoliage.attachAmbientFoliageTree(grassEntity, 1.0f, foliageType.getGrowthModel().getGrowthRate());
|
||||||
this.addEntity(grassEntity);
|
this.addEntity(grassEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -384,9 +382,9 @@ public class FoliageCell {
|
|||||||
RenderPipelineState renderPipelineState = Globals.renderingEngine.getRenderPipelineState();
|
RenderPipelineState renderPipelineState = Globals.renderingEngine.getRenderPipelineState();
|
||||||
OpenGLState openGLState = Globals.renderingEngine.getOpenGLState();
|
OpenGLState openGLState = Globals.renderingEngine.getOpenGLState();
|
||||||
|
|
||||||
Vector3f cameraModifiedPosition = new Vector3f((float)realPosition.x,(float)realPosition.y,(float)realPosition.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
|
Vector3f cameraModifiedPosition = new Vector3f((float)realPosition.x,(float)realPosition.y,(float)realPosition.z).sub(cameraCenter);
|
||||||
//frustum check entire cell
|
//frustum check entire cell
|
||||||
boolean shouldRender = true;//renderPipelineState.getFrustumIntersection().testSphere((float)(cameraModifiedPosition.x + boundingSphere.x), (float)(cameraModifiedPosition.y + boundingSphere.y), (float)(cameraModifiedPosition.z + boundingSphere.z), (float)(boundingSphere.r));
|
boolean shouldRender = renderPipelineState.getFrustumIntersection().testSphere((float)(cameraModifiedPosition.x + boundingSphere.x), (float)(cameraModifiedPosition.y + boundingSphere.y), (float)(cameraModifiedPosition.z + boundingSphere.z), (float)(boundingSphere.r));
|
||||||
if(shouldRender){
|
if(shouldRender){
|
||||||
//disable frustum check and instead perform at cell level
|
//disable frustum check and instead perform at cell level
|
||||||
boolean currentFrustumCheckState = renderPipelineState.shouldFrustumCheck();
|
boolean currentFrustumCheckState = renderPipelineState.shouldFrustumCheck();
|
||||||
@ -398,7 +396,7 @@ public class FoliageCell {
|
|||||||
|
|
||||||
|
|
||||||
modelMatrix = modelMatrix.identity();
|
modelMatrix = modelMatrix.identity();
|
||||||
cameraModifiedPosition = new Vector3f((float)grassPosition.x,(float)grassPosition.y,(float)grassPosition.z).sub(cameraCenter);
|
// cameraModifiedPosition = new Vector3f((float)grassPosition.x,(float)grassPosition.y,(float)grassPosition.z).sub(cameraCenter);
|
||||||
modelMatrix.translate(cameraModifiedPosition);
|
modelMatrix.translate(cameraModifiedPosition);
|
||||||
modelMatrix.rotate(new Quaterniond(grassRotation));
|
modelMatrix.rotate(new Quaterniond(grassRotation));
|
||||||
modelMatrix.scale(new Vector3d(EntityUtils.getScale(entity)));
|
modelMatrix.scale(new Vector3d(EntityUtils.getScale(entity)));
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package electrosphere.client.foliagemanager;
|
package electrosphere.client.foliagemanager;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3i;
|
import org.joml.Vector3i;
|
||||||
@ -65,80 +64,100 @@ public class FoliageChunk {
|
|||||||
* Initializes all cells in the chunk
|
* Initializes all cells in the chunk
|
||||||
*/
|
*/
|
||||||
public void initCells(){
|
public void initCells(){
|
||||||
Vector3d playerPos = EntityUtils.getPosition(Globals.playerEntity);
|
Globals.profiler.beginCpuSample("FoliageChunk.initCells");
|
||||||
this.currentChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos);
|
this.currentChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(worldPos);
|
||||||
// //evaluate top cells if chunk above this one exists
|
// //evaluate top cells if chunk above this one exists
|
||||||
this.aboveChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i(worldPos).add(0,1,0));
|
this.aboveChunkData = Globals.clientTerrainManager.getChunkDataAtWorldPoint(new Vector3i(worldPos).add(0,1,0));
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
//the sets to iterate through
|
|
||||||
ChunkTreeNode<FoliageCell> rootNode = this.chunkTree.getRoot();
|
|
||||||
List<ChunkTreeNode<FoliageCell>> openSet = new LinkedList<ChunkTreeNode<FoliageCell>>();
|
|
||||||
List<ChunkTreeNode<FoliageCell>> toInit = new LinkedList<ChunkTreeNode<FoliageCell>>();
|
|
||||||
openSet.add(rootNode);
|
|
||||||
|
|
||||||
//split into nodes
|
|
||||||
while(openSet.size() > 0){
|
|
||||||
ChunkTreeNode<FoliageCell> current = openSet.remove(0);
|
|
||||||
if(this.shouldSplit(playerPos, current)){
|
|
||||||
//add children for this one
|
|
||||||
ChunkTreeNode<FoliageCell> container = chunkTree.split(current);
|
|
||||||
openSet.addAll(container.getChildren());
|
|
||||||
} else {
|
|
||||||
//do nothing
|
|
||||||
toInit.add(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//init end-nodes as leaves
|
|
||||||
for(ChunkTreeNode<FoliageCell> current : toInit){
|
|
||||||
Vector3d realPos = Globals.clientWorldData.convertWorldToRealSpace(worldPos).add(new Vector3d(current.getMinBound()));
|
|
||||||
current.convertToLeaf(new FoliageCell(worldPos, current.getMinBound(), realPos, 4 - current.getLevel(), 1.0f));
|
|
||||||
current.getData().generate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates all cells in the chunk
|
* Updates all cells in the chunk
|
||||||
*/
|
*/
|
||||||
public void updateCells(){
|
public void updateCells(){
|
||||||
|
Globals.profiler.beginCpuSample("FoliageChunk.updateCells");
|
||||||
Vector3d playerPos = EntityUtils.getPosition(Globals.playerEntity);
|
Vector3d playerPos = EntityUtils.getPosition(Globals.playerEntity);
|
||||||
//the sets to iterate through
|
//the sets to iterate through
|
||||||
ChunkTreeNode<FoliageCell> rootNode = this.chunkTree.getRoot();
|
ChunkTreeNode<FoliageCell> rootNode = this.chunkTree.getRoot();
|
||||||
List<ChunkTreeNode<FoliageCell>> openSet = new LinkedList<ChunkTreeNode<FoliageCell>>();
|
this.recursivelyUpdateCells(rootNode, playerPos);
|
||||||
List<ChunkTreeNode<FoliageCell>> toInit = new LinkedList<ChunkTreeNode<FoliageCell>>();
|
|
||||||
List<ChunkTreeNode<FoliageCell>> toCleanup = new LinkedList<ChunkTreeNode<FoliageCell>>();
|
|
||||||
openSet.add(rootNode);
|
|
||||||
//split into nodes
|
//split into nodes
|
||||||
while(openSet.size() > 0){
|
// Globals.profiler.beginCpuSample("FoliageChunk.updateCells - evaluate split/join");
|
||||||
ChunkTreeNode<FoliageCell> current = openSet.remove(0);
|
// while(openSet.size() > 0){
|
||||||
|
// ChunkTreeNode<FoliageCell> current = openSet.remove(0);
|
||||||
|
|
||||||
if(this.shouldSplit(playerPos, current)){
|
// if(this.shouldSplit(playerPos, current)){
|
||||||
//add children for this one
|
// //add children for this one
|
||||||
ChunkTreeNode<FoliageCell> container = chunkTree.split(current);
|
// ChunkTreeNode<FoliageCell> container = chunkTree.split(current);
|
||||||
toInit.addAll(container.getChildren());
|
// toInit.addAll(container.getChildren());
|
||||||
toCleanup.add(current);
|
// toCleanup.add(current);
|
||||||
} else if(this.shouldJoin(playerPos, current)) {
|
// } else if(this.shouldJoin(playerPos, current)) {
|
||||||
//add children for this one
|
// //add children for this one
|
||||||
ChunkTreeNode<FoliageCell> newLeaf = chunkTree.join(current);
|
// ChunkTreeNode<FoliageCell> newLeaf = chunkTree.join(current);
|
||||||
toCleanup.addAll(current.getChildren());
|
// toCleanup.addAll(current.getChildren());
|
||||||
toCleanup.add(current);
|
// toCleanup.add(current);
|
||||||
toInit.add(newLeaf);
|
// toInit.add(newLeaf);
|
||||||
} else if(!current.isLeaf()){
|
// } else if(!current.isLeaf()){
|
||||||
openSet.addAll(current.getChildren());
|
// openSet.addAll(current.getChildren());
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// Globals.profiler.endCpuSample();
|
||||||
|
// Globals.profiler.beginCpuSample("FoliageChunk.updateCells - generate");
|
||||||
|
// //init end-nodes as leaves
|
||||||
|
// for(ChunkTreeNode<FoliageCell> current : toInit){
|
||||||
|
// Vector3d realPos = Globals.clientWorldData.convertWorldToRealSpace(worldPos).add(new Vector3d(current.getMinBound()));
|
||||||
|
// current.convertToLeaf(new FoliageCell(worldPos, current.getMinBound(), realPos, 5 - current.getLevel(), 1.0f));
|
||||||
|
// if(this.shouldGenerate(playerPos,current)){
|
||||||
|
// current.getData().generate();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Globals.profiler.endCpuSample();
|
||||||
|
// Globals.profiler.beginCpuSample("FoliageChunk.updateCells - destroy");
|
||||||
|
// //destroy orphan nodes
|
||||||
|
// for(ChunkTreeNode<FoliageCell> current : toCleanup){
|
||||||
|
// if(current.getData() != null){
|
||||||
|
// current.getData().destroy();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Globals.profiler.endCpuSample();
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively update child nodes
|
||||||
|
* @param node The root node
|
||||||
|
* @param playerPos The player's position
|
||||||
|
*/
|
||||||
|
private void recursivelyUpdateCells(ChunkTreeNode<FoliageCell> node, Vector3d playerPos){
|
||||||
|
if(this.shouldSplit(playerPos, node)){
|
||||||
|
//perform op
|
||||||
|
ChunkTreeNode<FoliageCell> container = chunkTree.split(node);
|
||||||
|
|
||||||
|
//do deletions
|
||||||
|
this.recursivelyDestroy(node);
|
||||||
|
|
||||||
|
//do creations
|
||||||
|
container.getChildren().forEach(child -> {
|
||||||
|
Vector3d realPos = new Vector3d(
|
||||||
|
worldPos.x * ChunkData.CHUNK_SIZE + child.getMinBound().x,
|
||||||
|
worldPos.y * ChunkData.CHUNK_SIZE + child.getMinBound().y,
|
||||||
|
worldPos.z * ChunkData.CHUNK_SIZE + child.getMinBound().z
|
||||||
|
);
|
||||||
|
child.convertToLeaf(new FoliageCell(worldPos, child.getMinBound(), realPos, 5 - child.getLevel(), 1.0f));
|
||||||
|
});
|
||||||
|
} else if(this.shouldJoin(playerPos, node)) {
|
||||||
|
//perform op
|
||||||
|
ChunkTreeNode<FoliageCell> newLeaf = chunkTree.join(node);
|
||||||
|
|
||||||
|
//do deletions
|
||||||
|
this.recursivelyDestroy(node);
|
||||||
|
|
||||||
|
//do creations
|
||||||
|
newLeaf.convertToLeaf(new FoliageCell(worldPos, newLeaf.getMinBound(), realPos, 5 - newLeaf.getLevel(), 1.0f));
|
||||||
|
} else if(shouldGenerate(playerPos, node)){
|
||||||
|
node.getData().generate();
|
||||||
|
} else if(!node.isLeaf()){
|
||||||
|
new LinkedList<>(node.getChildren()).forEach(child -> recursivelyUpdateCells(child, playerPos));
|
||||||
}
|
}
|
||||||
//init end-nodes as leaves
|
|
||||||
for(ChunkTreeNode<FoliageCell> current : toInit){
|
|
||||||
Vector3d realPos = Globals.clientWorldData.convertWorldToRealSpace(worldPos).add(new Vector3d(current.getMinBound()));
|
|
||||||
current.convertToLeaf(new FoliageCell(worldPos, current.getMinBound(), realPos, 5 - current.getLevel(), 1.0f));
|
|
||||||
current.getData().generate();
|
|
||||||
}
|
|
||||||
//destroy orphan nodes
|
|
||||||
for(ChunkTreeNode<FoliageCell> current : toCleanup){
|
|
||||||
if(current.getData() != null){
|
|
||||||
current.getData().destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,9 +215,11 @@ public class FoliageChunk {
|
|||||||
public boolean shouldSplit(Vector3d pos, ChunkTreeNode<FoliageCell> node){
|
public boolean shouldSplit(Vector3d pos, ChunkTreeNode<FoliageCell> node){
|
||||||
//breaking out into dedicated function so can add case handling ie if we want
|
//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
|
//to combine fullres nodes into larger nodes to conserve on draw calls
|
||||||
return this.getMinDistance(pos, node) <= FULL_RES_DIST &&
|
return
|
||||||
node.isLeaf() &&
|
node.isLeaf() &&
|
||||||
node.canSplit()
|
node.getLevel() < ChunkTree.MAX_LEVEL &&
|
||||||
|
node.canSplit() &&
|
||||||
|
this.getMinDistance(pos, node) <= FULL_RES_DIST
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,17 +232,56 @@ public class FoliageChunk {
|
|||||||
public boolean shouldJoin(Vector3d pos, ChunkTreeNode<FoliageCell> node){
|
public boolean shouldJoin(Vector3d pos, ChunkTreeNode<FoliageCell> node){
|
||||||
//breaking out into dedicated function so can add case handling ie if we want
|
//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
|
//to combine fullres nodes into larger nodes to conserve on draw calls
|
||||||
return this.getMinDistance(pos, node) > FULL_RES_DIST &&
|
return
|
||||||
!node.isLeaf()
|
node.getLevel() > 0 &&
|
||||||
|
!node.isLeaf() &&
|
||||||
|
this.getMinDistance(pos, node) > FULL_RES_DIST
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this cell should generate
|
||||||
|
* @param pos the player's position
|
||||||
|
* @param node the node
|
||||||
|
* @return true if should generate, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean shouldGenerate(Vector3d pos, ChunkTreeNode<FoliageCell> node){
|
||||||
|
return
|
||||||
|
node.getLevel() == ChunkTree.MAX_LEVEL &&
|
||||||
|
node.isLeaf() &&
|
||||||
|
node.getData() != null &&
|
||||||
|
node.getData().containedEntities.size() < 1 &&
|
||||||
|
this.getMinDistance(pos, node) <= FULL_RES_DIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the node should have destroy called on it
|
||||||
|
* @param node The node
|
||||||
|
* @return true if should destroy, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean shouldDestroy(ChunkTreeNode<FoliageCell> node){
|
||||||
|
return
|
||||||
|
node.getData() != null &&
|
||||||
|
node.getData().containedEntities.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the foliage chunk
|
* Destroys the foliage chunk
|
||||||
*/
|
*/
|
||||||
protected void destroy(){
|
protected void destroy(){
|
||||||
for(ChunkTreeNode<FoliageCell> leaf : this.chunkTree.getLeaves()){
|
this.recursivelyDestroy(this.chunkTree.getRoot());
|
||||||
leaf.getData().destroy();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively destroy a tree
|
||||||
|
* @param node The root of the tree
|
||||||
|
*/
|
||||||
|
private void recursivelyDestroy(ChunkTreeNode<FoliageCell> node){
|
||||||
|
if(node.getChildren().size() > 0){
|
||||||
|
node.getChildren().forEach(child -> recursivelyDestroy(child));
|
||||||
|
}
|
||||||
|
if(node.getData() != null){
|
||||||
|
node.getData().destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,8 +289,19 @@ public class FoliageChunk {
|
|||||||
* Draws all cells in the chunk
|
* Draws all cells in the chunk
|
||||||
*/
|
*/
|
||||||
protected void draw(){
|
protected void draw(){
|
||||||
for(ChunkTreeNode<FoliageCell> leaf : this.chunkTree.getLeaves()){
|
recursivelyDraw(this.chunkTree.getRoot());
|
||||||
leaf.getData().draw();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively draws all nodes
|
||||||
|
* @param node The root node
|
||||||
|
*/
|
||||||
|
private void recursivelyDraw(ChunkTreeNode<FoliageCell> node){
|
||||||
|
if(node.getChildren().size() > 0){
|
||||||
|
node.getChildren().forEach(child -> recursivelyDraw(child));
|
||||||
|
}
|
||||||
|
if(node.getData() != null){
|
||||||
|
node.getData().draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -93,6 +93,21 @@ public class ClientWorldData {
|
|||||||
return convertChunkToRealSpace(world);
|
return convertChunkToRealSpace(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a world position is in bounds or not
|
||||||
|
* @param worldPos The world position
|
||||||
|
* @return true if is in bounds, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean worldPosInBounds(Vector3i worldPos){
|
||||||
|
return worldPos.x >= convertRealToWorld(worldMinPoint.x) &&
|
||||||
|
worldPos.x < convertRealToWorld(worldMaxPoint.x) &&
|
||||||
|
worldPos.y >= convertRealToWorld(worldMinPoint.y) &&
|
||||||
|
worldPos.y < convertRealToWorld(worldMaxPoint.y) &&
|
||||||
|
worldPos.z >= convertRealToWorld(worldMinPoint.z) &&
|
||||||
|
worldPos.z < convertRealToWorld(worldMaxPoint.z)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a real space position to its world space equivalent
|
* Converts a real space position to its world space equivalent
|
||||||
* @param position The real space position
|
* @param position The real space position
|
||||||
|
|||||||
@ -447,6 +447,10 @@ public class Main {
|
|||||||
if(Globals.netMonitor != null){
|
if(Globals.netMonitor != null){
|
||||||
Globals.netMonitor.close();
|
Globals.netMonitor.close();
|
||||||
}
|
}
|
||||||
|
//shutdown profiler
|
||||||
|
if(Globals.profiler != null){
|
||||||
|
Globals.profiler.destroy();
|
||||||
|
}
|
||||||
//shutdown ode
|
//shutdown ode
|
||||||
if(initOde){
|
if(initOde){
|
||||||
OdeHelper.closeODE();
|
OdeHelper.closeODE();
|
||||||
|
|||||||
@ -69,4 +69,13 @@ public class Profiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the profiler
|
||||||
|
*/
|
||||||
|
public void destroy(){
|
||||||
|
if(PROFILE){
|
||||||
|
Remotery.rmt_DestroyGlobalInstance(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {
|
|||||||
Globals.clientWorldData = new ClientWorldData(
|
Globals.clientWorldData = new ClientWorldData(
|
||||||
//Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize
|
//Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize
|
||||||
new Vector3f(message.getworldMinX(),0,message.getworldMinY()),
|
new Vector3f(message.getworldMinX(),0,message.getworldMinY()),
|
||||||
new Vector3f(message.getworldMaxX(),3,message.getworldMaxY()),
|
new Vector3f(message.getworldMaxX(),32,message.getworldMaxY()),
|
||||||
ChunkData.CHUNK_SIZE,
|
ChunkData.CHUNK_SIZE,
|
||||||
message.getrandomDampener(),
|
message.getrandomDampener(),
|
||||||
message.getworldSizeDiscrete()
|
message.getworldSizeDiscrete()
|
||||||
|
|||||||
@ -126,21 +126,6 @@ public class ChunkTree<T> {
|
|||||||
return this.root;
|
return this.root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of leaves in the tree
|
|
||||||
*/
|
|
||||||
public int getNumLeaves() {
|
|
||||||
return this.getLeaves().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all leaf nodes
|
|
||||||
* @return All leaf nodes
|
|
||||||
*/
|
|
||||||
public List<ChunkTreeNode<T>> getLeaves(){
|
|
||||||
return this.nodes.stream().filter(node -> node.isLeaf()).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in a chunk tree
|
* A node in a chunk tree
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
package electrosphere.util.ds.octree;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit testing for the chunk octree implementation
|
||||||
|
*/
|
||||||
|
public class ChunkTreeTests {
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user