diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md
index 60c809e0..12c49bba 100644
--- a/docs/src/progress/renderertodo.md
+++ b/docs/src/progress/renderertodo.md
@@ -1928,6 +1928,7 @@ Fix town placement structure-road intersection test
(05/21/2025)
Kinematic collision templates now use geoms instead of setting kinematic (on client)
+Geom-only collidables on server
diff --git a/src/main/java/electrosphere/collision/CollisionEngine.java b/src/main/java/electrosphere/collision/CollisionEngine.java
index 264ba5a4..55c59ab7 100644
--- a/src/main/java/electrosphere/collision/CollisionEngine.java
+++ b/src/main/java/electrosphere/collision/CollisionEngine.java
@@ -25,6 +25,7 @@ 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;
@@ -94,16 +95,31 @@ public class CollisionEngine {
*/
public static final double DEFAULT_INTERACT_DISTANCE = 5.0;
- //world data that the collision engine leverages for position correction and the like
- CollisionWorldData collisionWorldData;
+ /**
+ * world data that the collision engine leverages for position correction and the like
+ */
+ private CollisionWorldData collisionWorldData;
- //Ode-specific stuff
+ /**
+ * The world object
+ */
private DWorld world;
+
+ /**
+ * The main space in the world
+ */
private DSpace space;
+
+ /**
+ * Lock for thread-safeing all ODE calls
+ */
private static ReentrantLock spaceLock = new ReentrantLock();
+
+ /**
+ * The contact group for caching collisions between collision and physics calls
+ */
private DJointGroup contactgroup;
- // maximum number of contact points per body
/**
*
Maximum number of contact points per body
* Note:
@@ -114,38 +130,57 @@ public class CollisionEngine {
*/
private static final int MAX_CONTACTS = 64;
- //The list of dbodies ode should be tracking
- List bodies = new ArrayList();
+ /**
+ * The list of dbodies ode should be tracking
+ */
+ private 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.
- Map bodyPointerMap = new HashMap();
+ /**
+ * 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();
- //The list of all collidables the engine is currently tracking
- List collidableList = new ArrayList();
+ /**
+ * 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();
+
+ /**
+ * The list of all collidables the engine is currently tracking
+ */
+ private List collidableList = new ArrayList();
/**
* Dynamic spatial offset applied to all operations on the space.
* This is used for world origin rebasing.
* This makes physics behave more consistently by moving far out objects to center around 0,0,0.
*/
- Vector3d floatingOrigin = new Vector3d(0,0,0);
+ private Vector3d floatingOrigin = new Vector3d(0,0,0);
- //callbacks for collision check
- RayCastCallback rayCastCallback = new RayCastCallback();
+ /**
+ * callbacks for collision check
+ */
+ private RayCastCallback rayCastCallback = new RayCastCallback();
- //the collision resolution callback
- CollisionResolutionCallback collisionResolutionCallback;
-
- //buffer for collisions
- DContactBuffer contacts = null;
+ /**
+ * the collision resolution callback
+ */
+ private CollisionResolutionCallback collisionResolutionCallback;
/**
* The body that contains all static shapes
*/
- DBody staticBody;
+ private DBody staticBody;
- // Callback for any near collisions in the broadphase of the collision check
+ /**
+ * Callback for any near collisions in the broadphase of the collision check
+ */
private DNearCallback nearCallback;
+
+ /**
+ * The base plane of the physics engine
+ */
+ private DPlane basePlane = null;
/**
* Constructor
@@ -160,7 +195,7 @@ public class CollisionEngine {
// world.setCFM(1e-10);
//base plane
- OdeHelper.createPlane(space, 0, 1, 0, 0);
+ basePlane = OdeHelper.createPlane(space, 0, 1, 0, 0);
//static body
staticBody = this.createDBody();
@@ -271,6 +306,9 @@ public class CollisionEngine {
public void simulatePhysics(float time){
Globals.profiler.beginCpuSample("physics");
spaceLock.lock();
+ // remove all contact joints
+ contactgroup.empty();
+ //main simulation
for(int i = 0; i < PHYSICS_SIMULATION_RESOLUTION; i++){
Globals.profiler.beginCpuSample("collide");
OdeHelper.spaceCollide(space, 0, nearCallback);
@@ -295,6 +333,7 @@ public class CollisionEngine {
public void collide(){
Globals.profiler.beginCpuSample("physics");
spaceLock.lock();
+ contactgroup.empty();
Globals.profiler.beginCpuSample("collide");
OdeHelper.spaceCollide(space, 0, nearCallback);
Globals.profiler.endCpuSample();
@@ -336,19 +375,52 @@ public class CollisionEngine {
}
//if collision is between static and disabled, skip
- if(o1.getCategoryBits() == Collidable.TYPE_STATIC_BIT && !b2.isEnabled()){
+ if(o1.getCategoryBits() == Collidable.TYPE_STATIC_BIT && b2 != null && !b2.isEnabled()){
return;
}
- if(o2.getCategoryBits() == Collidable.TYPE_STATIC_BIT && !b1.isEnabled()){
+ if(o2.getCategoryBits() == Collidable.TYPE_STATIC_BIT && b1 != null && !b1.isEnabled()){
return;
}
- Collidable c1 = bodyPointerMap.get(b1);
- Collidable c2 = bodyPointerMap.get(b2);
- if(c1 == null || c2 == null){
+ //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){
+ c1 = bodyPointerMap.get(b1);
+ } else if(o1.getBody() == null) {
+ c1 = geomPointerMap.get(o1);
+ }
+ Collidable c2 = null;
+ if(b2 != null){
+ c2 = bodyPointerMap.get(b2);
+ } else if(o2.getBody() == null) {
+ c2 = geomPointerMap.get(o2);
+ }
+
+ //make sure we have collidables for both
+ if(c1 == null || c2 == null){
+ String message = "Collidable is undefined!\n" +
+ o1 + " \n" +
+ o2 + " \n" +
+ b1 + " \n" +
+ b2 + " \n" +
+ c1 + " \n" +
+ c2 + " \n" +
+ "Obj 1 pointers:\n" +
+ this.bodyPointerMap.get(b1) + " \n" +
+ this.geomPointerMap.get(o1) + " \n" +
+ "Obj 2 pointers:\n" +
+ this.bodyPointerMap.get(b2) + " \n" +
+ this.geomPointerMap.get(o2) + " \n" +
+ ""
+ ;
+ throw new Error(message);
+ }
+
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - try collisions");
try {
//creates a buffer to store potential collisions
@@ -415,14 +487,20 @@ public class CollisionEngine {
//
//add contact to contact group
DJoint c = OdeHelper.createContactJoint(world,contactgroup,contact);
- c.attach(b1,b2);
+ if(b1 == null){
+ c.attach(b2,null);
+ } else if(b2 == null){
+ c.attach(b1,null);
+ } else {
+ c.attach(b1,b2);
+ }
// Use the default collision resolution
if(collisionResolutionCallback == null) {
CollisionEngine.resolveCollision(
contact.geom,
- bodyPointerMap.get(o1.getBody()),
- bodyPointerMap.get(o2.getBody()),
+ c1,
+ c2,
PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0),
PhysicsUtils.odeVecToJomlVec(contact.fdir1).mul(-1.0),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
@@ -430,8 +508,8 @@ public class CollisionEngine {
);
CollisionEngine.resolveCollision(
contact.geom,
- bodyPointerMap.get(o2.getBody()),
- bodyPointerMap.get(o1.getBody()),
+ c1,
+ c2,
PhysicsUtils.odeVecToJomlVec(contact.geom.normal),
PhysicsUtils.odeVecToJomlVec(contact.fdir1),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
@@ -443,8 +521,8 @@ public class CollisionEngine {
contact.geom,
o1,
o2,
- bodyPointerMap.get(o1.getBody()),
- bodyPointerMap.get(o2.getBody()),
+ c1,
+ c2,
PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0),
PhysicsUtils.odeVecToJomlVec(contact.fdir1).mul(-1.0),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
@@ -454,8 +532,8 @@ public class CollisionEngine {
contact.geom,
o2,
o1,
- bodyPointerMap.get(o2.getBody()),
- bodyPointerMap.get(o1.getBody()),
+ c2,
+ c1,
PhysicsUtils.odeVecToJomlVec(contact.geom.normal),
PhysicsUtils.odeVecToJomlVec(contact.fdir1),
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
@@ -566,6 +644,14 @@ public class CollisionEngine {
newRotation = PhysicsUtils.getRigidBodyRotation(rigidBody);
} else {
newRotation = PhysicsUtils.getGeomRotation(geom);
+ if(geom instanceof DCylinder || geom instanceof DCapsule){
+ newRotation.rotateX(-Math.PI/2.0);
+ }
+ }
+ if(geom != null){
+ CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(physicsEntity);
+ suggestedPosition.sub(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ());
+ newRotation.mul(new Quaterniond(template.getRotX(),template.getRotY(),template.getRotZ(),template.getRotW()).invert());
}
EntityUtils.getPosition(physicsEntity).set(suggestedPosition);
EntityUtils.getRotation(physicsEntity).set(newRotation);
@@ -612,6 +698,11 @@ public class CollisionEngine {
Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(rigidBody.getPosition());
rigidBody.setPosition(PhysicsUtils.jomlVecToOdeVec(existingPosition.add(delta)));
}
+ DGeom geom = PhysicsEntityUtils.getDGeom(physicsEntity);
+ if(geom != null){
+ Vector3d existingPosition = PhysicsUtils.odeVecToJomlVec(geom.getPosition());
+ geom.setPosition(PhysicsUtils.jomlVecToOdeVec(existingPosition.add(delta)));
+ }
}
}
spaceLock.unlock();
@@ -624,6 +715,9 @@ public class CollisionEngine {
* @param collidable The corresponding collidable
*/
public void registerCollisionObject(DBody body, Collidable collidable){
+ if(collidable == null){
+ throw new Error("Collidable is null!");
+ }
spaceLock.lock();
this.registerPhysicsObject(body);
bodyPointerMap.put(body,collidable);
@@ -631,6 +725,21 @@ public class CollisionEngine {
spaceLock.unlock();
}
+ /**
+ * Registers a collision object with the server
+ * @param geom The geom
+ * @param collidable The corresponding collidable
+ */
+ public void registerCollisionObject(DGeom geom, Collidable collidable){
+ if(collidable == null){
+ throw new Error("Collidable is null!");
+ }
+ spaceLock.lock();
+ geomPointerMap.put(geom,collidable);
+ collidableList.add(collidable);
+ spaceLock.unlock();
+ }
+
/**
* Deregisters a collidable from the physics engine
* @param collidable The collidable
@@ -765,7 +874,6 @@ public class CollisionEngine {
while(geomIterator.hasNext()){
DGeom geom = geomIterator.next();
space.remove(geom);
- geom.DESTRUCTOR();
geom.destroy();
}
//destroy all joints
@@ -1102,8 +1210,12 @@ public class CollisionEngine {
*/
protected void setGeomTransform(DGeom geom, Vector3d position, Quaterniond rotation){
spaceLock.lock();
- geom.setPosition(position.x, position.y, position.z);
- geom.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
+ geom.setPosition(position.x - this.floatingOrigin.x, position.y - this.floatingOrigin.y, position.z - this.floatingOrigin.z);
+ if(geom instanceof DCylinder || geom instanceof DCapsule){
+ geom.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(new Quaterniond(rotation).rotateX(Math.PI/2.0)));
+ } else {
+ geom.setQuaternion(PhysicsUtils.jomlQuatToOdeQuat(rotation));
+ }
spaceLock.unlock();
}
diff --git a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java
index 6abce99f..c759f5f6 100644
--- a/src/main/java/electrosphere/collision/PhysicsEntityUtils.java
+++ b/src/main/java/electrosphere/collision/PhysicsEntityUtils.java
@@ -58,8 +58,6 @@ public class PhysicsEntityUtils {
* @param physicsTemplate The collidable template
*/
public static void clientAttachCollidableTemplate(Entity rVal, CollidableTemplate physicsTemplate){
- DBody rigidBody = null;
- DGeom geom = null;
Collidable collidable;
double mass = 1.0f;
CollisionEngine engine = Globals.clientState.clientSceneWrapper.getCollisionEngine();
@@ -71,6 +69,7 @@ public class PhysicsEntityUtils {
categoryBit = Collidable.TYPE_STATIC_BIT;
}
if(physicsTemplate.getKinematic()){
+ DGeom geom = null;
switch(physicsTemplate.getType()){
case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
@@ -97,8 +96,8 @@ public class PhysicsEntityUtils {
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
- Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
+ engine.registerCollisionObject(geom, collidable);
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
//
@@ -125,8 +124,8 @@ public class PhysicsEntityUtils {
rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
- Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
+ engine.registerCollisionObject(geom, collidable);
} break;
case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
//
@@ -156,11 +155,12 @@ public class PhysicsEntityUtils {
rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
- Globals.clientState.clientSceneWrapper.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
+ engine.registerCollisionObject(geom, collidable);
} break;
}
} else {
+ DBody rigidBody = null;
switch(physicsTemplate.getType()){
case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
@@ -359,10 +359,10 @@ public class PhysicsEntityUtils {
Globals.clientState.clientScene.registerEntityToTag(rVal, EntityTags.COLLIDABLE);
} break;
}
- }
- //if we successfully attached the body, add a sync tree
- if(rigidBody != null){
- ClientPhysicsSyncTree.attachTree(rVal);
+ //if we successfully attached the body, add a sync tree
+ if(rigidBody != null){
+ ClientPhysicsSyncTree.attachTree(rVal);
+ }
}
}
@@ -374,7 +374,6 @@ public class PhysicsEntityUtils {
* @param physicsTemplate The collidable template
*/
public static void serverAttachCollidableTemplate(Realm realm, Entity rVal, CollidableTemplate physicsTemplate){
- DBody rigidBody = null;
Collidable collidable;
double mass = 1.0f;
if(physicsTemplate.getMass() != null){
@@ -384,208 +383,308 @@ public class PhysicsEntityUtils {
if(physicsTemplate.getKinematic()){
categoryBit = Collidable.TYPE_STATIC_BIT;
}
- switch(physicsTemplate.getType()){
- case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
+ if(physicsTemplate.getKinematic()){
+ DGeom geom = null;
+ switch(physicsTemplate.getType()){
+ case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
- //
- //create dbody
- rigidBody = CollisionBodyCreation.createCylinderBody(
- realm.getCollisionEngine(),
- physicsTemplate.getDimension1(),
- physicsTemplate.getDimension2(),
- categoryBit
- );
- if(physicsTemplate.getMass() != null){
- CollisionBodyCreation.setCylinderMass(
+ //
+ //create dbody
+ geom = CollisionBodyCreation.createCylinderShape(
realm.getCollisionEngine(),
- rigidBody,
- mass,
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
- new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
- new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
+ categoryBit
);
- }
- CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), rigidBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
- //
- //set offset from entity center
- CollisionBodyCreation.setOffsetPosition(
- realm.getCollisionEngine(),
- rigidBody,
- new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
- );
+ //
+ //create collidable and attach tracking
+ collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
+ PhysicsEntityUtils.setDGeom(rVal, geom);
- //
- //create collidable and attach tracking
- collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
- if(physicsTemplate.getLinearFriction() != null){
- collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
- }
- if(physicsTemplate.getRollingFriction() != null){
- collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
- }
- ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
- PhysicsEntityUtils.setDBody(rVal,rigidBody);
+ //
+ //store data
+ 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);
- //
- //store data
- 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
- );
- if(physicsTemplate.isAngularlyStatic()){
- realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
- }
- if(physicsTemplate.getKinematic()){
- Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
- rigidBody.disable();
- }
- rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
- rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
- rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
- rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
+ rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
- rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
-
- realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
- ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
- } break;
- case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
- //
- //create dbody
- rigidBody = CollisionBodyCreation.createCubeBody(
- realm.getCollisionEngine(),
- new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
- categoryBit
- );
- if(physicsTemplate.getMass() != null){
- CollisionBodyCreation.setBoxMass(
+ ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
+ realm.getCollisionEngine().registerCollisionObject(geom, collidable);
+ } break;
+ case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
+ //
+ //create dbody
+ geom = CollisionBodyCreation.createCubeShape(
realm.getCollisionEngine(),
- rigidBody,
- mass,
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
- new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
- new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
+ categoryBit
);
- }
- CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), rigidBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
- //
- //set offset from entity center
- CollisionBodyCreation.setOffsetPosition(
- realm.getCollisionEngine(),
- rigidBody,
- new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
- );
+ //
+ //create collidable and attach tracking
+ collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
+ PhysicsEntityUtils.setDGeom(rVal, geom);
- //
- //create collidable and attach tracking
- collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
- if(physicsTemplate.getLinearFriction() != null){
- collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
- }
- if(physicsTemplate.getRollingFriction() != null){
- collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
- }
- ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
- PhysicsEntityUtils.setDBody(rVal,rigidBody);
+ //
+ //store data
+ 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);
- //
- //store data
- 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
- );
- if(physicsTemplate.isAngularlyStatic()){
- realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
- }
- if(physicsTemplate.getKinematic()){
- Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
- rigidBody.disable();
- }
- rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
- rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
- rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
- rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
+ rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
- rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
-
- realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
- ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
- } break;
- case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
- //
- //create dbody
- rigidBody = CollisionBodyCreation.createCapsuleBody(
- realm.getCollisionEngine(),
- physicsTemplate.getDimension1(),
- physicsTemplate.getDimension2(),
- categoryBit
- );
- if(physicsTemplate.getMass() != null){
- CollisionBodyCreation.setCapsuleMass(
+ ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
+ realm.getCollisionEngine().registerCollisionObject(geom, collidable);
+ } break;
+ case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
+ //
+ //create dbody
+ geom = CollisionBodyCreation.createCapsuleShape(
realm.getCollisionEngine(),
- rigidBody,
- mass,
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2(),
- new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
- new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
+ categoryBit
);
- }
- CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), rigidBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
- //
- //set offset from entity center
- CollisionBodyCreation.setOffsetPosition(
- realm.getCollisionEngine(),
- rigidBody,
- new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
- );
+ //
+ //create collidable and attach tracking
+ collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
+ PhysicsEntityUtils.setDGeom(rVal, geom);
- //
- //create collidable and attach tracking
- collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
- if(physicsTemplate.getLinearFriction() != null){
- collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
- }
- if(physicsTemplate.getRollingFriction() != null){
- collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
- }
- ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
- PhysicsEntityUtils.setDBody(rVal,rigidBody);
+ //
+ //store data
+ 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);
- //
- //store data
- 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
- );
- if(physicsTemplate.isAngularlyStatic()){
- realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
- }
- if(physicsTemplate.getKinematic()){
- Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
- rigidBody.disable();
- }
- rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
- rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
- rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
- rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
+ rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
- rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
+ ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
+ realm.getCollisionEngine().registerCollisionObject(geom, collidable);
+ } break;
+ }
+ } else {
+ DBody rigidBody = null;
+ switch(physicsTemplate.getType()){
+ case CollidableTemplate.COLLIDABLE_TYPE_CYLINDER: {
- realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
- ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
- } break;
- }
- //if we successfully attached the body, add a sync tree
- if(rigidBody != null){
- ServerPhysicsSyncTree.attachTree(rVal);
+ //
+ //create dbody
+ rigidBody = CollisionBodyCreation.createCylinderBody(
+ realm.getCollisionEngine(),
+ physicsTemplate.getDimension1(),
+ physicsTemplate.getDimension2(),
+ categoryBit
+ );
+ if(physicsTemplate.getMass() != null){
+ CollisionBodyCreation.setCylinderMass(
+ realm.getCollisionEngine(),
+ rigidBody,
+ mass,
+ physicsTemplate.getDimension1(),
+ physicsTemplate.getDimension2(),
+ new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
+ new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
+ );
+ }
+ CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), rigidBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
+
+ //
+ //set offset from entity center
+ CollisionBodyCreation.setOffsetPosition(
+ realm.getCollisionEngine(),
+ rigidBody,
+ new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
+ );
+
+ //
+ //create collidable and attach tracking
+ collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
+ if(physicsTemplate.getLinearFriction() != null){
+ collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
+ }
+ if(physicsTemplate.getRollingFriction() != null){
+ collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
+ }
+ ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
+ PhysicsEntityUtils.setDBody(rVal,rigidBody);
+
+ //
+ //store data
+ 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
+ );
+ if(physicsTemplate.isAngularlyStatic()){
+ realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
+ }
+ if(physicsTemplate.getKinematic()){
+ Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
+ rigidBody.disable();
+ }
+ rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
+ rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
+ rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
+ rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
+
+ rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
+
+ realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
+ ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
+ } break;
+ case CollidableTemplate.COLLIDABLE_TYPE_CUBE: {
+ //
+ //create dbody
+ rigidBody = CollisionBodyCreation.createCubeBody(
+ realm.getCollisionEngine(),
+ new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
+ categoryBit
+ );
+ if(physicsTemplate.getMass() != null){
+ CollisionBodyCreation.setBoxMass(
+ realm.getCollisionEngine(),
+ rigidBody,
+ mass,
+ new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
+ new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
+ new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
+ );
+ }
+ CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), rigidBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
+
+ //
+ //set offset from entity center
+ CollisionBodyCreation.setOffsetPosition(
+ realm.getCollisionEngine(),
+ rigidBody,
+ new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
+ );
+
+ //
+ //create collidable and attach tracking
+ collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
+ if(physicsTemplate.getLinearFriction() != null){
+ collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
+ }
+ if(physicsTemplate.getRollingFriction() != null){
+ collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
+ }
+ ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
+ PhysicsEntityUtils.setDBody(rVal,rigidBody);
+
+ //
+ //store data
+ 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
+ );
+ if(physicsTemplate.isAngularlyStatic()){
+ realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
+ }
+ if(physicsTemplate.getKinematic()){
+ Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
+ rigidBody.disable();
+ }
+ rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
+ rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
+ rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
+ rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
+
+ rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
+
+ realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
+ ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
+ } break;
+ case CollidableTemplate.COLLIDABLE_TYPE_CAPSULE: {
+ //
+ //create dbody
+ rigidBody = CollisionBodyCreation.createCapsuleBody(
+ realm.getCollisionEngine(),
+ physicsTemplate.getDimension1(),
+ physicsTemplate.getDimension2(),
+ categoryBit
+ );
+ if(physicsTemplate.getMass() != null){
+ CollisionBodyCreation.setCapsuleMass(
+ realm.getCollisionEngine(),
+ rigidBody,
+ mass,
+ physicsTemplate.getDimension1(),
+ physicsTemplate.getDimension2(),
+ new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ()),
+ new Quaterniond(physicsTemplate.getRotX(), physicsTemplate.getRotY(), physicsTemplate.getRotZ(), physicsTemplate.getRotW())
+ );
+ }
+ CollisionBodyCreation.setAutoDisable(realm.getCollisionEngine(), rigidBody, true, LINEAR_THRESHOLD, ANGULAR_THRESHOLD, STEP_THRESHOLD);
+
+ //
+ //set offset from entity center
+ CollisionBodyCreation.setOffsetPosition(
+ realm.getCollisionEngine(),
+ rigidBody,
+ new Vector3d(physicsTemplate.getOffsetX(), physicsTemplate.getOffsetY(), physicsTemplate.getOffsetZ())
+ );
+
+ //
+ //create collidable and attach tracking
+ collidable = new Collidable(rVal, Collidable.TYPE_CREATURE, true);
+ if(physicsTemplate.getLinearFriction() != null){
+ collidable.getSurfaceParams().setLinearFriction(physicsTemplate.getLinearFriction());
+ }
+ if(physicsTemplate.getRollingFriction() != null){
+ collidable.getSurfaceParams().setRollingFriction(physicsTemplate.getRollingFriction());
+ }
+ ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
+ PhysicsEntityUtils.setDBody(rVal,rigidBody);
+
+ //
+ //store data
+ 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
+ );
+ if(physicsTemplate.isAngularlyStatic()){
+ realm.getCollisionEngine().setAngularlyStatic(rigidBody, true);
+ }
+ if(physicsTemplate.getKinematic()){
+ Globals.clientState.clientSceneWrapper.getCollisionEngine().setKinematic(rigidBody);
+ rigidBody.disable();
+ }
+ rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY_TRANSFORM, offsetTransform);
+ rVal.putData(EntityDataStrings.PHYSICS_MODEL_TEMPLATE, physicsTemplate);
+ rVal.putData(EntityDataStrings.PHYSICS_COLLIDABLE, collidable);
+ rVal.putData(EntityDataStrings.SERVER_COLLIDABLE_TREE, tree);
+
+ rVal.putData(EntityDataStrings.PHYSICS_MASS, mass);
+
+ realm.getCollisionEngine().registerCollisionObject(rigidBody, collidable);
+ ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
+ } break;
+ }
+ //if we successfully attached the body, add a sync tree
+ if(rigidBody != null){
+ ServerPhysicsSyncTree.attachTree(rVal);
+ }
}
}
diff --git a/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java b/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java
index f209e3aa..c3f46a56 100644
--- a/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java
+++ b/src/main/java/electrosphere/entity/types/collision/CollisionObjUtils.java
@@ -9,6 +9,7 @@ import electrosphere.collision.CollisionEngine;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable;
+import electrosphere.data.entity.collidable.CollidableTemplate;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
@@ -75,10 +76,20 @@ public class CollisionObjUtils {
EntityUtils.getPosition(e).set(position);
Quaterniond rotation = EntityUtils.getRotation(e);
DBody body = PhysicsEntityUtils.getDBody(e);
+ DGeom geom = PhysicsEntityUtils.getDGeom(e);
CollisionEngine collisionEngine = Globals.serverState.realmManager.getEntityRealm(e).getCollisionEngine();
if(body != null){
PhysicsUtils.setRigidBodyTransform(collisionEngine, position, rotation, body);
}
+ if(geom != null){
+ CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e);
+ PhysicsUtils.setGeomTransform(
+ collisionEngine,
+ new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()),
+ rotation,
+ geom
+ );
+ }
}
/**
@@ -95,7 +106,13 @@ public class CollisionObjUtils {
}
DGeom geom = PhysicsEntityUtils.getDGeom(e);
if(geom != null){
- PhysicsUtils.setGeomTransform(Globals.clientState.clientSceneWrapper.getCollisionEngine(), position, rotation, geom);
+ CollidableTemplate template = PhysicsEntityUtils.getPhysicsTemplate(e);
+ PhysicsUtils.setGeomTransform(
+ Globals.clientState.clientSceneWrapper.getCollisionEngine(),
+ new Vector3d(position).add(template.getOffsetX(),template.getOffsetY(),template.getOffsetZ()),
+ rotation,
+ geom
+ );
}
}
diff --git a/src/main/java/electrosphere/server/physics/collision/ServerHitboxResolutionCallback.java b/src/main/java/electrosphere/server/physics/collision/ServerHitboxResolutionCallback.java
index 5a6c1bc4..8fbf8d97 100644
--- a/src/main/java/electrosphere/server/physics/collision/ServerHitboxResolutionCallback.java
+++ b/src/main/java/electrosphere/server/physics/collision/ServerHitboxResolutionCallback.java
@@ -33,43 +33,45 @@ public class ServerHitboxResolutionCallback implements CollisionResolutionCallba
//basic error checking
if(impactorEntity == null){
- throw new IllegalStateException("Impactor's entity is null");
+ throw new Error("Impactor's entity is null");
}
if(receiverEntity == null){
- throw new IllegalStateException("Receiver's entity is null");
+ throw new Error("Receiver's entity is null");
}
if(!HitboxCollectionState.hasHitboxState(impactorEntity)){
- throw new IllegalStateException("Impactor state is null");
+ throw new Error("Impactor state is null");
}
if(!HitboxCollectionState.hasHitboxState(receiverEntity)){
- throw new IllegalStateException("Receiver state is null");
+ throw new Error("Receiver state is null");
}
if(impactorGeom == null){
- throw new IllegalStateException("Impactor geom is null");
+ throw new Error("Impactor geom is null");
}
if(receiverGeom == null){
- throw new IllegalStateException("Receiver geom is null");
+ throw new Error("Receiver geom is null");
}
if(!impactorState.getGeometries().contains(impactorGeom)){
+ boolean receiverStateContainsGeom = receiverState.getGeometries().contains(impactorGeom);
String message = "Impactor geom has wrong parent assigned!\n" +
"Problem geom: " + impactorGeom + "\n" +
- "All geometries tracked: " + impactorState.getGeometries() + "n\""
+ "All geometries tracked: " + impactorState.getGeometries() + "\n" +
+ "Receiver contains impactor: " + receiverStateContainsGeom + "\n"
;
- throw new IllegalStateException(message);
+ throw new Error(message);
}
if(impactorShapeStatus == null){
String message = "Impactor shape status is null\n" +
"Problem geom: " + impactorGeom + "\n" +
"All geometries tracked: " + impactorState.getGeometries() + "n\""
;
- throw new IllegalStateException(message);
+ throw new Error(message);
}
if(receiverShapeStatus == null){
String message = "Receiver shape status is null\n" +
"Problem geom: " + receiverGeom + "\n" +
"All geometries tracked: " + receiverState.getGeometries() + "n\""
;
- throw new IllegalStateException(message);
+ throw new Error(message);
}
diff --git a/src/main/java/electrosphere/server/simulation/MicroSimulation.java b/src/main/java/electrosphere/server/simulation/MicroSimulation.java
index 53758231..c67f1106 100644
--- a/src/main/java/electrosphere/server/simulation/MicroSimulation.java
+++ b/src/main/java/electrosphere/server/simulation/MicroSimulation.java
@@ -64,7 +64,9 @@ public class MicroSimulation {
//sum collidable impulses
Set collidables = dataCell.getScene().getEntitiesWithTag(EntityTags.COLLIDABLE);
for(Entity collidable : collidables){
- ServerCollidableTree.getServerCollidableTree(collidable).simulate((float)Globals.engineState.timekeeper.getSimFrameTime());
+ if(ServerCollidableTree.hasServerCollidableTree(collidable)){
+ ServerCollidableTree.getServerCollidableTree(collidable).simulate((float)Globals.engineState.timekeeper.getSimFrameTime());
+ }
}
//update actor transform caches
poseableEntities = dataCell.getScene().getEntitiesWithTag(EntityTags.POSEABLE);