terrain optimizations
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
183c98367c
commit
8ddbe36b3d
@ -990,6 +990,13 @@ Split leaf/nonleaf tracks for node evaluation optimization
|
|||||||
|
|
||||||
(11/11/2024)
|
(11/11/2024)
|
||||||
Chunk data now stored/transmitted in 17 dim instead of 16 dim (Thereby cutting down on network/storage cost)
|
Chunk data now stored/transmitted in 17 dim instead of 16 dim (Thereby cutting down on network/storage cost)
|
||||||
|
Unique actor concept
|
||||||
|
Asset manager pipeline to destroy models/meshes/textures
|
||||||
|
Terrain model freeing on destruction
|
||||||
|
Potential physics destruction fix
|
||||||
|
Join propagation further up tree
|
||||||
|
Lower client cache size (to fight memory stalling)
|
||||||
|
Manual free button on memory debug window
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -153,7 +153,11 @@ public class ClientDrawCellManager {
|
|||||||
* @param worldDim The size of the world in chunks
|
* @param worldDim The size of the world in chunks
|
||||||
*/
|
*/
|
||||||
public ClientDrawCellManager(VoxelTextureAtlas voxelTextureAtlas, int worldDim){
|
public ClientDrawCellManager(VoxelTextureAtlas voxelTextureAtlas, int worldDim){
|
||||||
this.chunkTree = new WorldOctTree<DrawCell>(new Vector3i(0,0,0), new Vector3i(worldDim, worldDim, worldDim));
|
this.chunkTree = new WorldOctTree<DrawCell>(
|
||||||
|
new Vector3i(0,0,0),
|
||||||
|
new Vector3i(worldDim, worldDim, worldDim)
|
||||||
|
);
|
||||||
|
this.chunkTree.getRoot().setData(DrawCell.generateTerrainCell(new Vector3i(0,0,0), chunkTree.getMaxLevel()));
|
||||||
this.worldDim = worldDim;
|
this.worldDim = worldDim;
|
||||||
this.textureAtlas = voxelTextureAtlas;
|
this.textureAtlas = voxelTextureAtlas;
|
||||||
}
|
}
|
||||||
@ -222,7 +226,7 @@ public class ClientDrawCellManager {
|
|||||||
if(evaluationMap.containsKey(node)){
|
if(evaluationMap.containsKey(node)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(node.getData() != null && node.getData().hasGenerated() && node.getData().isHomogenous()){
|
if(node.getData().hasGenerated() && node.getData().isHomogenous()){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(node.isLeaf()){
|
if(node.isLeaf()){
|
||||||
@ -230,11 +234,7 @@ public class ClientDrawCellManager {
|
|||||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.split");
|
Globals.profiler.beginCpuSample("ClientDrawCellManager.split");
|
||||||
//perform op
|
//perform op
|
||||||
WorldOctTreeNode<DrawCell> container = chunkTree.split(node);
|
WorldOctTreeNode<DrawCell> container = chunkTree.split(node);
|
||||||
|
container.setData(DrawCell.generateTerrainCell(container.getMinBound(), this.chunkTree.getMaxLevel() - container.getLevel()));
|
||||||
//do deletions
|
|
||||||
this.twoLayerDestroy(node);
|
|
||||||
node.convertToLeaf(null);
|
|
||||||
|
|
||||||
|
|
||||||
//do creations
|
//do creations
|
||||||
container.getChildren().forEach(child -> {
|
container.getChildren().forEach(child -> {
|
||||||
@ -244,9 +244,13 @@ public class ClientDrawCellManager {
|
|||||||
child.getMinBound().z
|
child.getMinBound().z
|
||||||
);
|
);
|
||||||
DrawCell drawCell = DrawCell.generateTerrainCell(cellWorldPos,this.chunkTree.getMaxLevel() - child.getLevel());
|
DrawCell drawCell = DrawCell.generateTerrainCell(cellWorldPos,this.chunkTree.getMaxLevel() - child.getLevel());
|
||||||
child.convertToLeaf(drawCell);
|
child.setLeaf(true);
|
||||||
|
child.setData(drawCell);
|
||||||
evaluationMap.put(child,true);
|
evaluationMap.put(child,true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//do deletions
|
||||||
|
this.twoLayerDestroy(node);
|
||||||
|
|
||||||
//update neighbors
|
//update neighbors
|
||||||
this.conditionalUpdateAdjacentNodes(container, container.getChildren().get(0).getLevel());
|
this.conditionalUpdateAdjacentNodes(container, container.getChildren().get(0).getLevel());
|
||||||
@ -298,32 +302,24 @@ public class ClientDrawCellManager {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(this.shouldJoin(playerPos, node, distCache)) {
|
if(this.shouldJoin(playerPos, node, distCache)) {
|
||||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.join");
|
this.join(node);
|
||||||
//perform op
|
|
||||||
WorldOctTreeNode<DrawCell> newLeaf = chunkTree.join(node);
|
|
||||||
|
|
||||||
//do deletions
|
|
||||||
this.twoLayerDestroy(node);
|
|
||||||
|
|
||||||
//do creations
|
|
||||||
DrawCell drawCell = DrawCell.generateTerrainCell(node.getMinBound(),this.chunkTree.getMaxLevel() - newLeaf.getLevel());
|
|
||||||
newLeaf.convertToLeaf(drawCell);
|
|
||||||
|
|
||||||
//update neighbors
|
|
||||||
this.conditionalUpdateAdjacentNodes(newLeaf, newLeaf.getLevel());
|
|
||||||
evaluationMap.put(newLeaf,true);
|
|
||||||
|
|
||||||
Globals.profiler.endCpuSample();
|
|
||||||
updated = true;
|
updated = true;
|
||||||
} else {
|
} else {
|
||||||
this.validCellCount++;
|
this.validCellCount++;
|
||||||
List<WorldOctTreeNode<DrawCell>> children = node.getChildren();
|
List<WorldOctTreeNode<DrawCell>> children = node.getChildren();
|
||||||
|
boolean isHomogenous = true;
|
||||||
for(int i = 0; i < 8; i++){
|
for(int i = 0; i < 8; i++){
|
||||||
WorldOctTreeNode<DrawCell> child = children.get(i);
|
WorldOctTreeNode<DrawCell> child = children.get(i);
|
||||||
boolean childUpdate = recursivelyUpdateCells(child, playerPos, evaluationMap, minLeafLod, distCache);
|
boolean childUpdate = recursivelyUpdateCells(child, playerPos, evaluationMap, minLeafLod, distCache);
|
||||||
if(childUpdate == true){
|
if(childUpdate == true){
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
if(!child.getData().hasGenerated() || !child.getData().isHomogenous()){
|
||||||
|
isHomogenous = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(isHomogenous){
|
||||||
|
this.join(node);
|
||||||
}
|
}
|
||||||
if((this.chunkTree.getMaxLevel() - node.getLevel()) < minLeafLod){
|
if((this.chunkTree.getMaxLevel() - node.getLevel()) < minLeafLod){
|
||||||
evaluationMap.put(node,true);
|
evaluationMap.put(node,true);
|
||||||
@ -394,7 +390,7 @@ public class ClientDrawCellManager {
|
|||||||
return
|
return
|
||||||
node.canSplit() &&
|
node.canSplit() &&
|
||||||
(node.getLevel() != this.chunkTree.getMaxLevel()) &&
|
(node.getLevel() != this.chunkTree.getMaxLevel()) &&
|
||||||
(node.getData() == null || !node.getData().hasGenerated() || !node.getData().isHomogenous()) &&
|
(!node.getData().hasGenerated() || !node.getData().isHomogenous()) &&
|
||||||
(node.getParent() != null || node == this.chunkTree.getRoot()) &&
|
(node.getParent() != null || node == this.chunkTree.getRoot()) &&
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
@ -613,6 +609,25 @@ public class ClientDrawCellManager {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins a parent node
|
||||||
|
* @param node The parent node
|
||||||
|
*/
|
||||||
|
private void join(WorldOctTreeNode<DrawCell> node){
|
||||||
|
Globals.profiler.beginCpuSample("ClientDrawCellManager.join");
|
||||||
|
//perform op
|
||||||
|
WorldOctTreeNode<DrawCell> newLeaf = chunkTree.join(node, DrawCell.generateTerrainCell(node.getMinBound(),node.getData().lod));
|
||||||
|
|
||||||
|
//do deletions
|
||||||
|
this.twoLayerDestroy(node);
|
||||||
|
|
||||||
|
//update neighbors
|
||||||
|
this.conditionalUpdateAdjacentNodes(newLeaf, newLeaf.getLevel());
|
||||||
|
evaluationMap.put(newLeaf,true);
|
||||||
|
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this cell should request chunk data
|
* Checks if this cell should request chunk data
|
||||||
* @param pos the player's position
|
* @param pos the player's position
|
||||||
|
|||||||
@ -113,6 +113,21 @@ public class DrawCell {
|
|||||||
rVal.worldPos = worldPos;
|
rVal.worldPos = worldPos;
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a homogenous drawcell object
|
||||||
|
*/
|
||||||
|
public static DrawCell generateHomogenousTerrainCell(
|
||||||
|
Vector3i worldPos,
|
||||||
|
int lod
|
||||||
|
){
|
||||||
|
DrawCell rVal = new DrawCell();
|
||||||
|
rVal.lod = lod;
|
||||||
|
rVal.worldPos = worldPos;
|
||||||
|
rVal.hasGenerated = true;
|
||||||
|
rVal.homogenous = true;
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a drawable entity based on this chunk
|
* Generates a drawable entity based on this chunk
|
||||||
|
|||||||
@ -55,7 +55,7 @@ public class ClientTerrainManager {
|
|||||||
public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
|
public static final int INTERPOLATION_RATIO = ServerTerrainManager.SERVER_TERRAIN_MANAGER_INTERPOLATION_RATIO;
|
||||||
|
|
||||||
//caches chunks from server
|
//caches chunks from server
|
||||||
static final int CACHE_SIZE = 5000 + (int)(ClientDrawCellManager.FULL_RES_DIST * 10) + (int)(ClientDrawCellManager.HALF_RES_DIST * 10);
|
static final int CACHE_SIZE = 1000 + (int)(ClientDrawCellManager.FULL_RES_DIST * 10) + (int)(ClientDrawCellManager.HALF_RES_DIST * 10);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size of the cache in bytes
|
* Size of the cache in bytes
|
||||||
|
|||||||
@ -76,6 +76,9 @@ public class ImGuiMemory {
|
|||||||
ImGui.text("Total Memory: " + formatMemory(totalMemory));
|
ImGui.text("Total Memory: " + formatMemory(totalMemory));
|
||||||
ImGui.text("Free Memory: " + formatMemory(freeMemory));
|
ImGui.text("Free Memory: " + formatMemory(freeMemory));
|
||||||
ImGui.text("Memory Usage: " + formatMemory(memoryUsage));
|
ImGui.text("Memory Usage: " + formatMemory(memoryUsage));
|
||||||
|
if(ImGui.button("Manual free")){
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
//memory usage graph
|
//memory usage graph
|
||||||
memoryGraphDataset.addPoint(memoryUsage);
|
memoryGraphDataset.addPoint(memoryUsage);
|
||||||
|
|||||||
@ -704,12 +704,21 @@ public class CollisionEngine {
|
|||||||
if(bodies.contains(body)){
|
if(bodies.contains(body)){
|
||||||
bodies.remove(body);
|
bodies.remove(body);
|
||||||
}
|
}
|
||||||
|
//destroy all geometries
|
||||||
Iterator<DGeom> geomIterator = body.getGeomIterator();
|
Iterator<DGeom> geomIterator = body.getGeomIterator();
|
||||||
while(geomIterator.hasNext()){
|
while(geomIterator.hasNext()){
|
||||||
DGeom geom = geomIterator.next();
|
DGeom geom = geomIterator.next();
|
||||||
space.remove(geom);
|
space.remove(geom);
|
||||||
|
geom.DESTRUCTOR();
|
||||||
geom.destroy();
|
geom.destroy();
|
||||||
}
|
}
|
||||||
|
//destroy all joints
|
||||||
|
for(int i = 0; i < body.getNumJoints(); i++){
|
||||||
|
DJoint joint = body.getJoint(i);
|
||||||
|
joint.DESTRUCTOR();
|
||||||
|
joint.destroy();
|
||||||
|
}
|
||||||
|
//destroy actual body
|
||||||
body.destroy();
|
body.destroy();
|
||||||
spaceLock.release();
|
spaceLock.release();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -261,6 +261,8 @@ public class Main {
|
|||||||
Globals.profiler.beginCpuSample("Load Assets");
|
Globals.profiler.beginCpuSample("Load Assets");
|
||||||
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin load assets");
|
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin load assets");
|
||||||
Globals.assetManager.loadAssetsInQueue();
|
Globals.assetManager.loadAssetsInQueue();
|
||||||
|
LoggerInterface.loggerEngine.DEBUG_LOOP("Begin delete assets");
|
||||||
|
Globals.assetManager.deleteModelsInDeleteQueue();
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,7 @@ public class AssetManager {
|
|||||||
|
|
||||||
Map<String,Model> modelsLoadedIntoMemory = new ConcurrentHashMap<String,Model>();
|
Map<String,Model> modelsLoadedIntoMemory = new ConcurrentHashMap<String,Model>();
|
||||||
List<String> modelsInQueue = new CopyOnWriteArrayList<String>();
|
List<String> modelsInQueue = new CopyOnWriteArrayList<String>();
|
||||||
|
List<String> modelsInDeleteQueue = new CopyOnWriteArrayList<String>();
|
||||||
List<MeshShaderOverride> shaderOverrides = new CopyOnWriteArrayList<MeshShaderOverride>();
|
List<MeshShaderOverride> shaderOverrides = new CopyOnWriteArrayList<MeshShaderOverride>();
|
||||||
|
|
||||||
Map<String,Texture> texturesLoadedIntoMemory = new ConcurrentHashMap<String,Texture>();
|
Map<String,Texture> texturesLoadedIntoMemory = new ConcurrentHashMap<String,Texture>();
|
||||||
@ -179,7 +180,18 @@ public class AssetManager {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all models in the delete queue
|
||||||
|
*/
|
||||||
|
public void deleteModelsInDeleteQueue(){
|
||||||
|
for(String modelPath : modelsInDeleteQueue){
|
||||||
|
Model model = this.fetchModel(modelPath);
|
||||||
|
if(model != null){
|
||||||
|
model.delete();
|
||||||
|
}
|
||||||
|
this.modelsLoadedIntoMemory.remove(modelPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -203,6 +215,14 @@ public class AssetManager {
|
|||||||
}
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues a model for deletion
|
||||||
|
* @param modelPath The path to the model
|
||||||
|
*/
|
||||||
|
public void queueModelForDeletion(String modelPath){
|
||||||
|
modelsInDeleteQueue.add(modelPath);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Registers a (presumably generated in code) model with the asset manager
|
Registers a (presumably generated in code) model with the asset manager
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import org.joml.Vector3d;
|
|||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.state.attach.AttachUtils;
|
import electrosphere.entity.state.attach.AttachUtils;
|
||||||
import electrosphere.entity.types.collision.CollisionObjUtils;
|
import electrosphere.entity.types.collision.CollisionObjUtils;
|
||||||
|
import electrosphere.renderer.actor.ActorUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client only entity utility functions
|
* Client only entity utility functions
|
||||||
@ -42,6 +43,11 @@ public class ClientEntityUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//delete unique model if present
|
||||||
|
if(entity.containsKey(EntityDataStrings.HAS_UNIQUE_MODEL)){
|
||||||
|
ActorUtils.queueActorForDeletion(entity);
|
||||||
|
}
|
||||||
|
|
||||||
//check for client-specific stuff
|
//check for client-specific stuff
|
||||||
Globals.renderingEngine.getLightManager().destroyPointLight(entity);
|
Globals.renderingEngine.getLightManager().destroyPointLight(entity);
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class EntityDataStrings {
|
|||||||
public static final String INSTANCED_ACTOR = "instancedActor";
|
public static final String INSTANCED_ACTOR = "instancedActor";
|
||||||
public static final String DRAW_INSTANCED = "drawInstanced";
|
public static final String DRAW_INSTANCED = "drawInstanced";
|
||||||
public static final String TEXTURE_INSTANCED_ACTOR = "textureInstancedActor";
|
public static final String TEXTURE_INSTANCED_ACTOR = "textureInstancedActor";
|
||||||
|
public static final String HAS_UNIQUE_MODEL = "hasUniqueModel";
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -69,7 +69,7 @@ public class ClientEditorMovementTree implements BehaviorTree {
|
|||||||
static final double STATE_DIFFERENCE_CREEP_MULTIPLIER = 0.001; //while the movement tree is idle, slowly creep the position of the entity towards the true server position by this amount
|
static final double STATE_DIFFERENCE_CREEP_MULTIPLIER = 0.001; //while the movement tree is idle, slowly creep the position of the entity towards the true server position by this amount
|
||||||
static final double STATE_DIFFERENCE_CREEP_CUTOFF = 0.01; //the cutoff for creep when we say it's "close enough"
|
static final double STATE_DIFFERENCE_CREEP_CUTOFF = 0.01; //the cutoff for creep when we say it's "close enough"
|
||||||
|
|
||||||
public static final float EDITOR_MAX_VELOCITY = 0.5f;
|
public static final float EDITOR_MAX_VELOCITY = 1.0f;
|
||||||
public static final float EDITOR_ACCEL = 1.0f;
|
public static final float EDITOR_ACCEL = 1.0f;
|
||||||
|
|
||||||
String animationStartUp = Animation.ANIMATION_MOVEMENT_STARTUP;
|
String animationStartUp = Animation.ANIMATION_MOVEMENT_STARTUP;
|
||||||
|
|||||||
@ -61,6 +61,7 @@ public class TerrainChunk {
|
|||||||
EntityCreationUtils.bypassShadowPass(rVal);
|
EntityCreationUtils.bypassShadowPass(rVal);
|
||||||
EntityCreationUtils.bypassVolumetics(rVal);
|
EntityCreationUtils.bypassVolumetics(rVal);
|
||||||
}
|
}
|
||||||
|
rVal.putData(EntityDataStrings.HAS_UNIQUE_MODEL, true);
|
||||||
} else {
|
} else {
|
||||||
LoggerInterface.loggerEngine.WARNING("Finished generating terrain polygons; however, entity has already been deleted.");
|
LoggerInterface.loggerEngine.WARNING("Finished generating terrain polygons; however, entity has already been deleted.");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,5 +40,13 @@ public class ActorUtils {
|
|||||||
return entityActor.getStaticMorph();
|
return entityActor.getStaticMorph();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues the model underlying an actor for deletion
|
||||||
|
* @param actorEntity The entity
|
||||||
|
*/
|
||||||
|
public static void queueActorForDeletion(Entity actorEntity){
|
||||||
|
Actor actor = EntityUtils.getActor(actorEntity);
|
||||||
|
Globals.assetManager.queueModelForDeletion(actor.getModelPath());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import electrosphere.engine.Globals;
|
|||||||
import electrosphere.renderer.OpenGLState;
|
import electrosphere.renderer.OpenGLState;
|
||||||
import electrosphere.renderer.texture.Texture;
|
import electrosphere.renderer.texture.Texture;
|
||||||
import org.lwjgl.assimp.AIMaterial;
|
import org.lwjgl.assimp.AIMaterial;
|
||||||
|
import org.lwjgl.opengl.GL40;
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||||
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
|
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
|
||||||
|
|
||||||
@ -138,4 +140,14 @@ public class Material {
|
|||||||
}
|
}
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the material
|
||||||
|
*/
|
||||||
|
public void free(){
|
||||||
|
GL40.glDeleteTextures(new int[]{
|
||||||
|
this.texturePointer,
|
||||||
|
this.normalPointer,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,6 +112,21 @@ public class Mesh {
|
|||||||
vertexArrayObject = glGenVertexArrays();
|
vertexArrayObject = glGenVertexArrays();
|
||||||
glBindVertexArray(vertexArrayObject);
|
glBindVertexArray(vertexArrayObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees this mesh
|
||||||
|
*/
|
||||||
|
public void free(){
|
||||||
|
GL40.glDeleteBuffers(new int[]{
|
||||||
|
vertexBuffer,
|
||||||
|
normalBuffer,
|
||||||
|
elementArrayBuffer,
|
||||||
|
boneWeightBuffer,
|
||||||
|
boneIndexBuffer,
|
||||||
|
textureCoordBuffer,
|
||||||
|
});
|
||||||
|
GL40.glDeleteVertexArrays(vertexArrayObject);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffers vertex data to the gpu under this mesh container
|
* Buffers vertex data to the gpu under this mesh container
|
||||||
|
|||||||
@ -293,6 +293,18 @@ public class Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes this model
|
||||||
|
*/
|
||||||
|
public void delete(){
|
||||||
|
for(Mesh mesh : this.meshes){
|
||||||
|
mesh.free();
|
||||||
|
}
|
||||||
|
for(Material material : this.materials){
|
||||||
|
material.free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs all animations for a given model
|
* Logs all animations for a given model
|
||||||
|
|||||||
@ -62,7 +62,7 @@ public class WorldOctTree <T> {
|
|||||||
this.maxLevel = (int)MathUtils.log2(dimRaw);
|
this.maxLevel = (int)MathUtils.log2(dimRaw);
|
||||||
this.nodes = new ArrayList<WorldOctTreeNode<T>>();
|
this.nodes = new ArrayList<WorldOctTreeNode<T>>();
|
||||||
this.root = new WorldOctTreeNode<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.root.setLeaf(true);
|
||||||
this.nodes.add(this.root);
|
this.nodes.add(this.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,9 +124,10 @@ public class WorldOctTree <T> {
|
|||||||
/**
|
/**
|
||||||
* Joins a non-leaf node's children into a single node
|
* Joins a non-leaf node's children into a single node
|
||||||
* @param parent The non-leaf
|
* @param parent The non-leaf
|
||||||
|
* @param data The container's data
|
||||||
* @return The new leaf node
|
* @return The new leaf node
|
||||||
*/
|
*/
|
||||||
public WorldOctTreeNode<T> join(WorldOctTreeNode<T> existing){
|
public WorldOctTreeNode<T> join(WorldOctTreeNode<T> existing, T data){
|
||||||
if(existing.isLeaf()){
|
if(existing.isLeaf()){
|
||||||
throw new IllegalArgumentException("Tried to split non-leaf!");
|
throw new IllegalArgumentException("Tried to split non-leaf!");
|
||||||
}
|
}
|
||||||
@ -134,6 +135,8 @@ public class WorldOctTree <T> {
|
|||||||
Vector3i max = existing.getMaxBound();
|
Vector3i max = existing.getMaxBound();
|
||||||
int currentLevel = existing.getLevel();
|
int currentLevel = existing.getLevel();
|
||||||
WorldOctTreeNode<T> newContainer = new WorldOctTreeNode<>(this, currentLevel, min, max);
|
WorldOctTreeNode<T> newContainer = new WorldOctTreeNode<>(this, currentLevel, min, max);
|
||||||
|
newContainer.setData(data);
|
||||||
|
newContainer.setLeaf(true);
|
||||||
|
|
||||||
//replace existing node
|
//replace existing node
|
||||||
this.replaceNode(existing,newContainer);
|
this.replaceNode(existing,newContainer);
|
||||||
@ -344,15 +347,6 @@ public class WorldOctTree <T> {
|
|||||||
return new WorldOctTreeNode<T>(tree, level, min, max);
|
return new WorldOctTreeNode<T>(tree, level, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts this node to a leaf
|
|
||||||
* @param data The data to put in the leaf
|
|
||||||
*/
|
|
||||||
public void convertToLeaf(T data){
|
|
||||||
this.isLeaf = true;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether this node is a leaf or not
|
* Sets whether this node is a leaf or not
|
||||||
* @param isLeaf true if it is a leaf, false otherwise
|
* @param isLeaf true if it is a leaf, false otherwise
|
||||||
|
|||||||
@ -37,10 +37,10 @@ public class ClientDrawCellManagerTests {
|
|||||||
int worldDiscreteSize = 64;
|
int worldDiscreteSize = 64;
|
||||||
Globals.clientWorldData = new ClientWorldData(new Vector3f(0), new Vector3f(worldDiscreteSize * ServerTerrainChunk.CHUNK_DIMENSION), 0, worldDiscreteSize);
|
Globals.clientWorldData = new ClientWorldData(new Vector3f(0), new Vector3f(worldDiscreteSize * ServerTerrainChunk.CHUNK_DIMENSION), 0, worldDiscreteSize);
|
||||||
ClientDrawCellManager manager = new ClientDrawCellManager(null, 64);
|
ClientDrawCellManager manager = new ClientDrawCellManager(null, 64);
|
||||||
double precomputedMidDist = 0;
|
|
||||||
Vector3i playerPos = new Vector3i(0,0,0);
|
Vector3i playerPos = new Vector3i(0,0,0);
|
||||||
WorldOctTreeNode<DrawCell> node = WorldOctTreeNode.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));
|
node.setLeaf(true);
|
||||||
|
node.setData(DrawCell.generateTerrainCell(new Vector3i(0,0,0),3));
|
||||||
|
|
||||||
assertTrue(manager.shouldSplit(playerPos, node, 0));
|
assertTrue(manager.shouldSplit(playerPos, node, 0));
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user