LOD component
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-05-24 16:56:31 -04:00
parent 6e0acf8b05
commit 6e55b7ee18
9 changed files with 370 additions and 0 deletions

View File

@ -1955,6 +1955,7 @@ Work on rotating structures
Towns spawn a population of characters when they are max-res'd
Hitbox synchronization work
LOD emitter service
LOD component that destroys far-away physics

View File

@ -369,6 +369,12 @@ public class EntityDataStrings {
public static final String TREE_SERVERGROWTH = "treeServerGrowth";
public static final String TREE_CLIENTGROWTH = "treeClientGrowth";
/**
* LOD component
*/
public static final String TREE_CLIENTLODTREE = "treeClientLODTree";
public static final String TREE_SERVERLODTREE = "treeServerLODTree";
/**
* Loot pool
*/

View File

@ -0,0 +1,143 @@
package electrosphere.entity.state.lod;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.Entity;
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
/**
* Creates a client LOD component
*/
@SynchronizedBehaviorTree(name = "clientLODTree", isServer = false, correspondingTree="serverLODTree")
public class ClientLODComponent implements BehaviorTree {
/**
* The current LOD level
*/
@SyncedField
private int lodLevel;
/**
* The cached lod level from the most recent call
*/
private int cachedLodLevel;
/**
* The parent entity
*/
private Entity parent;
@Override
public void simulate(float deltaTime) {
if(cachedLodLevel != lodLevel){
cachedLodLevel = lodLevel;
if(cachedLodLevel == ServerLODComponent.FULL_RES){
} else if(cachedLodLevel == ServerLODComponent.LOW_RES){
if(PhysicsEntityUtils.containsDBody(this.parent)){
PhysicsUtils.destroyPhysicsPair(
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
PhysicsEntityUtils.getDBody(this.parent),
PhysicsEntityUtils.getCollidable(this.parent)
);
}
}
}
}
/**
* <p> (initially) Automatically generated </p>
* <p>
* Attaches this tree to the entity.
* </p>
* @param entity The entity to attach to
* @param tree The behavior tree to attach
* @param params Optional parameters that will be provided to the constructor
*/
public static ClientLODComponent attachTree(Entity parent, Object ... params){
ClientLODComponent rVal = new ClientLODComponent(parent,params);
//!!WARNING!! from here below should not be touched
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
parent.putData(EntityDataStrings.TREE_CLIENTLODTREE, rVal);
Globals.clientState.clientSceneWrapper.getScene().registerBehaviorTree(rVal);
Globals.serverState.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_CLIENTLODTREE_ID);
return rVal;
}
/**
* <p> Automatically generated </p>
* <p>
* Detatches this tree from the entity.
* </p>
* @param entity The entity to detach to
* @param tree The behavior tree to detach
*/
public static void detachTree(Entity entity, BehaviorTree tree){
Globals.serverState.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_CLIENTLODTREE_ID);
}
/**
* <p> (initially) Automatically generated </p>
* <p> Private constructor to enforce using the attach methods </p>
* <p>
* Constructor
* </p>
* @param parent The parent entity of this tree
* @param params Optional parameters that can be provided when attaching the tree. All custom data required for creating this tree should be passed in this varargs.
*/
private ClientLODComponent(Entity parent, Object ... params){
this.parent = parent;
this.lodLevel = ServerLODComponent.FULL_RES;
this.cachedLodLevel = ServerLODComponent.FULL_RES;
}
/**
* <p>
* Gets the ClientLODComponent of the entity
* </p>
* @param entity the entity
* @return The ClientLODComponent
*/
public static ClientLODComponent getClientLODComponent(Entity entity){
return (ClientLODComponent)entity.getData(EntityDataStrings.TREE_CLIENTLODTREE);
}
/**
* <p>
* Checks if the entity has a ClientLODComponent component
* </p>
* @param entity the entity
* @return true if the entity contains the component, false otherwise
*/
public static boolean hasClientLODComponent(Entity entity){
return entity.containsKey(EntityDataStrings.TREE_CLIENTLODTREE);
}
/**
* <p> Automatically generated </p>
* <p>
* Sets lodLevel and handles the synchronization logic for it.
* </p>
* @param lodLevel The value to set lodLevel to.
*/
public void setLodLevel(int lodLevel){
this.lodLevel = lodLevel;
}
/**
* <p> Automatically generated </p>
* <p>
* Gets lodLevel.
* </p>
*/
public int getLodLevel(){
return lodLevel;
}
}

View File

@ -0,0 +1,179 @@
package electrosphere.entity.state.lod;
import org.joml.Vector3d;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.net.synchronization.enums.FieldIdEnums;
import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.utils.DataCellSearchUtils;
import electrosphere.net.parser.net.message.SynchronizationMessage;
import electrosphere.entity.Entity;
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
/**
* Creates a server LOD component
*/
@SynchronizedBehaviorTree(name = "serverLODTree", isServer = true, correspondingTree="clientLODTree")
public class ServerLODComponent implements BehaviorTree {
/**
* Radius after which we reduce LOD
*/
public static final int LOD_RADIUS = 32;
/**
* Full resolution LOD
*/
public static final int FULL_RES = 1;
/**
* Low resolution
*/
public static final int LOW_RES = 0;
/**
* The current LOD level
*/
@SyncedField
private int lodLevel;
/**
* The parent entity
*/
private Entity parent;
@Override
public void simulate(float deltaTime) {
Vector3d parentLoc = EntityUtils.getPosition(this.parent);
boolean fullRes = false;
for(Entity emitter : Globals.serverState.lodEmitterService.getEmitters()){
Vector3d emitterLoc = EntityUtils.getPosition(emitter);
double dist = parentLoc.distance(emitterLoc);
if(dist < LOD_RADIUS){
fullRes = true;
break;
}
}
if(fullRes){
if(lodLevel != FULL_RES){
//make full res
this.setLodLevel(FULL_RES);
}
} else {
if(lodLevel != LOW_RES){
//make low res
this.setLodLevel(LOW_RES);
Realm realm = Globals.serverState.realmManager.getEntityRealm(this.parent);
if(PhysicsEntityUtils.containsDBody(this.parent)){
PhysicsUtils.destroyPhysicsPair(
realm.getCollisionEngine(),
PhysicsEntityUtils.getDBody(this.parent),
PhysicsEntityUtils.getCollidable(this.parent)
);
}
}
}
}
/**
* <p> (initially) Automatically generated </p>
* <p>
* Attaches this tree to the entity.
* </p>
* @param entity The entity to attach to
* @param tree The behavior tree to attach
* @param params Optional parameters that will be provided to the constructor
*/
public static ServerLODComponent attachTree(Entity parent, Object ... params){
ServerLODComponent rVal = new ServerLODComponent(parent,params);
//!!WARNING!! from here below should not be touched
//This was generated automatically to properly alert various systems that the btree exists and should be tracked
ServerBehaviorTreeUtils.attachBTreeToEntity(parent, rVal);
parent.putData(EntityDataStrings.TREE_SERVERLODTREE, rVal);
Globals.serverState.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID);
return rVal;
}
/**
* <p> Automatically generated </p>
* <p>
* Detatches this tree from the entity.
* </p>
* @param entity The entity to detach to
* @param tree The behavior tree to detach
*/
public static void detachTree(Entity entity, BehaviorTree tree){
Globals.serverState.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID);
}
/**
* <p> (initially) Automatically generated </p>
* <p> Private constructor to enforce using the attach methods </p>
* <p>
* Constructor
* </p>
* @param parent The parent entity of this tree
* @param params Optional parameters that can be provided when attaching the tree. All custom data required for creating this tree should be passed in this varargs.
*/
private ServerLODComponent(Entity parent, Object ... params){
this.parent = parent;
this.lodLevel = ServerLODComponent.FULL_RES;
}
/**
* <p>
* Gets the ServerLODComponent of the entity
* </p>
* @param entity the entity
* @return The ServerLODComponent
*/
public static ServerLODComponent getServerLODComponent(Entity entity){
return (ServerLODComponent)entity.getData(EntityDataStrings.TREE_SERVERLODTREE);
}
/**
* <p>
* Checks if the entity has a ServerLODComponent component
* </p>
* @param entity the entity
* @return true if the entity contains the component, false otherwise
*/
public static boolean hasServerLODComponent(Entity entity){
return entity.containsKey(EntityDataStrings.TREE_SERVERLODTREE);
}
/**
* <p> Automatically generated </p>
* <p>
* Sets lodLevel and handles the synchronization logic for it.
* </p>
* @param lodLevel The value to set lodLevel to.
*/
public void setLodLevel(int lodLevel){
this.lodLevel = lodLevel;
if(DataCellSearchUtils.getEntityDataCell(parent) != null){
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientIntStateMessage(parent.getId(), BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID, FieldIdEnums.TREE_SERVERLODTREE_SYNCEDFIELD_LODLEVEL_ID, lodLevel));
}
}
/**
* <p> Automatically generated </p>
* <p>
* Gets lodLevel.
* </p>
*/
public int getLodLevel(){
return lodLevel;
}
}

View File

@ -65,6 +65,8 @@ import electrosphere.entity.state.inventory.UnrelationalInventoryState;
import electrosphere.entity.state.life.ClientLifeTree;
import electrosphere.entity.state.life.ServerLifeTree;
import electrosphere.entity.state.light.ClientPointLightComponent;
import electrosphere.entity.state.lod.ClientLODComponent;
import electrosphere.entity.state.lod.ServerLODComponent;
import electrosphere.entity.state.movement.editor.ClientEditorMovementTree;
import electrosphere.entity.state.movement.editor.ServerEditorMovementTree;
import electrosphere.entity.state.movement.fall.ClientFallTree;
@ -217,6 +219,7 @@ public class CommonEntityUtils {
if(rawType.getCollidable() != null){
CollidableTemplate physicsTemplate = rawType.getCollidable();
PhysicsEntityUtils.clientAttachCollidableTemplate(entity, physicsTemplate);
ClientLODComponent.attachTree(entity);
}
//
@ -539,6 +542,7 @@ public class CommonEntityUtils {
if(rawType.getCollidable() != null){
CollidableTemplate physicsTemplate = rawType.getCollidable();
PhysicsEntityUtils.serverAttachCollidableTemplate(realm, entity, physicsTemplate);
ServerLODComponent.attachTree(entity);
}
//
//

View File

@ -1,6 +1,7 @@
package electrosphere.net.synchronization.client;
import electrosphere.entity.state.lod.ClientLODComponent;
import electrosphere.entity.state.growth.ClientGrowthComponent;
import electrosphere.entity.state.furniture.ClientDoorState;
import electrosphere.entity.state.item.ClientChargeState;
@ -348,6 +349,16 @@ public class ClientSynchronizationManager {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID: {
switch(message.getfieldId()){
case FieldIdEnums.TREE_SERVERLODTREE_SYNCEDFIELD_LODLEVEL_ID:{
ClientLODComponent tree = ClientLODComponent.getClientLODComponent(entity);
if(tree != null){
tree.setLodLevel(message.getintValue());
}
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERSTANCECOMPONENT_ID: {
switch(message.getfieldId()){
case FieldIdEnums.TREE_SERVERSTANCECOMPONENT_SYNCEDFIELD_STATE_ID:{

View File

@ -25,6 +25,8 @@ public class BehaviorTreeIdEnums {
public static final int BTREE_SERVERCHARGESTATE_ID = 27;
public static final int BTREE_CLIENTLIFETREE_ID = 6;
public static final int BTREE_SERVERLIFETREE_ID = 13;
public static final int BTREE_CLIENTLODTREE_ID = 32;
public static final int BTREE_SERVERLODTREE_ID = 33;
public static final int BTREE_CLIENTSTANCECOMPONENT_ID = 20;
public static final int BTREE_SERVERSTANCECOMPONENT_ID = 21;
public static final int BTREE_CLIENTEDITORMOVEMENTTREE_ID = 24;

View File

@ -29,6 +29,8 @@ public class FieldIdEnums {
public static final int TREE_SERVERCHARGESTATE_SYNCEDFIELD_CHARGES_ID = 35;
public static final int TREE_CLIENTLIFETREE_SYNCEDFIELD_STATE_ID = 10;
public static final int TREE_SERVERLIFETREE_SYNCEDFIELD_STATE_ID = 17;
public static final int TREE_CLIENTLODTREE_SYNCEDFIELD_LODLEVEL_ID = 40;
public static final int TREE_SERVERLODTREE_SYNCEDFIELD_LODLEVEL_ID = 41;
public static final int TREE_CLIENTSTANCECOMPONENT_SYNCEDFIELD_STATE_ID = 28;
public static final int TREE_SERVERSTANCECOMPONENT_SYNCEDFIELD_STATE_ID = 29;
public static final int TREE_CLIENTEDITORMOVEMENTTREE_SYNCEDFIELD_FACING_ID = 32;

View File

@ -1,6 +1,8 @@
package electrosphere.net.synchronization.transport;
import electrosphere.entity.state.lod.ServerLODComponent;
import electrosphere.entity.state.lod.ClientLODComponent;
import electrosphere.entity.state.growth.ServerGrowthComponent;
import electrosphere.entity.state.growth.ClientGrowthComponent;
import electrosphere.entity.state.furniture.ServerDoorState;
@ -126,6 +128,10 @@ public class StateCollection {
ServerLifeTree tree = ServerLifeTree.getServerLifeTree(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERLIFETREE_ID,FieldIdEnums.TREE_SERVERLIFETREE_SYNCEDFIELD_STATE_ID,ClientLifeTree.getLifeStateEnumEnumAsShort(tree.getState())));
} break;
case BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID: {
ServerLODComponent tree = ServerLODComponent.getServerLODComponent(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID,FieldIdEnums.TREE_SERVERLODTREE_SYNCEDFIELD_LODLEVEL_ID,tree.getLodLevel()));
} break;
case BehaviorTreeIdEnums.BTREE_SERVERSTANCECOMPONENT_ID: {
ServerStanceComponent tree = ServerStanceComponent.getServerStanceComponent(entity);
collection.setValue(new SynchronizedFieldValue(BehaviorTreeIdEnums.BTREE_SERVERSTANCECOMPONENT_ID,FieldIdEnums.TREE_SERVERSTANCECOMPONENT_SYNCEDFIELD_STATE_ID,ClientStanceComponent.getCombatStanceEnumAsShort(tree.getState())));
@ -250,6 +256,14 @@ public class StateCollection {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID: {
ClientLODComponent tree = ClientLODComponent.getClientLODComponent(entity);
switch(syncedValue.getFieldId()){
case(FieldIdEnums.TREE_SERVERLODTREE_SYNCEDFIELD_LODLEVEL_ID): {
tree.setLodLevel(((Double)syncedValue.getValue()).intValue());
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERSTANCECOMPONENT_ID: {
ClientStanceComponent tree = ClientStanceComponent.getClientStanceComponent(entity);
switch(syncedValue.getFieldId()){
@ -401,6 +415,14 @@ public class StateCollection {
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERLODTREE_ID: {
ServerLODComponent tree = ServerLODComponent.getServerLODComponent(entity);
switch(syncedValue.getFieldId()){
case(FieldIdEnums.TREE_SERVERLODTREE_SYNCEDFIELD_LODLEVEL_ID): {
tree.setLodLevel(((Double)syncedValue.getValue()).intValue());
} break;
}
} break;
case BehaviorTreeIdEnums.BTREE_SERVERSTANCECOMPONENT_ID: {
ServerStanceComponent tree = ServerStanceComponent.getServerStanceComponent(entity);
switch(syncedValue.getFieldId()){