From 527cc7fbb7030a800c00e98d238e32264e5373cd Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Tue, 21 Aug 2018 07:37:52 +0200 Subject: [PATCH] Replace broad phase pair management custom array by List --- .../broadphase/BroadPhaseAlgorithm.cpp | 82 ++++--------------- .../broadphase/BroadPhaseAlgorithm.h | 21 ++--- src/containers/List.h | 61 +++++++++++++- test/tests/containers/TestList.h | 18 ++++ 4 files changed, 104 insertions(+), 78 deletions(-) diff --git a/src/collision/broadphase/BroadPhaseAlgorithm.cpp b/src/collision/broadphase/BroadPhaseAlgorithm.cpp index 43a1122e..fe577490 100644 --- a/src/collision/broadphase/BroadPhaseAlgorithm.cpp +++ b/src/collision/broadphase/BroadPhaseAlgorithm.cpp @@ -37,15 +37,9 @@ using namespace reactphysics3d; BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection) :mDynamicAABBTree(collisionDetection.getMemoryManager().getPoolAllocator(), DYNAMIC_TREE_AABB_GAP), mMovedShapes(collisionDetection.getMemoryManager().getPoolAllocator()), - mNbPotentialPairs(0), mNbAllocatedPotentialPairs(8), + mPotentialPairs(collisionDetection.getMemoryManager().getPoolAllocator()), mCollisionDetection(collisionDetection) { - PoolAllocator& poolAllocator = collisionDetection.getMemoryManager().getPoolAllocator(); - - // Allocate memory for the array of potential overlapping pairs - mPotentialPairs = static_cast(poolAllocator.allocate(mNbAllocatedPotentialPairs * sizeof(BroadPhasePair))); - assert(mPotentialPairs != nullptr); - #ifdef IS_PROFILING_ACTIVE mProfiler = nullptr; @@ -54,16 +48,6 @@ BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection) } -// Destructor -BroadPhaseAlgorithm::~BroadPhaseAlgorithm() { - - // Get the memory pool allocatory - PoolAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); - - // Release the memory for the array of potential overlapping pairs - poolAllocator.release(mPotentialPairs, mNbAllocatedPotentialPairs * sizeof(BroadPhasePair)); -} - // Return true if the two broad-phase collision shapes are overlapping bool BroadPhaseAlgorithm::testOverlappingShapes(const ProxyShape* shape1, const ProxyShape* shape2) const { @@ -158,7 +142,7 @@ void BroadPhaseAlgorithm::computeOverlappingPairs(MemoryManager& memoryManager) // TODO : Try to see if we can allocate potential pairs in single frame allocator // Reset the potential overlapping pairs - mNbPotentialPairs = 0; + mPotentialPairs.clear(); LinkedList overlappingNodes(memoryManager.getPoolAllocator()); @@ -191,22 +175,22 @@ void BroadPhaseAlgorithm::computeOverlappingPairs(MemoryManager& memoryManager) mMovedShapes.clear(); // Sort the array of potential overlapping pairs in order to remove duplicate pairs - std::sort(mPotentialPairs, mPotentialPairs + mNbPotentialPairs, BroadPhasePair::smallerThan); + std::sort(mPotentialPairs.begin(), mPotentialPairs.end(), BroadPhasePair::smallerThan); // Check all the potential overlapping pairs avoiding duplicates to report unique // overlapping pairs - uint i=0; - while (i < mNbPotentialPairs) { + auto it = mPotentialPairs.begin(); + while (it != mPotentialPairs.end()) { // Get a potential overlapping pair - BroadPhasePair* pair = mPotentialPairs + i; - i++; + BroadPhasePair& pair = *it; + ++it; - assert(pair->collisionShape1ID != pair->collisionShape2ID); + assert(pair.collisionShape1ID != pair.collisionShape2ID); // Get the two collision shapes of the pair - ProxyShape* shape1 = static_cast(mDynamicAABBTree.getNodeDataPointer(pair->collisionShape1ID)); - ProxyShape* shape2 = static_cast(mDynamicAABBTree.getNodeDataPointer(pair->collisionShape2ID)); + ProxyShape* shape1 = static_cast(mDynamicAABBTree.getNodeDataPointer(pair.collisionShape1ID)); + ProxyShape* shape2 = static_cast(mDynamicAABBTree.getNodeDataPointer(pair.collisionShape2ID)); // If the two proxy collision shapes are from the same body, skip it if (shape1->getBody()->getId() != shape2->getBody()->getId()) { @@ -216,35 +200,19 @@ void BroadPhaseAlgorithm::computeOverlappingPairs(MemoryManager& memoryManager) } // Skip the duplicate overlapping pairs - while (i < mNbPotentialPairs) { + while (it != mPotentialPairs.end()) { // Get the next pair - BroadPhasePair* nextPair = mPotentialPairs + i; + BroadPhasePair& nextPair = *it; // If the next pair is different from the previous one, we stop skipping pairs - if (nextPair->collisionShape1ID != pair->collisionShape1ID || - nextPair->collisionShape2ID != pair->collisionShape2ID) { + if (nextPair.collisionShape1ID != pair.collisionShape1ID || + nextPair.collisionShape2ID != pair.collisionShape2ID) { break; } - i++; + ++it; } } - - // If the number of potential overlapping pairs is less than the quarter of allocated - // number of overlapping pairs - if (mNbPotentialPairs < mNbAllocatedPotentialPairs / 4 && mNbPotentialPairs > 8) { - - PoolAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); - - // Reduce the number of allocated potential overlapping pairs - BroadPhasePair* oldPairs = mPotentialPairs; - uint oldNbAllocatedPotentialPairs = mNbAllocatedPotentialPairs; - mNbAllocatedPotentialPairs /= 2; - mPotentialPairs = static_cast(poolAllocator.allocate(mNbAllocatedPotentialPairs * sizeof(BroadPhasePair))); - assert(mPotentialPairs); - memcpy(mPotentialPairs, oldPairs, mNbPotentialPairs * sizeof(BroadPhasePair)); - poolAllocator.release(oldPairs, oldNbAllocatedPotentialPairs * sizeof(BroadPhasePair)); - } } // Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree @@ -257,25 +225,9 @@ void BroadPhaseAlgorithm::addOverlappingNodes(int referenceNodeId, const LinkedL // If both the nodes are the same, we do not create store the overlapping pair if (referenceNodeId != elem->data) { - // If we need to allocate more memory for the array of potential overlapping pairs - if (mNbPotentialPairs == mNbAllocatedPotentialPairs) { - - PoolAllocator& poolAllocator = mCollisionDetection.getMemoryManager().getPoolAllocator(); - - // Allocate more memory for the array of potential pairs - BroadPhasePair* oldPairs = mPotentialPairs; - uint oldNbAllocatedPotentialPairs = mNbAllocatedPotentialPairs; - mNbAllocatedPotentialPairs *= 2; - mPotentialPairs = static_cast(poolAllocator.allocate(mNbAllocatedPotentialPairs * sizeof(BroadPhasePair))); - assert(mPotentialPairs); - memcpy(mPotentialPairs, oldPairs, mNbPotentialPairs * sizeof(BroadPhasePair)); - poolAllocator.release(oldPairs, oldNbAllocatedPotentialPairs * sizeof(BroadPhasePair)); - } - // Add the new potential pair into the array of potential overlapping pairs - mPotentialPairs[mNbPotentialPairs].collisionShape1ID = std::min(referenceNodeId, elem->data); - mPotentialPairs[mNbPotentialPairs].collisionShape2ID = std::max(referenceNodeId, elem->data); - mNbPotentialPairs++; + mPotentialPairs.add(BroadPhasePair(std::min(referenceNodeId, elem->data), + std::max(referenceNodeId, elem->data))); } elem = elem->next; diff --git a/src/collision/broadphase/BroadPhaseAlgorithm.h b/src/collision/broadphase/BroadPhaseAlgorithm.h index 49f43121..037edb4c 100644 --- a/src/collision/broadphase/BroadPhaseAlgorithm.h +++ b/src/collision/broadphase/BroadPhaseAlgorithm.h @@ -59,8 +59,14 @@ struct BroadPhasePair { // -------------------- Methods -------------------- // + /// Constructor + BroadPhasePair(int shapeId1, int shapeId2) { + collisionShape1ID = shapeId1; + collisionShape2ID = shapeId2; + } + /// Method used to compare two pairs for sorting algorithm - static bool smallerThan(const BroadPhasePair& pair1, const BroadPhasePair& pair2); + static bool smallerThan(const BroadPhasePair &pair1, const BroadPhasePair &pair2); }; // class AABBOverlapCallback @@ -140,13 +146,7 @@ class BroadPhaseAlgorithm { Set mMovedShapes; /// Temporary array of potential overlapping pairs (with potential duplicates) - BroadPhasePair* mPotentialPairs; - - /// Number of potential overlapping pairs - uint mNbPotentialPairs; - - /// Number of allocated elements for the array of potential overlapping pairs - uint mNbAllocatedPotentialPairs; + List mPotentialPairs; /// Reference to the collision detection object CollisionDetection& mCollisionDetection; @@ -166,7 +166,7 @@ class BroadPhaseAlgorithm { BroadPhaseAlgorithm(CollisionDetection& collisionDetection); /// Destructor - ~BroadPhaseAlgorithm(); + ~BroadPhaseAlgorithm() = default; /// Deleted copy-constructor BroadPhaseAlgorithm(const BroadPhaseAlgorithm& algorithm) = delete; @@ -223,7 +223,8 @@ class BroadPhaseAlgorithm { }; // Method used to compare two pairs for sorting algorithm -inline bool BroadPhasePair::smallerThan(const BroadPhasePair& pair1, const BroadPhasePair& pair2) { +inline bool BroadPhasePair::smallerThan(const BroadPhasePair& pair1, + const BroadPhasePair& pair2) { if (pair1.collisionShape1ID < pair2.collisionShape1ID) return true; if (pair1.collisionShape1ID == pair2.collisionShape1ID) { diff --git a/src/containers/List.h b/src/containers/List.h index 5eacd495..9a7b1a3a 100755 --- a/src/containers/List.h +++ b/src/containers/List.h @@ -79,8 +79,10 @@ class List { using value_type = T; using difference_type = std::ptrdiff_t; using pointer = T*; + using const_pointer = T const*; using reference = T&; - using iterator_category = std::bidirectional_iterator_tag; + using const_reference = const T&; + using iterator_category = std::random_access_iterator_tag; /// Constructor Iterator() = default; @@ -98,13 +100,19 @@ class List { } /// Deferencable - reference operator*() const { + reference operator*() { + assert(mCurrentIndex >= 0 && mCurrentIndex < mSize); + return mBuffer[mCurrentIndex]; + } + + /// Const Deferencable + const_reference operator*() const { assert(mCurrentIndex >= 0 && mCurrentIndex < mSize); return mBuffer[mCurrentIndex]; } /// Deferencable - pointer operator->() const { + const_pointer operator->() const { assert(mCurrentIndex >= 0 && mCurrentIndex < mSize); return &(mBuffer[mCurrentIndex]); } @@ -138,6 +146,53 @@ class List { mCurrentIndex--; return tmp; } + + /// Plus operator + Iterator operator+(const difference_type& n) { + return Iterator(mBuffer, mCurrentIndex + n, mSize); + } + + /// Plus operator + Iterator& operator+=(const difference_type& n) { + mCurrentIndex += n; + return *this; + } + + /// Minus operator + Iterator operator-(const difference_type& n) { + return Iterator(mBuffer, mCurrentIndex - n, mSize); + } + + /// Minus operator + Iterator& operator-=(const difference_type& n) { + mCurrentIndex -= n; + return *this; + } + + /// Difference operator + difference_type operator-(const Iterator& iterator) const { + return mCurrentIndex - iterator.mCurrentIndex; + } + + /// Comparison operator + bool operator<(const Iterator& other) const { + return mCurrentIndex < other.mCurrentIndex; + } + + /// Comparison operator + bool operator>(const Iterator& other) const { + return mCurrentIndex > other.mCurrentIndex; + } + + /// Comparison operator + bool operator<=(const Iterator& other) const { + return mCurrentIndex <= other.mCurrentIndex; + } + + /// Comparison operator + bool operator>=(const Iterator& other) const { + return mCurrentIndex >= other.mCurrentIndex; + } /// Equality operator (it == end()) bool operator==(const Iterator& iterator) const { diff --git a/test/tests/containers/TestList.h b/test/tests/containers/TestList.h index 07cc5b4d..647bb350 100644 --- a/test/tests/containers/TestList.h +++ b/test/tests/containers/TestList.h @@ -375,6 +375,11 @@ class TestList : public Test { List::Iterator itEnd = list1.end(); List::Iterator it = list1.begin(); + test(itBegin < itEnd); + test(itBegin <= itEnd); + test(itEnd > itBegin); + test(itEnd >= itBegin); + test(itBegin == it); test(*it == 5); test(*(it++) == 5); @@ -399,6 +404,19 @@ class TestList : public Test { list2.add(*it); } test(list1 == list2); + + it = itBegin; + test(*(it + 2) == 8); + it += 2; + test(*it == 8); + test(*(it - 2) == 5); + it -= 2; + test(*it == 5); + test((itEnd - itBegin) == 4); + + it = itBegin; + *it = 19; + test(*it == 19); } };