Replace broad phase pair management custom array by List

This commit is contained in:
Daniel Chappuis 2018-08-21 07:37:52 +02:00
parent 0db50eb59c
commit 527cc7fbb7
4 changed files with 104 additions and 78 deletions

View File

@ -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<BroadPhasePair*>(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<int> 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<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(pair->collisionShape1ID));
ProxyShape* shape2 = static_cast<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(pair->collisionShape2ID));
ProxyShape* shape1 = static_cast<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(pair.collisionShape1ID));
ProxyShape* shape2 = static_cast<ProxyShape*>(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<BroadPhasePair*>(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<BroadPhasePair*>(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;

View File

@ -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<int> 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<BroadPhasePair> 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) {

View File

@ -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 {

View File

@ -375,6 +375,11 @@ class TestList : public Test {
List<int>::Iterator itEnd = list1.end();
List<int>::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);
}
};