Collision optimization
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-03-09 17:40:40 -05:00
parent 39134f9693
commit 027c93d4c7
10 changed files with 71 additions and 41 deletions

View File

@ -1,7 +1,7 @@
@page collision Collision Engine
[TOC]
## High Level Overview
The goal of the collision engine system is to allow parallel collision detection of different classes of objects.
@ -109,6 +109,8 @@ Each client scene creates a collision engine for physics on connection. Each sce
- Physics Entity
- Dynamic Physics Entity
- Collision Object - A collidable
- ODE Category - Ode has bits that control which 'categories' a given geometry falls in to. This is used to control behaviors applied to it.
- ODE Collision Bits - The mask of categories that a given geometry should collide with

View File

@ -136,6 +136,8 @@ Ability to attach ambient audio emitters to entities
Timekeeping class that defaults to gltf time and falls back to systemCurrentTimeMillis
Methods for sleeping physics bodies if nothing nearby them is dynamic (ie trees if there are no moving creatures near them)
- SAP2 space from ode4j specifically (ended up using BVH space instead)
@ -146,9 +148,6 @@ Timekeeping class that defaults to gltf time and falls back to systemCurrentTime
# TODO
Methods for sleeping physics bodies if nothing nearby them is dynamic (ie trees if there are no moving creatures near them)
- SAP2 space from ode4j specifically
De-dupe render calls via doing mutations in render pipeline status and dont call setting variables to values they are already set to
Clean up main method/class

View File

@ -128,7 +128,7 @@
<!--Ode4J-->
<!--License: Dual LGPL 2.1 OR BSD 3-clause-->
<!--https://github.com/tzaeschke/ode4j-->
<!--https://github.com/tzaeschke/ode4j -->
<!--https://tzaeschke.github.io/ode4j-old/ode4j-doc.html -->
<!--http://ode.org/wikiold/htmlfile1.html -->
<!--http://ode.org/wiki/index.php/Main_Page -->
@ -136,7 +136,7 @@
<dependency>
<groupId>org.ode4j</groupId>
<artifactId>core</artifactId>
<version>0.5.0</version>
<version>0.5.2</version>
</dependency>
<!--SQLITE-JDBC-->

View File

@ -40,8 +40,8 @@ public class CollisionBodyCreation {
* @param dimensions The dimensions of the plane
* @return The DBody
*/
public static DBody createPlaneBody(CollisionEngine collisionEngine, Vector3d dimensions){
DBox geom = collisionEngine.createCubeGeom(new Vector3d(dimensions.x,PLANE_WIDTH,dimensions.z));
public static DBody createPlaneBody(CollisionEngine collisionEngine, Vector3d dimensions, long categoryBits){
DBox geom = collisionEngine.createCubeGeom(new Vector3d(dimensions.x,PLANE_WIDTH,dimensions.z),categoryBits);
return collisionEngine.createDBody(geom);
}
@ -51,8 +51,8 @@ public class CollisionBodyCreation {
* @param dimensions The dimensions of the cube
* @return The DBody
*/
public static DBody createCubeBody(CollisionEngine collisionEngine, Vector3d dimensions){
DBox geom = collisionEngine.createCubeGeom(new Vector3d(dimensions));
public static DBody createCubeBody(CollisionEngine collisionEngine, Vector3d dimensions, long categoryBits){
DBox geom = collisionEngine.createCubeGeom(new Vector3d(dimensions),categoryBits);
return collisionEngine.createDBody(geom);
}
@ -62,8 +62,8 @@ public class CollisionBodyCreation {
* @param dimensions The dimensions of the cube
* @return The DBody
*/
public static DBody createCylinderBody(CollisionEngine collisionEngine, double radius, double length){
DCylinder geom = collisionEngine.createCylinderGeom(radius,length);
public static DBody createCylinderBody(CollisionEngine collisionEngine, double radius, double length, long categoryBits){
DCylinder geom = collisionEngine.createCylinderGeom(radius,length,categoryBits);
DBody returnBody = collisionEngine.createDBody(geom);
collisionEngine.setOffsetRotation(geom); //ode4j required geom to already be on body before rotating for some reason
return returnBody;
@ -75,8 +75,8 @@ public class CollisionBodyCreation {
* @param radius The radius of the sphere
* @return The DBody
*/
public static DBody createSphereBody(CollisionEngine collisionEngine, double radius){
DSphere geom = collisionEngine.createSphereGeom(radius);
public static DBody createSphereBody(CollisionEngine collisionEngine, double radius, long categoryBits){
DSphere geom = collisionEngine.createSphereGeom(radius,categoryBits);
return collisionEngine.createDBody(geom);
}
@ -86,7 +86,7 @@ public class CollisionBodyCreation {
* @param data The terrain data
* @return The DBody
*/
public static DBody generateBodyFromTerrainData(CollisionEngine collisionEngine, TerrainChunkData data){
public static DBody generateBodyFromTerrainData(CollisionEngine collisionEngine, TerrainChunkData data, long categoryBits){
DBody body = null;
//create data
@ -110,7 +110,7 @@ public class CollisionBodyCreation {
//create trimesh
if(vertices.length > 0){
DTriMesh triMesh = collisionEngine.createTrimeshGeom(vertices,indices);
DTriMesh triMesh = collisionEngine.createTrimeshGeom(vertices,indices,categoryBits);
body = collisionEngine.createDBody(triMesh);
}
@ -122,7 +122,7 @@ public class CollisionBodyCreation {
* @param scene The AIScene to generate a rigid body off of
* @return A rigid body based on the AIScene
*/
public static DBody generateRigidBodyFromAIScene(CollisionEngine collisionEngine, AIScene scene){
public static DBody generateRigidBodyFromAIScene(CollisionEngine collisionEngine, AIScene scene, long categoryBits){
DBody body = collisionEngine.createDBody(null);
@ -161,7 +161,7 @@ public class CollisionBodyCreation {
indicesPos++;
}
}
DTriMesh meshGeom = collisionEngine.createTrimeshGeom(verts, indices);
DTriMesh meshGeom = collisionEngine.createTrimeshGeom(verts, indices,categoryBits);
meshGeom.setBody(body);
}

View File

@ -72,7 +72,7 @@ public class CollisionEngine {
private DJointGroup contactgroup;
private static final int MAX_CONTACTS = 1; // maximum number of contact points per body
//The list of dbodies ode should be tracking
List<DBody> bodies = new ArrayList<DBody>();
@ -90,7 +90,7 @@ public class CollisionEngine {
public CollisionEngine(){
world = OdeHelper.createWorld();
space = OdeHelper.createHashSpace();
space = OdeHelper.createBHVSpace(Collidable.TYPE_STATIC_BIT);
contactgroup = OdeHelper.createJointGroup();
}
@ -545,11 +545,12 @@ public class CollisionEngine {
* @param indices The indices
* @return The DTriMesh
*/
protected DTriMesh createTrimeshGeom(float[] verts, int[] indices){
protected DTriMesh createTrimeshGeom(float[] verts, int[] indices, long categoryBits){
spaceLock.acquireUninterruptibly();
DTriMeshData data = OdeHelper.createTriMeshData();
data.build(verts, indices);
DTriMesh rVal = OdeHelper.createTriMesh(getSpace(), data);
rVal.setCategoryBits(categoryBits);
spaceLock.release();
return rVal;
}
@ -559,9 +560,10 @@ public class CollisionEngine {
* @param dimensions The dimensions of the box
* @return The DBox
*/
protected DBox createCubeGeom(Vector3d dimensions){
protected DBox createCubeGeom(Vector3d dimensions, long categoryBits){
spaceLock.acquireUninterruptibly();
DBox boxGeom = OdeHelper.createBox(space, dimensions.x, dimensions.y, dimensions.z);
boxGeom.setCategoryBits(categoryBits);
spaceLock.release();
return boxGeom;
}
@ -571,9 +573,10 @@ public class CollisionEngine {
* @param dimensions The dimensions of the cylinder. X is the radius, y is the total height.
* @return The cylinder geometry
*/
protected DCylinder createCylinderGeom(double radius, double length){
protected DCylinder createCylinderGeom(double radius, double length, long categoryBits){
spaceLock.acquireUninterruptibly();
DCylinder cylinderGeom = OdeHelper.createCylinder(space, radius, length);
cylinderGeom.setCategoryBits(categoryBits);
spaceLock.release();
return cylinderGeom;
}
@ -583,9 +586,10 @@ public class CollisionEngine {
* @param radius The radius of the sphere
* @return The sphere geometry
*/
protected DSphere createSphereGeom(double radius){
protected DSphere createSphereGeom(double radius, long categoryBits){
spaceLock.acquireUninterruptibly();
DSphere sphereGeom = OdeHelper.createSphere(space, radius);
sphereGeom.setCategoryBits(categoryBits);
spaceLock.release();
return sphereGeom;
}
@ -596,9 +600,10 @@ public class CollisionEngine {
* @param length The length of the capsule
* @return The capsule geometry
*/
protected DCapsule createCapsuleGeom(double radius, double length){
protected DCapsule createCapsuleGeom(double radius, double length, long categoryBits){
spaceLock.acquireUninterruptibly();
DCapsule capsuleGeom = OdeHelper.createCapsule(space, radius, length);
capsuleGeom.setCategoryBits(categoryBits);
spaceLock.release();
return capsuleGeom;
}

View File

@ -41,7 +41,8 @@ public class PhysicsEntityUtils {
rigidBody = CollisionBodyCreation.createCylinderBody(
Globals.clientSceneWrapper.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2()
physicsTemplate.getDimension2(),
Collidable.TYPE_CREATURE_BIT
);
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE);
ClientCollidableTree tree = new ClientCollidableTree(rVal,collidable,rigidBody);
@ -72,7 +73,8 @@ public class PhysicsEntityUtils {
case "CUBE": {
rigidBody = CollisionBodyCreation.createCubeBody(
Globals.clientSceneWrapper.getCollisionEngine(),
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3())
new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),
Collidable.TYPE_CREATURE_BIT
);
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE);
ClientCollidableTree tree = new ClientCollidableTree(rVal,collidable,rigidBody);
@ -119,7 +121,8 @@ public class PhysicsEntityUtils {
rigidBody = CollisionBodyCreation.createCylinderBody(
realm.getCollisionEngine(),
physicsTemplate.getDimension1(),
physicsTemplate.getDimension2()
physicsTemplate.getDimension2(),
Collidable.TYPE_CREATURE_BIT
);
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE);
ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
@ -143,7 +146,7 @@ public class PhysicsEntityUtils {
ServerEntityTagUtils.attachTagToEntity(rVal, EntityTags.COLLIDABLE);
} break;
case "CUBE": {
rigidBody = CollisionBodyCreation.createCubeBody(realm.getCollisionEngine(),new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()));
rigidBody = CollisionBodyCreation.createCubeBody(realm.getCollisionEngine(),new Vector3d(physicsTemplate.getDimension1(),physicsTemplate.getDimension2(),physicsTemplate.getDimension3()),Collidable.TYPE_CREATURE_BIT);
collidable = new Collidable(rVal, Collidable.TYPE_CREATURE);
ServerCollidableTree tree = new ServerCollidableTree(rVal,collidable,rigidBody);
rVal.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);
@ -234,7 +237,7 @@ public class PhysicsEntityUtils {
}
}
DTriMesh triMesh = collisionEngine.createTrimeshGeom(vertices,indices);
DTriMesh triMesh = collisionEngine.createTrimeshGeom(vertices,indices,Collidable.TYPE_STATIC_BIT);
DBody body = collisionEngine.createDBody(triMesh);
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(body, new Collidable(terrain,Collidable.TYPE_TERRAIN));
@ -252,7 +255,7 @@ public class PhysicsEntityUtils {
*/
public static DBody clientAttachTerrainChunkRigidBody(Entity terrain, TerrainChunkData data){
Vector3d position = EntityUtils.getPosition(terrain);
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientSceneWrapper.getCollisionEngine(), data);
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(Globals.clientSceneWrapper.getCollisionEngine(), data,Collidable.TYPE_STATIC_BIT);
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_TERRAIN));
@ -271,7 +274,7 @@ public class PhysicsEntityUtils {
public static DBody serverAttachTerrainChunkRigidBody(Entity terrain, TerrainChunkData data){
Vector3d position = EntityUtils.getPosition(terrain);
Realm terrainRealm = Globals.realmManager.getEntityRealm(terrain);
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(terrainRealm.getCollisionEngine(),data);
DBody terrainBody = CollisionBodyCreation.generateBodyFromTerrainData(terrainRealm.getCollisionEngine(),data,Collidable.TYPE_STATIC_BIT);
terrainRealm.getCollisionEngine().registerCollisionObject(terrainBody, new Collidable(terrain,Collidable.TYPE_TERRAIN));
terrain.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, terrainBody);

View File

@ -26,13 +26,31 @@ public class Collidable {
//The impulses to be applied to this collidable
List<Impulse> impulses = new CopyOnWriteArrayList<Impulse>();
//these should have corresponding category bits along with them
public static final String TYPE_STATIC = "static";
public static final long TYPE_STATIC_BIT = 0x1;
public static final String TYPE_TERRAIN = "terrain";
public static final long TYPE_TERRAIN_BIT = 0x2;
public static final String TYPE_CREATURE = "creature";
public static final long TYPE_CREATURE_BIT = 0x4;
public static final String TYPE_STRUCTURE = "structure";
public static final long TYPE_STRUCTURE_BIT = 0x8;
public static final String TYPE_ITEM = "item";
public static final long TYPE_ITEM_BIT = 0x10;
public static final String TYPE_FORCE = "force";
public static final long TYPE_FORCE_BIT = 0x20;
public static final String TYPE_OBJECT = "object";
public static final long TYPE_OBJECT_BIT = 0x40;
public static final String TYPE_FOLIAGE_STATIC = "foliageStatic";
public static final long TYPE_FOLIAGE_BIT = 0x80;
public Collidable(Entity parent, String type){

View File

@ -4,6 +4,7 @@ import electrosphere.audio.AudioBuffer;
import electrosphere.collision.CollisionBodyCreation;
import electrosphere.collision.CollisionEngine;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.renderer.Mesh;
import electrosphere.renderer.Model;
import electrosphere.renderer.ShaderProgram;
@ -78,7 +79,7 @@ public class AssetManager {
physicsMeshesToLoad.remove(physicsMeshQueueItem);
physicsMeshesLoadedIntoMemory.put(
getCollisionMeshMapKey(physicsMeshQueueItem.collisionEngine,currentPath),
CollisionBodyCreation.generateRigidBodyFromAIScene(physicsMeshQueueItem.collisionEngine,aiScene)
CollisionBodyCreation.generateRigidBodyFromAIScene(physicsMeshQueueItem.collisionEngine,aiScene,Collidable.TYPE_STATIC_BIT)
);
}
}

View File

@ -29,7 +29,7 @@ public class CollisionObjUtils {
float mass = 1.0f;
DBody planeObject = CollisionBodyCreation.createPlaneBody(Globals.clientSceneWrapper.getCollisionEngine(),new Vector3d(scale));
DBody planeObject = CollisionBodyCreation.createPlaneBody(Globals.clientSceneWrapper.getCollisionEngine(),new Vector3d(scale),Collidable.TYPE_STATIC_BIT);
PhysicsUtils.setRigidBodyTransform(Globals.clientSceneWrapper.getCollisionEngine(), position, rotation, planeObject);
Collidable collidable = new Collidable(rVal, Collidable.TYPE_STRUCTURE);
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(planeObject, collidable);
@ -55,7 +55,7 @@ public class CollisionObjUtils {
float mass = 1.0f;
DBody planeObject = CollisionBodyCreation.createPlaneBody(realm.getCollisionEngine(),new Vector3d(scale));
DBody planeObject = CollisionBodyCreation.createPlaneBody(realm.getCollisionEngine(),new Vector3d(scale),Collidable.TYPE_STATIC_BIT);
PhysicsUtils.setRigidBodyTransform(realm.getCollisionEngine(), position, rotation, planeObject);
Collidable collidable = new Collidable(rVal, Collidable.TYPE_STRUCTURE);
realm.getCollisionEngine().registerCollisionObject(planeObject, collidable);
@ -82,7 +82,7 @@ public class CollisionObjUtils {
float mass = 1.0f;
DBody cubeObject = CollisionBodyCreation.createCubeBody(Globals.clientSceneWrapper.getCollisionEngine(),new Vector3d(scale));
DBody cubeObject = CollisionBodyCreation.createCubeBody(Globals.clientSceneWrapper.getCollisionEngine(),new Vector3d(scale),Collidable.TYPE_STATIC_BIT);
PhysicsUtils.setRigidBodyTransform(Globals.clientSceneWrapper.getCollisionEngine(), position, rotation, cubeObject);
Collidable collidable = new Collidable(rVal, Collidable.TYPE_STRUCTURE);
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(cubeObject, collidable);
@ -108,7 +108,7 @@ public class CollisionObjUtils {
float mass = 1.0f;
DBody cubeObject = CollisionBodyCreation.createCubeBody(realm.getCollisionEngine(),new Vector3d(scale));
DBody cubeObject = CollisionBodyCreation.createCubeBody(realm.getCollisionEngine(),new Vector3d(scale),Collidable.TYPE_STATIC_BIT);
PhysicsUtils.setRigidBodyTransform(realm.getCollisionEngine(), position, rotation, cubeObject);
Collidable collidable = new Collidable(rVal, Collidable.TYPE_STRUCTURE);
realm.getCollisionEngine().registerCollisionObject(cubeObject, collidable);
@ -133,7 +133,7 @@ public class CollisionObjUtils {
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
float mass = 1.0f;
DBody cubeObject = CollisionBodyCreation.createCylinderBody(Globals.clientSceneWrapper.getCollisionEngine(),scale.x,scale.y);
DBody cubeObject = CollisionBodyCreation.createCylinderBody(Globals.clientSceneWrapper.getCollisionEngine(),scale.x,scale.y,Collidable.TYPE_STATIC_BIT);
PhysicsUtils.setRigidBodyTransform(Globals.clientSceneWrapper.getCollisionEngine(), position, rotation, cubeObject);
Collidable collidable = new Collidable(rVal, Collidable.TYPE_STRUCTURE);
Globals.clientSceneWrapper.getCollisionEngine().registerCollisionObject(cubeObject, collidable);
@ -161,7 +161,7 @@ public class CollisionObjUtils {
Entity rVal = EntityCreationUtils.createServerEntity(realm, new Vector3d(position));
float mass = 1.0f;
DBody cubeObject = CollisionBodyCreation.createCylinderBody(realm.getCollisionEngine(),scale.x,scale.y);
DBody cubeObject = CollisionBodyCreation.createCylinderBody(realm.getCollisionEngine(),scale.x,scale.y,Collidable.TYPE_STATIC_BIT);
PhysicsUtils.setRigidBodyTransform(realm.getCollisionEngine(), position, rotation, cubeObject);
Collidable collidable = new Collidable(rVal, Collidable.TYPE_STRUCTURE);
realm.getCollisionEngine().registerCollisionObject(cubeObject, collidable);

View File

@ -121,7 +121,8 @@ public class ProceduralTree {
DBody rigidBody = CollisionBodyCreation.createCylinderBody(
Globals.clientSceneWrapper.getCollisionEngine(),
treeModel.getPhysicsBody().getDimension1(),
treeModel.getPhysicsBody().getDimension2()
treeModel.getPhysicsBody().getDimension2(),
Collidable.TYPE_STATIC_BIT
);
Collidable collidable = new Collidable(trunkChild, Collidable.TYPE_OBJECT);
trunkChild.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);
@ -379,7 +380,8 @@ public class ProceduralTree {
DBody rigidBody = CollisionBodyCreation.createCylinderBody(
realm.getCollisionEngine(),
treeModel.getPhysicsBody().getDimension1(),
treeModel.getPhysicsBody().getDimension2()
treeModel.getPhysicsBody().getDimension2(),
Collidable.TYPE_STATIC_BIT
);
Collidable collidable = new Collidable(trunkChild, Collidable.TYPE_FOLIAGE_STATIC);
trunkChild.putData(EntityDataStrings.PHYSICS_COLLISION_BODY, rigidBody);