From d0fbab77ce7e5b913a98bad459ae665be9aa0cb5 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Tue, 26 Mar 2019 22:57:38 +0100 Subject: [PATCH] Simplify broad-phase --- src/body/Body.cpp | 8 +++ src/body/CollisionBody.cpp | 7 ++- src/body/CollisionBody.h | 9 ++-- src/body/RigidBody.cpp | 4 +- src/collision/CollisionDetection.cpp | 8 +-- src/collision/broadphase/DynamicAABBTree.cpp | 2 +- src/engine/CollisionWorld.cpp | 4 ++ src/systems/BroadPhaseSystem.cpp | 55 ++++---------------- src/systems/BroadPhaseSystem.h | 4 -- test/tests/collision/TestDynamicAABBTree.h | 1 + testbed/common/PhysicsObject.cpp | 2 - 11 files changed, 37 insertions(+), 67 deletions(-) diff --git a/src/body/Body.cpp b/src/body/Body.cpp index a9b1d0eb..c322c53e 100644 --- a/src/body/Body.cpp +++ b/src/body/Body.cpp @@ -52,6 +52,8 @@ Body::Body(Entity entity, bodyindex id) void Body::setIsActive(bool isActive) { mIsActive = isActive; + setIsSleeping(isActive); + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, "Body " + std::to_string(mID) + ": Set isActive=" + (mIsActive ? "true" : "false")); @@ -60,6 +62,12 @@ void Body::setIsActive(bool isActive) { // Set the variable to know whether or not the body is sleeping void Body::setIsSleeping(bool isSleeping) { + // If the body is not active, do nothing (it is sleeping) + if (!mIsActive) { + assert(mIsSleeping); + return; + } + if (isSleeping) { mSleepTime = decimal(0.0); } diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 0af2cd25..5ff628e4 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -250,9 +250,6 @@ void CollisionBody::setIsActive(bool isActive) { Body::setIsActive(isActive); - // Enable the components - mWorld.notifyBodyDisabled(mEntity, !isActive); - // If we have to activate the body if (isActive) { @@ -426,6 +423,9 @@ void CollisionBody::setTransform(const Transform& transform) { // TODO : Make sure this method is never called from the internal physics engine + // Awake the body if it is sleeping + setIsSleeping(false); + // Update the transform of the body mWorld.mTransformComponents.setTransform(mEntity, transform); @@ -436,7 +436,6 @@ void CollisionBody::setTransform(const Transform& transform) { "Body " + std::to_string(mID) + ": Set transform=" + transform.to_string()); } - // Set the variable to know whether or not the body is sleeping void CollisionBody::setIsSleeping(bool isSleeping) { diff --git a/src/body/CollisionBody.h b/src/body/CollisionBody.h index 9f20de8b..018eb87e 100644 --- a/src/body/CollisionBody.h +++ b/src/body/CollisionBody.h @@ -101,6 +101,9 @@ class CollisionBody : public Body { /// Reset the mIsAlreadyInIsland variable of the body and contact manifolds int resetIsAlreadyInIslandAndCountManifolds(); + /// Set the variable to know whether or not the body is sleeping + virtual void setIsSleeping(bool isSleeping) override; + public : // -------------------- Methods -------------------- // @@ -132,9 +135,6 @@ class CollisionBody : public Body { /// Set the current position and orientation virtual void setTransform(const Transform& transform); - /// Set the variable to know whether or not the body is sleeping - virtual void setIsSleeping(bool isSleeping) override; - /// Add a collision shape to the body. virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, const Transform& transform); @@ -163,9 +163,6 @@ class CollisionBody : public Body { /// Return a pointer to a given proxy-shape of the body ProxyShape* getProxyShape(uint proxyShapeIndex); - /// Return the linked list of proxy shapes of that body - const ProxyShape* getProxyShapesList() const; - /// Return the number of proxy-shapes associated with this body uint getNbProxyShapes() const; diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index a456bdbe..d637d0a7 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -606,14 +606,14 @@ Vector3 RigidBody::getAngularVelocity() const { // Set the variable to know whether or not the body is sleeping void RigidBody::setIsSleeping(bool isSleeping) { + CollisionBody::setIsSleeping(isSleeping); + if (isSleeping) { mWorld.mDynamicsComponents.setLinearVelocity(mEntity, Vector3::zero()); mWorld.mDynamicsComponents.setAngularVelocity(mEntity, Vector3::zero()); mExternalForce.setToZero(); mExternalTorque.setToZero(); } - - CollisionBody::setIsSleeping(isSleeping); } #ifdef IS_PROFILING_ACTIVE diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index caabf756..5d09b87d 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -345,16 +345,16 @@ void CollisionDetection::broadPhaseNotifyOverlappingPair(ProxyShape* shape1, Pro assert(shape2->getBroadPhaseId() != -1); assert(shape1->getBroadPhaseId() != shape2->getBroadPhaseId()); - // Check if the collision filtering allows collision between the two shapes - if ((shape1->getCollideWithMaskBits() & shape2->getCollisionCategoryBits()) == 0 || - (shape1->getCollisionCategoryBits() & shape2->getCollideWithMaskBits()) == 0) return; - // Compute the overlapping pair ID Pair pairID = OverlappingPair::computeID(shape1, shape2); // Check if the overlapping pair already exists if (mOverlappingPairs.containsKey(pairID)) return; + // Check if the collision filtering allows collision between the two shapes + if ((shape1->getCollideWithMaskBits() & shape2->getCollisionCategoryBits()) == 0 || + (shape1->getCollisionCategoryBits() & shape2->getCollideWithMaskBits()) == 0) return; + // Create the overlapping pair and add it into the set of overlapping pairs OverlappingPair* newPair = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(OverlappingPair))) OverlappingPair(shape1, shape2, mMemoryManager.getPoolAllocator(), diff --git a/src/collision/broadphase/DynamicAABBTree.cpp b/src/collision/broadphase/DynamicAABBTree.cpp index f693ab79..80635721 100644 --- a/src/collision/broadphase/DynamicAABBTree.cpp +++ b/src/collision/broadphase/DynamicAABBTree.cpp @@ -603,7 +603,7 @@ void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb, Dynam while(stack.getNbElements() > 0) { // Get the next node ID to visit - int nodeIDToVisit = stack.pop(); + const int nodeIDToVisit = stack.pop(); // Skip it if it is a null node if (nodeIDToVisit == TreeNode::NULL_TREE_NODE) continue; diff --git a/src/engine/CollisionWorld.cpp b/src/engine/CollisionWorld.cpp index 5ae61e12..977030b8 100644 --- a/src/engine/CollisionWorld.cpp +++ b/src/engine/CollisionWorld.cpp @@ -256,6 +256,10 @@ void CollisionWorld::notifyBodyDisabled(Entity bodyEntity, bool isDisabled) { mBodyComponents.setIsEntityDisabled(bodyEntity, isDisabled); mTransformComponents.setIsEntityDisabled(bodyEntity, isDisabled); + if (mDynamicsComponents.hasComponent(bodyEntity)) { + mDynamicsComponents.setIsEntityDisabled(bodyEntity, isDisabled); + } + // For each proxy-shape of the body const List& proxyShapesEntities = mBodyComponents.getProxyShapes(bodyEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { diff --git a/src/systems/BroadPhaseSystem.cpp b/src/systems/BroadPhaseSystem.cpp index 8d9a0174..d9b0480e 100644 --- a/src/systems/BroadPhaseSystem.cpp +++ b/src/systems/BroadPhaseSystem.cpp @@ -41,7 +41,6 @@ BroadPhaseSystem::BroadPhaseSystem(CollisionDetection& collisionDetection, Proxy mProxyShapesComponents(proxyShapesComponents), mTransformsComponents(transformComponents), mDynamicsComponents(dynamicsComponents), mMovedShapes(collisionDetection.getMemoryManager().getPoolAllocator()), - mPotentialPairs(collisionDetection.getMemoryManager().getPoolAllocator()), mCollisionDetection(collisionDetection) { #ifdef IS_PROFILING_ACTIVE @@ -206,9 +205,6 @@ void BroadPhaseSystem::reportAllShapesOverlappingWithAABB(const AABB& aabb, List // Compute all the overlapping pairs of collision shapes void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager) { - // Reset the potential overlapping pairs - mPotentialPairs.clear(); - List overlappingNodes(memoryManager.getPoolAllocator()); // For all collision shapes that have moved (or have been created) during the last simulation step @@ -237,55 +233,26 @@ void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager) { // Reset the array of collision shapes that have move (or have been created) during the // last simulation step mMovedShapes.clear(); - - // Check all the potential overlapping pairs avoiding duplicates to report unique overlapping pairs - auto it = mPotentialPairs.begin(); - while (it != mPotentialPairs.end()) { - - // Get a potential overlapping pair - BroadPhasePair& pair = *it; - ++it; - - assert(pair.shape1BroadPhaseId != pair.shape2BroadPhaseId); - - // Get the two collision shapes of the pair - ProxyShape* shape1 = static_cast(mDynamicAABBTree.getNodeDataPointer(pair.shape1BroadPhaseId)); - ProxyShape* shape2 = static_cast(mDynamicAABBTree.getNodeDataPointer(pair.shape2BroadPhaseId)); - - // If the two proxy collision shapes are from the same body, skip it - if (shape1->getBody()->getId() != shape2->getBody()->getId()) { - - // Notify the collision detection about the overlapping pair - mCollisionDetection.broadPhaseNotifyOverlappingPair(shape1, shape2); - } - - // Skip the duplicate overlapping pairs - while (it != mPotentialPairs.end()) { - - // Get the next pair - BroadPhasePair& nextPair = *it; - - // If the next pair is different from the previous one, we stop skipping pairs - if (nextPair.shape1BroadPhaseId != pair.shape1BroadPhaseId || - nextPair.shape2BroadPhaseId != pair.shape2BroadPhaseId) { - break; - } - ++it; - } - } } // Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree void BroadPhaseSystem::addOverlappingNodes(int referenceNodeId, const List& overlappingNodes) { - // For each overlapping node in the linked list + // For each overlapping node in the list for (uint i=0; i < overlappingNodes.size(); i++) { - // If both the nodes are the same, we do not create the overlapping pair if (referenceNodeId != overlappingNodes[i]) { - // Add the new potential pair into the array of potential overlapping pairs - mPotentialPairs.add(BroadPhasePair(referenceNodeId, overlappingNodes[i])); + // Get the two collision shapes of the pair + ProxyShape* shape1 = static_cast(mDynamicAABBTree.getNodeDataPointer(referenceNodeId)); + ProxyShape* shape2 = static_cast(mDynamicAABBTree.getNodeDataPointer(overlappingNodes[i])); + + // If the two proxy collision shapes are from the same body, skip it + if (shape1->getBody()->getId() != shape2->getBody()->getId()) { + + // Notify the collision detection about the overlapping pair + mCollisionDetection.broadPhaseNotifyOverlappingPair(shape1, shape2); + } } } } diff --git a/src/systems/BroadPhaseSystem.h b/src/systems/BroadPhaseSystem.h index d57a0ac8..7f991bbd 100644 --- a/src/systems/BroadPhaseSystem.h +++ b/src/systems/BroadPhaseSystem.h @@ -33,7 +33,6 @@ #include "components/ProxyShapeComponents.h" #include "components/TransformComponents.h" #include "components/DynamicsComponents.h" -#include "collision/broadphase/BroadPhasePair.h" #include /// Namespace ReactPhysics3D @@ -129,9 +128,6 @@ class BroadPhaseSystem { /// for overlapping in the next simulation step. Set mMovedShapes; - /// Temporary array of potential overlapping pairs (with potential duplicates) - Set mPotentialPairs; - /// Reference to the collision detection object CollisionDetection& mCollisionDetection; diff --git a/test/tests/collision/TestDynamicAABBTree.h b/test/tests/collision/TestDynamicAABBTree.h index 6878955d..dd453bd4 100755 --- a/test/tests/collision/TestDynamicAABBTree.h +++ b/test/tests/collision/TestDynamicAABBTree.h @@ -39,6 +39,7 @@ class TestOverlapCallback : public DynamicAABBTreeOverlapCallback { public : + // TODO : Replace this by rp3d::List std::vector mOverlapNodes; // Called when a overlapping node has been found during the call to diff --git a/testbed/common/PhysicsObject.cpp b/testbed/common/PhysicsObject.cpp index ca23caef..7f5a8ba2 100644 --- a/testbed/common/PhysicsObject.cpp +++ b/testbed/common/PhysicsObject.cpp @@ -75,8 +75,6 @@ void PhysicsObject::setTransform(const rp3d::Transform& transform) { // Reset the transform mBody->setTransform(transform); - mBody->setIsSleeping(false); - // Reset the velocity of the rigid body rp3d::RigidBody* rigidBody = dynamic_cast(mBody); if (rigidBody != nullptr) {