From ea523e47d33b6ca030b92b1f70fea86f95035637 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Sat, 15 Sep 2018 10:14:26 +0200 Subject: [PATCH] Use List instead of linked lists for narrow phase infos during collision detection --- src/collision/CollisionDetection.cpp | 275 ++++++++---------- src/collision/CollisionDetection.h | 10 +- src/collision/ContactManifoldSet.cpp | 5 - src/collision/MiddlePhaseTriangleCallback.cpp | 5 +- src/collision/MiddlePhaseTriangleCallback.h | 9 +- src/collision/NarrowPhaseInfo.cpp | 2 +- src/collision/NarrowPhaseInfo.h | 3 - 7 files changed, 142 insertions(+), 167 deletions(-) diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index c835c4e7..d47b6691 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -49,7 +49,7 @@ using namespace std; // Constructor CollisionDetection::CollisionDetection(CollisionWorld* world, MemoryManager& memoryManager) - : mMemoryManager(memoryManager), mWorld(world), mNarrowPhaseInfoList(nullptr), + : mMemoryManager(memoryManager), mWorld(world), mNarrowPhaseInfos(mMemoryManager.getPoolAllocator()), mOverlappingPairs(mMemoryManager.getPoolAllocator()), mBroadPhaseAlgorithm(*this), mNoCollisionPairs(mMemoryManager.getPoolAllocator()), mIsCollisionShapesAdded(false) { @@ -80,9 +80,6 @@ void CollisionDetection::computeCollisionDetection() { // Compute the narrow-phase collision detection computeNarrowPhase(); - - // Reset the linked list of narrow-phase info - mNarrowPhaseInfoList = nullptr; } // Compute the broad-phase collision detection @@ -162,29 +159,17 @@ void CollisionDetection::computeMiddlePhase() { // No middle-phase is necessary, simply create a narrow phase info // for the narrow-phase collision detection - NarrowPhaseInfo* firstNarrowPhaseInfo = mNarrowPhaseInfoList; - mNarrowPhaseInfoList = new (mMemoryManager.allocate(MemoryManager::AllocationType::Frame, sizeof(NarrowPhaseInfo))) + NarrowPhaseInfo* narrowPhaseInfo = new (mMemoryManager.allocate(MemoryManager::AllocationType::Frame, sizeof(NarrowPhaseInfo))) NarrowPhaseInfo(pair, shape1->getCollisionShape(), shape2->getCollisionShape(), shape1->getLocalToWorldTransform(), shape2->getLocalToWorldTransform(), mMemoryManager.getSingleFrameAllocator()); - mNarrowPhaseInfoList->next = firstNarrowPhaseInfo; + mNarrowPhaseInfos.add(narrowPhaseInfo); } // Concave vs Convex algorithm else if ((!isShape1Convex && isShape2Convex) || (!isShape2Convex && isShape1Convex)) { - NarrowPhaseInfo* narrowPhaseInfo = nullptr; - computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getSingleFrameAllocator(), &narrowPhaseInfo); - - // Add all the narrow-phase info object reported by the callback into the - // list of all the narrow-phase info object - while (narrowPhaseInfo != nullptr) { - NarrowPhaseInfo* next = narrowPhaseInfo->next; - narrowPhaseInfo->next = mNarrowPhaseInfoList; - mNarrowPhaseInfoList = narrowPhaseInfo; - - narrowPhaseInfo = next; - } + computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getSingleFrameAllocator(), mNarrowPhaseInfos); } // Concave vs Concave shape else { @@ -200,7 +185,7 @@ void CollisionDetection::computeMiddlePhase() { // Compute the concave vs convex middle-phase algorithm for a given pair of bodies void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, MemoryAllocator& allocator, - NarrowPhaseInfo** firstNarrowPhaseInfo) { + List& narrowPhaseInfos) { ProxyShape* shape1 = pair->getShape1(); ProxyShape* shape2 = pair->getShape2(); @@ -226,7 +211,7 @@ void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair // Set the parameters of the callback object MiddlePhaseTriangleCallback middlePhaseCallback(pair, concaveProxyShape, convexProxyShape, - concaveShape, allocator); + concaveShape, narrowPhaseInfos, allocator); #ifdef IS_PROFILING_ACTIVE @@ -243,10 +228,6 @@ void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair // Call the convex vs triangle callback for each triangle of the concave shape concaveShape->testAllTriangles(middlePhaseCallback, aabb); - - // Add all the narrow-phase info object reported by the callback into the - // list of all the narrow-phase info object - *firstNarrowPhaseInfo = middlePhaseCallback.narrowPhaseInfoList; } // Compute the narrow-phase collision detection @@ -254,29 +235,33 @@ void CollisionDetection::computeNarrowPhase() { RP3D_PROFILE("CollisionDetection::computeNarrowPhase()", mProfiler); - List narrowPhaseInfos(mMemoryManager.getSingleFrameAllocator()); + List collidingNarrowPhaseInfos(mMemoryManager.getSingleFrameAllocator()); - NarrowPhaseInfo* currentNarrowPhaseInfo = mNarrowPhaseInfoList; - while (currentNarrowPhaseInfo != nullptr) { + // For each narrow phase info to process + for(uint i=0; i < mNarrowPhaseInfos.size(); i++) { + + NarrowPhaseInfo* narrowPhaseInfo = mNarrowPhaseInfos[i]; + + assert(narrowPhaseInfo->contactPoints == nullptr); // Select the narrow phase algorithm to use according to the two collision shapes - const CollisionShapeType shape1Type = currentNarrowPhaseInfo->collisionShape1->getType(); - const CollisionShapeType shape2Type = currentNarrowPhaseInfo->collisionShape2->getType(); + const CollisionShapeType shape1Type = narrowPhaseInfo->collisionShape1->getType(); + const CollisionShapeType shape2Type = narrowPhaseInfo->collisionShape2->getType(); NarrowPhaseAlgorithm* narrowPhaseAlgorithm = selectNarrowPhaseAlgorithm(shape1Type, shape2Type); // If there is no collision algorithm between those two kinds of shapes, skip it if (narrowPhaseAlgorithm != nullptr) { - LastFrameCollisionInfo* lastCollisionFrameInfo = currentNarrowPhaseInfo->getLastFrameCollisionInfo(); - - narrowPhaseInfos.add(currentNarrowPhaseInfo); + LastFrameCollisionInfo* lastCollisionFrameInfo = narrowPhaseInfo->getLastFrameCollisionInfo(); // Use the narrow-phase collision detection algorithm to check // if there really is a collision. If a collision occurs, the // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(currentNarrowPhaseInfo, true, mMemoryManager.getSingleFrameAllocator())) { + if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getSingleFrameAllocator())) { lastCollisionFrameInfo->wasColliding = true; + + collidingNarrowPhaseInfos.add(narrowPhaseInfo); } else { lastCollisionFrameInfo->wasColliding = false; @@ -285,12 +270,10 @@ void CollisionDetection::computeNarrowPhase() { // The previous frame collision info is now valid lastCollisionFrameInfo->isValid = true; } - - currentNarrowPhaseInfo = currentNarrowPhaseInfo->next; } // Convert the potential contact into actual contacts - processAllPotentialContacts(narrowPhaseInfos, mOverlappingPairs); + processAllPotentialContacts(collidingNarrowPhaseInfos, mOverlappingPairs); // Add all the contact manifolds (between colliding bodies) to the bodies addAllContactManifoldsToBodies(); @@ -299,9 +282,9 @@ void CollisionDetection::computeNarrowPhase() { reportAllContacts(); // Destroy the narrow phase infos - for (auto it = narrowPhaseInfos.begin(); it != narrowPhaseInfos.end(); ++it) { + for(uint i=0; i < mNarrowPhaseInfos.size(); i++) { - NarrowPhaseInfo* narrowPhaseInfo = *it; + NarrowPhaseInfo* narrowPhaseInfo = mNarrowPhaseInfos[i]; // Call the destructor narrowPhaseInfo->~NarrowPhaseInfo(); @@ -309,6 +292,9 @@ void CollisionDetection::computeNarrowPhase() { // Release the allocated memory for the narrow phase info mMemoryManager.release(MemoryManager::AllocationType::Frame, narrowPhaseInfo, sizeof(NarrowPhaseInfo)); } + + // Clear the list of narrow-phase infos + mNarrowPhaseInfos.clear(); } // Allow the broadphase to notify the collision detection about an overlapping pair. @@ -437,23 +423,24 @@ void CollisionDetection::addContactManifoldToBody(OverlappingPair* pair) { } /// Convert the potential contact into actual contacts -void CollisionDetection::processAllPotentialContacts(const List& narrowPhaseInfos, +void CollisionDetection::processAllPotentialContacts(const List& collidingNarrowPhaseInfos, const OverlappingPairMap& overlappingPairs) { RP3D_PROFILE("CollisionDetection::processAllPotentialContacts()", mProfiler); // For each narrow phase info object - for (auto it = narrowPhaseInfos.begin(); it != narrowPhaseInfos.end(); ++it) { + for(uint i=0; i < collidingNarrowPhaseInfos.size(); i++) { - NarrowPhaseInfo* narrowPhaseInfo = *it; + NarrowPhaseInfo* narrowPhaseInfo = collidingNarrowPhaseInfos[i]; assert(narrowPhaseInfo != nullptr); + assert(narrowPhaseInfo->contactPoints != nullptr); - if (narrowPhaseInfo->contactPoints != nullptr) { + // Transfer the contact points from the narrow phase info to the overlapping pair + narrowPhaseInfo->overlappingPair->addPotentialContactPoints(narrowPhaseInfo); - // Transfer the contact points from the narrow phase info to the overlapping pair - narrowPhaseInfo->overlappingPair->addPotentialContactPoints(narrowPhaseInfo); - } + // Remove the contacts points from the narrow phase info object. + narrowPhaseInfo->resetContactPoints(); } // For each overlapping pairs in contact during the narrow-phase @@ -491,7 +478,7 @@ void CollisionDetection::reportAllContacts() { } // Compute the middle-phase collision detection between two proxy shapes -NarrowPhaseInfo* CollisionDetection::computeMiddlePhaseForProxyShapes(OverlappingPair* pair) { +void CollisionDetection::computeMiddlePhaseForProxyShapes(OverlappingPair* pair, List& outNarrowPhaseInfos) { ProxyShape* shape1 = pair->getShape1(); ProxyShape* shape2 = pair->getShape2(); @@ -501,8 +488,6 @@ NarrowPhaseInfo* CollisionDetection::computeMiddlePhaseForProxyShapes(Overlappin const bool isShape1Convex = shape1->getCollisionShape()->isConvex(); const bool isShape2Convex = shape2->getCollisionShape()->isConvex(); - NarrowPhaseInfo* narrowPhaseInfo = nullptr; - pair->makeLastFrameCollisionInfosObsolete(); // If both shapes are convex @@ -510,10 +495,11 @@ NarrowPhaseInfo* CollisionDetection::computeMiddlePhaseForProxyShapes(Overlappin // No middle-phase is necessary, simply create a narrow phase info // for the narrow-phase collision detection - narrowPhaseInfo = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + NarrowPhaseInfo* narrowPhaseInfo = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(NarrowPhaseInfo))) NarrowPhaseInfo(pair, shape1->getCollisionShape(), shape2->getCollisionShape(), shape1->getLocalToWorldTransform(), shape2->getLocalToWorldTransform(), mMemoryManager.getPoolAllocator()); + outNarrowPhaseInfos.add(narrowPhaseInfo); } // Concave vs Convex algorithm @@ -521,12 +507,10 @@ NarrowPhaseInfo* CollisionDetection::computeMiddlePhaseForProxyShapes(Overlappin // Run the middle-phase collision detection algorithm to find the triangles of the concave // shape we need to use during the narrow-phase collision detection - computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getPoolAllocator(), &narrowPhaseInfo); + computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getPoolAllocator(), outNarrowPhaseInfos); } pair->clearObsoleteLastFrameCollisionInfos(); - - return narrowPhaseInfo; } // Report all the bodies that overlap with the aabb in parameter @@ -572,6 +556,8 @@ void CollisionDetection::testAABBOverlap(const AABB& aabb, OverlapCallback* over // Return true if two bodies overlap bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) { + List narrowPhaseInfos(mMemoryManager.getPoolAllocator()); + // For each proxy shape proxy shape of the first body ProxyShape* body1ProxyShape = body1->getProxyShapesList(); while (body1ProxyShape != nullptr) { @@ -591,13 +577,17 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) OverlappingPair pair(body1ProxyShape, body2ProxyShape, mMemoryManager.getPoolAllocator(), mMemoryManager.getPoolAllocator(), mWorld->mConfig); + narrowPhaseInfos.clear(); + // Compute the middle-phase collision detection between the two shapes - NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(&pair); + computeMiddlePhaseForProxyShapes(&pair, narrowPhaseInfos); bool isColliding = false; // For each narrow-phase info object - while (narrowPhaseInfo != nullptr) { + for(uint i=0; i < narrowPhaseInfos.size(); i++) { + + NarrowPhaseInfo* narrowPhaseInfo = narrowPhaseInfos[i]; // If we have not found a collision yet if (!isColliding) { @@ -618,14 +608,11 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) } } - NarrowPhaseInfo* currentNarrowPhaseInfo = narrowPhaseInfo; - narrowPhaseInfo = narrowPhaseInfo->next; - // Call the destructor - currentNarrowPhaseInfo->~NarrowPhaseInfo(); + narrowPhaseInfo->~NarrowPhaseInfo(); // Release the allocated memory - mMemoryManager.release(MemoryManager::AllocationType::Pool, currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, narrowPhaseInfo, sizeof(NarrowPhaseInfo)); } // Return if we have found a narrow-phase collision @@ -651,6 +638,7 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl assert(overlapCallback != nullptr); Set reportedBodies(mMemoryManager.getPoolAllocator()); + List narrowPhaseInfos(mMemoryManager.getPoolAllocator()); // For each proxy shape proxy shape of the body ProxyShape* bodyProxyShape = body->getProxyShapesList(); @@ -687,13 +675,17 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl OverlappingPair pair(bodyProxyShape, proxyShape, mMemoryManager.getPoolAllocator(), mMemoryManager.getPoolAllocator(), mWorld->mConfig); + narrowPhaseInfos.clear(); + // Compute the middle-phase collision detection between the two shapes - NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(&pair); + computeMiddlePhaseForProxyShapes(&pair, narrowPhaseInfos); bool isColliding = false; // For each narrow-phase info object - while (narrowPhaseInfo != nullptr) { + for (uint i=0; inext; - // Call the destructor - currentNarrowPhaseInfo->~NarrowPhaseInfo(); + narrowPhaseInfo->~NarrowPhaseInfo(); // Release the allocated memory - mMemoryManager.release(MemoryManager::AllocationType::Pool, currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, narrowPhaseInfo, sizeof(NarrowPhaseInfo)); } // Return if we have found a narrow-phase collision @@ -795,33 +784,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body } // Compute the middle-phase collision detection between the two shapes - NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(pair); - - // For each narrow-phase info object - while (narrowPhaseInfo != nullptr) { - - allNarrowPhaseInfos.add(narrowPhaseInfo); - - const CollisionShapeType shape1Type = narrowPhaseInfo->collisionShape1->getType(); - const CollisionShapeType shape2Type = narrowPhaseInfo->collisionShape2->getType(); - - // Select the narrow phase algorithm to use according to the two collision shapes - NarrowPhaseAlgorithm* narrowPhaseAlgorithm = selectNarrowPhaseAlgorithm(shape1Type, shape2Type); - - // If there is a collision algorithm for those two kinds of shapes - if (narrowPhaseAlgorithm != nullptr) { - - // Use the narrow-phase collision detection algorithm to check - // if there really is a collision. If a collision occurs, the - // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { - - collidingNarrowPhaseInfos.add(narrowPhaseInfo); - } - } - - narrowPhaseInfo = narrowPhaseInfo->next; - } + computeMiddlePhaseForProxyShapes(pair, allNarrowPhaseInfos); } // Go to the next proxy shape @@ -832,6 +795,30 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body body1ProxyShape = body1ProxyShape->getNext(); } + // For each narrow-phase info object + for (uint i=0; i < allNarrowPhaseInfos.size(); i++) { + + NarrowPhaseInfo* narrowPhaseInfo = allNarrowPhaseInfos[i]; + + const CollisionShapeType shape1Type = narrowPhaseInfo->collisionShape1->getType(); + const CollisionShapeType shape2Type = narrowPhaseInfo->collisionShape2->getType(); + + // Select the narrow phase algorithm to use according to the two collision shapes + NarrowPhaseAlgorithm* narrowPhaseAlgorithm = selectNarrowPhaseAlgorithm(shape1Type, shape2Type); + + // If there is a collision algorithm for those two kinds of shapes + if (narrowPhaseAlgorithm != nullptr) { + + // Use the narrow-phase collision detection algorithm to check + // if there really is a collision. If a collision occurs, the + // notifyContact() callback method will be called. + if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { + + collidingNarrowPhaseInfos.add(narrowPhaseInfo); + } + } + } + // Process the potential contacts processAllPotentialContacts(collidingNarrowPhaseInfos, overlappingPairs); @@ -853,9 +840,9 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body } // Destroy the narrow phase infos - for (auto it = allNarrowPhaseInfos.begin(); it != allNarrowPhaseInfos.end(); ++it) { + for (uint i=0; i < allNarrowPhaseInfos.size(); i++) { - NarrowPhaseInfo* narrowPhaseInfo = *it; + NarrowPhaseInfo* narrowPhaseInfo = allNarrowPhaseInfos[i]; // Call the destructor narrowPhaseInfo->~NarrowPhaseInfo(); @@ -926,33 +913,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c } // Compute the middle-phase collision detection between the two shapes - NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(pair); - - // For each narrow-phase info object - while (narrowPhaseInfo != nullptr) { - - allNarrowPhaseInfos.add(narrowPhaseInfo); - - const CollisionShapeType shape1Type = narrowPhaseInfo->collisionShape1->getType(); - const CollisionShapeType shape2Type = narrowPhaseInfo->collisionShape2->getType(); - - // Select the narrow phase algorithm to use according to the two collision shapes - NarrowPhaseAlgorithm* narrowPhaseAlgorithm = selectNarrowPhaseAlgorithm(shape1Type, shape2Type); - - // If there is a collision algorithm for those two kinds of shapes - if (narrowPhaseAlgorithm != nullptr) { - - // Use the narrow-phase collision detection algorithm to check - // if there really is a collision. If a collision occurs, the - // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { - - collidingNarrowPhaseInfos.add(narrowPhaseInfo); - } - } - - narrowPhaseInfo = narrowPhaseInfo->next; - } + computeMiddlePhaseForProxyShapes(pair, allNarrowPhaseInfos); } } @@ -965,6 +926,30 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c } } + // For each narrow-phase info object + for (auto it = allNarrowPhaseInfos.begin(); it != allNarrowPhaseInfos.end(); ++it) { + + NarrowPhaseInfo* narrowPhaseInfo = *it; + + const CollisionShapeType shape1Type = narrowPhaseInfo->collisionShape1->getType(); + const CollisionShapeType shape2Type = narrowPhaseInfo->collisionShape2->getType(); + + // Select the narrow phase algorithm to use according to the two collision shapes + NarrowPhaseAlgorithm* narrowPhaseAlgorithm = selectNarrowPhaseAlgorithm(shape1Type, shape2Type); + + // If there is a collision algorithm for those two kinds of shapes + if (narrowPhaseAlgorithm != nullptr) { + + // Use the narrow-phase collision detection algorithm to check + // if there really is a collision. If a collision occurs, the + // notifyContact() callback method will be called. + if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { + + collidingNarrowPhaseInfos.add(narrowPhaseInfo); + } + } + } + // Process the potential contacts processAllPotentialContacts(collidingNarrowPhaseInfos, overlappingPairs); @@ -986,9 +971,9 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c } // Destroy the narrow phase infos - for (auto it = allNarrowPhaseInfos.begin(); it != allNarrowPhaseInfos.end(); ++it) { + for (uint i=0; i < allNarrowPhaseInfos.size(); i++) { - NarrowPhaseInfo* narrowPhaseInfo = *it; + NarrowPhaseInfo* narrowPhaseInfo = allNarrowPhaseInfos[i]; // Call the destructor narrowPhaseInfo->~NarrowPhaseInfo(); @@ -1047,32 +1032,30 @@ void CollisionDetection::testCollision(CollisionCallback* callback) { mBroadPhaseAlgorithm.testOverlappingShapes(shape1, shape2)) { // Compute the middle-phase collision detection between the two shapes - NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(pair); + computeMiddlePhaseForProxyShapes(pair, allNarrowPhaseInfos); + } + } - // For each narrow-phase info object - while (narrowPhaseInfo != nullptr) { + // For each narrow-phase info object + for (uint i=0; i < allNarrowPhaseInfos.size(); i++) { - allNarrowPhaseInfos.add(narrowPhaseInfo); + NarrowPhaseInfo* narrowPhaseInfo = allNarrowPhaseInfos[i]; - const CollisionShapeType shape1Type = narrowPhaseInfo->collisionShape1->getType(); - const CollisionShapeType shape2Type = narrowPhaseInfo->collisionShape2->getType(); + const CollisionShapeType shape1Type = narrowPhaseInfo->collisionShape1->getType(); + const CollisionShapeType shape2Type = narrowPhaseInfo->collisionShape2->getType(); - // Select the narrow phase algorithm to use according to the two collision shapes - NarrowPhaseAlgorithm* narrowPhaseAlgorithm = selectNarrowPhaseAlgorithm(shape1Type, shape2Type); + // Select the narrow phase algorithm to use according to the two collision shapes + NarrowPhaseAlgorithm* narrowPhaseAlgorithm = selectNarrowPhaseAlgorithm(shape1Type, shape2Type); - // If there is a collision algorithm for those two kinds of shapes - if (narrowPhaseAlgorithm != nullptr) { + // If there is a collision algorithm for those two kinds of shapes + if (narrowPhaseAlgorithm != nullptr) { - // Use the narrow-phase collision detection algorithm to check - // if there really is a collision. If a collision occurs, the - // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { + // Use the narrow-phase collision detection algorithm to check + // if there really is a collision. If a collision occurs, the + // notifyContact() callback method will be called. + if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { - collidingNarrowPhaseInfos.add(narrowPhaseInfo); - } - } - - narrowPhaseInfo = narrowPhaseInfo->next; + collidingNarrowPhaseInfos.add(narrowPhaseInfo); } } } @@ -1098,9 +1081,9 @@ void CollisionDetection::testCollision(CollisionCallback* callback) { } // Destroy the narrow phase infos - for (auto it = allNarrowPhaseInfos.begin(); it != allNarrowPhaseInfos.end(); ++it) { + for (uint i=0; i < allNarrowPhaseInfos.size(); i++) { - NarrowPhaseInfo* narrowPhaseInfo = *it; + NarrowPhaseInfo* narrowPhaseInfo = allNarrowPhaseInfos[i]; // Call the destructor narrowPhaseInfo->~NarrowPhaseInfo(); diff --git a/src/collision/CollisionDetection.h b/src/collision/CollisionDetection.h index 958d14b1..bd49f10f 100644 --- a/src/collision/CollisionDetection.h +++ b/src/collision/CollisionDetection.h @@ -78,8 +78,8 @@ class CollisionDetection { /// Pointer to the physics world CollisionWorld* mWorld; - /// Pointer to the first narrow-phase info of the linked list - NarrowPhaseInfo* mNarrowPhaseInfoList; + /// List of narrow phase infos + List mNarrowPhaseInfos; /// Broad-phase overlapping pairs OverlappingPairMap mOverlappingPairs; @@ -127,13 +127,13 @@ class CollisionDetection { /// Compute the concave vs convex middle-phase algorithm for a given pair of bodies void computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, MemoryAllocator& allocator, - NarrowPhaseInfo** firstNarrowPhaseInfo); + List& narrowPhaseInfos); /// Compute the middle-phase collision detection between two proxy shapes - NarrowPhaseInfo* computeMiddlePhaseForProxyShapes(OverlappingPair* pair); + void computeMiddlePhaseForProxyShapes(OverlappingPair* pair, List& outNarrowPhaseInfos); /// Convert the potential contact into actual contacts - void processAllPotentialContacts(const List& narrowPhaseInfos, + void processAllPotentialContacts(const List& collidingNarrowPhaseInfos, const OverlappingPairMap& overlappingPairs); /// Report contacts for all the colliding overlapping pairs diff --git a/src/collision/ContactManifoldSet.cpp b/src/collision/ContactManifoldSet.cpp index 2cbfc409..0dc40ebd 100644 --- a/src/collision/ContactManifoldSet.cpp +++ b/src/collision/ContactManifoldSet.cpp @@ -94,11 +94,6 @@ void ContactManifoldSet::addContactPoints(NarrowPhaseInfo* narrowPhaseInfo) { contactPoint = contactPoint->next; } - - // All the contact point info of the narrow-phase info have been moved - // into the potential contacts of the overlapping pair. We can now - // remove the contacts points from the narrow phase info object. - narrowPhaseInfo->resetContactPoints(); } // Return the total number of contact points in the set of manifolds diff --git a/src/collision/MiddlePhaseTriangleCallback.cpp b/src/collision/MiddlePhaseTriangleCallback.cpp index b1583f25..7520fbae 100644 --- a/src/collision/MiddlePhaseTriangleCallback.cpp +++ b/src/collision/MiddlePhaseTriangleCallback.cpp @@ -51,13 +51,12 @@ void MiddlePhaseTriangleCallback::testTriangle(const Vector3* trianglePoints, co ProxyShape* shape2 = isShape1Convex ? mConcaveProxyShape : mConvexProxyShape; // Create a narrow phase info for the narrow-phase collision detection - NarrowPhaseInfo* firstNarrowPhaseInfo = narrowPhaseInfoList; - narrowPhaseInfoList = new (mAllocator.allocate(sizeof(NarrowPhaseInfo))) + NarrowPhaseInfo* narrowPhaseInfo = new (mAllocator.allocate(sizeof(NarrowPhaseInfo))) NarrowPhaseInfo(mOverlappingPair, isShape1Convex ? mConvexProxyShape->getCollisionShape() : triangleShape, isShape1Convex ? triangleShape : mConvexProxyShape->getCollisionShape(), shape1->getLocalToWorldTransform(), shape2->getLocalToWorldTransform(), mAllocator); - narrowPhaseInfoList->next = firstNarrowPhaseInfo; + mOutNarrowPhaseInfos.add(narrowPhaseInfo); } diff --git a/src/collision/MiddlePhaseTriangleCallback.h b/src/collision/MiddlePhaseTriangleCallback.h index 51408715..a952d7b3 100644 --- a/src/collision/MiddlePhaseTriangleCallback.h +++ b/src/collision/MiddlePhaseTriangleCallback.h @@ -66,6 +66,9 @@ class MiddlePhaseTriangleCallback : public TriangleCallback { /// Pointer to the concave collision shape const ConcaveShape* mConcaveShape; + /// Reference to the list of narrow-phase infos + List& mOutNarrowPhaseInfos; + /// Reference to the single-frame memory allocator MemoryAllocator& mAllocator; @@ -78,17 +81,15 @@ class MiddlePhaseTriangleCallback : public TriangleCallback { public: - /// Pointer to the first element of the linked-list of narrow-phase info - NarrowPhaseInfo* narrowPhaseInfoList; - /// Constructor MiddlePhaseTriangleCallback(OverlappingPair* overlappingPair, ProxyShape* concaveProxyShape, ProxyShape* convexProxyShape, const ConcaveShape* concaveShape, + List& outNarrowPhaseInfos, MemoryAllocator& allocator) :mOverlappingPair(overlappingPair), mConcaveProxyShape(concaveProxyShape), mConvexProxyShape(convexProxyShape), mConcaveShape(concaveShape), - mAllocator(allocator), narrowPhaseInfoList(nullptr) { + mOutNarrowPhaseInfos(outNarrowPhaseInfos), mAllocator(allocator) { } diff --git a/src/collision/NarrowPhaseInfo.cpp b/src/collision/NarrowPhaseInfo.cpp index be4c6ab4..0ee63d0a 100644 --- a/src/collision/NarrowPhaseInfo.cpp +++ b/src/collision/NarrowPhaseInfo.cpp @@ -37,7 +37,7 @@ NarrowPhaseInfo::NarrowPhaseInfo(OverlappingPair* pair, CollisionShape* shape1, const Transform& shape2Transform, MemoryAllocator& shapeAllocator) : overlappingPair(pair), collisionShape1(shape1), collisionShape2(shape2), shape1ToWorldTransform(shape1Transform), shape2ToWorldTransform(shape2Transform), - contactPoints(nullptr), next(nullptr), collisionShapeAllocator(shapeAllocator) { + contactPoints(nullptr), collisionShapeAllocator(shapeAllocator) { // Add a collision info for the two collision shapes into the overlapping pair (if not present yet) overlappingPair->addLastFrameInfoIfNecessary(shape1->getId(), shape2->getId()); diff --git a/src/collision/NarrowPhaseInfo.h b/src/collision/NarrowPhaseInfo.h index 99f9ffc7..38aa6af6 100644 --- a/src/collision/NarrowPhaseInfo.h +++ b/src/collision/NarrowPhaseInfo.h @@ -65,9 +65,6 @@ struct NarrowPhaseInfo { /// Linked-list of contact points created during the narrow-phase ContactPointInfo* contactPoints; - /// Pointer to the next element in the linked list - NarrowPhaseInfo* next; - /// Memory allocator for the collision shape (Used to release TriangleShape memory in destructor) MemoryAllocator& collisionShapeAllocator;