From d894a40d2eae9d70fea94f10dc12a9e74d6919b4 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Tue, 19 Nov 2019 18:35:22 +0100 Subject: [PATCH] Working on middle-phase collision detection --- src/body/RigidBody.cpp | 23 +++ src/body/RigidBody.h | 3 + .../CapsuleVsCapsuleNarrowPhaseInfoBatch.cpp | 4 +- .../CapsuleVsCapsuleNarrowPhaseInfoBatch.h | 2 +- .../narrowphase/NarrowPhaseInfoBatch.cpp | 4 +- .../narrowphase/NarrowPhaseInfoBatch.h | 2 +- .../narrowphase/NarrowPhaseInput.cpp | 14 +- src/collision/narrowphase/NarrowPhaseInput.h | 2 +- .../SphereVsCapsuleNarrowPhaseInfoBatch.cpp | 4 +- .../SphereVsCapsuleNarrowPhaseInfoBatch.h | 2 +- .../SphereVsSphereNarrowPhaseInfoBatch.cpp | 4 +- .../SphereVsSphereNarrowPhaseInfoBatch.h | 2 +- src/collision/shapes/CollisionShape.h | 6 +- src/engine/OverlappingPairs.cpp | 132 +++++++------ src/engine/OverlappingPairs.h | 35 ++-- src/systems/CollisionDetectionSystem.cpp | 183 +++++------------- src/systems/CollisionDetectionSystem.h | 3 +- 17 files changed, 200 insertions(+), 225 deletions(-) diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index 5bb38982..6712c739 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -98,6 +98,9 @@ void RigidBody::setType(BodyType type) { // Awake the body setIsSleeping(false); + // Update the active status of currently overlapping pairs + updateOverlappingPairs(); + // Ask the broad-phase to test again the collision shapes of the body for collision // detection (as if the body has moved) askForBroadPhaseCollisionCheck(); @@ -683,6 +686,9 @@ void RigidBody::setIsSleeping(bool isSleeping) { // Notify all the components mWorld.setBodyDisabled(mEntity, isSleeping); + // Update the currently overlapping pairs + updateOverlappingPairs(); + if (isSleeping) { mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, Vector3::zero()); @@ -696,6 +702,23 @@ void RigidBody::setIsSleeping(bool isSleeping) { (isSleeping ? "true" : "false")); } +// Update whether the current overlapping pairs where this body is involed are active or not +void RigidBody::updateOverlappingPairs() { + + // For each proxy-shape of the body + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); + for (uint i=0; i < proxyShapesEntities.size(); i++) { + + // Get the currently overlapping pairs for this proxy-shape + List overlappingPairs = mWorld.mProxyShapesComponents.getOverlappingPairs(proxyShapesEntities[i]); + + for (uint j=0; j < overlappingPairs.size(); j++) { + + mWorld.mCollisionDetection.mOverlappingPairs.updateOverlappingPairIsActive(overlappingPairs[j]); + } + } +} + /// Return the inverse of the inertia tensor in world coordinates. const Matrix3x3 RigidBody::getInertiaTensorInverseWorld(CollisionWorld& world, Entity bodyEntity) { diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h index 0a83d5af..85413051 100644 --- a/src/body/RigidBody.h +++ b/src/body/RigidBody.h @@ -73,6 +73,9 @@ class RigidBody : public CollisionBody { /// Set the variable to know whether or not the body is sleeping void setIsSleeping(bool isSleeping); + /// Update whether the current overlapping pairs where this body is involed are active or not + void updateOverlappingPairs(); + /// Return the inverse of the inertia tensor in world coordinates. static const Matrix3x3 getInertiaTensorInverseWorld(CollisionWorld& world, Entity bodyEntity); diff --git a/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.cpp b/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.cpp index 879fb258..cba95097 100644 --- a/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.cpp +++ b/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.cpp @@ -38,7 +38,7 @@ CapsuleVsCapsuleNarrowPhaseInfoBatch::CapsuleVsCapsuleNarrowPhaseInfoBatch(Memor } // Add shapes to be tested during narrow-phase collision detection into the batch -void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, +void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform) { assert(shape1->getType() == CollisionShapeType::CAPSULE); @@ -60,7 +60,7 @@ void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Ent isColliding.add(false); // Add a collision info for the two collision shapes into the overlapping pair (if not present yet) - LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId()); + LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId()); lastFrameCollisionInfos.add(lastFrameInfo); } diff --git a/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.h b/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.h index 645ee76c..84366756 100644 --- a/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.h +++ b/src/collision/narrowphase/CapsuleVsCapsuleNarrowPhaseInfoBatch.h @@ -61,7 +61,7 @@ struct CapsuleVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch { virtual ~CapsuleVsCapsuleNarrowPhaseInfoBatch() = default; /// Add shapes to be tested during narrow-phase collision detection into the batch - virtual void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, + virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform); diff --git a/src/collision/narrowphase/NarrowPhaseInfoBatch.cpp b/src/collision/narrowphase/NarrowPhaseInfoBatch.cpp index 7e53dd6a..a44fd5b8 100644 --- a/src/collision/narrowphase/NarrowPhaseInfoBatch.cpp +++ b/src/collision/narrowphase/NarrowPhaseInfoBatch.cpp @@ -48,7 +48,7 @@ NarrowPhaseInfoBatch::~NarrowPhaseInfoBatch() { } // Add shapes to be tested during narrow-phase collision detection into the batch -void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, +void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform, MemoryAllocator& shapeAllocator) { @@ -64,7 +64,7 @@ void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, isColliding.add(false); // Add a collision info for the two collision shapes into the overlapping pair (if not present yet) - LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId()); + LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId()); lastFrameCollisionInfos.add(lastFrameInfo); } diff --git a/src/collision/narrowphase/NarrowPhaseInfoBatch.h b/src/collision/narrowphase/NarrowPhaseInfoBatch.h index 9a76642f..37086222 100644 --- a/src/collision/narrowphase/NarrowPhaseInfoBatch.h +++ b/src/collision/narrowphase/NarrowPhaseInfoBatch.h @@ -103,7 +103,7 @@ struct NarrowPhaseInfoBatch { uint getNbObjects() const; /// Add shapes to be tested during narrow-phase collision detection into the batch - void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, + void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform, MemoryAllocator& shapeAllocator); diff --git a/src/collision/narrowphase/NarrowPhaseInput.cpp b/src/collision/narrowphase/NarrowPhaseInput.cpp index 6c00889c..a68ab508 100644 --- a/src/collision/narrowphase/NarrowPhaseInput.cpp +++ b/src/collision/narrowphase/NarrowPhaseInput.cpp @@ -39,28 +39,28 @@ NarrowPhaseInput::NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs& } // Add shapes to be tested during narrow-phase collision detection into the batch -void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, +void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, MemoryAllocator& shapeAllocator) { switch (narrowPhaseAlgorithmType) { case NarrowPhaseAlgorithmType::SphereVsSphere: - mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); + mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); break; case NarrowPhaseAlgorithmType::SphereVsCapsule: - mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); + mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); break; case NarrowPhaseAlgorithmType::CapsuleVsCapsule: - mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); + mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); break; case NarrowPhaseAlgorithmType::SphereVsConvexPolyhedron: - mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator); + mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator); break; case NarrowPhaseAlgorithmType::CapsuleVsConvexPolyhedron: - mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator); + mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator); break; case NarrowPhaseAlgorithmType::ConvexPolyhedronVsConvexPolyhedron: - mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator); + mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator); break; case NarrowPhaseAlgorithmType::None: // Must never happen diff --git a/src/collision/narrowphase/NarrowPhaseInput.h b/src/collision/narrowphase/NarrowPhaseInput.h index f5256155..c37bce67 100644 --- a/src/collision/narrowphase/NarrowPhaseInput.h +++ b/src/collision/narrowphase/NarrowPhaseInput.h @@ -67,7 +67,7 @@ class NarrowPhaseInput { NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs); /// Add shapes to be tested during narrow-phase collision detection into the batch - void addNarrowPhaseTest(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, + void addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, MemoryAllocator& shapeAllocator); diff --git a/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.cpp b/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.cpp index b5baa27d..05f25910 100644 --- a/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.cpp +++ b/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.cpp @@ -39,7 +39,7 @@ SphereVsCapsuleNarrowPhaseInfoBatch::SphereVsCapsuleNarrowPhaseInfoBatch(MemoryA } // Add shapes to be tested during narrow-phase collision detection into the batch -void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, +void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform) { bool isSphereShape1 = shape1->getType() == CollisionShapeType::SPHERE; @@ -63,7 +63,7 @@ void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Enti isColliding.add(false); // Add a collision info for the two collision shapes into the overlapping pair (if not present yet) - LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId()); + LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId()); lastFrameCollisionInfos.add(lastFrameInfo); } diff --git a/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.h b/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.h index 9145967d..e2a4964d 100644 --- a/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.h +++ b/src/collision/narrowphase/SphereVsCapsuleNarrowPhaseInfoBatch.h @@ -61,7 +61,7 @@ struct SphereVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch { virtual ~SphereVsCapsuleNarrowPhaseInfoBatch() = default; /// Add shapes to be tested during narrow-phase collision detection into the batch - virtual void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, + virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform); diff --git a/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.cpp b/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.cpp index 27a67f68..a5a8269f 100644 --- a/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.cpp +++ b/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.cpp @@ -36,7 +36,7 @@ SphereVsSphereNarrowPhaseInfoBatch::SphereVsSphereNarrowPhaseInfoBatch(MemoryAll } // Add shapes to be tested during narrow-phase collision detection into the batch -void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, +void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform) { assert(shape1->getType() == CollisionShapeType::SPHERE); @@ -56,7 +56,7 @@ void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entit isColliding.add(false); // Add a collision info for the two collision shapes into the overlapping pair (if not present yet) - LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId()); + LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId()); lastFrameCollisionInfos.add(lastFrameInfo); } diff --git a/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.h b/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.h index 4087f90f..f5e352a7 100644 --- a/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.h +++ b/src/collision/narrowphase/SphereVsSphereNarrowPhaseInfoBatch.h @@ -55,7 +55,7 @@ struct SphereVsSphereNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch { virtual ~SphereVsSphereNarrowPhaseInfoBatch() override = default; /// Add shapes to be tested during narrow-phase collision detection into the batch - virtual void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, + virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform); diff --git a/src/collision/shapes/CollisionShape.h b/src/collision/shapes/CollisionShape.h index edf1f9c6..440df9e1 100644 --- a/src/collision/shapes/CollisionShape.h +++ b/src/collision/shapes/CollisionShape.h @@ -73,7 +73,7 @@ class CollisionShape { CollisionShapeName mName; /// Unique identifier of the shape inside an overlapping pair - uint mId; + uint32 mId; #ifdef IS_PROFILING_ACTIVE @@ -125,7 +125,7 @@ class CollisionShape { virtual void getLocalBounds(Vector3& min, Vector3& max) const=0; /// Return the id of the shape - uint getId() const; + uint32 getId() const; /// Return the local inertia tensor of the collision shapes virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const=0; @@ -166,7 +166,7 @@ inline CollisionShapeType CollisionShape::getType() const { } // Return the id of the shape -inline uint CollisionShape::getId() const { +inline uint32 CollisionShape::getId() const { return mId; } diff --git a/src/engine/OverlappingPairs.cpp b/src/engine/OverlappingPairs.cpp index a1912e28..0b1aad3f 100644 --- a/src/engine/OverlappingPairs.cpp +++ b/src/engine/OverlappingPairs.cpp @@ -38,8 +38,9 @@ OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, M CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, Set &noCollisionPairs, CollisionDispatch &collisionDispatch) : mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator), mNbPairs(0), mConcavePairsStartIndex(0), mPairDataSize(sizeof(uint64) + sizeof(int32) + sizeof(int32) + sizeof(Entity) + - sizeof(Entity) + sizeof(Map) + - sizeof(bool) + sizeof(bool) + sizeof(NarrowPhaseAlgorithmType)), + sizeof(Entity) + sizeof(Map) + + sizeof(bool) + sizeof(bool) + sizeof(NarrowPhaseAlgorithmType) + + sizeof(bool)), mNbAllocatedPairs(0), mBuffer(nullptr), mMapPairIdToPairIndex(persistentMemoryAllocator), mProxyShapeComponents(proxyShapeComponents), mCollisionBodyComponents(collisionBodyComponents), @@ -205,10 +206,11 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) { int32* newPairBroadPhaseId2 = reinterpret_cast(newPairBroadPhaseId1 + nbPairsToAllocate); Entity* newProxyShapes1 = reinterpret_cast(newPairBroadPhaseId2 + nbPairsToAllocate); Entity* newProxyShapes2 = reinterpret_cast(newProxyShapes1 + nbPairsToAllocate); - Map* newLastFrameCollisionInfos = reinterpret_cast*>(newProxyShapes2 + nbPairsToAllocate); + Map* newLastFrameCollisionInfos = reinterpret_cast*>(newProxyShapes2 + nbPairsToAllocate); bool* newNeedToTestOverlap = reinterpret_cast(newLastFrameCollisionInfos + nbPairsToAllocate); bool* newIsActive = reinterpret_cast(newNeedToTestOverlap + nbPairsToAllocate); NarrowPhaseAlgorithmType* newNarrowPhaseAlgorithmType = reinterpret_cast(newIsActive + nbPairsToAllocate); + bool* newIsShape1Convex = reinterpret_cast(newNarrowPhaseAlgorithmType + nbPairsToAllocate); // If there was already pairs before if (mNbPairs > 0) { @@ -219,10 +221,11 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) { memcpy(newPairBroadPhaseId2, mPairBroadPhaseId2, mNbPairs * sizeof(int32)); memcpy(newProxyShapes1, mProxyShapes1, mNbPairs * sizeof(Entity)); memcpy(newProxyShapes2, mProxyShapes2, mNbPairs * sizeof(Entity)); - memcpy(newLastFrameCollisionInfos, mLastFrameCollisionInfos, mNbPairs * sizeof(Map)); + memcpy(newLastFrameCollisionInfos, mLastFrameCollisionInfos, mNbPairs * sizeof(Map)); memcpy(newNeedToTestOverlap, mNeedToTestOverlap, mNbPairs * sizeof(bool)); memcpy(newIsActive, mIsActive, mNbPairs * sizeof(bool)); memcpy(newNarrowPhaseAlgorithmType, mNarrowPhaseAlgorithmType, mNbPairs * sizeof(NarrowPhaseAlgorithmType)); + memcpy(newIsShape1Convex, mIsShape1Convex, mNbPairs * sizeof(bool)); // Deallocate previous memory mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize); @@ -238,43 +241,57 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) { mNeedToTestOverlap = newNeedToTestOverlap; mIsActive = newIsActive; mNarrowPhaseAlgorithmType = newNarrowPhaseAlgorithmType; + mIsShape1Convex = newIsShape1Convex; mNbAllocatedPairs = nbPairsToAllocate; } // Add an overlapping pair -uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2, bool isActive) { +uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2) { RP3D_PROFILE("OverlappingPairs::addPair()", mProfiler); const CollisionShape* collisionShape1 = mProxyShapeComponents.getCollisionShape(shape1->getEntity()); const CollisionShape* collisionShape2 = mProxyShapeComponents.getCollisionShape(shape2->getEntity()); - // Prepare to add new pair (allocate memory if necessary and compute insertion index) - uint64 index = prepareAddPair(collisionShape1->isConvex() && collisionShape2->isConvex()); + const bool isShape1Convex = collisionShape1->isConvex(); + const bool isShape2Convex = collisionShape2->isConvex(); + const bool isConvexVsConvex = isShape1Convex && isShape2Convex; - const uint32 shape1Id = static_cast(shape1->getBroadPhaseId()); - const uint32 shape2Id = static_cast(shape2->getBroadPhaseId()); + // Prepare to add new pair (allocate memory if necessary and compute insertion index) + uint64 index = prepareAddPair(isConvexVsConvex); + + const uint32 broadPhase1Id = static_cast(shape1->getBroadPhaseId()); + const uint32 broadPhase2Id = static_cast(shape2->getBroadPhaseId()); // Compute a unique id for the overlapping pair - const uint64 pairId = pairNumbers(std::max(shape1Id, shape2Id), std::min(shape1Id, shape2Id)); + const uint64 pairId = pairNumbers(std::max(broadPhase1Id, broadPhase2Id), std::min(broadPhase1Id, broadPhase2Id)); assert(!mMapPairIdToPairIndex.containsKey(pairId)); // Select the narrow phase algorithm to use according to the two collision shapes - NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(), - collisionShape2->getType()); + NarrowPhaseAlgorithmType algorithmType; + if (isConvexVsConvex) { + + algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(), collisionShape2->getType()); + } + else { + + algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(isShape1Convex ? collisionShape1->getType() : collisionShape2->getType(), + CollisionShapeType::CONVEX_POLYHEDRON); + } + // Insert the new component data new (mPairIds + index) uint64(pairId); new (mPairBroadPhaseId1 + index) int32(shape1->getBroadPhaseId()); new (mPairBroadPhaseId2 + index) int32(shape2->getBroadPhaseId()); new (mProxyShapes1 + index) Entity(shape1->getEntity()); new (mProxyShapes2 + index) Entity(shape2->getEntity()); - new (mLastFrameCollisionInfos + index) Map(mPersistentAllocator); + new (mLastFrameCollisionInfos + index) Map(mPersistentAllocator); new (mNeedToTestOverlap + index) bool(false); - new (mIsActive + index) bool(isActive); + new (mIsActive + index) bool(true); new (mNarrowPhaseAlgorithmType + index) NarrowPhaseAlgorithmType(algorithmType); - + new (mIsShape1Convex + index) bool(isShape1Convex); // Map the entity with the new component lookup index mMapPairIdToPairIndex.add(Pair(pairId, index)); @@ -290,6 +307,8 @@ uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2, bool is assert(mConcavePairsStartIndex <= mNbPairs); assert(mNbPairs == static_cast(mMapPairIdToPairIndex.size())); + updateOverlappingPairIsActive(pairId); + return pairId; } @@ -305,10 +324,11 @@ void OverlappingPairs::movePairToIndex(uint64 srcIndex, uint64 destIndex) { mPairBroadPhaseId2[destIndex] = mPairBroadPhaseId2[srcIndex]; new (mProxyShapes1 + destIndex) Entity(mProxyShapes1[srcIndex]); new (mProxyShapes2 + destIndex) Entity(mProxyShapes2[srcIndex]); - new (mLastFrameCollisionInfos + destIndex) Map(mLastFrameCollisionInfos[srcIndex]); + new (mLastFrameCollisionInfos + destIndex) Map(mLastFrameCollisionInfos[srcIndex]); mNeedToTestOverlap[destIndex] = mNeedToTestOverlap[srcIndex]; mIsActive[destIndex] = mIsActive[srcIndex]; new (mNarrowPhaseAlgorithmType + destIndex) NarrowPhaseAlgorithmType(mNarrowPhaseAlgorithmType[srcIndex]); + mIsShape1Convex[destIndex] = mIsShape1Convex[srcIndex]; // Destroy the source pair destroyPair(srcIndex); @@ -330,10 +350,11 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) { int32 pairBroadPhaseId2 = mPairBroadPhaseId2[index1]; Entity proxyShape1 = mProxyShapes1[index1]; Entity proxyShape2 = mProxyShapes2[index1]; - Map lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]); + Map lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]); bool needTestOverlap = mNeedToTestOverlap[index1]; bool isActive = mIsActive[index1]; NarrowPhaseAlgorithmType narrowPhaseAlgorithmType = mNarrowPhaseAlgorithmType[index1]; + bool isShape1Convex = mIsShape1Convex[index1]; // Destroy pair 1 destroyPair(index1); @@ -346,10 +367,11 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) { mPairBroadPhaseId2[index2] = pairBroadPhaseId2; new (mProxyShapes1 + index2) Entity(proxyShape1); new (mProxyShapes2 + index2) Entity(proxyShape2); - new (mLastFrameCollisionInfos + index2) Map(lastFrameCollisionInfo); + new (mLastFrameCollisionInfos + index2) Map(lastFrameCollisionInfo); mNeedToTestOverlap[index2] = needTestOverlap; mIsActive[index2] = isActive; new (mNarrowPhaseAlgorithmType + index2) NarrowPhaseAlgorithmType(narrowPhaseAlgorithmType); + mIsShape1Convex[index2] = isShape1Convex; // Update the pairID to pair index mapping mMapPairIdToPairIndex.add(Pair(pairId, index2)); @@ -370,33 +392,60 @@ void OverlappingPairs::destroyPair(uint64 index) { mProxyShapes1[index].~Entity(); mProxyShapes2[index].~Entity(); - mLastFrameCollisionInfos[index].~Map(); + mLastFrameCollisionInfos[index].~Map(); mNarrowPhaseAlgorithmType[index].~NarrowPhaseAlgorithmType(); } -// Add a new last frame collision info if it does not exist for the given shapes already -LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pairId, uint shapeId1, uint shapeId2) { - - RP3D_PROFILE("OverlappingPairs::addLastFrameInfoIfNecessary()", mProfiler); +// Update whether a given overlapping pair is active or not +void OverlappingPairs::updateOverlappingPairIsActive(uint64 pairId) { assert(mMapPairIdToPairIndex.containsKey(pairId)); - const uint64 index = mMapPairIdToPairIndex[pairId]; - assert(index < mNbPairs); + const uint64 pairIndex = mMapPairIdToPairIndex[pairId]; + + const Entity proxyShape1 = mProxyShapes1[pairIndex]; + const Entity proxyShape2 = mProxyShapes2[pairIndex]; + + const Entity body1 = mProxyShapeComponents.getBody(proxyShape1); + const Entity body2 = mProxyShapeComponents.getBody(proxyShape2); + + const bool isBody1Enabled = !mCollisionBodyComponents.getIsEntityDisabled(body1); + const bool isBody2Enabled = !mCollisionBodyComponents.getIsEntityDisabled(body2); + const bool isBody1Static = mRigidBodyComponents.hasComponent(body1) && + mRigidBodyComponents.getBodyType(body1) == BodyType::STATIC; + const bool isBody2Static = mRigidBodyComponents.hasComponent(body2) && + mRigidBodyComponents.getBodyType(body2) == BodyType::STATIC; + + const bool isBody1Active = isBody1Enabled && !isBody1Static; + const bool isBody2Active = isBody2Enabled && !isBody2Static; + + // Check if the bodies are in the set of bodies that cannot collide between each other + bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1, body2); + bool bodiesCanCollide = !mNoCollisionPairs.contains(bodiesIndex); + + mIsActive[pairIndex] = bodiesCanCollide && (isBody1Active || isBody2Active); +} + +// Add a new last frame collision info if it does not exist for the given shapes already +LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2) { + + RP3D_PROFILE("OverlappingPairs::addLastFrameInfoIfNecessary()", mProfiler); + + assert(pairIndex < mNbPairs); // Try to get the corresponding last frame collision info - const ShapeIdPair shapeIdPair(shapeId1, shapeId2); + const uint64 shapesId = pairNumbers(std::max(shapeId1, shapeId2), std::min(shapeId1, shapeId2)); // If there is no collision info for those two shapes already - auto it = mLastFrameCollisionInfos[index].find(shapeIdPair); - if (it == mLastFrameCollisionInfos[index].end()) { + auto it = mLastFrameCollisionInfos[pairIndex].find(shapesId); + if (it == mLastFrameCollisionInfos[pairIndex].end()) { // Create a new collision info LastFrameCollisionInfo* collisionInfo = new (mPersistentAllocator.allocate(sizeof(LastFrameCollisionInfo))) LastFrameCollisionInfo(); // Add it into the map of collision infos - mLastFrameCollisionInfos[index].add(Pair(shapeIdPair, collisionInfo)); + mLastFrameCollisionInfos[pairIndex].add(Pair(shapesId, collisionInfo)); return collisionInfo; } @@ -439,28 +488,3 @@ void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() { } } } - -// Return true if the overlapping pair between two shapes is active -bool OverlappingPairs::computeIsPairActive(ProxyShape* shape1, ProxyShape* shape2) { - - const Entity body1Entity = mProxyShapeComponents.getBody(shape1->getEntity()); - const Entity body2Entity = mProxyShapeComponents.getBody(shape2->getEntity()); - - const bool isStaticRigidBody1 = mRigidBodyComponents.hasComponent(body1Entity) && - mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC; - const bool isStaticRigidBody2 = mRigidBodyComponents.hasComponent(body2Entity) && - mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC; - - // Check that at least one body is enabled (active and awake) and not static - // TODO : Do not test this every frame - bool isBody1Active = !mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; - bool isBody2Active = !mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; - if (!isBody1Active && !isBody2Active) return false; - - // Check if the bodies are in the set of bodies that cannot collide between each other - // TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation - bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity); - if (mNoCollisionPairs.contains(bodiesIndex) > 0) return false; - - return true; -} diff --git a/src/engine/OverlappingPairs.h b/src/engine/OverlappingPairs.h index 34fe478f..b4148c2c 100644 --- a/src/engine/OverlappingPairs.h +++ b/src/engine/OverlappingPairs.h @@ -104,11 +104,6 @@ struct LastFrameCollisionInfo { */ class OverlappingPairs { - public: - - // TODO : Try to use a pairing function like pairNumbers() here - using ShapeIdPair = Pair; - private: // -------------------- Constants -------------------- // @@ -165,7 +160,7 @@ class OverlappingPairs { /// If two convex shapes overlap, we have a single collision data but if one shape is concave, /// we might have collision data for several overlapping triangles. The key in the map is the /// shape Ids of the two collision shapes. - Map* mLastFrameCollisionInfos; + Map* mLastFrameCollisionInfos; /// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap bool* mNeedToTestOverlap; @@ -176,6 +171,9 @@ class OverlappingPairs { /// Array with the pointer to the narrow-phase algorithm for each overlapping pair NarrowPhaseAlgorithmType* mNarrowPhaseAlgorithmType; + /// True if the first shape of the pair is convex + bool* mIsShape1Convex; + /// Reference to the proxy-shapes components ProxyShapeComponents& mProxyShapeComponents; @@ -235,7 +233,7 @@ class OverlappingPairs { OverlappingPairs& operator=(const OverlappingPairs& pair) = delete; /// Add an overlapping pair - uint64 addPair(ProxyShape* shape1, ProxyShape* shape2, bool isActive); + uint64 addPair(ProxyShape* shape1, ProxyShape* shape2); /// Remove a component at a given index void removePair(uint64 pairId); @@ -261,14 +259,20 @@ class OverlappingPairs { /// Notify if a given pair is active or not void setIsPairActive(uint64 pairId, bool isActive); + /// Return the index of a given overlapping pair in the internal array + uint64 getPairIndex(uint64 pairId) const; + /// Return the last frame collision info - LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, ShapeIdPair& shapeIds); + LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, uint64 shapesId); /// Return a reference to the temporary memory allocator MemoryAllocator& getTemporaryAllocator(); /// Add a new last frame collision info if it does not exist for the given shapes already - LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint64 pairId, uint shapeId1, uint shapeId2); + LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2); + + /// Update whether a given overlapping pair is active or not + void updateOverlappingPairIsActive(uint64 pairId); /// Delete all the obsolete last frame collision info void clearObsoleteLastFrameCollisionInfos(); @@ -276,9 +280,6 @@ class OverlappingPairs { /// Return the pair of bodies index of the pair static bodypair computeBodiesIndexPair(Entity body1Entity, Entity body2Entity); - /// Return true if the overlapping pair between two shapes is active - bool computeIsPairActive(ProxyShape* shape1, ProxyShape* shape2); - /// Set if we need to test a given pair for overlap void setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap); @@ -317,14 +318,20 @@ inline void OverlappingPairs::setIsPairActive(uint64 pairId, bool isActive) { mIsActive[mMapPairIdToPairIndex[pairId]] = isActive; } +// Return the index of a given overlapping pair in the internal array +inline uint64 OverlappingPairs::getPairIndex(uint64 pairId) const { + assert(mMapPairIdToPairIndex.containsKey(pairId)); + return mMapPairIdToPairIndex[pairId]; +} + // Return the last frame collision info for a given shape id or nullptr if none is found -inline LastFrameCollisionInfo* OverlappingPairs::getLastFrameCollisionInfo(uint64 pairId, ShapeIdPair& shapeIds) { +inline LastFrameCollisionInfo* OverlappingPairs::getLastFrameCollisionInfo(uint64 pairId, uint64 shapesId) { assert(mMapPairIdToPairIndex.containsKey(pairId)); const uint64 index = mMapPairIdToPairIndex[pairId]; assert(index < mNbPairs); - Map::Iterator it = mLastFrameCollisionInfos[index].find(shapeIds); + Map::Iterator it = mLastFrameCollisionInfos[index].find(shapesId); if (it != mLastFrameCollisionInfos[index].end()) { return it->second; } diff --git a/src/systems/CollisionDetectionSystem.cpp b/src/systems/CollisionDetectionSystem.cpp index 2894dceb..165de8ec 100644 --- a/src/systems/CollisionDetectionSystem.cpp +++ b/src/systems/CollisionDetectionSystem.cpp @@ -189,7 +189,7 @@ void CollisionDetectionSystem::updateOverlappingPairs(const ListgetCollisionShape()->isConvex() || shape2->getCollisionShape()->isConvex()) { // Add the new overlapping pair - mOverlappingPairs.addPair(shape1, shape2, mOverlappingPairs.computeIsPairActive(shape1, shape2)); + mOverlappingPairs.addPair(shape1, shape2); } } } @@ -217,84 +217,47 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairs& overlappingP // For each possible convex vs convex pair of bodies for (uint64 i=0; i < overlappingPairs.getNbConvexVsConvexPairs(); i++) { - const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i]; - const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i]; - - const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1Entity); - const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2Entity); - - assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != -1); - assert(mProxyShapesComponents.mBroadPhaseId[proxyShape2Index] != -1); - assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != mProxyShapesComponents.mBroadPhaseId[proxyShape2Index]); - - const Entity body1Entity = mProxyShapesComponents.mBodiesEntities[proxyShape1Index]; - const Entity body2Entity = mProxyShapesComponents.mBodiesEntities[proxyShape2Index]; - - const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) && - mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC; - const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) && - mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC; + assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != -1); + assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i]) != -1); + assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i])); // Check that at least one body is enabled (active and awake) and not static // TODO : Do not test this every frame - bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; - bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; - if (!isBody1Active && !isBody2Active) continue; + if (mOverlappingPairs.mIsActive[i]) { - // Check if the bodies are in the set of bodies that cannot collide between each other - // TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation - bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity); - if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue; + const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i]; + const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i]; - CollisionShape* collisionShape1 = mProxyShapesComponents.mCollisionShapes[proxyShape1Index]; - CollisionShape* collisionShape2 = mProxyShapesComponents.mCollisionShapes[proxyShape2Index]; + const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1Entity); + const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2Entity); - NarrowPhaseAlgorithmType algorithmType = overlappingPairs.mNarrowPhaseAlgorithmType[i]; + CollisionShape* collisionShape1 = mProxyShapesComponents.mCollisionShapes[proxyShape1Index]; + CollisionShape* collisionShape2 = mProxyShapesComponents.mCollisionShapes[proxyShape2Index]; - // No middle-phase is necessary, simply create a narrow phase info - // for the narrow-phase collision detection - narrowPhaseInput.addNarrowPhaseTest(overlappingPairs.mPairIds[i], proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2, - mProxyShapesComponents.mLocalToWorldTransforms[proxyShape1Index], - mProxyShapesComponents.mLocalToWorldTransforms[proxyShape2Index], - algorithmType, mMemoryManager.getSingleFrameAllocator()); + NarrowPhaseAlgorithmType algorithmType = overlappingPairs.mNarrowPhaseAlgorithmType[i]; + // No middle-phase is necessary, simply create a narrow phase info + // for the narrow-phase collision detection + narrowPhaseInput.addNarrowPhaseTest(overlappingPairs.mPairIds[i], i, proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2, + mProxyShapesComponents.mLocalToWorldTransforms[proxyShape1Index], + mProxyShapesComponents.mLocalToWorldTransforms[proxyShape2Index], + algorithmType, mMemoryManager.getSingleFrameAllocator()); + } } // For each possible convex vs concave pair of bodies - uint64 convexVsConcaveStartIndex = overlappingPairs.getConvexVsConcavePairsStartIndex(); + const uint64 convexVsConcaveStartIndex = overlappingPairs.getConvexVsConcavePairsStartIndex(); for (uint64 i=convexVsConcaveStartIndex; i < convexVsConcaveStartIndex + overlappingPairs.getNbConvexVsConcavePairs(); i++) { - const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i]; - const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i]; - - const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1Entity); - const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2Entity); - - assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != -1); - assert(mProxyShapesComponents.mBroadPhaseId[proxyShape2Index] != -1); - assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != mProxyShapesComponents.mBroadPhaseId[proxyShape2Index]); - - const Entity body1Entity = mProxyShapesComponents.mBodiesEntities[proxyShape1Index]; - const Entity body2Entity = mProxyShapesComponents.mBodiesEntities[proxyShape2Index]; - - const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) && - mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC; - const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) && - mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC; + assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != -1); + assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i]) != -1); + assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i])); // Check that at least one body is enabled (active and awake) and not static - // TODO : Do not test this every frame - bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; - bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; - if (!isBody1Active && !isBody2Active) continue; + if (mOverlappingPairs.mIsActive[i]) { - // Check if the bodies are in the set of bodies that cannot collide between each other - // TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation - bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity); - if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue; - - computeConvexVsConcaveMiddlePhase(overlappingPairs.mPairIds[i], proxyShape1Entity, proxyShape2Entity, - mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput); + computeConvexVsConcaveMiddlePhase(i, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput); + } } } @@ -324,25 +287,6 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List& assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1); assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity)); - const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity); - const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity); - - const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) && - mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC; - const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) && - mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC; - - // Check that at least one body is enabled (active and awake) and not static - // TODO : Do not test this every frame - bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; - bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; - if (!isBody1Active && !isBody2Active) continue; - - // Check if the bodies are in the set of bodies that cannot collide between each other - // TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation - bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity); - if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue; - CollisionShape* collisionShape1 = mProxyShapesComponents.getCollisionShape(proxyShape1Entity); CollisionShape* collisionShape2 = mProxyShapesComponents.getCollisionShape(proxyShape2Entity); @@ -350,7 +294,7 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List& // No middle-phase is necessary, simply create a narrow phase info // for the narrow-phase collision detection - narrowPhaseInput.addNarrowPhaseTest(pairId, proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2, + narrowPhaseInput.addNarrowPhaseTest(pairId, pairIndex, proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2, mProxyShapesComponents.getLocalToWorldTransform(proxyShape1Entity), mProxyShapesComponents.getLocalToWorldTransform(proxyShape2Entity), algorithmType, mMemoryManager.getSingleFrameAllocator()); @@ -361,78 +305,52 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List& for (uint p=0; p < concavePairs.size(); p++) { const uint64 pairId = concavePairs[p]; + const uint64 pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId]; - const uint pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId]; + assert(mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes1[pairIndex]) != -1); + assert(mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes2[pairIndex]) != -1); + assert(mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes1[pairIndex]) != mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes2[pairIndex])); - const Entity proxyShape1Entity = mOverlappingPairs.mProxyShapes1[pairIndex]; - const Entity proxyShape2Entity = mOverlappingPairs.mProxyShapes2[pairIndex]; - - assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1); - assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1); - assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity)); - - const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity); - const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity); - - const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) && - mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC; - const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) && - mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC; - - // Check that at least one body is enabled (active and awake) and not static - // TODO : Do not test this every frame - bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; - bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; - if (!isBody1Active && !isBody2Active) continue; - - // Check if the bodies are in the set of bodies that cannot collide between each other - // TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation - bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity); - if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue; - - computeConvexVsConcaveMiddlePhase(pairId, proxyShape1Entity, proxyShape2Entity, - mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput); + computeConvexVsConcaveMiddlePhase(pairIndex, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput); } } // Compute the concave vs convex middle-phase algorithm for a given pair of bodies -void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairId, Entity proxyShape1, Entity proxyShape2, - MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput) { +void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairIndex, MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput) { RP3D_PROFILE("CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase()", mProfiler); - ProxyShape* shape1 = mProxyShapesComponents.getProxyShape(proxyShape1); - ProxyShape* shape2 = mProxyShapesComponents.getProxyShape(proxyShape2); + const Entity proxyShape1 = mOverlappingPairs.mProxyShapes1[pairIndex]; + const Entity proxyShape2 = mOverlappingPairs.mProxyShapes2[pairIndex]; + + const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1); + const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2); + + ProxyShape* shape1 = mProxyShapesComponents.mProxyShapes[proxyShape1Index]; + ProxyShape* shape2 = mProxyShapesComponents.mProxyShapes[proxyShape2Index]; - ProxyShape* convexProxyShape; - ProxyShape* concaveProxyShape; ConvexShape* convexShape; ConcaveShape* concaveShape; - const bool isShape1Convex = shape1->getCollisionShape()->isConvex(); + const bool isShape1Convex = mOverlappingPairs.mIsShape1Convex[pairIndex]; // Collision shape 1 is convex, collision shape 2 is concave if (isShape1Convex) { - convexProxyShape = shape1; convexShape = static_cast(shape1->getCollisionShape()); - concaveProxyShape = shape2; concaveShape = static_cast(shape2->getCollisionShape()); } else { // Collision shape 2 is convex, collision shape 1 is concave - convexProxyShape = shape2; convexShape = static_cast(shape2->getCollisionShape()); - concaveProxyShape = shape1; concaveShape = static_cast(shape1->getCollisionShape()); } - // Select the narrow phase algorithm to use according to the two collision shapes - NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(convexShape->getType(), - CollisionShapeType::CONVEX_POLYHEDRON); + assert(mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex] != NarrowPhaseAlgorithmType::None); - assert(algorithmType != NarrowPhaseAlgorithmType::None); + Transform& shape1LocalToWorldTransform = mProxyShapesComponents.mLocalToWorldTransforms[proxyShape1Index]; + Transform& shape2LocalToWorldTransform = mProxyShapesComponents.mLocalToWorldTransforms[proxyShape2Index]; // Compute the convex shape AABB in the local-space of the convex shape - const Transform convexToConcaveTransform = mProxyShapesComponents.getLocalToWorldTransform(concaveProxyShape->getEntity()).getInverse() * - mProxyShapesComponents.getLocalToWorldTransform(convexProxyShape->getEntity()); + const Transform convexToConcaveTransform = (isShape1Convex ? shape2LocalToWorldTransform : shape1LocalToWorldTransform).getInverse() * + (isShape1Convex ? shape1LocalToWorldTransform : shape2LocalToWorldTransform); AABB aabb; convexShape->computeAABB(aabb, convexToConcaveTransform); @@ -463,11 +381,10 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairId, #endif // Create a narrow phase info for the narrow-phase collision detection - narrowPhaseInput.addNarrowPhaseTest(pairId, proxyShape1, proxyShape2, isShape1Convex ? convexShape : triangleShape, + narrowPhaseInput.addNarrowPhaseTest(mOverlappingPairs.mPairIds[pairIndex], pairIndex, proxyShape1, proxyShape2, isShape1Convex ? convexShape : triangleShape, isShape1Convex ? triangleShape : convexShape, - mProxyShapesComponents.getLocalToWorldTransform(proxyShape1), - mProxyShapesComponents.getLocalToWorldTransform(proxyShape2), - algorithmType, allocator); + shape1LocalToWorldTransform, shape2LocalToWorldTransform, + mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex], allocator); } } diff --git a/src/systems/CollisionDetectionSystem.h b/src/systems/CollisionDetectionSystem.h index a15a6fde..8128c03e 100644 --- a/src/systems/CollisionDetectionSystem.h +++ b/src/systems/CollisionDetectionSystem.h @@ -206,7 +206,7 @@ class CollisionDetectionSystem { bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool reportContacts, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator); /// Compute the concave vs convex middle-phase algorithm for a given pair of bodies - void computeConvexVsConcaveMiddlePhase(uint64 pairId, Entity proxyShape1, Entity proxyShape2, MemoryAllocator& allocator, + void computeConvexVsConcaveMiddlePhase(uint64 pairIndex, MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput); /// Swap the previous and current contacts lists @@ -358,6 +358,7 @@ class CollisionDetectionSystem { friend class DynamicsWorld; friend class ConvexMeshShape; + friend class RigidBody; }; // Return a reference to the collision dispatch configuration