From 7b6cc59d305379e3918c40de2e4cf003a6fcaf1f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Jun 2015 11:40:48 -0700 Subject: [PATCH] basic support for collision groups --- interface/src/avatar/AvatarMotionState.cpp | 6 ++ interface/src/avatar/AvatarMotionState.h | 2 + .../src/DynamicCharacterController.cpp | 3 +- libraries/physics/src/EntityMotionState.cpp | 5 ++ libraries/physics/src/EntityMotionState.h | 2 + libraries/physics/src/ObjectMotionState.h | 2 + libraries/physics/src/PhysicsEngine.cpp | 25 +++++++- libraries/physics/src/PhysicsEngine.h | 59 +++++++++++++++++++ 8 files changed, 100 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 530225b319..7a5fb5662c 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -10,6 +10,7 @@ // #include +#include #include "Avatar.h" #include "AvatarMotionState.h" @@ -151,6 +152,11 @@ QUuid AvatarMotionState::getSimulatorID() const { void AvatarMotionState::bump() { } +// virtual +int16_t AvatarMotionState::computeCollisionGroup() { + return COLLISION_GROUP_OTHER_AVATAR; +} + // virtual void AvatarMotionState::clearObjectBackPointer() { ObjectMotionState::clearObjectBackPointer(); diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 68c687d65b..79a4d23179 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -61,6 +61,8 @@ public: void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; } + virtual int16_t computeCollisionGroup(); + friend class AvatarManager; protected: diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index 5d2a1798f9..b55975c11a 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -5,6 +5,7 @@ #include "BulletUtil.h" #include "DynamicCharacterController.h" +#include "PhysicsEngine.h" const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const float DEFAULT_GRAVITY = -5.0f; @@ -267,7 +268,7 @@ void DynamicCharacterController::setDynamicsWorld(btDynamicsWorld* world) { if (world && _rigidBody) { _dynamicsWorld = world; _pendingFlags &= ~ PENDING_FLAG_JUMP; - _dynamicsWorld->addRigidBody(_rigidBody); + _dynamicsWorld->addRigidBody(_rigidBody, COLLISION_GROUP_MY_AVATAR, COLLISION_MASK_MY_AVATAR); _dynamicsWorld->addAction(this); //reset(_dynamicsWorld); } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9a24aabb34..c7cbca7ea7 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -517,3 +517,8 @@ QString EntityMotionState::getName() { } return ""; } + +// virtual +int16_t EntityMotionState::computeCollisionGroup() { + return COLLISION_GROUP_DEFAULT; +} diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 65279dc01a..da1a5b5d81 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -77,6 +77,8 @@ public: virtual QString getName(); + virtual int16_t computeCollisionGroup(); + friend class PhysicalEntitySimulation; protected: diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 246ed16627..fc0c58b5da 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -123,6 +123,8 @@ public: virtual QString getName() { return ""; } + virtual int16_t computeCollisionGroup() = 0; + friend class PhysicsEngine; protected: diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index b622a37136..5d6823c403 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -23,8 +23,19 @@ uint32_t PhysicsEngine::getNumSubsteps() { } PhysicsEngine::PhysicsEngine(const glm::vec3& offset) : - _originOffset(offset), - _characterController(nullptr) { + _originOffset(offset), + _characterController(nullptr) { + // build table of masks with their group as the key + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_DEFAULT), COLLISION_MASK_DEFAULT); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_STATIC), COLLISION_MASK_STATIC); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_KINEMATIC), COLLISION_MASK_KINEMATIC); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_DEBRIS), COLLISION_MASK_DEBRIS); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_TRIGGER), COLLISION_MASK_TRIGGER); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_MY_AVATAR), COLLISION_MASK_MY_AVATAR); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_MY_ATTACHMENT), COLLISION_MASK_MY_ATTACHMENT); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_OTHER_AVATAR), COLLISION_MASK_OTHER_AVATAR); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_OTHER_ATTACHMENT), COLLISION_MASK_OTHER_ATTACHMENT); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_COLLISIONLESS), COLLISION_MASK_COLLISIONLESS); } PhysicsEngine::~PhysicsEngine() { @@ -125,7 +136,8 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) { body->setFlags(BT_DISABLE_WORLD_GRAVITY); motionState->updateBodyMaterialProperties(); - _dynamicsWorld->addRigidBody(body); + int16_t group = motionState->computeCollisionGroup(); + _dynamicsWorld->addRigidBody(body, group, getCollisionMask(group)); motionState->getAndClearIncomingDirtyFlags(); } @@ -417,6 +429,7 @@ void PhysicsEngine::setCharacterController(DynamicCharacterController* character } } +// static bool PhysicsEngine::physicsInfoIsActive(void* physicsInfo) { if (!physicsInfo) { return false; @@ -431,6 +444,7 @@ bool PhysicsEngine::physicsInfoIsActive(void* physicsInfo) { return body->isActive(); } +// static bool PhysicsEngine::getBodyLocation(void* physicsInfo, glm::vec3& positionReturn, glm::quat& rotationReturn) { if (!physicsInfo) { return false; @@ -448,3 +462,8 @@ bool PhysicsEngine::getBodyLocation(void* physicsInfo, glm::vec3& positionReturn return true; } + +int16_t PhysicsEngine::getCollisionMask(int16_t group) const { + const int16_t* mask = _collisionMasks.find(btHashInt((int)group)); + return mask ? *mask : COLLISION_MASK_DEFAULT; +} diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 9ff85c9f11..f0bd8ba4e9 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -25,6 +25,61 @@ #include "ObjectMotionState.h" #include "ThreadSafeDynamicsWorld.h" +/* Note: These are the collision groups defined in btBroadphaseProxy. Only + * DefaultFilter and StaticFilter are explicitly used by Bullet (when the + * collision filter of an object is not manually specified), the rest are + * merely suggestions. + * +enum CollisionFilterGroups { + DefaultFilter = 1, + StaticFilter = 2, + KinematicFilter = 4, + DebrisFilter = 8, + SensorTrigger = 16, + CharacterFilter = 32, + AllFilter = -1 +} + * + * When using custom collision filters we pretty much need to do all or nothing. + * We'll be doing it all which means we define our own groups and build custom masks + * for everything. + * +*/ + +const int16_t COLLISION_GROUP_DEFAULT = 1 << 0; +const int16_t COLLISION_GROUP_STATIC = 1 << 1; +const int16_t COLLISION_GROUP_KINEMATIC = 1 << 2; +const int16_t COLLISION_GROUP_DEBRIS = 1 << 3; +const int16_t COLLISION_GROUP_TRIGGER = 1 << 4; +const int16_t COLLISION_GROUP_MY_AVATAR = 1 << 5; +const int16_t COLLISION_GROUP_OTHER_AVATAR = 1 << 6; +const int16_t COLLISION_GROUP_MY_ATTACHMENT = 1 << 7; +const int16_t COLLISION_GROUP_OTHER_ATTACHMENT = 1 << 8; +// ... +const int16_t COLLISION_GROUP_COLLISIONLESS = 1 << 15; + + +/* Note: In order for objectA to collide with objectB at the filter stage + * both (groupA & maskB) and (groupB & maskA) must be non-zero. + */ +// DEFAULT collides with everything except COLLISIONLESS +const int16_t COLLISION_MASK_DEFAULT = ~ COLLISION_GROUP_COLLISIONLESS; +const int16_t COLLISION_MASK_STATIC = COLLISION_MASK_DEFAULT; +const int16_t COLLISION_MASK_KINEMATIC = COLLISION_MASK_DEFAULT; +// DEBRIS also doesn't collide with: other DEBRIS, and TRIGGER +const int16_t COLLISION_MASK_DEBRIS = ~ (COLLISION_GROUP_COLLISIONLESS + | COLLISION_GROUP_DEBRIS + | COLLISION_GROUP_TRIGGER); +// TRIGGER also doesn't collide with: DEBRIS, TRIGGER, and STATIC (TRIGGER only detects moveable things that matter) +const int16_t COLLISION_MASK_TRIGGER = COLLISION_MASK_DEBRIS & ~(COLLISION_GROUP_STATIC); +// AVATAR also doesn't collide with: corresponding ATTACHMENT +const int16_t COLLISION_MASK_MY_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_ATTACHMENT); +const int16_t COLLISION_MASK_MY_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_AVATAR); +const int16_t COLLISION_MASK_OTHER_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_ATTACHMENT); +const int16_t COLLISION_MASK_OTHER_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_AVATAR); +// ... +const int16_t COLLISION_MASK_COLLISIONLESS = 0; + const float HALF_SIMULATION_EXTENT = 512.0f; // meters // simple class for keeping track of contacts @@ -91,9 +146,12 @@ public: void dumpNextStats() { _dumpNextStats = true; } + // TODO: Andrew to move these to ObjectMotionState static bool physicsInfoIsActive(void* physicsInfo); static bool getBodyLocation(void* physicsInfo, glm::vec3& positionReturn, glm::quat& rotationReturn); + int16_t getCollisionMask(int16_t group) const; + private: void removeContacts(ObjectMotionState* motionState); @@ -121,6 +179,7 @@ private: QUuid _sessionID; CollisionEvents _collisionEvents; + btHashMap _collisionMasks; }; #endif // hifi_PhysicsEngine_h