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

This commit is contained in:
austin 2025-06-04 17:37:05 -04:00
parent 60feb2ed59
commit f9d8ad0adb
5 changed files with 177 additions and 104 deletions

View File

@ -2110,6 +2110,7 @@ Fix physics performance issues
(06/04/2025)
ServerGroundMovementTree actually moves collidable-based entities
Client uses non-rigid-body collidables for farther away entities (via client LOD tree)

View File

@ -67,7 +67,6 @@ public class PhysicsEntityUtils {
public static void clientAttachCollidableTemplate(Entity rVal, CollidableTemplate physicsTemplate){
Collidable collidable;
double mass = 1.0f;
CollisionEngine engine = Globals.clientState.clientSceneWrapper.getCollisionEngine();
if(physicsTemplate.getMass() != null){
mass = physicsTemplate.getMass();
}
@ -77,96 +76,7 @@ public class PhysicsEntityUtils {
}
CollisionEngine.lockOde();
if(physicsTemplate.getKinematic()){
DGeom geom = null;
switch(physicsTemplate.getType()){
case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
//
//create dbody
geom = CollisionBodyCreation.createCylinderShape(
engine,
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotate(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW() //rotate
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
engine.registerCollisionObject(geom, collidable, EntityUtils.getPosition(rVal));
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
//
//create dbody
geom = CollisionBodyCreation.createCubeShape(
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
categoryBit
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal,geom);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
engine.registerCollisionObject(geom, collidable, EntityUtils.getPosition(rVal));
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
//
//create dbody
geom = CollisionBodyCreation.createCapsuleShape(
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal,geom);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
engine.registerCollisionObject(geom, collidable, EntityUtils.getPosition(rVal));
} break;
}
PhysicsEntityUtils.clientAttachGeom(rVal, physicsTemplate, EntityUtils.getPosition(rVal));
} else {
DBody rigidBody = null;
switch(physicsTemplate.getType()){
@ -366,16 +276,128 @@ public class PhysicsEntityUtils {
} break;
}
//if we successfully attached the body, add a sync tree
if(rigidBody != null){
ClientPhysicsSyncTree.attachTree(rVal);
if(ClientGravityTree.hasClientGravityTree(rVal)){
ClientGravityTree.getClientGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
ClientPhysicsSyncTree.attachTree(rVal);
if(ClientGravityTree.hasClientGravityTree(rVal)){
ClientGravityTree.getClientGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
}
CollisionEngine.unlockOde();
}
/**
* [SERVER ONLY] Attaches a collidable template to a given entity
* @param rVal The entity
* @param physicsTemplate The collidable template
* @return The geometry object
*/
public static DGeom clientAttachGeom(Entity rVal, CollidableTemplate physicsTemplate, Vector3d position){
DGeom geom = null;
Collidable collidable;
double mass = 1.0f;
long categoryBit = Collidable.TYPE_CREATURE_BIT;
if(physicsTemplate.getKinematic()){
categoryBit = Collidable.TYPE_STATIC_BIT;
}
CollisionEngine engine = Globals.clientState.clientSceneWrapper.getCollisionEngine();
CollisionEngine.lockOde();
switch(physicsTemplate.getType()){
case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
//
//create dbody
geom = CollisionBodyCreation.createCylinderShape(
engine,
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal, geom);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotate(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW() //rotate
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
engine.registerCollisionObject(geom, collidable, EntityUtils.getPosition(rVal));
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
//
//create dbody
geom = CollisionBodyCreation.createCubeShape(
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
categoryBit
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal,geom);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
engine.registerCollisionObject(geom, collidable, EntityUtils.getPosition(rVal));
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
//
//create dbody
geom = CollisionBodyCreation.createCapsuleShape(
Globals.clientState.clientSceneWrapper.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
categoryBit
);
//
//create collidable and link to structures
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
PhysicsEntityUtils.setDGeom(rVal,geom);
//
//store values
Matrix4d offsetTransform = new Matrix4d().translationRotateScale(
physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ(), //translate
physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW(), //rotate
1, 1, 1 //scale
);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
engine.registerCollisionObject(geom, collidable, EntityUtils.getPosition(rVal));
} break;
}
//if we successfully attached the body, add a sync tree
ClientPhysicsSyncTree.attachTree(rVal);
if(ClientGravityTree.hasClientGravityTree(rVal)){
ClientGravityTree.getClientGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
CollisionEngine.unlockOde();
return geom;
}
/**
* [SERVER ONLY] Attaches a collidable template to a given entity
@ -599,11 +621,9 @@ public class PhysicsEntityUtils {
} break;
}
//if we successfully attached the body, add a sync tree
if(rigidBody != null){
ServerPhysicsSyncTree.attachTree(rVal);
if(ServerGravityTree.hasServerGravityTree(rVal)){
ServerGravityTree.getServerGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
ServerPhysicsSyncTree.attachTree(rVal);
if(ServerGravityTree.hasServerGravityTree(rVal)){
ServerGravityTree.getServerGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
}
CollisionEngine.unlockOde();
@ -726,6 +746,10 @@ public class PhysicsEntityUtils {
realm.getCollisionEngine().registerCollisionObject(geom, collidable, position);
} break;
}
ServerPhysicsSyncTree.attachTree(rVal);
if(ServerGravityTree.hasServerGravityTree(rVal)){
ServerGravityTree.getServerGravityTree(rVal).updatePhysicsPair(PhysicsEntityUtils.getCollidable(rVal),PhysicsEntityUtils.getDBody(rVal));
}
CollisionEngine.unlockOde();
return geom;
}

View File

@ -13,6 +13,7 @@ import electrosphere.entity.Entity;
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.entity.btree.BehaviorTree;
import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.net.synchronization.annotation.SyncedField;
import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
@ -76,6 +77,13 @@ public class ClientLODComponent implements BehaviorTree {
PhysicsEntityUtils.getCollidable(this.parent)
);
}
CommonEntityType type = CommonEntityUtils.getCommonData(this.parent);
if(type.getCollidable() != null){
if(CreatureUtils.hasControllerPlayerId(parent)){
throw new Error("Should not be attaching a geometry to a player entity!");
}
PhysicsEntityUtils.clientAttachGeom(parent, type.getCollidable(), EntityUtils.getPosition(parent));
}
}
}
}

View File

@ -3,6 +3,7 @@ package electrosphere.entity.state.physicssync;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DGeom;
import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.client.terrain.foliage.FoliageCellManager;
@ -59,6 +60,7 @@ public class ClientPhysicsSyncTree implements BehaviorTree {
Vector3d angularForce = new Vector3d();
boolean enabled = latestMessage.getbodyEnabled();
DBody body = PhysicsEntityUtils.getDBody(parent);
DGeom geom = PhysicsEntityUtils.getDGeom(parent);
//
//bust distance caches if this is the player's entity and we've traveled a long distance suddenly
@ -77,7 +79,12 @@ public class ClientPhysicsSyncTree implements BehaviorTree {
//Synchronize data
EntityUtils.setPosition(parent, position);
EntityUtils.getRotation(parent).set(rotationFromServer);
PhysicsUtils.synchronizeData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), body, position, rotationFromServer, linearVelocity, angularVelocity, linearForce, angularForce, enabled);
if(body != null){
PhysicsUtils.synchronizeData(Globals.clientState.clientSceneWrapper.getCollisionEngine(), body, position, rotationFromServer, linearVelocity, angularVelocity, linearForce, angularForce, enabled);
}
if(geom != null){
PhysicsUtils.setGeomTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), position, rotationFromServer, geom);
}
//
//update facing vector if relevant

View File

@ -3,6 +3,7 @@ package electrosphere.entity.state.physicssync;
import org.joml.Quaterniond;
import org.joml.Vector3d;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DGeom;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
@ -44,8 +45,8 @@ public class ServerPhysicsSyncTree implements BehaviorTree {
Vector3d position = EntityUtils.getPosition(parent);
Quaterniond rotation = EntityUtils.getRotation(parent);
DBody body = PhysicsEntityUtils.getDBody(parent);
if(body == null){
} else {
DGeom geom = PhysicsEntityUtils.getDGeom(parent);
if(body != null){
//velocities
Vector3d linearVel = PhysicsUtils.odeVecToJomlVec(body.getLinearVel());
Vector3d angularVel = PhysicsUtils.odeVecToJomlVec(body.getAngularVel());
@ -83,6 +84,38 @@ public class ServerPhysicsSyncTree implements BehaviorTree {
);
}
}
if(geom != null){
if(position.distance(lastSentPosition) > UPDATE_THRESHOLD || 1.0 - rotation.dot(lastSentRotation) > UPDATE_THRESHOLD){
lastSentPosition.set(position);
lastSentRotation.set(rotation);
DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(
EntityMessage.constructsyncPhysicsMessage(
parent.getId(),
Globals.engineState.timekeeper.getNumberOfSimFramesElapsed(),
position.x,
position.y,
position.z,
rotation.x,
rotation.y,
rotation.z,
rotation.w,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
false
)
);
}
}
}
/**