Voxel system improvements
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
596b0f6624
commit
a44255060d
@ -1061,6 +1061,10 @@ Fix hitbox destruction logic to not double-delete
|
|||||||
|
|
||||||
(11/17/2024)
|
(11/17/2024)
|
||||||
Mountain generation work
|
Mountain generation work
|
||||||
|
Fix flickering chunks on unload
|
||||||
|
Fix draw cell distance cache busting on far distances
|
||||||
|
Fix skybox not updating position with player entity
|
||||||
|
Add Scene shorthand for registering runnables as behavior trees
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -209,7 +209,8 @@ 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()));
|
DrawCell containerCell = DrawCell.generateTerrainCell(container.getMinBound(), this.chunkTree.getMaxLevel() - container.getLevel());
|
||||||
|
container.setData(containerCell);
|
||||||
container.getData().transferChunkData(node.getData());
|
container.getData().transferChunkData(node.getData());
|
||||||
|
|
||||||
//do creations
|
//do creations
|
||||||
@ -220,6 +221,7 @@ 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());
|
||||||
|
drawCell.registerNotificationTarget(node.getData());
|
||||||
child.setLeaf(true);
|
child.setLeaf(true);
|
||||||
child.setData(drawCell);
|
child.setData(drawCell);
|
||||||
evaluationMap.put(child,true);
|
evaluationMap.put(child,true);
|
||||||
@ -233,13 +235,13 @@ public class ClientDrawCellManager {
|
|||||||
|
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if(shouldRequest(playerPos, node, minLeafLod, distCache)){
|
} else if(this.shouldRequest(playerPos, node, minLeafLod, distCache)){
|
||||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.request");
|
Globals.profiler.beginCpuSample("ClientDrawCellManager.request");
|
||||||
|
|
||||||
//calculate what to request
|
//calculate what to request
|
||||||
DrawCell cell = node.getData();
|
DrawCell cell = node.getData();
|
||||||
List<DrawCellFace> highResFaces = null;
|
List<DrawCellFace> highResFaces = null;
|
||||||
if(shouldSolveFaces(node,playerPos, distCache)){
|
if(this.shouldSolveFaces(node,playerPos, distCache)){
|
||||||
highResFaces = this.solveHighResFace(node);
|
highResFaces = this.solveHighResFace(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,17 +253,17 @@ public class ClientDrawCellManager {
|
|||||||
|
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if(shouldGenerate(playerPos, node, minLeafLod, distCache)){
|
} else if(this.shouldGenerate(playerPos, node, minLeafLod, distCache)){
|
||||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.generate");
|
Globals.profiler.beginCpuSample("ClientDrawCellManager.generate");
|
||||||
int lodLevel = this.getLODLevel(node);
|
int lodLevel = this.getLODLevel(node);
|
||||||
|
|
||||||
//high res faces
|
//high res faces
|
||||||
List<DrawCellFace> highResFaces = null;
|
List<DrawCellFace> highResFaces = null;
|
||||||
if(shouldSolveFaces(node,playerPos, distCache)){
|
if(this.shouldSolveFaces(node,playerPos, distCache)){
|
||||||
highResFaces = this.solveHighResFace(node);
|
highResFaces = this.solveHighResFace(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(containsDataToGenerate(node,highResFaces)){
|
if(this.containsDataToGenerate(node,highResFaces)){
|
||||||
node.getData().generateDrawableEntity(textureAtlas, lodLevel, highResFaces);
|
node.getData().generateDrawableEntity(textureAtlas, lodLevel, highResFaces);
|
||||||
if(node.getData().getFailedGenerationAttempts() > FAILED_GENERATION_ATTEMPT_THRESHOLD){
|
if(node.getData().getFailedGenerationAttempts() > FAILED_GENERATION_ATTEMPT_THRESHOLD){
|
||||||
node.getData().setHasRequested(false);
|
node.getData().setHasRequested(false);
|
||||||
@ -284,21 +286,28 @@ public class ClientDrawCellManager {
|
|||||||
this.validCellCount++;
|
this.validCellCount++;
|
||||||
List<WorldOctTreeNode<DrawCell>> children = node.getChildren();
|
List<WorldOctTreeNode<DrawCell>> children = node.getChildren();
|
||||||
boolean isHomogenous = true;
|
boolean isHomogenous = true;
|
||||||
|
boolean fullyGenerated = 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 = this.recursivelyUpdateCells(child, playerPos, evaluationMap, minLeafLod, distCache);
|
||||||
if(childUpdate == true){
|
if(childUpdate == true){
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
if(!child.getData().hasGenerated() || !child.getData().isHomogenous()){
|
if(!child.getData().hasGenerated()){
|
||||||
|
fullyGenerated = false;
|
||||||
|
}
|
||||||
|
if(!child.getData().isHomogenous()){
|
||||||
isHomogenous = false;
|
isHomogenous = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
WorldOctTreeNode<DrawCell> newNode = null;
|
||||||
if(isHomogenous){
|
if(isHomogenous){
|
||||||
WorldOctTreeNode<DrawCell> newNode = this.join(node);
|
newNode = this.join(node);
|
||||||
newNode.getData().setHasGenerated(true);
|
|
||||||
newNode.getData().setHomogenous(true);
|
newNode.getData().setHomogenous(true);
|
||||||
}
|
}
|
||||||
|
if(fullyGenerated && newNode != null){
|
||||||
|
newNode.getData().setHasGenerated(true);
|
||||||
|
}
|
||||||
if((this.chunkTree.getMaxLevel() - node.getLevel()) < minLeafLod){
|
if((this.chunkTree.getMaxLevel() - node.getLevel()) < minLeafLod){
|
||||||
evaluationMap.put(node,true);
|
evaluationMap.put(node,true);
|
||||||
}
|
}
|
||||||
@ -331,12 +340,17 @@ public class ClientDrawCellManager {
|
|||||||
if(
|
if(
|
||||||
lastPlayerPos.x / 16 != currentPlayerPos.x / 16 || lastPlayerPos.z / 16 != currentPlayerPos.z / 16 || lastPlayerPos.z / 16 != currentPlayerPos.z / 16
|
lastPlayerPos.x / 16 != currentPlayerPos.x / 16 || lastPlayerPos.z / 16 != currentPlayerPos.z / 16 || lastPlayerPos.z / 16 != currentPlayerPos.z / 16
|
||||||
){
|
){
|
||||||
return SIXTEENTH_RES_LOD;
|
return this.chunkTree.getMaxLevel();
|
||||||
|
}
|
||||||
|
if(
|
||||||
|
lastPlayerPos.x / 16 != currentPlayerPos.x / 16 || lastPlayerPos.z / 16 != currentPlayerPos.z / 16 || lastPlayerPos.z / 16 != currentPlayerPos.z / 16
|
||||||
|
){
|
||||||
|
return SIXTEENTH_RES_LOD + 2;
|
||||||
}
|
}
|
||||||
if(
|
if(
|
||||||
lastPlayerPos.x / 8 != currentPlayerPos.x / 8 || lastPlayerPos.z / 8 != currentPlayerPos.z / 8 || lastPlayerPos.z / 8 != currentPlayerPos.z / 8
|
lastPlayerPos.x / 8 != currentPlayerPos.x / 8 || lastPlayerPos.z / 8 != currentPlayerPos.z / 8 || lastPlayerPos.z / 8 != currentPlayerPos.z / 8
|
||||||
){
|
){
|
||||||
return EIGHTH_RES_LOD;
|
return SIXTEENTH_RES_LOD + 1;
|
||||||
}
|
}
|
||||||
if(
|
if(
|
||||||
lastPlayerPos.x / 4 != currentPlayerPos.x / 4 || lastPlayerPos.z / 4 != currentPlayerPos.z / 4 || lastPlayerPos.z / 4 != currentPlayerPos.z / 4
|
lastPlayerPos.x / 4 != currentPlayerPos.x / 4 || lastPlayerPos.z / 4 != currentPlayerPos.z / 4 || lastPlayerPos.z / 4 != currentPlayerPos.z / 4
|
||||||
@ -593,12 +607,14 @@ public class ClientDrawCellManager {
|
|||||||
*/
|
*/
|
||||||
private WorldOctTreeNode<DrawCell> join(WorldOctTreeNode<DrawCell> node){
|
private WorldOctTreeNode<DrawCell> join(WorldOctTreeNode<DrawCell> node){
|
||||||
Globals.profiler.beginCpuSample("ClientDrawCellManager.join");
|
Globals.profiler.beginCpuSample("ClientDrawCellManager.join");
|
||||||
//perform op
|
|
||||||
WorldOctTreeNode<DrawCell> newLeaf = chunkTree.join(node, DrawCell.generateTerrainCell(node.getMinBound(),node.getData().lod));
|
|
||||||
newLeaf.getData().transferChunkData(node.getData());
|
|
||||||
|
|
||||||
//do deletions
|
//queue destructions prior to join -- the join operator clears all children on node
|
||||||
this.twoLayerDestroy(node);
|
this.recursivelyDestroy(node);
|
||||||
|
|
||||||
|
//perform op
|
||||||
|
DrawCell newLeafCell = DrawCell.generateTerrainCell(node.getMinBound(),node.getData().lod);
|
||||||
|
WorldOctTreeNode<DrawCell> newLeaf = chunkTree.join(node, newLeafCell);
|
||||||
|
newLeaf.getData().transferChunkData(node.getData());
|
||||||
|
|
||||||
//update neighbors
|
//update neighbors
|
||||||
this.conditionalUpdateAdjacentNodes(newLeaf, newLeaf.getLevel());
|
this.conditionalUpdateAdjacentNodes(newLeaf, newLeaf.getLevel());
|
||||||
@ -663,7 +679,6 @@ public class ClientDrawCellManager {
|
|||||||
*/
|
*/
|
||||||
public boolean shouldGenerate(Vector3i pos, WorldOctTreeNode<DrawCell> node, int minLeafLod, int distCache){
|
public boolean shouldGenerate(Vector3i pos, WorldOctTreeNode<DrawCell> node, int minLeafLod, int distCache){
|
||||||
return
|
return
|
||||||
node.getData() != null &&
|
|
||||||
!node.getData().hasGenerated() &&
|
!node.getData().hasGenerated() &&
|
||||||
(this.chunkTree.getMaxLevel() - node.getLevel()) <= minLeafLod &&
|
(this.chunkTree.getMaxLevel() - node.getLevel()) <= minLeafLod &&
|
||||||
(
|
(
|
||||||
@ -725,7 +740,10 @@ public class ClientDrawCellManager {
|
|||||||
*/
|
*/
|
||||||
private void recursivelyDestroy(WorldOctTreeNode<DrawCell> node){
|
private void recursivelyDestroy(WorldOctTreeNode<DrawCell> node){
|
||||||
if(node.getChildren().size() > 0){
|
if(node.getChildren().size() > 0){
|
||||||
node.getChildren().forEach(child -> recursivelyDestroy(child));
|
for(WorldOctTreeNode<DrawCell> child : node.getChildren()){
|
||||||
|
child.getData().destroy();
|
||||||
|
}
|
||||||
|
// node.getChildren().forEach(child -> recursivelyDestroy(child));
|
||||||
}
|
}
|
||||||
if(node.getData() != null){
|
if(node.getData() != null){
|
||||||
node.getData().destroy();
|
node.getData().destroy();
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import org.joml.Vector3d;
|
|||||||
import org.joml.Vector3i;
|
import org.joml.Vector3i;
|
||||||
|
|
||||||
import electrosphere.client.terrain.cache.ChunkData;
|
import electrosphere.client.terrain.cache.ChunkData;
|
||||||
import electrosphere.collision.CollisionEngine;
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.ClientEntityUtils;
|
import electrosphere.entity.ClientEntityUtils;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
@ -88,6 +87,16 @@ public class DrawCell {
|
|||||||
* The cached minimum distance
|
* The cached minimum distance
|
||||||
*/
|
*/
|
||||||
double cachedMinDistance = -1;
|
double cachedMinDistance = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Target to notify on generation completion
|
||||||
|
*/
|
||||||
|
DrawCell notifyTarget = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of cells that have alerted this one
|
||||||
|
*/
|
||||||
|
int generationAlertCount = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,10 +170,14 @@ public class DrawCell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(modelEntity != null){
|
modelEntity = TerrainChunk.clientCreateTerrainChunkEntity(
|
||||||
ClientEntityUtils.destroyEntity(modelEntity);
|
this.chunkData,
|
||||||
}
|
this.notifyTarget,
|
||||||
modelEntity = TerrainChunk.clientCreateTerrainChunkEntity(this.chunkData, lod, atlas, this.hasPolygons());
|
this.modelEntity,
|
||||||
|
lod,
|
||||||
|
atlas,
|
||||||
|
this.hasPolygons()
|
||||||
|
);
|
||||||
ClientEntityUtils.initiallyPositionEntity(modelEntity, this.getRealPos(), new Quaterniond());
|
ClientEntityUtils.initiallyPositionEntity(modelEntity, this.getRealPos(), new Quaterniond());
|
||||||
this.setHasGenerated(true);
|
this.setHasGenerated(true);
|
||||||
}
|
}
|
||||||
@ -188,6 +201,24 @@ public class DrawCell {
|
|||||||
protected Vector3i getWorldPos(){
|
protected Vector3i getWorldPos(){
|
||||||
return new Vector3i(worldPos);
|
return new Vector3i(worldPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a target draw cell to notify once this one has completed generating its model
|
||||||
|
* @param notifyTarget The target to notify
|
||||||
|
*/
|
||||||
|
public void registerNotificationTarget(DrawCell notifyTarget){
|
||||||
|
this.notifyTarget = notifyTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alerts this draw cell that a child it is waiting on has generated
|
||||||
|
*/
|
||||||
|
public void alertToGeneration(){
|
||||||
|
this.generationAlertCount++;
|
||||||
|
if(this.generationAlertCount > 8){
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys a drawcell including its physics
|
* Destroys a drawcell including its physics
|
||||||
@ -200,8 +231,6 @@ public class DrawCell {
|
|||||||
if(framesSimulated < FRAMES_TO_WAIT_BEFORE_DESTRUCTION){
|
if(framesSimulated < FRAMES_TO_WAIT_BEFORE_DESTRUCTION){
|
||||||
framesSimulated++;
|
framesSimulated++;
|
||||||
} else {
|
} else {
|
||||||
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
|
|
||||||
collisionEngine.destroyPhysics(modelEntity);
|
|
||||||
ClientEntityUtils.destroyEntity(modelEntity);
|
ClientEntityUtils.destroyEntity(modelEntity);
|
||||||
Globals.clientScene.deregisterBehaviorTree(this);
|
Globals.clientScene.deregisterBehaviorTree(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,11 @@ import electrosphere.client.scene.ClientWorldData;
|
|||||||
import electrosphere.client.terrain.cache.ChunkData;
|
import electrosphere.client.terrain.cache.ChunkData;
|
||||||
import electrosphere.client.terrain.cache.ClientTerrainCache;
|
import electrosphere.client.terrain.cache.ClientTerrainCache;
|
||||||
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
||||||
|
import electrosphere.client.terrain.cells.DrawCell;
|
||||||
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.ClientEntityUtils;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.types.terrain.TerrainChunkData;
|
import electrosphere.entity.types.terrain.TerrainChunkData;
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||||
@ -277,11 +280,11 @@ public class ClientTerrainManager {
|
|||||||
* @param data The chunk data (triangles, normals, etc)
|
* @param data The chunk data (triangles, normals, etc)
|
||||||
* @return The model path that is promised to eventually reflect the terrain model when it makes it to gpu
|
* @return The model path that is promised to eventually reflect the terrain model when it makes it to gpu
|
||||||
*/
|
*/
|
||||||
public static String queueTerrainGridGeneration(TerrainChunkData data, VoxelTextureAtlas atlas){
|
public static String queueTerrainGridGeneration(TerrainChunkData data, VoxelTextureAtlas atlas, DrawCell notifyTarget, Entity toDelete){
|
||||||
String promisedHash = "";
|
String promisedHash = "";
|
||||||
UUID newUUID = UUID.randomUUID();
|
UUID newUUID = UUID.randomUUID();
|
||||||
promisedHash = newUUID.toString();
|
promisedHash = newUUID.toString();
|
||||||
TerrainChunkGenQueueItem queueItem = new TerrainChunkGenQueueItem(data, promisedHash, atlas);
|
TerrainChunkGenQueueItem queueItem = new TerrainChunkGenQueueItem(data, promisedHash, atlas, notifyTarget, toDelete);
|
||||||
lock.acquireUninterruptibly();
|
lock.acquireUninterruptibly();
|
||||||
terrainChunkGenerationQueue.add(queueItem);
|
terrainChunkGenerationQueue.add(queueItem);
|
||||||
lock.release();
|
lock.release();
|
||||||
@ -297,6 +300,12 @@ public class ClientTerrainManager {
|
|||||||
for(TerrainChunkGenQueueItem queueItem : terrainChunkGenerationQueue){
|
for(TerrainChunkGenQueueItem queueItem : terrainChunkGenerationQueue){
|
||||||
Model terrainModel = TerrainChunkModelGeneration.generateTerrainModel(queueItem.getData(), queueItem.getAtlas());
|
Model terrainModel = TerrainChunkModelGeneration.generateTerrainModel(queueItem.getData(), queueItem.getAtlas());
|
||||||
Globals.assetManager.registerModelToSpecificString(terrainModel, queueItem.getPromisedHash());
|
Globals.assetManager.registerModelToSpecificString(terrainModel, queueItem.getPromisedHash());
|
||||||
|
if(queueItem.notifyTarget != null){
|
||||||
|
queueItem.notifyTarget.alertToGeneration();
|
||||||
|
}
|
||||||
|
if(queueItem.toDelete != null){
|
||||||
|
ClientEntityUtils.destroyEntity(queueItem.toDelete);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
terrainChunkGenerationQueue.clear();
|
terrainChunkGenerationQueue.clear();
|
||||||
lock.release();
|
lock.release();
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package electrosphere.client.terrain.manager;
|
package electrosphere.client.terrain.manager;
|
||||||
|
|
||||||
|
import electrosphere.client.terrain.cells.DrawCell;
|
||||||
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.types.terrain.TerrainChunkData;
|
import electrosphere.entity.types.terrain.TerrainChunkData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,16 +17,35 @@ public class TerrainChunkGenQueueItem {
|
|||||||
//the texture atlas
|
//the texture atlas
|
||||||
VoxelTextureAtlas atlas;
|
VoxelTextureAtlas atlas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The draw cell to notify once this model is fully available to render
|
||||||
|
*/
|
||||||
|
DrawCell notifyTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The optional entity to delete on generation of this target
|
||||||
|
*/
|
||||||
|
Entity toDelete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a queue item
|
* Creates a queue item
|
||||||
* @param data
|
* @param data
|
||||||
* @param promisedHash
|
* @param promisedHash
|
||||||
* @param atlas
|
* @param atlas
|
||||||
|
* @param notifyTarget The draw cell to notify once this model is fully available to render
|
||||||
*/
|
*/
|
||||||
public TerrainChunkGenQueueItem(TerrainChunkData data, String promisedHash, VoxelTextureAtlas atlas){
|
public TerrainChunkGenQueueItem(
|
||||||
|
TerrainChunkData data,
|
||||||
|
String promisedHash,
|
||||||
|
VoxelTextureAtlas atlas,
|
||||||
|
DrawCell notifyTarget,
|
||||||
|
Entity toDelete
|
||||||
|
){
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.promisedHash = promisedHash;
|
this.promisedHash = promisedHash;
|
||||||
this.atlas = atlas;
|
this.atlas = atlas;
|
||||||
|
this.notifyTarget = notifyTarget;
|
||||||
|
this.toDelete = toDelete;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -250,6 +250,9 @@ public class ClientLoading {
|
|||||||
DrawableUtils.disableCulling(skybox);
|
DrawableUtils.disableCulling(skybox);
|
||||||
EntityUtils.getRotation(skybox).rotateX((float)(-Math.PI/2.0f));
|
EntityUtils.getRotation(skybox).rotateX((float)(-Math.PI/2.0f));
|
||||||
EntityUtils.getScale(skybox).mul(600000.0f);
|
EntityUtils.getScale(skybox).mul(600000.0f);
|
||||||
|
Globals.clientScene.registerBehaviorTree(() -> {
|
||||||
|
EntityUtils.getPosition(skybox).set(EntityUtils.getPosition(Globals.playerEntity));
|
||||||
|
});
|
||||||
Globals.assetManager.queueOverrideMeshShader("Models/environment/skyboxSphere.fbx", "Sphere", "Shaders/entities/skysphere/skysphere.vs", "Shaders/entities/skysphere/skysphere.fs");
|
Globals.assetManager.queueOverrideMeshShader("Models/environment/skyboxSphere.fbx", "Sphere", "Shaders/entities/skysphere/skysphere.vs", "Shaders/entities/skysphere/skysphere.fs");
|
||||||
|
|
||||||
//cloud ring pseudo skybox
|
//cloud ring pseudo skybox
|
||||||
|
|||||||
@ -47,6 +47,7 @@ public class EntityDataStrings {
|
|||||||
Terrain Entity
|
Terrain Entity
|
||||||
*/
|
*/
|
||||||
public static final String TERRAIN_IS_TERRAIN = "terrainEntity";
|
public static final String TERRAIN_IS_TERRAIN = "terrainEntity";
|
||||||
|
public static final String CORRESPONDING_DRAW_CELL = "correspondingDrawCell";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fluid Entity
|
* Fluid Entity
|
||||||
|
|||||||
@ -155,6 +155,16 @@ public class Scene {
|
|||||||
behaviorTreeList.add(tree);
|
behaviorTreeList.add(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new behavior tree that executes a task
|
||||||
|
* @param task The task
|
||||||
|
*/
|
||||||
|
public void registerBehaviorTree(Runnable task){
|
||||||
|
this.registerBehaviorTree(new BehaviorTree(){public void simulate(float deltaTime) {
|
||||||
|
task.run();
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deregisters a behavior tree from the scene
|
* Deregisters a behavior tree from the scene
|
||||||
* @param tree The behavior tree to deregister
|
* @param tree The behavior tree to deregister
|
||||||
|
|||||||
@ -7,10 +7,12 @@ import org.joml.Quaterniond;
|
|||||||
import org.joml.Vector3d;
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
||||||
|
import electrosphere.client.terrain.cells.DrawCell;
|
||||||
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
import electrosphere.client.terrain.cells.VoxelTextureAtlas;
|
||||||
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
||||||
import electrosphere.collision.PhysicsEntityUtils;
|
import electrosphere.collision.PhysicsEntityUtils;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.ClientEntityUtils;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.EntityCreationUtils;
|
import electrosphere.entity.EntityCreationUtils;
|
||||||
import electrosphere.entity.EntityDataStrings;
|
import electrosphere.entity.EntityDataStrings;
|
||||||
@ -36,11 +38,20 @@ public class TerrainChunk {
|
|||||||
/**
|
/**
|
||||||
* Creates a client terrain chunk based on weights and values provided
|
* Creates a client terrain chunk based on weights and values provided
|
||||||
* @param chunkData the chunk data to generate with
|
* @param chunkData the chunk data to generate with
|
||||||
|
* @param toDelete The entity to delete on full generation of this entity
|
||||||
|
* @param notifyTarget The target draw cell to notify once this has successfully generated its model
|
||||||
* @param levelOfDetail Increasing value that increments level of detail. 0 would be full resolution, 1 would be half resolution and so on. Only generates physics if levelOfDetail is 0
|
* @param levelOfDetail Increasing value that increments level of detail. 0 would be full resolution, 1 would be half resolution and so on. Only generates physics if levelOfDetail is 0
|
||||||
* @param hasPolygons true if the chunk has polygons to generate a model with, false otherwise
|
* @param hasPolygons true if the chunk has polygons to generate a model with, false otherwise
|
||||||
* @return The terrain chunk entity
|
* @return The terrain chunk entity
|
||||||
*/
|
*/
|
||||||
public static Entity clientCreateTerrainChunkEntity(TransvoxelChunkData chunkData, int levelOfDetail, VoxelTextureAtlas atlas, boolean hasPolygons){
|
public static Entity clientCreateTerrainChunkEntity(
|
||||||
|
TransvoxelChunkData chunkData,
|
||||||
|
DrawCell notifyTarget,
|
||||||
|
Entity toDelete,
|
||||||
|
int levelOfDetail,
|
||||||
|
VoxelTextureAtlas atlas,
|
||||||
|
boolean hasPolygons
|
||||||
|
){
|
||||||
Globals.profiler.beginAggregateCpuSample("TerrainChunk.clientCreateTerrainChunkEntity");
|
Globals.profiler.beginAggregateCpuSample("TerrainChunk.clientCreateTerrainChunkEntity");
|
||||||
|
|
||||||
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
|
||||||
@ -52,7 +63,7 @@ public class TerrainChunk {
|
|||||||
data = TransvoxelModelGeneration.generateTerrainChunkData(chunkData);
|
data = TransvoxelModelGeneration.generateTerrainChunkData(chunkData);
|
||||||
data.constructBuffers();
|
data.constructBuffers();
|
||||||
if(Globals.clientScene.containsEntity(rVal)){
|
if(Globals.clientScene.containsEntity(rVal)){
|
||||||
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data, atlas);
|
String modelPath = ClientTerrainManager.queueTerrainGridGeneration(data, atlas, notifyTarget, toDelete);
|
||||||
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
|
EntityCreationUtils.makeEntityDrawablePreexistingModel(rVal, modelPath);
|
||||||
if(levelOfDetail == ClientDrawCellManager.FULL_RES_LOD){
|
if(levelOfDetail == ClientDrawCellManager.FULL_RES_LOD){
|
||||||
PhysicsEntityUtils.clientAttachTerrainChunkRigidBody(rVal, data);
|
PhysicsEntityUtils.clientAttachTerrainChunkRigidBody(rVal, data);
|
||||||
@ -63,6 +74,12 @@ public class TerrainChunk {
|
|||||||
}
|
}
|
||||||
rVal.putData(EntityDataStrings.HAS_UNIQUE_MODEL, true);
|
rVal.putData(EntityDataStrings.HAS_UNIQUE_MODEL, true);
|
||||||
} else {
|
} else {
|
||||||
|
if(notifyTarget != null){
|
||||||
|
notifyTarget.alertToGeneration();
|
||||||
|
}
|
||||||
|
if(toDelete != null){
|
||||||
|
ClientEntityUtils.destroyEntity(toDelete);
|
||||||
|
}
|
||||||
LoggerInterface.loggerEngine.DEBUG("Finished generating terrain polygons; however, entity has already been deleted.");
|
LoggerInterface.loggerEngine.DEBUG("Finished generating terrain polygons; however, entity has already been deleted.");
|
||||||
}
|
}
|
||||||
} catch (Error e){
|
} catch (Error e){
|
||||||
@ -71,6 +88,13 @@ public class TerrainChunk {
|
|||||||
LoggerInterface.loggerEngine.ERROR(e);
|
LoggerInterface.loggerEngine.ERROR(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if(notifyTarget != null){
|
||||||
|
notifyTarget.alertToGeneration();
|
||||||
|
}
|
||||||
|
if(toDelete != null){
|
||||||
|
ClientEntityUtils.destroyEntity(toDelete);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rVal.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
rVal.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user