From aa0956477d639c755adae62ac2eb4178deda7a25 Mon Sep 17 00:00:00 2001
From: austin
Date: Wed, 4 Jun 2025 11:53:42 -0400
Subject: [PATCH] physics performance work
---
.../electrosphere/client/ClientState.java | 3 +-
.../collision/CollisionBodyCreation.java | 2 +-
.../collision/CollisionEngine.java | 211 +++++++++++++----
.../collision/PhysicsCallback.java | 221 ++++++++++++++++++
.../collision/PhysicsEntityUtils.java | 23 +-
.../electrosphere/collision/PhysicsUtils.java | 9 +
.../collision/RayCastCallback.java | 4 +-
.../entity/collidable/CollidableTemplate.java | 22 ++
.../server/datacell/RealmManager.java | 10 +-
.../gridded/GriddedDataCellManager.java | 6 +
.../datacell/physics/PhysicsDataCell.java | 6 +-
.../CollisionEngineStaticSpaceTests.java | 78 +++++++
12 files changed, 526 insertions(+), 69 deletions(-)
create mode 100644 src/main/java/electrosphere/collision/PhysicsCallback.java
create mode 100644 src/test/java/electrosphere/collision/CollisionEngineStaticSpaceTests.java
diff --git a/src/main/java/electrosphere/client/ClientState.java b/src/main/java/electrosphere/client/ClientState.java
index 1d5b9d7f..a64f7462 100644
--- a/src/main/java/electrosphere/client/ClientState.java
+++ b/src/main/java/electrosphere/client/ClientState.java
@@ -16,6 +16,7 @@ import electrosphere.client.terrain.cells.ClientDrawCellManager;
import electrosphere.client.terrain.foliage.FoliageCellManager;
import electrosphere.client.terrain.manager.ClientTerrainManager;
import electrosphere.collision.CollisionEngine;
+import electrosphere.collision.PhysicsCallback;
import electrosphere.data.entity.common.CommonEntityType;
import electrosphere.data.voxel.VoxelType;
import electrosphere.engine.Globals;
@@ -189,7 +190,7 @@ public class ClientState {
* Constructor
*/
public ClientState(){
- this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, new CollisionEngine("clientPhysics"), CollisionEngine.create("clientChem", new ClientChemistryCollisionCallback()), new CollisionEngine("clientInteraction"));
+ this.clientSceneWrapper = new ClientSceneWrapper(this.clientScene, CollisionEngine.create("clientPhysics", new PhysicsCallback()), CollisionEngine.create("clientChem", new ClientChemistryCollisionCallback()), new CollisionEngine("clientInteraction"));
this.clientTemporalService = (ClientTemporalService)Globals.engineState.serviceManager.registerService(new ClientTemporalService());
}
diff --git a/src/main/java/electrosphere/collision/CollisionBodyCreation.java b/src/main/java/electrosphere/collision/CollisionBodyCreation.java
index 09042e07..32172698 100644
--- a/src/main/java/electrosphere/collision/CollisionBodyCreation.java
+++ b/src/main/java/electrosphere/collision/CollisionBodyCreation.java
@@ -264,7 +264,7 @@ public class CollisionBodyCreation {
* @param geom the geometry
*/
public static void destroyShape(CollisionEngine collisionEngine, DGeom geom){
- collisionEngine.destroyGeom(geom);
+ collisionEngine.destroyDGeom(geom);
}
/**
diff --git a/src/main/java/electrosphere/collision/CollisionEngine.java b/src/main/java/electrosphere/collision/CollisionEngine.java
index f382af42..770bc2e4 100644
--- a/src/main/java/electrosphere/collision/CollisionEngine.java
+++ b/src/main/java/electrosphere/collision/CollisionEngine.java
@@ -26,7 +26,6 @@ import org.ode4j.ode.DGeom.DNearCallback;
import org.ode4j.ode.DJoint;
import org.ode4j.ode.DJointGroup;
import org.ode4j.ode.DMass;
-import org.ode4j.ode.DPlane;
import org.ode4j.ode.DRay;
import org.ode4j.ode.DSpace;
import org.ode4j.ode.DSphere;
@@ -114,12 +113,17 @@ public class CollisionEngine {
/**
* The world object
*/
- private DWorld world;
+ protected DWorld world;
/**
* The main space in the world
*/
- private DBhvSpace space;
+ protected DBhvSpace space;
+
+ /**
+ * Space for storing static geoms
+ */
+ protected DSpace staticGeomSpace;
/**
* Lock for thread-safeing all ODE calls
@@ -129,7 +133,7 @@ public class CollisionEngine {
/**
* The contact group for caching collisions between collision and physics calls
*/
- private DJointGroup contactgroup;
+ protected DJointGroup contactgroup;
/**
* Maximum number of contact points per body
@@ -139,27 +143,27 @@ public class CollisionEngine {
* I used a value of 10 for a long time and found that cubes were sinking into TriMeshes.
*
*/
- private static final int MAX_CONTACTS = 64;
+ protected static final int MAX_CONTACTS = 64;
/**
* The list of dbodies ode should be tracking
*/
- private List bodies = new ArrayList();
+ protected List bodies = new ArrayList();
/**
* This is used to relate DBody's back to their collidables so that when the library detects a collision, the callback can know which collidables are involved.
*/
- private Map bodyPointerMap = new HashMap();
+ protected Map bodyPointerMap = new HashMap();
/**
* This is used to relate DGeom's back to their collidables so that when the library detects a collision, the callback can know which collidables are involved.
*/
- private Map geomPointerMap = new HashMap();
+ protected Map geomPointerMap = new HashMap();
/**
* The list of all collidables the engine is currently tracking
*/
- private List collidableList = new ArrayList();
+ protected List collidableList = new ArrayList();
/**
* Dynamic spatial offset applied to all operations on the space.
@@ -183,16 +187,21 @@ public class CollisionEngine {
*/
private DNearCallback nearCallback;
- /**
- * The base plane of the physics engine
- */
- private DPlane basePlane = null;
-
/**
* Number of geometries
*/
private int geomCount = 0;
+ /**
+ * The near collision count
+ */
+ protected int nearCollisionCount = 0;
+
+ /**
+ * The number of collisions that make it all the way to creating impulses
+ */
+ protected int finalCollisionCount = 0;
+
/**
* Tracks whether the engine has rebased or not
*/
@@ -202,12 +211,12 @@ public class CollisionEngine {
/**
* buffer for storing potential collisions
*/
- private DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS);
+ protected DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS);
/**
* The name of the collision engine
*/
- private final String name;
+ protected final String name;
/**
* Constructor
@@ -222,9 +231,6 @@ public class CollisionEngine {
// world.setContactSurfaceLayer(0.001);
// world.setCFM(1e-10);
- //base plane
- basePlane = OdeHelper.createPlane(space, 0, 1, 0, 0);
-
contactgroup = OdeHelper.createJointGroup();
this.nearCallback = new DNearCallback() {
@Override
@@ -243,6 +249,18 @@ public class CollisionEngine {
return rVal;
}
+ /**
+ * Creates a collision engine with a specified callback
+ */
+ public static CollisionEngine create(String name, PhysicsCallback callback){
+ CollisionEngine rVal = new CollisionEngine(name);
+ rVal.nearCallback = callback;
+ callback.engine = rVal;
+ rVal.staticGeomSpace = OdeHelper.createBHVSpace(Collidable.TYPE_STATIC_BIT);
+ rVal.staticGeomSpace.setCategoryBits(Collidable.TYPE_STATIC_BIT);
+ return rVal;
+ }
+
/**
* Resolves collisions in the engine
@@ -333,6 +351,9 @@ public class CollisionEngine {
public void simulatePhysics(){
Globals.profiler.beginCpuSample("physics");
spaceLock.lock();
+ //reset tracking
+ this.nearCollisionCount = 0;
+ this.finalCollisionCount = 0;
// remove all contact joints
contactgroup.empty();
//main simulation
@@ -340,7 +361,6 @@ public class CollisionEngine {
Globals.profiler.beginCpuSample("collide");
OdeHelper.spaceCollide(space, 0, nearCallback);
Globals.profiler.endCpuSample();
- // space.collide2(space, collisionWorldData, nearCallback);
//simulate physics
Globals.profiler.beginCpuSample("step physics");
@@ -378,8 +398,16 @@ public class CollisionEngine {
* @param o2 the second collision body
*/
private void nearCallback(Object data, DGeom o1, DGeom o2){
+ if(this.name.equals("serverPhysics")){
+ this.nearCollisionCount++;
+ }
// if (o1->body && o2->body) return;
+ //ie if both are in static space
+ if(o1 == o2){
+ return;
+ }
+
//if the collision is static-on-static, skip
if(o1.getCategoryBits() == Collidable.TYPE_STATIC_BIT && o2.getCategoryBits() == Collidable.TYPE_STATIC_BIT){
return;
@@ -400,11 +428,6 @@ public class CollisionEngine {
return;
}
- //check if we're colliding against the base plane
- if(o1 == this.basePlane || o2 == this.basePlane){
- return;
- }
-
//get the collidables for each geom
Collidable c1 = null;
if(b1 != null){
@@ -444,59 +467,118 @@ public class CollisionEngine {
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - Full collision phase");
try {
+ Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - setup");
//null out the contact buffer
contacts.nullify();
SurfaceParams surfaceParams1 = c1.getSurfaceParams();
- SurfaceParams surfaceParams2 = c2.getSurfaceParams();
+ SurfaceParams surfaceParams2 = null;
+ if(c2 != null){
+ surfaceParams2 = c2.getSurfaceParams();
+ }
for (int i=0; i