physics performance work
This commit is contained in:
parent
81337d0eb9
commit
aa0956477d
@ -16,6 +16,7 @@ import electrosphere.client.terrain.cells.ClientDrawCellManager;
|
|||||||
import electrosphere.client.terrain.foliage.FoliageCellManager;
|
import electrosphere.client.terrain.foliage.FoliageCellManager;
|
||||||
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
import electrosphere.client.terrain.manager.ClientTerrainManager;
|
||||||
import electrosphere.collision.CollisionEngine;
|
import electrosphere.collision.CollisionEngine;
|
||||||
|
import electrosphere.collision.PhysicsCallback;
|
||||||
import electrosphere.data.entity.common.CommonEntityType;
|
import electrosphere.data.entity.common.CommonEntityType;
|
||||||
import electrosphere.data.voxel.VoxelType;
|
import electrosphere.data.voxel.VoxelType;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
@ -189,7 +190,7 @@ public class ClientState {
|
|||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public ClientState(){
|
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());
|
this.clientTemporalService = (ClientTemporalService)Globals.engineState.serviceManager.registerService(new ClientTemporalService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -264,7 +264,7 @@ public class CollisionBodyCreation {
|
|||||||
* @param geom the geometry
|
* @param geom the geometry
|
||||||
*/
|
*/
|
||||||
public static void destroyShape(CollisionEngine collisionEngine, DGeom geom){
|
public static void destroyShape(CollisionEngine collisionEngine, DGeom geom){
|
||||||
collisionEngine.destroyGeom(geom);
|
collisionEngine.destroyDGeom(geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -26,7 +26,6 @@ import org.ode4j.ode.DGeom.DNearCallback;
|
|||||||
import org.ode4j.ode.DJoint;
|
import org.ode4j.ode.DJoint;
|
||||||
import org.ode4j.ode.DJointGroup;
|
import org.ode4j.ode.DJointGroup;
|
||||||
import org.ode4j.ode.DMass;
|
import org.ode4j.ode.DMass;
|
||||||
import org.ode4j.ode.DPlane;
|
|
||||||
import org.ode4j.ode.DRay;
|
import org.ode4j.ode.DRay;
|
||||||
import org.ode4j.ode.DSpace;
|
import org.ode4j.ode.DSpace;
|
||||||
import org.ode4j.ode.DSphere;
|
import org.ode4j.ode.DSphere;
|
||||||
@ -114,12 +113,17 @@ public class CollisionEngine {
|
|||||||
/**
|
/**
|
||||||
* The world object
|
* The world object
|
||||||
*/
|
*/
|
||||||
private DWorld world;
|
protected DWorld world;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main space in the 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
|
* 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
|
* The contact group for caching collisions between collision and physics calls
|
||||||
*/
|
*/
|
||||||
private DJointGroup contactgroup;
|
protected DJointGroup contactgroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p> Maximum number of contact points per body </p>
|
* <p> Maximum number of contact points per body </p>
|
||||||
@ -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.
|
* I used a value of 10 for a long time and found that cubes were sinking into TriMeshes.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
private static final int MAX_CONTACTS = 64;
|
protected static final int MAX_CONTACTS = 64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of dbodies ode should be tracking
|
* The list of dbodies ode should be tracking
|
||||||
*/
|
*/
|
||||||
private List<DBody> bodies = new ArrayList<DBody>();
|
protected List<DBody> bodies = new ArrayList<DBody>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* 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<DBody,Collidable> bodyPointerMap = new HashMap<DBody,Collidable>();
|
protected Map<DBody,Collidable> bodyPointerMap = new HashMap<DBody,Collidable>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* 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<DGeom,Collidable> geomPointerMap = new HashMap<DGeom,Collidable>();
|
protected Map<DGeom,Collidable> geomPointerMap = new HashMap<DGeom,Collidable>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of all collidables the engine is currently tracking
|
* The list of all collidables the engine is currently tracking
|
||||||
*/
|
*/
|
||||||
private List<Collidable> collidableList = new ArrayList<Collidable>();
|
protected List<Collidable> collidableList = new ArrayList<Collidable>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic spatial offset applied to all operations on the space.
|
* Dynamic spatial offset applied to all operations on the space.
|
||||||
@ -183,16 +187,21 @@ public class CollisionEngine {
|
|||||||
*/
|
*/
|
||||||
private DNearCallback nearCallback;
|
private DNearCallback nearCallback;
|
||||||
|
|
||||||
/**
|
|
||||||
* The base plane of the physics engine
|
|
||||||
*/
|
|
||||||
private DPlane basePlane = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of geometries
|
* Number of geometries
|
||||||
*/
|
*/
|
||||||
private int geomCount = 0;
|
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
|
* Tracks whether the engine has rebased or not
|
||||||
*/
|
*/
|
||||||
@ -202,12 +211,12 @@ public class CollisionEngine {
|
|||||||
/**
|
/**
|
||||||
* buffer for storing potential collisions
|
* 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
|
* The name of the collision engine
|
||||||
*/
|
*/
|
||||||
private final String name;
|
protected final String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -222,9 +231,6 @@ public class CollisionEngine {
|
|||||||
// world.setContactSurfaceLayer(0.001);
|
// world.setContactSurfaceLayer(0.001);
|
||||||
// world.setCFM(1e-10);
|
// world.setCFM(1e-10);
|
||||||
|
|
||||||
//base plane
|
|
||||||
basePlane = OdeHelper.createPlane(space, 0, 1, 0, 0);
|
|
||||||
|
|
||||||
contactgroup = OdeHelper.createJointGroup();
|
contactgroup = OdeHelper.createJointGroup();
|
||||||
this.nearCallback = new DNearCallback() {
|
this.nearCallback = new DNearCallback() {
|
||||||
@Override
|
@Override
|
||||||
@ -243,6 +249,18 @@ public class CollisionEngine {
|
|||||||
return rVal;
|
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
|
* Resolves collisions in the engine
|
||||||
@ -333,6 +351,9 @@ public class CollisionEngine {
|
|||||||
public void simulatePhysics(){
|
public void simulatePhysics(){
|
||||||
Globals.profiler.beginCpuSample("physics");
|
Globals.profiler.beginCpuSample("physics");
|
||||||
spaceLock.lock();
|
spaceLock.lock();
|
||||||
|
//reset tracking
|
||||||
|
this.nearCollisionCount = 0;
|
||||||
|
this.finalCollisionCount = 0;
|
||||||
// remove all contact joints
|
// remove all contact joints
|
||||||
contactgroup.empty();
|
contactgroup.empty();
|
||||||
//main simulation
|
//main simulation
|
||||||
@ -340,7 +361,6 @@ public class CollisionEngine {
|
|||||||
Globals.profiler.beginCpuSample("collide");
|
Globals.profiler.beginCpuSample("collide");
|
||||||
OdeHelper.spaceCollide(space, 0, nearCallback);
|
OdeHelper.spaceCollide(space, 0, nearCallback);
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
// space.collide2(space, collisionWorldData, nearCallback);
|
|
||||||
|
|
||||||
//simulate physics
|
//simulate physics
|
||||||
Globals.profiler.beginCpuSample("step physics");
|
Globals.profiler.beginCpuSample("step physics");
|
||||||
@ -378,8 +398,16 @@ public class CollisionEngine {
|
|||||||
* @param o2 the second collision body
|
* @param o2 the second collision body
|
||||||
*/
|
*/
|
||||||
private void nearCallback(Object data, DGeom o1, DGeom o2){
|
private void nearCallback(Object data, DGeom o1, DGeom o2){
|
||||||
|
if(this.name.equals("serverPhysics")){
|
||||||
|
this.nearCollisionCount++;
|
||||||
|
}
|
||||||
// if (o1->body && o2->body) return;
|
// 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 the collision is static-on-static, skip
|
||||||
if(o1.getCategoryBits() == Collidable.TYPE_STATIC_BIT && o2.getCategoryBits() == Collidable.TYPE_STATIC_BIT){
|
if(o1.getCategoryBits() == Collidable.TYPE_STATIC_BIT && o2.getCategoryBits() == Collidable.TYPE_STATIC_BIT){
|
||||||
return;
|
return;
|
||||||
@ -400,11 +428,6 @@ public class CollisionEngine {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if we're colliding against the base plane
|
|
||||||
if(o1 == this.basePlane || o2 == this.basePlane){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get the collidables for each geom
|
//get the collidables for each geom
|
||||||
Collidable c1 = null;
|
Collidable c1 = null;
|
||||||
if(b1 != null){
|
if(b1 != null){
|
||||||
@ -444,59 +467,118 @@ public class CollisionEngine {
|
|||||||
|
|
||||||
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - Full collision phase");
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - Full collision phase");
|
||||||
try {
|
try {
|
||||||
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - setup");
|
||||||
//null out the contact buffer
|
//null out the contact buffer
|
||||||
contacts.nullify();
|
contacts.nullify();
|
||||||
SurfaceParams surfaceParams1 = c1.getSurfaceParams();
|
SurfaceParams surfaceParams1 = c1.getSurfaceParams();
|
||||||
SurfaceParams surfaceParams2 = c2.getSurfaceParams();
|
SurfaceParams surfaceParams2 = null;
|
||||||
|
if(c2 != null){
|
||||||
|
surfaceParams2 = c2.getSurfaceParams();
|
||||||
|
}
|
||||||
for (int i=0; i<MAX_CONTACTS; i++) {
|
for (int i=0; i<MAX_CONTACTS; i++) {
|
||||||
DContact contact = contacts.get(i);
|
DContact contact = contacts.get(i);
|
||||||
contact.surface.mode = surfaceParams1.getMode();
|
contact.surface.mode = surfaceParams1.getMode();
|
||||||
contact.surface.mu = surfaceParams1.getMu();
|
contact.surface.mu = surfaceParams1.getMu();
|
||||||
if(surfaceParams1.getRho() != null){
|
if(surfaceParams1.getRho() != null){
|
||||||
contact.surface.rho = surfaceParams1.getRho();
|
contact.surface.rho = surfaceParams1.getRho();
|
||||||
} else if(surfaceParams2.getRho() != null){
|
} else if(surfaceParams2 != null && surfaceParams2.getRho() != null){
|
||||||
contact.surface.rho = surfaceParams2.getRho();
|
contact.surface.rho = surfaceParams2.getRho();
|
||||||
}
|
}
|
||||||
if(surfaceParams1.getRho2() != null){
|
if(surfaceParams1.getRho2() != null){
|
||||||
contact.surface.rho2 = surfaceParams1.getRho2();
|
contact.surface.rho2 = surfaceParams1.getRho2();
|
||||||
} else if(surfaceParams2.getRho2() != null){
|
} else if(surfaceParams2 != null && surfaceParams2.getRho2() != null){
|
||||||
contact.surface.rho = surfaceParams2.getRho2();
|
contact.surface.rho = surfaceParams2.getRho2();
|
||||||
}
|
}
|
||||||
if(surfaceParams1.getRhoN() != null){
|
if(surfaceParams1.getRhoN() != null){
|
||||||
contact.surface.rhoN = surfaceParams1.getRhoN();
|
contact.surface.rhoN = surfaceParams1.getRhoN();
|
||||||
} else if(surfaceParams2.getRhoN() != null){
|
} else if(surfaceParams2 != null && surfaceParams2.getRhoN() != null){
|
||||||
contact.surface.rho = surfaceParams2.getRhoN();
|
contact.surface.rho = surfaceParams2.getRhoN();
|
||||||
}
|
}
|
||||||
if(surfaceParams1.getBounce() != null){
|
if(surfaceParams1.getBounce() != null){
|
||||||
contact.surface.bounce = surfaceParams1.getBounce();
|
contact.surface.bounce = surfaceParams1.getBounce();
|
||||||
} else if(surfaceParams2.getBounce() != null){
|
} else if(surfaceParams2 != null && surfaceParams2.getBounce() != null){
|
||||||
contact.surface.rho = surfaceParams2.getBounce();
|
contact.surface.rho = surfaceParams2.getBounce();
|
||||||
}
|
}
|
||||||
if(surfaceParams1.getBounceVel() != null){
|
if(surfaceParams1.getBounceVel() != null){
|
||||||
contact.surface.bounce_vel = surfaceParams1.getBounceVel();
|
contact.surface.bounce_vel = surfaceParams1.getBounceVel();
|
||||||
} else if(surfaceParams2.getBounceVel() != null){
|
} else if(surfaceParams2 != null && surfaceParams2.getBounceVel() != null){
|
||||||
contact.surface.rho = surfaceParams2.getBounceVel();
|
contact.surface.rho = surfaceParams2.getBounceVel();
|
||||||
}
|
}
|
||||||
if(surfaceParams1.getSoftErp() != null){
|
if(surfaceParams1.getSoftErp() != null){
|
||||||
contact.surface.soft_erp = surfaceParams1.getSoftErp();
|
contact.surface.soft_erp = surfaceParams1.getSoftErp();
|
||||||
} else if(surfaceParams2.getSoftErp() != null){
|
} else if(surfaceParams2 != null && surfaceParams2.getSoftErp() != null){
|
||||||
contact.surface.rho = surfaceParams2.getSoftErp();
|
contact.surface.rho = surfaceParams2.getSoftErp();
|
||||||
}
|
}
|
||||||
if(surfaceParams1.getSoftCfm() != null){
|
if(surfaceParams1.getSoftCfm() != null){
|
||||||
contact.surface.soft_cfm = surfaceParams1.getSoftCfm();
|
contact.surface.soft_cfm = surfaceParams1.getSoftCfm();
|
||||||
} else if(surfaceParams2.getSoftCfm() != null){
|
} else if(surfaceParams2 != null && surfaceParams2.getSoftCfm() != null){
|
||||||
contact.surface.rho = surfaceParams2.getSoftCfm();
|
contact.surface.rho = surfaceParams2.getSoftCfm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
//calculate collisions
|
//calculate collisions
|
||||||
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - OdeHelper.collide");
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - OdeHelper.collide");
|
||||||
int numc = OdeHelper.collide(o1,o2,MAX_CONTACTS,contacts.getGeomBuffer());
|
int numc = OdeHelper.collide(o1,o2,MAX_CONTACTS,contacts.getGeomBuffer());
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
//create DContacts based on each collision that occurs
|
//create DContacts based on each collision that occurs
|
||||||
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - contact iterations");
|
||||||
if(numc != 0){
|
if(numc != 0){
|
||||||
for(int i=0; i<numc; i++){
|
for(int i=0; i<numc; i++){
|
||||||
DContact contact = contacts.get(i);
|
DContact contact = contacts.get(i);
|
||||||
|
|
||||||
|
//this triggers if o2 is the static geom space and we did an inner collide to find the geom within that space to collide with
|
||||||
|
if(o2 == this.staticGeomSpace){
|
||||||
|
//get the opposite geom from the collision
|
||||||
|
if(contact.geom.g1 == o1){
|
||||||
|
o2 = contact.geom.g2;
|
||||||
|
} else if(contact.geom.g2 == o1){
|
||||||
|
o2 = contact.geom.g1;
|
||||||
|
} else {
|
||||||
|
String message = "Failed to get collidable from geom within static geom space!\n" +
|
||||||
|
"Geoms:\n" +
|
||||||
|
o1 + " \n" +
|
||||||
|
o2 + " \n" +
|
||||||
|
"Bodies:\n" +
|
||||||
|
b1 + " \n" +
|
||||||
|
b2 + " \n" +
|
||||||
|
"Colliders:\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" +
|
||||||
|
"Contact geoms:\n" +
|
||||||
|
contact.geom.g1 + "\n" +
|
||||||
|
contact.geom.g2 + "\n" +
|
||||||
|
"";
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
c2 = geomPointerMap.get(o2);
|
||||||
|
if(c2 == null){
|
||||||
|
String message = "Failed to get collidable from geom within static geom space!\n" +
|
||||||
|
"Geoms:\n" +
|
||||||
|
o1 + " \n" +
|
||||||
|
o2 + " \n" +
|
||||||
|
"Bodies:\n" +
|
||||||
|
b1 + " \n" +
|
||||||
|
b2 + " \n" +
|
||||||
|
"Colliders:\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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//special code for ray casting
|
//special code for ray casting
|
||||||
if (o1 instanceof DRay || o2 instanceof DRay){
|
if (o1 instanceof DRay || o2 instanceof DRay){
|
||||||
DVector3 end = new DVector3();
|
DVector3 end = new DVector3();
|
||||||
@ -565,8 +647,12 @@ public class CollisionEngine {
|
|||||||
(float)contact.geom.depth
|
(float)contact.geom.depth
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//tracking updates
|
||||||
|
this.finalCollisionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
} catch(ArrayIndexOutOfBoundsException ex){
|
} catch(ArrayIndexOutOfBoundsException ex){
|
||||||
//I've found that ode4j occasionally throws an exception on the OdeHelper.collide function.
|
//I've found that ode4j occasionally throws an exception on the OdeHelper.collide function.
|
||||||
//I don't know why it has out of bounds elements, but it's happening.
|
//I don't know why it has out of bounds elements, but it's happening.
|
||||||
@ -1587,18 +1673,6 @@ public class CollisionEngine {
|
|||||||
geom.setBody(null);
|
geom.setBody(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys a geometry
|
|
||||||
* @param geom The geometry
|
|
||||||
*/
|
|
||||||
protected void destroyGeom(DGeom geom){
|
|
||||||
spaceLock.lock();
|
|
||||||
this.space.remove(geom);
|
|
||||||
geom.destroy();
|
|
||||||
this.geomCount--;
|
|
||||||
spaceLock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a geom to a body
|
* Attaches a geom to a body
|
||||||
* @param body the body
|
* @param body the body
|
||||||
@ -1608,6 +1682,19 @@ public class CollisionEngine {
|
|||||||
geom.setBody(body);
|
geom.setBody(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the geometry to the static geom space
|
||||||
|
* @param staticGeom The geom (ie a cylinder, cube, etc)
|
||||||
|
*/
|
||||||
|
protected void addToStaticSpace(DGeom staticGeom){
|
||||||
|
// spaceLock.lock();
|
||||||
|
// if(staticGeom.getSpace() != null){
|
||||||
|
// staticGeom.getSpace().remove(staticGeom);
|
||||||
|
// }
|
||||||
|
// this.staticGeomSpace.add(staticGeom);
|
||||||
|
// spaceLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the ode library
|
* Locks the ode library
|
||||||
*/
|
*/
|
||||||
@ -1636,6 +1723,8 @@ public class CollisionEngine {
|
|||||||
"Space geom count: " + this.space.getNumGeoms() + "\n" +
|
"Space geom count: " + this.space.getNumGeoms() + "\n" +
|
||||||
"Tracked geom count: " + this.geomCount + "\n" +
|
"Tracked geom count: " + this.geomCount + "\n" +
|
||||||
"Floating origin: " + this.floatingOrigin.x + "," + this.floatingOrigin.y + "," + this.floatingOrigin.z + "\n" +
|
"Floating origin: " + this.floatingOrigin.x + "," + this.floatingOrigin.y + "," + this.floatingOrigin.z + "\n" +
|
||||||
|
"Near Collision Count: " + this.nearCollisionCount + "\n" +
|
||||||
|
"Final Collision Count: " + this.finalCollisionCount + "\n" +
|
||||||
""
|
""
|
||||||
;
|
;
|
||||||
return message;
|
return message;
|
||||||
@ -1664,6 +1753,38 @@ public class CollisionEngine {
|
|||||||
public Vector3d getFloatingOrigin(){
|
public Vector3d getFloatingOrigin(){
|
||||||
return new Vector3d(this.floatingOrigin);
|
return new Vector3d(this.floatingOrigin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the world of the engine
|
||||||
|
* @return The world of the engine
|
||||||
|
*/
|
||||||
|
protected DWorld getWorld(){
|
||||||
|
return this.world;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the space of the engine
|
||||||
|
* @return The space of the engine
|
||||||
|
*/
|
||||||
|
protected DSpace getSpace(){
|
||||||
|
return this.space;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the near collision count
|
||||||
|
* @return The near collision count
|
||||||
|
*/
|
||||||
|
protected int getNearCollisionCount(){
|
||||||
|
return nearCollisionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of collisions that make it to the point of creating joints/impulses
|
||||||
|
* @return The number of collisions
|
||||||
|
*/
|
||||||
|
protected int getFinalCollisionCount(){
|
||||||
|
return finalCollisionCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
221
src/main/java/electrosphere/collision/PhysicsCallback.java
Normal file
221
src/main/java/electrosphere/collision/PhysicsCallback.java
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
package electrosphere.collision;
|
||||||
|
|
||||||
|
import org.ode4j.math.DVector3;
|
||||||
|
import org.ode4j.ode.DBody;
|
||||||
|
import org.ode4j.ode.DContact;
|
||||||
|
import org.ode4j.ode.DContactJoint;
|
||||||
|
import org.ode4j.ode.DGeom;
|
||||||
|
import org.ode4j.ode.DGeom.DNearCallback;
|
||||||
|
import org.ode4j.ode.DJoint;
|
||||||
|
import org.ode4j.ode.DRay;
|
||||||
|
import org.ode4j.ode.OdeHelper;
|
||||||
|
|
||||||
|
import electrosphere.collision.collidable.Collidable;
|
||||||
|
import electrosphere.collision.collidable.SurfaceParams;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.logger.LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Near callback for main physics engine
|
||||||
|
*/
|
||||||
|
public class PhysicsCallback implements DNearCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The collision engine that will invoke this callback
|
||||||
|
*/
|
||||||
|
protected CollisionEngine engine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public PhysicsCallback(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void call(Object data, DGeom o1, DGeom o2) {
|
||||||
|
if(engine.name.equals("serverPhysics")){
|
||||||
|
engine.nearCollisionCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ie if both are in static space
|
||||||
|
if(o1 == o2){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if neither are bodies
|
||||||
|
if(o1.getBody() == null && o2.getBody() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit without doing anything if the two bodies are connected by a joint
|
||||||
|
DBody b1 = o1.getBody();
|
||||||
|
DBody b2 = o2.getBody();
|
||||||
|
if(b1 != null && b2 != null && OdeHelper.areConnectedExcluding(b1,b2,DContactJoint.class)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(o1 == engine.staticGeomSpace){
|
||||||
|
OdeHelper.spaceCollide2(o2, engine.staticGeomSpace, 0, this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(o2 == engine.staticGeomSpace){
|
||||||
|
OdeHelper.spaceCollide2(o1, engine.staticGeomSpace, 0, this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the collidables for each geom
|
||||||
|
Collidable c1 = null;
|
||||||
|
if(b1 != null){
|
||||||
|
c1 = engine.bodyPointerMap.get(b1);
|
||||||
|
} else if(o1.getBody() == null) {
|
||||||
|
c1 = engine.geomPointerMap.get(o1);
|
||||||
|
}
|
||||||
|
Collidable c2 = null;
|
||||||
|
if(b2 != null){
|
||||||
|
c2 = engine.bodyPointerMap.get(b2);
|
||||||
|
} else if(o2.getBody() == null) {
|
||||||
|
c2 = engine.geomPointerMap.get(o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//make sure we have collidables for both
|
||||||
|
if(c1 == null || c2 == null){
|
||||||
|
String message = "Collidable is undefined!\n" +
|
||||||
|
"Geoms:\n" +
|
||||||
|
o1 + " \n" +
|
||||||
|
o2 + " \n" +
|
||||||
|
"Bodies:\n" +
|
||||||
|
b1 + " \n" +
|
||||||
|
b2 + " \n" +
|
||||||
|
"Colliders:\n" +
|
||||||
|
c1 + " \n" +
|
||||||
|
c2 + " \n" +
|
||||||
|
"Obj 1 pointers:\n" +
|
||||||
|
engine.bodyPointerMap.get(b1) + " \n" +
|
||||||
|
engine.geomPointerMap.get(o1) + " \n" +
|
||||||
|
"Obj 2 pointers:\n" +
|
||||||
|
engine.bodyPointerMap.get(b2) + " \n" +
|
||||||
|
engine.geomPointerMap.get(o2) + " \n" +
|
||||||
|
""
|
||||||
|
;
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - Full collision phase");
|
||||||
|
try {
|
||||||
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - setup");
|
||||||
|
//null out the contact buffer
|
||||||
|
engine.contacts.nullify();
|
||||||
|
SurfaceParams surfaceParams1 = c1.getSurfaceParams();
|
||||||
|
SurfaceParams surfaceParams2 = null;
|
||||||
|
if(c2 != null){
|
||||||
|
surfaceParams2 = c2.getSurfaceParams();
|
||||||
|
}
|
||||||
|
for (int i=0; i< CollisionEngine.MAX_CONTACTS; i++) {
|
||||||
|
DContact contact = engine.contacts.get(i);
|
||||||
|
contact.surface.mode = surfaceParams1.getMode();
|
||||||
|
contact.surface.mu = surfaceParams1.getMu();
|
||||||
|
if(surfaceParams1.getRho() != null){
|
||||||
|
contact.surface.rho = surfaceParams1.getRho();
|
||||||
|
} else if(surfaceParams2 != null && surfaceParams2.getRho() != null){
|
||||||
|
contact.surface.rho = surfaceParams2.getRho();
|
||||||
|
}
|
||||||
|
if(surfaceParams1.getRho2() != null){
|
||||||
|
contact.surface.rho2 = surfaceParams1.getRho2();
|
||||||
|
} else if(surfaceParams2 != null && surfaceParams2.getRho2() != null){
|
||||||
|
contact.surface.rho = surfaceParams2.getRho2();
|
||||||
|
}
|
||||||
|
if(surfaceParams1.getRhoN() != null){
|
||||||
|
contact.surface.rhoN = surfaceParams1.getRhoN();
|
||||||
|
} else if(surfaceParams2 != null && surfaceParams2.getRhoN() != null){
|
||||||
|
contact.surface.rho = surfaceParams2.getRhoN();
|
||||||
|
}
|
||||||
|
if(surfaceParams1.getBounce() != null){
|
||||||
|
contact.surface.bounce = surfaceParams1.getBounce();
|
||||||
|
} else if(surfaceParams2 != null && surfaceParams2.getBounce() != null){
|
||||||
|
contact.surface.rho = surfaceParams2.getBounce();
|
||||||
|
}
|
||||||
|
if(surfaceParams1.getBounceVel() != null){
|
||||||
|
contact.surface.bounce_vel = surfaceParams1.getBounceVel();
|
||||||
|
} else if(surfaceParams2 != null && surfaceParams2.getBounceVel() != null){
|
||||||
|
contact.surface.rho = surfaceParams2.getBounceVel();
|
||||||
|
}
|
||||||
|
if(surfaceParams1.getSoftErp() != null){
|
||||||
|
contact.surface.soft_erp = surfaceParams1.getSoftErp();
|
||||||
|
} else if(surfaceParams2 != null && surfaceParams2.getSoftErp() != null){
|
||||||
|
contact.surface.rho = surfaceParams2.getSoftErp();
|
||||||
|
}
|
||||||
|
if(surfaceParams1.getSoftCfm() != null){
|
||||||
|
contact.surface.soft_cfm = surfaceParams1.getSoftCfm();
|
||||||
|
} else if(surfaceParams2 != null && surfaceParams2.getSoftCfm() != null){
|
||||||
|
contact.surface.rho = surfaceParams2.getSoftCfm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
//calculate collisions
|
||||||
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - OdeHelper.collide");
|
||||||
|
int numc = OdeHelper.collide(o1,o2,CollisionEngine.MAX_CONTACTS,engine.contacts.getGeomBuffer());
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
//create DContacts based on each collision that occurs
|
||||||
|
Globals.profiler.beginAggregateCpuSample("CollisionEngine.nearCallback - contact iterations");
|
||||||
|
if(numc != 0){
|
||||||
|
for(int i=0; i<numc; i++){
|
||||||
|
DContact contact = engine.contacts.get(i);
|
||||||
|
|
||||||
|
//special code for ray casting
|
||||||
|
if (o1 instanceof DRay || o2 instanceof DRay){
|
||||||
|
DVector3 end = new DVector3();
|
||||||
|
end.eqSum(contact.geom.pos, contact.geom.normal, contact.geom.depth);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
//add contact to contact group
|
||||||
|
DJoint c = OdeHelper.createContactJoint(engine.world,engine.contactgroup,contact);
|
||||||
|
if(b1 == null){
|
||||||
|
if(b2 == null){
|
||||||
|
} else {
|
||||||
|
c.attach(null,b2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(b2 == null){
|
||||||
|
c.attach(b1,null);
|
||||||
|
} else {
|
||||||
|
c.attach(b1,b2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the default collision resolution
|
||||||
|
CollisionEngine.resolveCollision(
|
||||||
|
contact.geom,
|
||||||
|
c1,
|
||||||
|
c2,
|
||||||
|
PhysicsUtils.odeVecToJomlVec(contact.geom.normal).mul(-1.0),
|
||||||
|
PhysicsUtils.odeVecToJomlVec(contact.fdir1).mul(-1.0),
|
||||||
|
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
|
||||||
|
(float)contact.geom.depth
|
||||||
|
);
|
||||||
|
CollisionEngine.resolveCollision(
|
||||||
|
contact.geom,
|
||||||
|
c2,
|
||||||
|
c1,
|
||||||
|
PhysicsUtils.odeVecToJomlVec(contact.geom.normal),
|
||||||
|
PhysicsUtils.odeVecToJomlVec(contact.fdir1),
|
||||||
|
PhysicsUtils.odeVecToJomlVec(contact.geom.pos),
|
||||||
|
(float)contact.geom.depth
|
||||||
|
);
|
||||||
|
|
||||||
|
//tracking updates
|
||||||
|
engine.finalCollisionCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
} catch(ArrayIndexOutOfBoundsException ex){
|
||||||
|
//I've found that ode4j occasionally throws an exception on the OdeHelper.collide function.
|
||||||
|
//I don't know why it has out of bounds elements, but it's happening.
|
||||||
|
//Catching the exception here allows the engine to keep running at least.
|
||||||
|
LoggerInterface.loggerEngine.ERROR("ode4j error", ex);
|
||||||
|
}
|
||||||
|
Globals.profiler.endCpuSample();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -399,7 +399,8 @@ public class PhysicsEntityUtils {
|
|||||||
}
|
}
|
||||||
CollisionEngine.lockOde();
|
CollisionEngine.lockOde();
|
||||||
if(physicsTemplate.getKinematic()){
|
if(physicsTemplate.getKinematic()){
|
||||||
PhysicsEntityUtils.serverAttachGeom(realm,rVal,physicsTemplate);
|
DGeom geom = PhysicsEntityUtils.serverAttachGeom(realm,rVal,physicsTemplate);
|
||||||
|
PhysicsUtils.makeGeomStatic(realm.getCollisionEngine(), geom);
|
||||||
} else {
|
} else {
|
||||||
DBody rigidBody = null;
|
DBody rigidBody = null;
|
||||||
switch(physicsTemplate.getType()){
|
switch(physicsTemplate.getType()){
|
||||||
@ -625,10 +626,7 @@ public class PhysicsEntityUtils {
|
|||||||
}
|
}
|
||||||
Collidable collidable;
|
Collidable collidable;
|
||||||
double mass = 1.0f;
|
double mass = 1.0f;
|
||||||
long categoryBit = Collidable.TYPE_CREATURE_BIT;
|
long categoryBit = Collidable.TYPE_STATIC_BIT;
|
||||||
if(physicsTemplate.getKinematic()){
|
|
||||||
categoryBit = Collidable.TYPE_STATIC_BIT;
|
|
||||||
}
|
|
||||||
CollisionEngine.lockOde();
|
CollisionEngine.lockOde();
|
||||||
DGeom geom = null;
|
DGeom geom = null;
|
||||||
switch(physicsTemplate.getType()){
|
switch(physicsTemplate.getType()){
|
||||||
@ -726,6 +724,9 @@ public class PhysicsEntityUtils {
|
|||||||
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
|
realm.getCollisionEngine().registerCollisionObject(geom, collidable);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
if(geom != null){
|
||||||
|
realm.getCollisionEngine().addToStaticSpace(geom);
|
||||||
|
}
|
||||||
CollisionEngine.unlockOde();
|
CollisionEngine.unlockOde();
|
||||||
return geom;
|
return geom;
|
||||||
}
|
}
|
||||||
@ -825,6 +826,7 @@ public class PhysicsEntityUtils {
|
|||||||
PhysicsEntityUtils.setCollidable(terrain, collidable);
|
PhysicsEntityUtils.setCollidable(terrain, collidable);
|
||||||
realm.getCollisionEngine().registerCollisionObject(terrainCollider, collidable);
|
realm.getCollisionEngine().registerCollisionObject(terrainCollider, collidable);
|
||||||
PhysicsEntityUtils.setDGeom(terrain,terrainCollider);
|
PhysicsEntityUtils.setDGeom(terrain,terrainCollider);
|
||||||
|
PhysicsUtils.makeGeomStatic(realm.getCollisionEngine(), terrainCollider);
|
||||||
|
|
||||||
return terrainCollider;
|
return terrainCollider;
|
||||||
}
|
}
|
||||||
@ -860,6 +862,7 @@ public class PhysicsEntityUtils {
|
|||||||
PhysicsEntityUtils.setCollidable(terrain, collidable);
|
PhysicsEntityUtils.setCollidable(terrain, collidable);
|
||||||
realm.getCollisionEngine().registerCollisionObject(terrainBody, collidable);
|
realm.getCollisionEngine().registerCollisionObject(terrainBody, collidable);
|
||||||
PhysicsEntityUtils.setDGeom(terrain,terrainBody);
|
PhysicsEntityUtils.setDGeom(terrain,terrainBody);
|
||||||
|
PhysicsUtils.makeGeomStatic(realm.getCollisionEngine(), terrainBody);
|
||||||
|
|
||||||
return terrainBody;
|
return terrainBody;
|
||||||
}
|
}
|
||||||
@ -905,15 +908,7 @@ public class PhysicsEntityUtils {
|
|||||||
*/
|
*/
|
||||||
public static void serverDestroyPhysics(Entity entity){
|
public static void serverDestroyPhysics(Entity entity){
|
||||||
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
|
Realm realm = Globals.serverState.realmManager.getEntityRealm(entity);
|
||||||
if(PhysicsEntityUtils.containsDBody(entity)){
|
realm.getCollisionEngine().destroyPhysics(entity);
|
||||||
PhysicsUtils.destroyPhysicsPair(
|
|
||||||
realm.getCollisionEngine(),
|
|
||||||
PhysicsEntityUtils.getDBody(entity),
|
|
||||||
PhysicsEntityUtils.getCollidable(entity)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
PhysicsEntityUtils.setCollidable(entity, null);
|
|
||||||
PhysicsEntityUtils.clearGeomAndBody(entity);
|
|
||||||
Vector3d entityPos = EntityUtils.getPosition(entity);
|
Vector3d entityPos = EntityUtils.getPosition(entity);
|
||||||
ServerEntityUtils.repositionEntity(entity, entityPos);
|
ServerEntityUtils.repositionEntity(entity, entityPos);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,6 +136,15 @@ public class PhysicsUtils {
|
|||||||
collisionEngine.synchronizeData(body, position, rotation, linearVel, angularVel, linearForce, angularForce);
|
collisionEngine.synchronizeData(body, position, rotation, linearVel, angularVel, linearForce, angularForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a geom to the static geom space
|
||||||
|
* @param collisionEngine The collision engine
|
||||||
|
* @param geom The geom
|
||||||
|
*/
|
||||||
|
public static void makeGeomStatic(CollisionEngine collisionEngine, DGeom geom){
|
||||||
|
collisionEngine.addToStaticSpace(geom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the position + rotation + scale of a body
|
* Sets the position + rotation + scale of a body
|
||||||
|
|||||||
@ -98,8 +98,8 @@ void RayCallback(void *Data, dGeomID Geometry1, dGeomID Geometry2) {
|
|||||||
Globals.profiler.beginAggregateCpuSample("RayCastCallback - try collisions");
|
Globals.profiler.beginAggregateCpuSample("RayCastCallback - try collisions");
|
||||||
if(
|
if(
|
||||||
rayCastData.collidableTypeMask == null ||
|
rayCastData.collidableTypeMask == null ||
|
||||||
(o1 instanceof DRay && rayCastData.collidableTypeMask.contains(collidable2.getType())) ||
|
(o1 instanceof DRay && collidable2 != null && rayCastData.collidableTypeMask.contains(collidable2.getType())) ||
|
||||||
(o2 instanceof DRay && rayCastData.collidableTypeMask.contains(collidable1.getType()))
|
(o2 instanceof DRay && collidable1 != null && rayCastData.collidableTypeMask.contains(collidable1.getType()))
|
||||||
){
|
){
|
||||||
//creates a buffer to store potential collisions
|
//creates a buffer to store potential collisions
|
||||||
DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); // up to MAX_CONTACTS contacts per box-box
|
DContactBuffer contacts = new DContactBuffer(MAX_CONTACTS); // up to MAX_CONTACTS contacts per box-box
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package electrosphere.data.entity.collidable;
|
package electrosphere.data.entity.collidable;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A template for a rigid body that should be attached to an entity
|
* A template for a rigid body that should be attached to an entity
|
||||||
*/
|
*/
|
||||||
@ -105,6 +107,26 @@ public class CollidableTemplate {
|
|||||||
*/
|
*/
|
||||||
String collisionType;
|
String collisionType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base constructor
|
||||||
|
*/
|
||||||
|
public CollidableTemplate(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a box template
|
||||||
|
* @param dims The dimensions of the box
|
||||||
|
* @return The template
|
||||||
|
*/
|
||||||
|
public static CollidableTemplate getBoxTemplate(Vector3d dims){
|
||||||
|
CollidableTemplate rVal = new CollidableTemplate();
|
||||||
|
rVal.type = CollidableTemplate.COLLIDABLE_TYPE_CUBE;
|
||||||
|
rVal.dimension1 = (float)dims.x;
|
||||||
|
rVal.dimension2 = (float)dims.y;
|
||||||
|
rVal.dimension3 = (float)dims.z;
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The primitive shape type
|
* The primitive shape type
|
||||||
* @return The primitive shape
|
* @return The primitive shape
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import org.joml.Vector3d;
|
|||||||
|
|
||||||
import electrosphere.collision.CollisionEngine;
|
import electrosphere.collision.CollisionEngine;
|
||||||
import electrosphere.collision.CollisionWorldData;
|
import electrosphere.collision.CollisionWorldData;
|
||||||
|
import electrosphere.collision.PhysicsCallback;
|
||||||
import electrosphere.collision.hitbox.HitboxManager;
|
import electrosphere.collision.hitbox.HitboxManager;
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
@ -61,14 +62,15 @@ public class RealmManager {
|
|||||||
//create chemistry engine
|
//create chemistry engine
|
||||||
CollisionEngine chemistryEngine = new CollisionEngine("serverChem");
|
CollisionEngine chemistryEngine = new CollisionEngine("serverChem");
|
||||||
chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback());
|
chemistryEngine.setCollisionResolutionCallback(new ServerChemistryCollisionCallback());
|
||||||
return new Realm(
|
Realm rVal = new Realm(
|
||||||
new ServerWorldData(),
|
new ServerWorldData(),
|
||||||
new CollisionEngine("serverPhysics"),
|
CollisionEngine.create("serverPhysics", new PhysicsCallback()),
|
||||||
chemistryEngine,
|
chemistryEngine,
|
||||||
new HitboxManager(new ServerHitboxResolutionCallback()),
|
new HitboxManager(new ServerHitboxResolutionCallback()),
|
||||||
ServerContentManager.createServerContentManager(false, null),
|
ServerContentManager.createServerContentManager(false, null),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +79,7 @@ public class RealmManager {
|
|||||||
*/
|
*/
|
||||||
public Realm createGriddedRealm(ServerWorldData serverWorldData, ServerContentManager serverContentManager){
|
public Realm createGriddedRealm(ServerWorldData serverWorldData, ServerContentManager serverContentManager){
|
||||||
//create collision engine
|
//create collision engine
|
||||||
CollisionEngine collisionEngine = new CollisionEngine("serverPhysics");
|
CollisionEngine collisionEngine = CollisionEngine.create("serverPhysics", new PhysicsCallback());
|
||||||
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
|
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
|
||||||
//create chemistry engine
|
//create chemistry engine
|
||||||
CollisionEngine chemistryEngine = new CollisionEngine("serverChem");
|
CollisionEngine chemistryEngine = new CollisionEngine("serverChem");
|
||||||
@ -111,7 +113,7 @@ public class RealmManager {
|
|||||||
ServerWorldData serverWorldData = ServerWorldData.createFixedWorldData(minPoint, maxPoint);
|
ServerWorldData serverWorldData = ServerWorldData.createFixedWorldData(minPoint, maxPoint);
|
||||||
|
|
||||||
//create collision engine
|
//create collision engine
|
||||||
CollisionEngine collisionEngine = new CollisionEngine("serverPhysics");
|
CollisionEngine collisionEngine = CollisionEngine.create("serverPhysics", new PhysicsCallback());
|
||||||
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
|
collisionEngine.setCollisionWorldData(new CollisionWorldData(serverWorldData));
|
||||||
|
|
||||||
//create chemistry engine
|
//create chemistry engine
|
||||||
|
|||||||
@ -576,6 +576,12 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
|||||||
});
|
});
|
||||||
Globals.profiler.endCpuSample();
|
Globals.profiler.endCpuSample();
|
||||||
|
|
||||||
|
//destroy physics
|
||||||
|
PhysicsDataCell physicsCell = this.posPhysicsMap.get(key);
|
||||||
|
if(physicsCell != null){
|
||||||
|
physicsCell.destroyPhysics();
|
||||||
|
}
|
||||||
|
|
||||||
//deregister from all tracking structures
|
//deregister from all tracking structures
|
||||||
parent.deregisterCell(cell);
|
parent.deregisterCell(cell);
|
||||||
groundDataCells.remove(key);
|
groundDataCells.remove(key);
|
||||||
|
|||||||
@ -102,8 +102,10 @@ public class PhysicsDataCell {
|
|||||||
*/
|
*/
|
||||||
public void destroyPhysics(){
|
public void destroyPhysics(){
|
||||||
Realm realm = Globals.serverState.realmManager.getEntityRealm(physicsEntity);
|
Realm realm = Globals.serverState.realmManager.getEntityRealm(physicsEntity);
|
||||||
realm.getCollisionEngine().destroyPhysics(physicsEntity);
|
if(realm != null){
|
||||||
realm.getCollisionEngine().destroyPhysics(blockPhysicsEntity);
|
realm.getCollisionEngine().destroyPhysics(physicsEntity);
|
||||||
|
realm.getCollisionEngine().destroyPhysics(blockPhysicsEntity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,78 @@
|
|||||||
|
package electrosphere.collision;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
|
import org.ode4j.ode.DBox;
|
||||||
|
|
||||||
|
import electrosphere.data.entity.collidable.CollidableTemplate;
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.EntityCreationUtils;
|
||||||
|
import electrosphere.server.datacell.Realm;
|
||||||
|
import electrosphere.test.annotations.IntegrationTest;
|
||||||
|
import electrosphere.test.template.EntityTestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for specifically the static space geoms
|
||||||
|
*/
|
||||||
|
public class CollisionEngineStaticSpaceTests extends EntityTestTemplate {
|
||||||
|
|
||||||
|
@IntegrationTest
|
||||||
|
public void staticSpaceTest1(){
|
||||||
|
Realm realm = Globals.serverState.realmManager.first();
|
||||||
|
CollisionEngine collisionEngine = realm.getCollisionEngine();
|
||||||
|
|
||||||
|
//base plane + static space
|
||||||
|
assertEquals(2, collisionEngine.getSpace().getNumGeoms());
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntegrationTest
|
||||||
|
public void test_nearCollisionCount_1(){
|
||||||
|
Realm realm = Globals.serverState.realmManager.first();
|
||||||
|
CollisionEngine collisionEngine = realm.getCollisionEngine();
|
||||||
|
|
||||||
|
//simulate the physics
|
||||||
|
collisionEngine.simulatePhysics();
|
||||||
|
|
||||||
|
//base plane + static space TIMES number of calls to simulate physics
|
||||||
|
int expected = 0 * CollisionEngine.PHYSICS_SIMULATION_RESOLUTION;
|
||||||
|
assertEquals(expected, collisionEngine.getFinalCollisionCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntegrationTest
|
||||||
|
public void test_nearCollisionCount_2(){
|
||||||
|
Realm realm = Globals.serverState.realmManager.first();
|
||||||
|
CollisionEngine collisionEngine = realm.getCollisionEngine();
|
||||||
|
|
||||||
|
DBox box = collisionEngine.createCubeGeom(new Vector3d(1,1,1), 0);
|
||||||
|
collisionEngine.addToStaticSpace(box);
|
||||||
|
|
||||||
|
//simulate the physics
|
||||||
|
collisionEngine.simulatePhysics();
|
||||||
|
|
||||||
|
assertEquals(0, collisionEngine.getFinalCollisionCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntegrationTest
|
||||||
|
public void test_nearCollisionCount_3(){
|
||||||
|
Realm realm = Globals.serverState.realmManager.first();
|
||||||
|
CollisionEngine collisionEngine = realm.getCollisionEngine();
|
||||||
|
|
||||||
|
Entity ent1 = EntityCreationUtils.createServerEntity(realm, new Vector3d(0));
|
||||||
|
PhysicsEntityUtils.serverAttachGeom(realm, ent1, CollidableTemplate.getBoxTemplate(new Vector3d(1,1,1)));
|
||||||
|
|
||||||
|
PhysicsEntityUtils.serverAttachCollidableTemplate(realm, ent1, CollidableTemplate.getBoxTemplate(new Vector3d(1,1,1)), new Vector3d(0));
|
||||||
|
|
||||||
|
int expectedBoxBoxCollisions = 4;
|
||||||
|
|
||||||
|
int expectedTotalCollisions = expectedBoxBoxCollisions * CollisionEngine.PHYSICS_SIMULATION_RESOLUTION;
|
||||||
|
|
||||||
|
|
||||||
|
//simulate the physics
|
||||||
|
collisionEngine.simulatePhysics();
|
||||||
|
|
||||||
|
assertEquals(expectedTotalCollisions, collisionEngine.getFinalCollisionCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user