Working on middle-phase collision detection

This commit is contained in:
Daniel Chappuis 2019-11-17 20:52:18 +01:00
parent 44e07e0bd9
commit 6b3a65b914
14 changed files with 604 additions and 362 deletions

View File

@ -72,8 +72,6 @@ uint32 Components::prepareAddComponent(bool isSleeping) {
// Add the component at the end of the array
index = mNbComponents;
mDisabledStartIndex = index;
}
// If the component to add is not part of a disabled entity
else {

View File

@ -52,9 +52,6 @@ class Components {
/// Number of components to allocated at the beginning
const uint32 INIT_NB_ALLOCATED_COMPONENTS = 10;
/// Number of valid entities to hit before stopping garbage collection
const uint32 GARBAGE_COLLECTION_MAX_VALID_ENTITIES = 5;
// -------------------- Attributes -------------------- //
/// Memory allocator

View File

@ -37,7 +37,7 @@ using namespace reactphysics3d;
ProxyShapeComponents::ProxyShapeComponents(MemoryAllocator& allocator)
:Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) +
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) +
sizeof(unsigned short) + sizeof(Transform)) {
sizeof(unsigned short) + sizeof(Transform) + sizeof(List<uint64>)) {
// Allocate memory for the components data
allocate(INIT_NB_ALLOCATED_COMPONENTS);
@ -66,6 +66,7 @@ void ProxyShapeComponents::allocate(uint32 nbComponentsToAllocate) {
unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(newMasses + nbComponentsToAllocate);
unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate);
Transform* newLocalToWorldTransforms = reinterpret_cast<Transform*>(newCollideWithMaskBits + nbComponentsToAllocate);
List<uint64>* newOverlappingPairs = reinterpret_cast<List<uint64>*>(newLocalToWorldTransforms + nbComponentsToAllocate);
// If there was already components before
if (mNbComponents > 0) {
@ -81,6 +82,7 @@ void ProxyShapeComponents::allocate(uint32 nbComponentsToAllocate) {
memcpy(newCollisionCategoryBits, mCollisionCategoryBits, mNbComponents * sizeof(unsigned short));
memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short));
memcpy(newLocalToWorldTransforms, mLocalToWorldTransforms, mNbComponents * sizeof(Transform));
memcpy(newOverlappingPairs, mOverlappingPairs, mNbComponents * sizeof(List<uint64>));
// Deallocate previous memory
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize);
@ -98,6 +100,7 @@ void ProxyShapeComponents::allocate(uint32 nbComponentsToAllocate) {
mCollisionCategoryBits = newCollisionCategoryBits;
mCollideWithMaskBits = newCollideWithMaskBits;
mLocalToWorldTransforms = newLocalToWorldTransforms;
mOverlappingPairs = newOverlappingPairs;
mNbAllocatedComponents = nbComponentsToAllocate;
}
@ -119,6 +122,7 @@ void ProxyShapeComponents::addComponent(Entity proxyShapeEntity, bool isSleeping
new (mCollisionCategoryBits + index) unsigned short(component.collisionCategoryBits);
new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits);
new (mLocalToWorldTransforms + index) Transform(component.localToWorldTransform);
new (mOverlappingPairs + index) List<uint64>(mMemoryAllocator);
// Map the entity with the new component lookup index
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity, index));
@ -145,6 +149,7 @@ void ProxyShapeComponents::moveComponentToIndex(uint32 srcIndex, uint32 destInde
new (mCollisionCategoryBits + destIndex) unsigned short(mCollisionCategoryBits[srcIndex]);
new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]);
new (mLocalToWorldTransforms + destIndex) Transform(mLocalToWorldTransforms[srcIndex]);
new (mOverlappingPairs + destIndex) List<uint64>(mOverlappingPairs[srcIndex]);
// Destroy the source component
destroyComponent(srcIndex);
@ -171,6 +176,7 @@ void ProxyShapeComponents::swapComponents(uint32 index1, uint32 index2) {
unsigned short collisionCategoryBits1 = mCollisionCategoryBits[index1];
unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1];
Transform localToWorldTransform1 = mLocalToWorldTransforms[index1];
List<uint64> overlappingPairs = mOverlappingPairs[index1];
// Destroy component 1
destroyComponent(index1);
@ -188,6 +194,7 @@ void ProxyShapeComponents::swapComponents(uint32 index1, uint32 index2) {
new (mCollisionCategoryBits + index2) unsigned short(collisionCategoryBits1);
new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1);
new (mLocalToWorldTransforms + index2) Transform(localToWorldTransform1);
new (mOverlappingPairs + index2) List<uint64>(overlappingPairs);
// Update the entity to component index mapping
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity1, index2));
@ -212,4 +219,5 @@ void ProxyShapeComponents::destroyComponent(uint32 index) {
mLocalToBodyTransforms[index].~Transform();
mCollisionShapes[index] = nullptr;
mLocalToWorldTransforms[index].~Transform();
mOverlappingPairs[index].~List<uint64>();
}

View File

@ -92,6 +92,9 @@ class ProxyShapeComponents : public Components {
/// Array with the local-to-world transforms of the proxy-shapes
Transform* mLocalToWorldTransforms;
/// Array with the list of involved overlapping pairs for each proxy-shape
List<uint64>* mOverlappingPairs;
// -------------------- Methods -------------------- //
/// Allocate memory for a given number of components
@ -185,6 +188,9 @@ class ProxyShapeComponents : public Components {
/// Set the local-to-world transform of a proxy-shape
void setLocalToWorldTransform(Entity proxyShapeEntity, const Transform& transform);
/// Return a reference to the list of overlapping pairs for a given proxy-shape
List<uint64>& getOverlappingPairs(Entity proxyShapeEntity);
// -------------------- Friendship -------------------- //
friend class BroadPhaseSystem;
@ -302,6 +308,14 @@ inline void ProxyShapeComponents::setLocalToWorldTransform(Entity proxyShapeEnti
mLocalToWorldTransforms[mMapEntityToComponentIndex[proxyShapeEntity]] = transform;
}
// Return a reference to the list of overlapping pairs for a given proxy-shape
inline List<uint64>& ProxyShapeComponents::getOverlappingPairs(Entity proxyShapeEntity) {
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mOverlappingPairs[mMapEntityToComponentIndex[proxyShapeEntity]];
}
}
#endif

View File

@ -123,6 +123,7 @@ class Map {
// Compute the next larger prime size
mCapacity = getPrimeSize(capacity);
assert(mCapacity >= 0);
// Allocate memory for the buckets
mBuckets = static_cast<int*>(mAllocator.allocate(mCapacity * sizeof(int)));
@ -142,6 +143,8 @@ class Map {
mNbUsedEntries = 0;
mNbFreeEntries = 0;
mFreeIndex = -1;
assert(size() >= 0);
}
/// Expand the capacity of the map
@ -200,6 +203,8 @@ class Map {
mCapacity = newCapacity;
mBuckets = newBuckets;
mEntries = newEntries;
assert(mCapacity >= 0);
}
/// Return the index of the entry with a given key or -1 if there is no entry with this key
@ -371,6 +376,8 @@ class Map {
:mNbUsedEntries(map.mNbUsedEntries), mNbFreeEntries(map.mNbFreeEntries), mCapacity(map.mCapacity),
mBuckets(nullptr), mEntries(nullptr), mAllocator(map.mAllocator), mFreeIndex(map.mFreeIndex) {
assert(capacity() >= 0);
if (mCapacity > 0) {
// Allocate memory for the buckets
@ -380,7 +387,7 @@ class Map {
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
// Copy the buckets
std::uninitialized_copy(map.mBuckets, map.mBuckets + mCapacity, mBuckets);
std::uninitialized_copy(map.mBuckets, map.mBuckets + mCapacity, mBuckets);
// Copy the entries
for (int i=0; i < mCapacity; i++) {
@ -392,7 +399,11 @@ class Map {
new (mEntries[i].keyValue) Pair<K,V>(*(map.mEntries[i].keyValue));
}
}
}
assert(size() >= 0);
assert((*this) == map);
}
/// Destructor
@ -483,6 +494,7 @@ class Map {
mNbUsedEntries++;
}
assert(size() >= 0);
assert(mEntries[entryIndex].keyValue == nullptr);
mEntries[entryIndex].hashCode = hashCode;
mEntries[entryIndex].next = mBuckets[bucket];
@ -551,6 +563,8 @@ class Map {
}
}
assert(size() >= 0);
// Return the end iterator
return end();
}
@ -575,6 +589,8 @@ class Map {
mFreeIndex = -1;
mNbUsedEntries = 0;
mNbFreeEntries = 0;
assert(size() >= 0);
}
// If elements have been allocated
@ -599,6 +615,7 @@ class Map {
/// Return the number of elements in the map
int size() const {
assert(mNbUsedEntries - mNbFreeEntries >= 0);
return mNbUsedEntries - mNbFreeEntries;
}
@ -649,6 +666,7 @@ class Map {
}
if (entry == -1) {
assert(false);
throw std::runtime_error("No item with given key has been found in the map");
}
@ -716,6 +734,7 @@ class Map {
// Compute the next larger prime size
mCapacity = getPrimeSize(map.mCapacity);
assert(mCapacity >= 0);
// Allocate memory for the buckets
mBuckets = static_cast<int*>(mAllocator.allocate(mCapacity * sizeof(int)));
@ -743,6 +762,8 @@ class Map {
}
}
assert(size() >= 0);
return *this;
}

View File

@ -43,7 +43,7 @@ CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logge
mJointsComponents(mMemoryManager.getBaseAllocator()), mBallAndSocketJointsComponents(mMemoryManager.getBaseAllocator()),
mFixedJointsComponents(mMemoryManager.getBaseAllocator()), mHingeJointsComponents(mMemoryManager.getBaseAllocator()),
mSliderJointsComponents(mMemoryManager.getBaseAllocator()),
mCollisionDetection(this, mProxyShapesComponents, mTransformComponents, mRigidBodyComponents, mMemoryManager),
mCollisionDetection(this, mProxyShapesComponents, mTransformComponents, mCollisionBodyComponents, mRigidBodyComponents, mMemoryManager),
mBodies(mMemoryManager.getPoolAllocator()), mEventListener(nullptr),
mName(worldSettings.worldName), mIsProfilerCreatedByUser(profiler != nullptr),
mIsLoggerCreatedByUser(logger != nullptr) {

View File

@ -273,7 +273,6 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
rigidBody->removeAllCollisionShapes();
// Destroy all the joints in which the rigid body to be destroyed is involved
JointListElement* element;
const List<Entity>& joints = mRigidBodyComponents.getJoints(rigidBody->getEntity());
for (uint32 i=0; i < joints.size(); i++) {
destroyJoint(mJointsComponents.getJoint(joints[i]));

View File

@ -32,124 +32,107 @@
using namespace reactphysics3d;
// Constructor
OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator, ProxyShapeComponents& proxyShapeComponents)
OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator, ProxyShapeComponents& proxyShapeComponents,
CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, Set<bodypair> &noCollisionPairs)
: mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
mNbPairs(0), mConcavePairsStartIndex(0), mPairDataSize(sizeof(uint64) + sizeof(int32) + sizeof(int32) + sizeof(Entity) +
sizeof(Entity) + sizeof(Map<ShapeIdPair, LastFrameCollisionInfo*>) +
sizeof(bool) + sizeof(bool)),
mNbAllocatedPairs(0), mBuffer(nullptr),
mMapPairIdToPairIndex(persistentMemoryAllocator),
mConvexPairIds(mPersistentAllocator), mConvexProxyShapes1(mPersistentAllocator), mConvexProxyShapes2(mPersistentAllocator),
mConcavePairIds(mPersistentAllocator), mConcaveProxyShapes1(mPersistentAllocator), mConcaveProxyShapes2(mPersistentAllocator),
mConvexLastFrameCollisionInfos(mPersistentAllocator), mConcaveLastFrameCollisionInfos(mPersistentAllocator),
mConvexNeedToTestOverlap(mPersistentAllocator), mConcaveNeedToTestOverlap(mPersistentAllocator),
mProxyShapeComponents(proxyShapeComponents) {
mProxyShapeComponents(proxyShapeComponents), mCollisionBodyComponents(collisionBodyComponents),
mRigidBodyComponents(rigidBodyComponents), mNoCollisionPairs(noCollisionPairs) {
}
// Allocate memory for the components data
allocate(INIT_NB_ALLOCATED_PAIRS);
}
// Destructor
OverlappingPairs::~OverlappingPairs() {
// If there are allocated pairs
if (mNbAllocatedPairs > 0) {
// Destroy all the remaining pairs
for (uint32 i = 0; i < mNbPairs; i++) {
// Remove all the remaining last frame collision info
for (auto it = mLastFrameCollisionInfos[i].begin(); it != mLastFrameCollisionInfos[i].end(); ++it) {
// Call the constructor
it->second->~LastFrameCollisionInfo();
// Release memory
mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
}
// Remove the involved overlapping pair to the two proxy-shapes
assert(mProxyShapeComponents.getOverlappingPairs(mProxyShapes1[i]).find(mPairIds[i]) != mProxyShapeComponents.getOverlappingPairs(mProxyShapes1[i]).end());
assert(mProxyShapeComponents.getOverlappingPairs(mProxyShapes2[i]).find(mPairIds[i]) != mProxyShapeComponents.getOverlappingPairs(mProxyShapes2[i]).end());
mProxyShapeComponents.getOverlappingPairs(mProxyShapes1[i]).remove(mPairIds[i]);
mProxyShapeComponents.getOverlappingPairs(mProxyShapes2[i]).remove(mPairIds[i]);
destroyPair(i);
}
// Size for the data of a single pair (in bytes)
const size_t totalSizeBytes = mNbAllocatedPairs * mPairDataSize;
// Release the allocated memory
mPersistentAllocator.release(mBuffer, totalSizeBytes);
}
}
/// Add an overlapping pair
uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2) {
// Compute the index where we need to insert the new pair
uint64 OverlappingPairs::prepareAddPair(bool isConvexVsConvex) {
// TODO : Maybe use entities in parameters
const CollisionShape* collisionShape1 = mProxyShapeComponents.getCollisionShape(shape1->getEntity());
const CollisionShape* collisionShape2 = mProxyShapeComponents.getCollisionShape(shape2->getEntity());
const uint32 shape1Id = static_cast<uint32>(shape1->getBroadPhaseId());
const uint32 shape2Id = static_cast<uint32>(shape2->getBroadPhaseId());
// Compute a unique id for the overlapping pair
const uint64 pairId = pairNumbers(std::max(shape1Id, shape2Id), std::min(shape1Id, shape2Id));
// If both shapes are convex
if (collisionShape1->isConvex() && collisionShape2->isConvex()) {
const uint nbConvexPairs = static_cast<uint>(mConvexPairIds.size());
mConvexPairIds.add(pairId);
mConvexProxyShapes1.add(shape1->getEntity());
mConvexProxyShapes2.add(shape2->getEntity());
mConvexNeedToTestOverlap.add(false);
// TODO: Make sure we use the correct allocator here
mConvexLastFrameCollisionInfos.add(Map<ShapeIdPair, LastFrameCollisionInfo*>(mPersistentAllocator));
// Add a mapping to the index in the internal arrays
mMapPairIdToPairIndex.add(Pair<uint64, PairLocation>(pairId, PairLocation(true, nbConvexPairs)));
// If we need to allocate more components
if (mNbPairs == mNbAllocatedPairs) {
allocate(mNbAllocatedPairs * 2);
}
uint64 index;
// If the pair to add is not convex vs convex or there are no concave pairs yet
if (!isConvexVsConvex) {
// Add the component at the end of the array
index = mNbPairs;
}
// If the pair to add is convex vs convex
else {
const uint nbConcavePairs = static_cast<uint>(mConcavePairIds.size());
// If there already are convex vs concave pairs
if (mConcavePairsStartIndex != mNbPairs) {
mConcavePairIds.add(pairId);
mConcaveProxyShapes1.add(shape1->getEntity());
mConcaveProxyShapes2.add(shape2->getEntity());
mConcaveNeedToTestOverlap.add(true);
// Move the first convex vs concave pair to the end of the array
movePairToIndex(mConcavePairsStartIndex, mNbPairs);
}
// TODO: Make sure we use the correct allocator here
mConcaveLastFrameCollisionInfos.add(Map<ShapeIdPair, LastFrameCollisionInfo*>(mPersistentAllocator));
index = mConcavePairsStartIndex;
// Add a mapping to the index in the internal arrays
mMapPairIdToPairIndex.add(Pair<uint64, PairLocation>(pairId, PairLocation(false, nbConcavePairs)));
mConcavePairsStartIndex++;
}
return pairId;
return index;
}
// Remove an overlapping pair
uint64 OverlappingPairs::removePair(uint64 pairId) {
// Remove a component at a given index
void OverlappingPairs::removePair(uint64 pairId) {
RP3D_PROFILE("OverlappingPairs::removePair()", mProfiler);
assert(mMapPairIdToPairIndex.containsKey(pairId));
const PairLocation& pairLocation = mMapPairIdToPairIndex[pairId];
uint64 index = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs);
if (pairLocation.isConvexVsConvex) {
assert(pairLocation.pairIndex < mConvexPairIds.size());
const uint64 lastPairId = mConvexPairIds[mConvexPairIds.size() - 1];
const PairLocation lastPairLocation = mMapPairIdToPairIndex[lastPairId];
// Remap the last pair location
if (pairLocation.pairIndex < mConvexPairIds.size() - 1) {
mMapPairIdToPairIndex[lastPairId] = PairLocation(lastPairLocation.isConvexVsConvex, pairLocation.pairIndex);
}
// Remove the pair (the pair is replaced by the last one of the lists)
mConvexPairIds.removeAtAndReplaceWithLast(pairLocation.pairIndex);
mConvexProxyShapes1.removeAtAndReplaceWithLast(pairLocation.pairIndex);
mConvexProxyShapes2.removeAtAndReplaceWithLast(pairLocation.pairIndex);
mConvexNeedToTestOverlap.removeAtAndReplaceWithLast(pairLocation.pairIndex);
}
else {
assert(pairLocation.pairIndex < mConcavePairIds.size());
const uint64 lastPairId = mConcavePairIds[mConcavePairIds.size() - 1];
const PairLocation lastPairLocation = mMapPairIdToPairIndex[lastPairId];
// Remap the last pair location
if (pairLocation.pairIndex < mConcavePairIds.size() - 1) {
mMapPairIdToPairIndex[lastPairId] = PairLocation(lastPairLocation.isConvexVsConvex, pairLocation.pairIndex);
}
// Remove the pair (the pair is replaced by the last one of the lists)
mConcavePairIds.removeAtAndReplaceWithLast(pairLocation.pairIndex);
mConcaveProxyShapes1.removeAtAndReplaceWithLast(pairLocation.pairIndex);
mConcaveProxyShapes2.removeAtAndReplaceWithLast(pairLocation.pairIndex);
mConcaveNeedToTestOverlap.removeAtAndReplaceWithLast(pairLocation.pairIndex);
}
mMapPairIdToPairIndex.remove(pairId);
List<Map<ShapeIdPair, LastFrameCollisionInfo*>>& lastFrameCollisionInfos = pairLocation.isConvexVsConvex ?
mConvexLastFrameCollisionInfos : mConcaveLastFrameCollisionInfos;
// We want to keep the arrays tightly packed. Therefore, when a pair is removed,
// we replace it with the last element of the array. But we need to make sure that convex
// and concave pairs stay grouped together.
// Remove all the remaining last frame collision info
for (auto it = lastFrameCollisionInfos[pairLocation.pairIndex].begin(); it != lastFrameCollisionInfos[pairLocation.pairIndex].end(); ++it) {
for (auto it = mLastFrameCollisionInfos[index].begin(); it != mLastFrameCollisionInfos[index].end(); ++it) {
// Call the constructor
it->second->~LastFrameCollisionInfo();
@ -158,19 +141,223 @@ uint64 OverlappingPairs::removePair(uint64 pairId) {
mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
}
lastFrameCollisionInfos.removeAtAndReplaceWithLast(pairLocation.pairIndex);
}
// Remove the involved overlapping pair to the two proxy-shapes
assert(mProxyShapeComponents.getOverlappingPairs(mProxyShapes1[index]).find(pairId) != mProxyShapeComponents.getOverlappingPairs(mProxyShapes1[index]).end());
assert(mProxyShapeComponents.getOverlappingPairs(mProxyShapes2[index]).find(pairId) != mProxyShapeComponents.getOverlappingPairs(mProxyShapes2[index]).end());
mProxyShapeComponents.getOverlappingPairs(mProxyShapes1[index]).remove(pairId);
mProxyShapeComponents.getOverlappingPairs(mProxyShapes2[index]).remove(pairId);
// Try to find a pair with a given id, return true if the pair is found and the corresponding PairLocation
bool OverlappingPairs::findPair(uint64 pairId, PairLocation& pairLocation) {
// Destroy the pair
destroyPair(index);
auto it = mMapPairIdToPairIndex.find(pairId);
if (it != mMapPairIdToPairIndex.end()) {
pairLocation = it->second;
return true;
// If the pair to remove is convex vs concave
if (index >= mConcavePairsStartIndex) {
// If the pair is not the last one
if (index != mNbPairs - 1) {
// We replace it by the last convex vs concave pair
movePairToIndex(mNbPairs - 1, index);
}
}
else { // If the pair to remove is convex vs convex
// If it not the last convex vs convex pair
if (index != mConcavePairsStartIndex - 1) {
// We replace it by the last convex vs convex pair
movePairToIndex(mConcavePairsStartIndex - 1, index);
}
// If there are convex vs concave pairs at the end
if (mConcavePairsStartIndex != mNbPairs) {
// We replace the last convex vs convex pair by the last convex vs concave pair
movePairToIndex(mNbPairs - 1, mConcavePairsStartIndex - 1);
}
mConcavePairsStartIndex--;
}
return false;
mNbPairs--;
assert(mConcavePairsStartIndex <= mNbPairs);
assert(mNbPairs == static_cast<uint32>(mMapPairIdToPairIndex.size()));
}
// Allocate memory for a given number of pairs
void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
assert(nbPairsToAllocate > mNbAllocatedPairs);
// Size for the data of a single component (in bytes)
const size_t totalSizeBytes = nbPairsToAllocate * mPairDataSize;
// Allocate memory
void* newBuffer = mPersistentAllocator.allocate(totalSizeBytes);
assert(newBuffer != nullptr);
// New pointers to components data
uint64* newPairIds = static_cast<uint64*>(newBuffer);
int32* newPairBroadPhaseId1 = reinterpret_cast<int32*>(newPairIds + nbPairsToAllocate);
int32* newPairBroadPhaseId2 = reinterpret_cast<int32*>(newPairBroadPhaseId1 + nbPairsToAllocate);
Entity* newProxyShapes1 = reinterpret_cast<Entity*>(newPairBroadPhaseId2 + nbPairsToAllocate);
Entity* newProxyShapes2 = reinterpret_cast<Entity*>(newProxyShapes1 + nbPairsToAllocate);
Map<ShapeIdPair, LastFrameCollisionInfo*>* newLastFrameCollisionInfos = reinterpret_cast<Map<ShapeIdPair, LastFrameCollisionInfo*>*>(newProxyShapes2 + nbPairsToAllocate);
bool* newNeedToTestOverlap = reinterpret_cast<bool*>(newLastFrameCollisionInfos + nbPairsToAllocate);
bool* newIsActive = reinterpret_cast<bool*>(newNeedToTestOverlap + nbPairsToAllocate);
// If there was already pairs before
if (mNbPairs > 0) {
// Copy component data from the previous buffer to the new one
memcpy(newPairIds, mPairIds, mNbPairs * sizeof(uint64));
memcpy(newPairBroadPhaseId1, mPairBroadPhaseId1, mNbPairs * sizeof(int32));
memcpy(newPairBroadPhaseId2, mPairBroadPhaseId2, mNbPairs * sizeof(int32));
memcpy(newProxyShapes1, mProxyShapes1, mNbPairs * sizeof(Entity));
memcpy(newProxyShapes2, mProxyShapes2, mNbPairs * sizeof(Entity));
memcpy(newLastFrameCollisionInfos, mLastFrameCollisionInfos, mNbPairs * sizeof(Map<ShapeIdPair, LastFrameCollisionInfo*>));
memcpy(newNeedToTestOverlap, mNeedToTestOverlap, mNbPairs * sizeof(bool));
memcpy(newIsActive, mIsActive, mNbPairs * sizeof(bool));
// Deallocate previous memory
mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize);
}
mBuffer = newBuffer;
mPairIds = newPairIds;
mPairBroadPhaseId1 = newPairBroadPhaseId1;
mPairBroadPhaseId2 = newPairBroadPhaseId2;
mProxyShapes1 = newProxyShapes1;
mProxyShapes2 = newProxyShapes2;
mLastFrameCollisionInfos = newLastFrameCollisionInfos;
mNeedToTestOverlap = newNeedToTestOverlap;
mIsActive = newIsActive;
mNbAllocatedPairs = nbPairsToAllocate;
}
// Add an overlapping pair
uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2, bool isActive) {
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 uint32 shape1Id = static_cast<uint32>(shape1->getBroadPhaseId());
const uint32 shape2Id = static_cast<uint32>(shape2->getBroadPhaseId());
// Compute a unique id for the overlapping pair
const uint64 pairId = pairNumbers(std::max(shape1Id, shape2Id), std::min(shape1Id, shape2Id));
assert(!mMapPairIdToPairIndex.containsKey(pairId));
// 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<ShapeIdPair, LastFrameCollisionInfo*>(mPersistentAllocator);
new (mNeedToTestOverlap + index) bool(false);
new (mIsActive + index) bool(isActive);
// Map the entity with the new component lookup index
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index));
// Add the involved overlapping pair to the two proxy-shapes
assert(mProxyShapeComponents.getOverlappingPairs(shape1->getEntity()).find(pairId) == mProxyShapeComponents.getOverlappingPairs(shape1->getEntity()).end());
assert(mProxyShapeComponents.getOverlappingPairs(shape2->getEntity()).find(pairId) == mProxyShapeComponents.getOverlappingPairs(shape2->getEntity()).end());
mProxyShapeComponents.getOverlappingPairs(shape1->getEntity()).add(pairId);
mProxyShapeComponents.getOverlappingPairs(shape2->getEntity()).add(pairId);
mNbPairs++;
assert(mConcavePairsStartIndex <= mNbPairs);
assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
return pairId;
}
// Move a pair from a source to a destination index in the pairs array
// The destination location must contain a constructed object
void OverlappingPairs::movePairToIndex(uint64 srcIndex, uint64 destIndex) {
const uint64 pairId = mPairIds[srcIndex];
// Copy the data of the source pair to the destination location
mPairIds[destIndex] = mPairIds[srcIndex];
mPairBroadPhaseId1[destIndex] = mPairBroadPhaseId1[srcIndex];
mPairBroadPhaseId2[destIndex] = mPairBroadPhaseId2[srcIndex];
new (mProxyShapes1 + destIndex) Entity(mProxyShapes1[srcIndex]);
new (mProxyShapes2 + destIndex) Entity(mProxyShapes2[srcIndex]);
new (mLastFrameCollisionInfos + destIndex) Map<ShapeIdPair, LastFrameCollisionInfo*>(mLastFrameCollisionInfos[srcIndex]);
mNeedToTestOverlap[destIndex] = mNeedToTestOverlap[srcIndex];
mIsActive[destIndex] = mIsActive[srcIndex];
// Destroy the source pair
destroyPair(srcIndex);
assert(!mMapPairIdToPairIndex.containsKey(pairId));
// Update the pairId to pair index mapping
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, destIndex));
assert(mMapPairIdToPairIndex[mPairIds[destIndex]] == destIndex);
}
// Swap two pairs in the array
void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
// Copy pair 1 data
uint64 pairId = mPairIds[index1];
int32 pairBroadPhaseId1 = mPairBroadPhaseId1[index1];
int32 pairBroadPhaseId2 = mPairBroadPhaseId2[index1];
Entity proxyShape1 = mProxyShapes1[index1];
Entity proxyShape2 = mProxyShapes2[index1];
Map<ShapeIdPair, LastFrameCollisionInfo*> lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]);
bool needTestOverlap = mNeedToTestOverlap[index1];
bool isActive = mIsActive[index1];
// Destroy pair 1
destroyPair(index1);
movePairToIndex(index2, index1);
// Reconstruct pair 1 at pair 2 location
mPairIds[index2] = pairId;
mPairBroadPhaseId1[index2] = pairBroadPhaseId1;
mPairBroadPhaseId2[index2] = pairBroadPhaseId2;
new (mProxyShapes1 + index2) Entity(proxyShape1);
new (mProxyShapes2 + index2) Entity(proxyShape2);
new (mLastFrameCollisionInfos + index2) Map<ShapeIdPair, LastFrameCollisionInfo*>(lastFrameCollisionInfo);
mNeedToTestOverlap[index2] = needTestOverlap;
mIsActive[index2] = isActive;
// Update the pairID to pair index mapping
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index2));
assert(mMapPairIdToPairIndex[mPairIds[index1]] == index1);
assert(mMapPairIdToPairIndex[mPairIds[index2]] == index2);
assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
}
// Destroy a pair at a given index
void OverlappingPairs::destroyPair(uint64 index) {
assert(index < mNbPairs);
assert(mMapPairIdToPairIndex[mPairIds[index]] == index);
mMapPairIdToPairIndex.remove(mPairIds[index]);
mProxyShapes1[index].~Entity();
mProxyShapes2[index].~Entity();
mLastFrameCollisionInfos[index].~Map<ShapeIdPair, LastFrameCollisionInfo*>();
}
// Add a new last frame collision info if it does not exist for the given shapes already
@ -180,24 +367,22 @@ LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pai
assert(mMapPairIdToPairIndex.containsKey(pairId));
PairLocation& pairLocation = mMapPairIdToPairIndex[pairId];
List<Map<ShapeIdPair, LastFrameCollisionInfo*>>& lastFrameCollisionInfos = pairLocation.isConvexVsConvex ?
mConvexLastFrameCollisionInfos : mConcaveLastFrameCollisionInfos;
const uint64 index = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs);
// Try to get the corresponding last frame collision info
const ShapeIdPair shapeIdPair(shapeId1, shapeId2);
// TODO : Remove test
auto it = lastFrameCollisionInfos[pairLocation.pairIndex].find(shapeIdPair);
// If there is no collision info for those two shapes already
if (it == lastFrameCollisionInfos[pairLocation.pairIndex].end()) {
auto it = mLastFrameCollisionInfos[index].find(shapeIdPair);
if (it == mLastFrameCollisionInfos[index].end()) {
// Create a new collision info
LastFrameCollisionInfo* collisionInfo = new (mPersistentAllocator.allocate(sizeof(LastFrameCollisionInfo)))
LastFrameCollisionInfo();
// Add it into the map of collision infos
lastFrameCollisionInfos[pairLocation.pairIndex].add(Pair<ShapeIdPair, LastFrameCollisionInfo*>(shapeIdPair, collisionInfo));
mLastFrameCollisionInfos[index].add(Pair<ShapeIdPair, LastFrameCollisionInfo*>(shapeIdPair, collisionInfo));
return collisionInfo;
}
@ -216,10 +401,10 @@ void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() {
RP3D_PROFILE("OverlappingPairs::clearObsoleteLastFrameCollisionInfos()", mProfiler);
// For each convex vs convex overlapping pair
for (uint p=0; p < mConvexLastFrameCollisionInfos.size(); p++) {
for (uint64 i=0; i < mNbPairs; i++) {
// For each collision info
for (auto it = mConvexLastFrameCollisionInfos[p].begin(); it != mConvexLastFrameCollisionInfos[p].end(); ) {
for (auto it = mLastFrameCollisionInfos[i].begin(); it != mLastFrameCollisionInfos[i].end(); ) {
// If the collision info is obsolete
if (it->second->isObsolete) {
@ -228,32 +413,7 @@ void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() {
it->second->~LastFrameCollisionInfo();
mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
it = mConvexLastFrameCollisionInfos[p].remove(it);
}
else { // If the collision info is not obsolete
// Do not delete it but mark it as obsolete
it->second->isObsolete = true;
++it;
}
}
}
// For each convex vs concave overlapping pair
for (uint p=0; p < mConcaveLastFrameCollisionInfos.size(); p++) {
// For each collision info
for (auto it = mConcaveLastFrameCollisionInfos[p].begin(); it != mConcaveLastFrameCollisionInfos[p].end(); ) {
// If the collision info is obsolete
if (it->second->isObsolete) {
// Delete it
it->second->~LastFrameCollisionInfo();
mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
it = mConcaveLastFrameCollisionInfos[p].remove(it);
it = mLastFrameCollisionInfos[i].remove(it);
}
else { // If the collision info is not obsolete
@ -265,3 +425,28 @@ 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;
}

View File

@ -30,9 +30,12 @@
#include "collision/ProxyShape.h"
#include "containers/Map.h"
#include "containers/Pair.h"
#include "containers/Set.h"
#include "containers/containers_common.h"
#include "utils/Profiler.h"
#include "components/ProxyShapeComponents.h"
#include "components/CollisionBodyComponents.h"
#include "components/RigidBodyComponents.h"
#include <cstddef>
/// ReactPhysics3D namespace
@ -106,26 +109,11 @@ class OverlappingPairs {
private:
/// Structure PairLocation
struct PairLocation {
// -------------------- Constants -------------------- //
/// True if the pair is a convex vs convex overlap
bool isConvexVsConvex;
/// Index of the overlapping pair in the internal arrays
uint32 pairIndex;
/// Constructor
PairLocation() :isConvexVsConvex(true), pairIndex(0) {
}
/// Constructor
PairLocation(bool isConvexVsConvex, uint32 index)
:isConvexVsConvex(isConvexVsConvex), pairIndex(index) {
}
};
/// Number of pairs to allocated at the beginning
const uint32 INIT_NB_ALLOCATED_PAIRS = 10;
// -------------------- Attributes -------------------- //
@ -133,54 +121,68 @@ class OverlappingPairs {
MemoryAllocator& mPersistentAllocator;
/// Memory allocator used to allocated memory for the ContactManifoldInfo and ContactPointInfo
// TODO : Do we need to keep this ?
MemoryAllocator& mTempMemoryAllocator;
/// Map a pair id to its local location
Map<uint64, PairLocation> mMapPairIdToPairIndex;
/// Current number of components
uint64 mNbPairs;
/// Index in the array of the first convex vs concave pair
uint64 mConcavePairsStartIndex;
/// Size (in bytes) of a single pair
size_t mPairDataSize;
/// Number of allocated pairs
uint64 mNbAllocatedPairs;
/// Allocated memory for all the data of the pairs
void* mBuffer;
/// Map a pair id to the internal array index
Map<uint64, uint64> mMapPairIdToPairIndex;
/// Ids of the convex vs convex pairs
// TODO : Check if we need this array
List<uint64> mConvexPairIds;
uint64* mPairIds;
/// List of Entity of the first proxy-shape of the convex vs convex pairs
List<Entity> mConvexProxyShapes1;
/// Array with the broad-phase Ids of the first shape
int32* mPairBroadPhaseId1;
/// List of Entity of the second proxy-shape of the convex vs convex pairs
List<Entity> mConvexProxyShapes2;
/// Array with the broad-phase Ids of the second shape
int32* mPairBroadPhaseId2;
/// Ids of the convex vs concave pairs
// TODO : Check if we need this array
List<uint64> mConcavePairIds;
/// Array of Entity of the first proxy-shape of the convex vs convex pairs
Entity* mProxyShapes1;
/// List of Entity of the first proxy-shape of the convex vs concave pairs
List<Entity> mConcaveProxyShapes1;
/// List of Entity of the second proxy-shape of the convex vs concave pairs
List<Entity> mConcaveProxyShapes2;
/// Array of Entity of the second proxy-shape of the convex vs convex pairs
Entity* mProxyShapes2;
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
/// Temporal coherence data store collision information about the last frame.
/// 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.
List<Map<ShapeIdPair, LastFrameCollisionInfo*>> mConvexLastFrameCollisionInfos;
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
/// Temporal coherence data store collision information about the last frame.
/// 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.
List<Map<ShapeIdPair, LastFrameCollisionInfo*>> mConcaveLastFrameCollisionInfos;
Map<ShapeIdPair, LastFrameCollisionInfo*>* mLastFrameCollisionInfos;
/// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
List<bool> mConvexNeedToTestOverlap;
bool* mNeedToTestOverlap;
/// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
List<bool> mConcaveNeedToTestOverlap;
/// True if the overlapping pair is active (at least one body of the pair is active and not static)
bool* mIsActive;
/// Reference to the proxy-shapes components
ProxyShapeComponents& mProxyShapeComponents;
/// Reference to the collision body components
CollisionBodyComponents& mCollisionBodyComponents;
/// Reference to the rigid bodies components
RigidBodyComponents& mRigidBodyComponents;
/// Reference to the set of bodies that cannot collide with each others
Set<bodypair>& mNoCollisionPairs;
#ifdef IS_PROFILING_ACTIVE
/// Pointer to the profiler
@ -188,13 +190,31 @@ class OverlappingPairs {
#endif
// -------------------- Methods -------------------- //
/// Allocate memory for a given number of pairs
void allocate(uint64 nbPairsToAllocate);
/// Compute the index where we need to insert the new pair
uint64 prepareAddPair(bool isConvexVsConvex);
/// Destroy a pair at a given index
void destroyPair(uint64 index);
// Move a pair from a source to a destination index in the pairs array
void movePairToIndex(uint64 srcIndex, uint64 destIndex);
/// Swap two pairs in the array
void swapPairs(uint64 index1, uint64 index2);
public:
// -------------------- Methods -------------------- //
/// Constructor
OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator,
ProxyShapeComponents& proxyShapeComponents);
ProxyShapeComponents& proxyShapeComponents, CollisionBodyComponents& collisionBodyComponents,
RigidBodyComponents& rigidBodyComponents, Set<bodypair>& noCollisionPairs);
/// Destructor
~OverlappingPairs();
@ -206,13 +226,22 @@ class OverlappingPairs {
OverlappingPairs& operator=(const OverlappingPairs& pair) = delete;
/// Add an overlapping pair
uint64 addPair(ProxyShape* shape1, ProxyShape* shape2);
uint64 addPair(ProxyShape* shape1, ProxyShape* shape2, bool isActive);
/// Remove an overlapping pair
uint64 removePair(uint64 pairId);
/// Remove a component at a given index
void removePair(uint64 pairId);
/// Try to find a pair with a given id, return true if the pair is found and the corresponding PairLocation
bool findPair(uint64 pairId, PairLocation& pairLocation);
/// Return the number of pairs
uint64 getNbPairs() const;
/// Return the number of convex vs convex pairs
uint64 getNbConvexVsConvexPairs() const;
/// Return the number of convex vs concave pairs
uint64 getNbConvexVsConcavePairs() const;
/// Return the starting index of the convex vs concave pairs
uint64 getConvexVsConcavePairsStartIndex() const;
/// Return the entity of the first proxy-shape
Entity getProxyShape1(uint64 pairId) const;
@ -220,6 +249,9 @@ class OverlappingPairs {
/// Return the entity of the second proxy-shape
Entity getProxyShape2(uint64 pairId) const;
/// Notify if a given pair is active or not
void setIsPairActive(uint64 pairId, bool isActive);
/// Return the last frame collision info
LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, ShapeIdPair& shapeIds);
@ -235,6 +267,12 @@ 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);
#ifdef IS_PROFILING_ACTIVE
/// Set the profiler
@ -251,29 +289,34 @@ class OverlappingPairs {
// Return the entity of the first proxy-shape
inline Entity OverlappingPairs::getProxyShape1(uint64 pairId) const {
assert(mMapPairIdToPairIndex.containsKey(pairId));
const PairLocation& pairLocation = mMapPairIdToPairIndex[pairId];
const List<Entity> proxyShapes1 = pairLocation.isConvexVsConvex ? mConvexProxyShapes1 : mConcaveProxyShapes1;
return proxyShapes1[pairLocation.pairIndex];
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
return mProxyShapes1[mMapPairIdToPairIndex[pairId]];
}
// Return the entity of the second proxy-shape
inline Entity OverlappingPairs::getProxyShape2(uint64 pairId) const {
assert(mMapPairIdToPairIndex.containsKey(pairId));
const PairLocation& pairLocation = mMapPairIdToPairIndex[pairId];
const List<Entity> proxyShapes2 = pairLocation.isConvexVsConvex ? mConvexProxyShapes2 : mConcaveProxyShapes2;
return proxyShapes2[pairLocation.pairIndex];
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
return mProxyShapes2[mMapPairIdToPairIndex[pairId]];
}
// Notify if a given pair is active or not
inline void OverlappingPairs::setIsPairActive(uint64 pairId, bool isActive) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
mIsActive[mMapPairIdToPairIndex[pairId]] = isActive;
}
// 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) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
const PairLocation& pairLocation = mMapPairIdToPairIndex[pairId];
const List<Map<ShapeIdPair, LastFrameCollisionInfo*>>& lastFrameCollisionInfos = pairLocation.isConvexVsConvex ?
mConvexLastFrameCollisionInfos : mConcaveLastFrameCollisionInfos;
const uint64 index = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs);
Map<ShapeIdPair, LastFrameCollisionInfo*>::Iterator it = lastFrameCollisionInfos[pairLocation.pairIndex].find(shapeIds);
if (it != lastFrameCollisionInfos[pairLocation.pairIndex].end()) {
Map<ShapeIdPair, LastFrameCollisionInfo*>::Iterator it = mLastFrameCollisionInfos[index].find(shapeIds);
if (it != mLastFrameCollisionInfos[index].end()) {
return it->second;
}
@ -291,11 +334,37 @@ inline bodypair OverlappingPairs::computeBodiesIndexPair(Entity body1Entity, Ent
return indexPair;
}
// Return the number of pairs
inline uint64 OverlappingPairs::getNbPairs() const {
return mNbPairs;
}
// Return the number of convex vs convex pairs
inline uint64 OverlappingPairs::getNbConvexVsConvexPairs() const {
return mConcavePairsStartIndex;
}
// Return the number of convex vs concave pairs
inline uint64 OverlappingPairs::getNbConvexVsConcavePairs() const {
return mNbPairs - mConcavePairsStartIndex;
}
// Return the starting index of the convex vs concave pairs
inline uint64 OverlappingPairs::getConvexVsConcavePairsStartIndex() const {
return mConcavePairsStartIndex;
}
// Return a reference to the temporary memory allocator
inline MemoryAllocator& OverlappingPairs::getTemporaryAllocator() {
return mTempMemoryAllocator;
}
// Set if we need to test a given pair for overlap
inline void OverlappingPairs::setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
mNeedToTestOverlap[mMapPairIdToPairIndex[pairId]] = needToTestOverlap;
}
#ifdef IS_PROFILING_ACTIVE
// Set the profiler

View File

@ -54,7 +54,7 @@ PoolAllocator::PoolAllocator() {
// If the mMapSizeToHeapIndex has not been initialized yet
if (!isMapSizeToHeadIndexInitialized) {
// Initialize the array that contains the sizes the memory units that will
// Initialize the array that contains the sizes of the memory units that will
// be allocated in each different heap
for (uint i=0; i < NB_HEAPS; i++) {
mUnitSizes[i] = (i+1) * 8;
@ -100,6 +100,8 @@ PoolAllocator::~PoolAllocator() {
// allocated memory.
void* PoolAllocator::allocate(size_t size) {
assert(size > 0);
// We cannot allocate zero bytes
if (size == 0) return nullptr;
@ -173,6 +175,8 @@ void* PoolAllocator::allocate(size_t size) {
// Release previously allocated memory.
void PoolAllocator::release(void* pointer, size_t size) {
assert(size > 0);
// Cannot release a 0-byte allocated memory
if (size == 0) return;

View File

@ -51,13 +51,10 @@ BroadPhaseSystem::BroadPhaseSystem(CollisionDetectionSystem& collisionDetection,
}
// Return true if the two broad-phase collision shapes are overlapping
bool BroadPhaseSystem::testOverlappingShapes(Entity proxyShape1Entity, Entity proxyShape2Entity) const {
bool BroadPhaseSystem::testOverlappingShapes(int32 shape1BroadPhaseId, int32 shape2BroadPhaseId) const {
RP3D_PROFILE("CollisionDetectionSystem::testOverlappingShapes()", mProfiler);
const int32 shape1BroadPhaseId = mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity);
const int32 shape2BroadPhaseId = mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity);
assert(shape1BroadPhaseId != -1 && shape2BroadPhaseId != -1);
// Get the two AABBs of the collision shapes
@ -92,7 +89,7 @@ void BroadPhaseSystem::addProxyCollisionShape(ProxyShape* proxyShape, const AABB
// Add the collision shape into the array of bodies that have moved (or have been created)
// during the last simulation step
addMovedCollisionShape(proxyShape->getBroadPhaseId());
addMovedCollisionShape(proxyShape->getBroadPhaseId(), proxyShape);
}
// Remove a proxy collision shape from the broad-phase collision detection
@ -130,11 +127,13 @@ void BroadPhaseSystem::updateProxyShapes(decimal timeStep) {
RP3D_PROFILE("BroadPhaseSystem::updateProxyShapes()", mProfiler);
// Update all the enabled proxy-shape components
updateProxyShapesComponents(0, mProxyShapesComponents.getNbEnabledComponents(), timeStep);
if (mProxyShapesComponents.getNbEnabledComponents() > 0) {
updateProxyShapesComponents(0, mProxyShapesComponents.getNbEnabledComponents(), timeStep);
}
}
// Notify the broad-phase that a collision shape has moved and need to be updated
void BroadPhaseSystem::updateProxyShapeInternal(int32 broadPhaseId, const AABB& aabb, const Vector3& displacement) {
void BroadPhaseSystem::updateProxyShapeInternal(int32 broadPhaseId, ProxyShape* proxyShape, const AABB& aabb, const Vector3& displacement) {
assert(broadPhaseId >= 0);
@ -147,7 +146,7 @@ void BroadPhaseSystem::updateProxyShapeInternal(int32 broadPhaseId, const AABB&
// Add the collision shape into the array of shapes that have moved (or have been created)
// during the last simulation step
addMovedCollisionShape(broadPhaseId);
addMovedCollisionShape(broadPhaseId, proxyShape);
}
}
@ -167,6 +166,7 @@ void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 nbI
// For each proxy-shape component to update
for (uint32 i = startIndex; i < startIndex + nbItems; i++) {
// TODO : Can we remove this test
const int32 broadPhaseId = mProxyShapesComponents.mBroadPhaseIds[i];
if (broadPhaseId != -1) {
@ -188,13 +188,27 @@ void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 nbI
mProxyShapesComponents.mCollisionShapes[i]->computeAABB(aabb, transform * mProxyShapesComponents.mLocalToBodyTransforms[i]);
// Update the broad-phase state for the proxy collision shape
updateProxyShapeInternal(broadPhaseId, aabb, displacement);
updateProxyShapeInternal(broadPhaseId, mProxyShapesComponents.mProxyShapes[i], aabb, displacement);
}
}
}
// Add a collision shape in the array of shapes that have moved in the last simulation step
// and that need to be tested again for broad-phase overlapping.
void BroadPhaseSystem::addMovedCollisionShape(int broadPhaseID, ProxyShape* proxyShape) {
assert(broadPhaseID != -1);
// Store the broad-phase ID into the array of shapes that have moved
mMovedShapes.add(broadPhaseID);
// Notify that the overlapping pairs where this shape is involved need to be tested for overlap
mCollisionDetection.notifyOverlappingPairsToTestOverlap(proxyShape);
}
// Compute all the overlapping pairs of collision shapes
void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager, List<Pair<int, int>>& overlappingNodes) {
void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager, List<Pair<int32, int32>>& overlappingNodes) {
RP3D_PROFILE("CollisionDetectionSystem::computeOverlappingPairs()", mProfiler);

View File

@ -140,7 +140,7 @@ class BroadPhaseSystem {
// -------------------- Methods -------------------- //
/// Notify the Dynamic AABB tree that a proxy-shape needs to be updated
void updateProxyShapeInternal(int32 broadPhaseId, const AABB& aabb, const Vector3& displacement);
void updateProxyShapeInternal(int32 broadPhaseId, ProxyShape* proxyShape, const AABB& aabb, const Vector3& displacement);
/// Update the broad-phase state of some proxy-shapes components
void updateProxyShapesComponents(uint32 startIndex, uint32 nbItems, decimal timeStep);
@ -176,20 +176,20 @@ class BroadPhaseSystem {
/// Add a collision shape in the array of shapes that have moved in the last simulation step
/// and that need to be tested again for broad-phase overlapping.
void addMovedCollisionShape(int broadPhaseID);
void addMovedCollisionShape(int broadPhaseID, ProxyShape* proxyShape);
/// Remove a collision shape from the array of shapes that have moved in the last simulation
/// step and that need to be tested again for broad-phase overlapping.
void removeMovedCollisionShape(int broadPhaseID);
/// Compute all the overlapping pairs of collision shapes
void computeOverlappingPairs(MemoryManager& memoryManager, List<Pair<int, int>>& overlappingNodes);
void computeOverlappingPairs(MemoryManager& memoryManager, List<Pair<int32, int32>>& overlappingNodes);
/// Return the proxy shape corresponding to the broad-phase node id in parameter
ProxyShape* getProxyShapeForBroadPhaseId(int broadPhaseId) const;
/// Return true if the two broad-phase collision shapes are overlapping
bool testOverlappingShapes(Entity proxyShape1Entity, Entity proxyShape2Entity) const;
bool testOverlappingShapes(int32 shape1BroadPhaseId, int32 shape2BroadPhaseId) const;
/// Return the fat AABB of a given broad-phase shape
const AABB& getFatAABB(int broadPhaseId) const;
@ -211,16 +211,6 @@ inline const AABB& BroadPhaseSystem::getFatAABB(int broadPhaseId) const {
return mDynamicAABBTree.getFatAABB(broadPhaseId);
}
// Add a collision shape in the array of shapes that have moved in the last simulation step
// and that need to be tested again for broad-phase overlapping.
inline void BroadPhaseSystem::addMovedCollisionShape(int broadPhaseID) {
assert(broadPhaseID != -1);
// Store the broad-phase ID into the array of shapes that have moved
mMovedShapes.add(broadPhaseID);
}
// Remove a collision shape from the array of shapes that have moved in the last simulation step
// and that need to be tested again for broad-phase overlapping.
inline void BroadPhaseSystem::removeMovedCollisionShape(int broadPhaseID) {

View File

@ -52,12 +52,14 @@ using namespace std;
// Constructor
CollisionDetectionSystem::CollisionDetectionSystem(CollisionWorld* world, ProxyShapeComponents& proxyShapesComponents, TransformComponents& transformComponents,
RigidBodyComponents& rigidBodyComponents, MemoryManager& memoryManager)
CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, MemoryManager& memoryManager)
: mMemoryManager(memoryManager), mProxyShapesComponents(proxyShapesComponents),
mCollisionDispatch(mMemoryManager.getPoolAllocator()), mWorld(world),
mOverlappingPairs(mMemoryManager.getPoolAllocator(), mMemoryManager.getSingleFrameAllocator(), mProxyShapesComponents),
mNoCollisionPairs(mMemoryManager.getPoolAllocator()),
mOverlappingPairs(mMemoryManager.getPoolAllocator(), mMemoryManager.getSingleFrameAllocator(), mProxyShapesComponents,
collisionBodyComponents, rigidBodyComponents, mNoCollisionPairs),
mBroadPhaseSystem(*this, mProxyShapesComponents, transformComponents, rigidBodyComponents),
mNoCollisionPairs(mMemoryManager.getPoolAllocator()), mMapBroadPhaseIdToProxyShapeEntity(memoryManager.getPoolAllocator()),
mMapBroadPhaseIdToProxyShapeEntity(memoryManager.getPoolAllocator()),
mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator(), mOverlappingPairs), mPotentialContactPoints(mMemoryManager.getSingleFrameAllocator()),
// TODO : We should probably use single frame allocator for mPotentialContactPoints, mPotentialContactManifolds, mMapPairIdToOverlappingPairContacts
mPotentialContactManifolds(mMemoryManager.getSingleFrameAllocator()), mContactPairs1(mMemoryManager.getPoolAllocator()),
@ -100,12 +102,10 @@ void CollisionDetectionSystem::computeBroadPhase() {
RP3D_PROFILE("CollisionDetectionSystem::computeBroadPhase()", mProfiler);
resetNeedToTestOverlap();
// Ask the broad-phase to compute all the shapes overlapping the shapes that
// have moved or have been added in the last frame. This call can only add new
// overlapping pairs in the collision detection.
List<Pair<int, int>> overlappingNodes(mMemoryManager.getPoolAllocator(), 32);
List<Pair<int32, int32>> overlappingNodes(mMemoryManager.getPoolAllocator(), 32);
mBroadPhaseSystem.computeOverlappingPairs(mMemoryManager, overlappingNodes);
// Create new overlapping pairs if necessary
@ -115,63 +115,38 @@ void CollisionDetectionSystem::computeBroadPhase() {
removeNonOverlappingPairs();
}
// Set the needToTestOverlap value of each overlapping pair to true
void CollisionDetectionSystem::resetNeedToTestOverlap() {
RP3D_PROFILE("CollisionDetectionSystem::resetNeedToTestOverlap()", mProfiler);
// For each possible convex vs convex collision pair of bodies
for (uint i=0; i < mOverlappingPairs.mConvexNeedToTestOverlap.size(); i++) {
mOverlappingPairs.mConvexNeedToTestOverlap[i] = true;
}
// For each possible convex vs concave collision pair of bodies
for (uint i=0; i < mOverlappingPairs.mConcaveNeedToTestOverlap.size(); i++) {
mOverlappingPairs.mConcaveNeedToTestOverlap[i] = true;
}
}
// Remove pairs that are not overlapping anymore
void CollisionDetectionSystem::removeNonOverlappingPairs() {
RP3D_PROFILE("CollisionDetectionSystem::removeNonOverlappingPairs()", mProfiler);
// For each possible convex vs convex pair of bodies
for (uint i=0; i < mOverlappingPairs.mConvexPairIds.size(); i++) {
for (uint64 i=0; i < mOverlappingPairs.getNbPairs(); i++) {
// Check if we need to test overlap. If so, test if the two shapes are still overlapping.
// Otherwise, we destroy the overlapping pair
if (mOverlappingPairs.mConvexNeedToTestOverlap[i] &&
!mBroadPhaseSystem.testOverlappingShapes(mOverlappingPairs.mConvexProxyShapes1[i], mOverlappingPairs.mConvexProxyShapes2[i])) {
if (mOverlappingPairs.mNeedToTestOverlap[i]) {
mOverlappingPairs.removePair(mOverlappingPairs.mConvexPairIds[i]);
i--;
}
}
// For each possible convex vs concave pair of bodies
for (uint i=0; i < mOverlappingPairs.mConcavePairIds.size(); i++) {
// Check if we need to test overlap. If so, test if the two shapes are still overlapping.
// Otherwise, we destroy the overlapping pair
if (mOverlappingPairs.mConcaveNeedToTestOverlap[i] &&
!mBroadPhaseSystem.testOverlappingShapes(mOverlappingPairs.mConcaveProxyShapes1[i], mOverlappingPairs.mConcaveProxyShapes2[i])) {
mOverlappingPairs.removePair(mOverlappingPairs.mConcavePairIds[i]);
i--;
if(mBroadPhaseSystem.testOverlappingShapes(mOverlappingPairs.mPairBroadPhaseId1[i], mOverlappingPairs.mPairBroadPhaseId2[i])) {
mOverlappingPairs.mNeedToTestOverlap[i] = false;
}
else {
mOverlappingPairs.removePair(mOverlappingPairs.mPairIds[i]);
i--;
}
}
}
}
// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int, int>>& overlappingNodes) {
void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int32>>& overlappingNodes) {
RP3D_PROFILE("CollisionDetectionSystem::updateOverlappingPairs()", mProfiler);
// For each overlapping pair of nodes
for (uint i=0; i < overlappingNodes.size(); i++) {
Pair<int, int> nodePair = overlappingNodes[i];
Pair<int32, int32> nodePair = overlappingNodes[i];
assert(nodePair.first != -1);
assert(nodePair.second != -1);
@ -194,8 +169,8 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int, int>>
const uint64 pairId = pairNumbers(std::max(nodePair.first, nodePair.second), std::min(nodePair.first, nodePair.second));
// Check if the overlapping pair already exists
OverlappingPairs::PairLocation pairLocation;
if (!mOverlappingPairs.findPair(pairId, pairLocation)) {
auto it = mOverlappingPairs.mMapPairIdToPairIndex.find(pairId);
if (it == mOverlappingPairs.mMapPairIdToPairIndex.end()) {
unsigned short shape1CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape1Entity);
unsigned short shape2CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape2Entity);
@ -214,17 +189,14 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int, int>>
if (shape1->getCollisionShape()->isConvex() || shape2->getCollisionShape()->isConvex()) {
// Add the new overlapping pair
mOverlappingPairs.addPair(shape1, shape2);
mOverlappingPairs.addPair(shape1, shape2, mOverlappingPairs.computeIsPairActive(shape1, shape2));
}
}
}
else {
// We do not need to test the pair for overlap because it has just been reported that they still overlap
List<bool>& pairsNeedToTestOverlap = pairLocation.isConvexVsConvex ? mOverlappingPairs.mConvexNeedToTestOverlap :
mOverlappingPairs.mConcaveNeedToTestOverlap;
pairsNeedToTestOverlap[pairLocation.pairIndex] = false;
mOverlappingPairs.mNeedToTestOverlap[it->second] = false;
}
}
}
@ -243,10 +215,10 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairs& overlappingP
overlappingPairs.clearObsoleteLastFrameCollisionInfos();
// For each possible convex vs convex pair of bodies
for (uint i=0; i < overlappingPairs.mConvexPairIds.size(); i++) {
for (uint64 i=0; i < overlappingPairs.getNbConvexVsConvexPairs(); i++) {
const Entity proxyShape1Entity = overlappingPairs.mConvexProxyShapes1[i];
const Entity proxyShape2Entity = overlappingPairs.mConvexProxyShapes2[i];
const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i];
const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i];
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
@ -280,7 +252,7 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairs& overlappingP
// No middle-phase is necessary, simply create a narrow phase info
// for the narrow-phase collision detection
narrowPhaseInput.addNarrowPhaseTest(overlappingPairs.mConvexPairIds[i], proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2,
narrowPhaseInput.addNarrowPhaseTest(overlappingPairs.mPairIds[i], proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2,
mProxyShapesComponents.getLocalToWorldTransform(proxyShape1Entity),
mProxyShapesComponents.getLocalToWorldTransform(proxyShape2Entity),
algorithmType, mMemoryManager.getSingleFrameAllocator());
@ -288,10 +260,11 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairs& overlappingP
}
// For each possible convex vs concave pair of bodies
for (uint i=0; i < overlappingPairs.mConcavePairIds.size(); i++) {
uint64 convexVsConcaveStartIndex = overlappingPairs.getConvexVsConcavePairsStartIndex();
for (uint64 i=convexVsConcaveStartIndex; i < convexVsConcaveStartIndex + overlappingPairs.getNbConvexVsConcavePairs(); i++) {
const Entity proxyShape1Entity = overlappingPairs.mConcaveProxyShapes1[i];
const Entity proxyShape2Entity = overlappingPairs.mConcaveProxyShapes2[i];
const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i];
const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i];
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
@ -316,7 +289,7 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairs& overlappingP
bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity);
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
computeConvexVsConcaveMiddlePhase(overlappingPairs.mConcavePairIds[i], proxyShape1Entity, proxyShape2Entity,
computeConvexVsConcaveMiddlePhase(overlappingPairs.mPairIds[i], proxyShape1Entity, proxyShape2Entity,
mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
}
}
@ -333,16 +306,15 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
mOverlappingPairs.clearObsoleteLastFrameCollisionInfos();
// For each possible convex vs convex pair of bodies
for (uint p=0; p < convexPairs.size(); p++) {
for (uint64 p=0; p < convexPairs.size(); p++) {
const uint64 pairId = convexPairs[p];
OverlappingPairs::PairLocation& pairLoc = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
assert(pairLoc.isConvexVsConvex);
const uint pairIndex = pairLoc.pairIndex;
const uint64 pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
assert(pairIndex < mOverlappingPairs.getNbPairs());
const Entity proxyShape1Entity = mOverlappingPairs.mConvexProxyShapes1[pairIndex];
const Entity proxyShape2Entity = mOverlappingPairs.mConvexProxyShapes2[pairIndex];
const Entity proxyShape1Entity = mOverlappingPairs.mProxyShapes1[pairIndex];
const Entity proxyShape2Entity = mOverlappingPairs.mProxyShapes2[pairIndex];
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
@ -388,12 +360,10 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
const uint64 pairId = concavePairs[p];
OverlappingPairs::PairLocation& pairLoc = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
assert(!pairLoc.isConvexVsConvex);
const uint pairIndex = pairLoc.pairIndex;
const uint pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
const Entity proxyShape1Entity = mOverlappingPairs.mConcaveProxyShapes1[pairIndex];
const Entity proxyShape2Entity = mOverlappingPairs.mConcaveProxyShapes2[pairIndex];
const Entity proxyShape1Entity = mOverlappingPairs.mProxyShapes1[pairIndex];
const Entity proxyShape2Entity = mOverlappingPairs.mProxyShapes2[pairIndex];
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
@ -651,6 +621,19 @@ void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInput& nar
computeSnapshotContactPairs(convexPolyhedronVsConvexPolyhedronBatch, overlapPairs);
}
// Notify that the overlapping pairs where a given proxy-shape is involved need to be tested for overlap
void CollisionDetectionSystem::notifyOverlappingPairsToTestOverlap(ProxyShape* proxyShape) {
// Get the overlapping pairs involved with this proxy-shape
List<uint64>& overlappingPairs = mProxyShapesComponents.getOverlappingPairs(proxyShape->getEntity());
for (uint i=0; i < overlappingPairs.size(); i++) {
// Notify that the overlapping pair needs to be testbed for overlap
mOverlappingPairs.setNeedToTestOverlap(overlappingPairs[i], true);
}
}
// Convert the potential overlapping bodies for the testOverlap() methods
void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) const {
@ -963,32 +946,14 @@ void CollisionDetectionSystem::removeProxyCollisionShape(ProxyShape* proxyShape)
assert(proxyShapeBroadPhaseId != -1);
assert(mMapBroadPhaseIdToProxyShapeEntity.containsKey(proxyShapeBroadPhaseId));
// Remove all the convex vs convex overlapping pairs involving this proxy shape
for (uint i=0; i < mOverlappingPairs.mConvexPairIds.size(); i++) {
// Remove all the overlapping pairs involving this proxy shape
List<uint64>& overlappingPairs = mProxyShapesComponents.getOverlappingPairs(proxyShape->getEntity());
while(overlappingPairs.size() > 0) {
if (mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mConvexProxyShapes1[i]) == proxyShapeBroadPhaseId ||
mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mConvexProxyShapes2[i]) == proxyShapeBroadPhaseId) {
// TODO : Remove all the contact manifold of the overlapping pair from the contact manifolds list of the two bodies involved
// TODO : Remove all the contact manifold of the overlapping pair from the contact manifolds list of the two bodies involved
// Remove the overlapping pair
mOverlappingPairs.removePair(mOverlappingPairs.mConvexPairIds[i]);
i--;
}
}
// Remove all the convex vs concave overlapping pairs involving this proxy shape
for (uint i=0; i < mOverlappingPairs.mConcavePairIds.size(); i++) {
if (mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mConcaveProxyShapes1[i]) == proxyShapeBroadPhaseId ||
mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mConcaveProxyShapes2[i]) == proxyShapeBroadPhaseId) {
// TODO : Remove all the contact manifold of the overlapping pair from the contact manifolds list of the two bodies involved
// Remove the overlapping pair
mOverlappingPairs.removePair(mOverlappingPairs.mConcavePairIds[i]);
i--;
}
// Remove the overlapping pair
mOverlappingPairs.removePair(overlappingPairs[0]);
}
mMapBroadPhaseIdToProxyShapeEntity.remove(proxyShapeBroadPhaseId);
@ -1205,9 +1170,7 @@ void CollisionDetectionSystem::reducePotentialContactManifolds(List<ContactPair>
// If there are two many contact points in the manifold
if (manifold.potentialContactPointsIndices.size() > MAX_CONTACT_POINTS_IN_MANIFOLD) {
OverlappingPairs::PairLocation pairLoc = mOverlappingPairs.mMapPairIdToPairIndex[manifold.pairId];
Entity proxyShape1 = pairLoc.isConvexVsConvex ? mOverlappingPairs.mConvexProxyShapes1[pairLoc.pairIndex] :
mOverlappingPairs.mConcaveProxyShapes1[pairLoc.pairIndex];
Entity proxyShape1 = mOverlappingPairs.mProxyShapes1[mOverlappingPairs.mMapPairIdToPairIndex[manifold.pairId]];
Transform shape1LocalToWorldTransoform = mProxyShapesComponents.getLocalToWorldTransform(proxyShape1);
@ -1572,22 +1535,12 @@ void CollisionDetectionSystem::testCollision(CollisionCallback& callback) {
void CollisionDetectionSystem::filterOverlappingPairs(Entity bodyEntity, List<uint64>& convexPairs, List<uint64>& concavePairs) const {
// For each possible collision pair of bodies
for (uint i=0; i < mOverlappingPairs.mConvexPairIds.size(); i++) {
for (uint i=0; i < mOverlappingPairs.getNbPairs(); i++) {
if (mProxyShapesComponents.getBody(mOverlappingPairs.mConvexProxyShapes1[i]) == bodyEntity ||
mProxyShapesComponents.getBody(mOverlappingPairs.mConvexProxyShapes2[i]) == bodyEntity) {
if (mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes1[i]) == bodyEntity ||
mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes2[i]) == bodyEntity) {
convexPairs.add(mOverlappingPairs.mConvexPairIds[i]);
}
}
// For each possible collision pair of bodies
for (uint i=0; i < mOverlappingPairs.mConcavePairIds.size(); i++) {
if (mProxyShapesComponents.getBody(mOverlappingPairs.mConcaveProxyShapes1[i]) == bodyEntity ||
mProxyShapesComponents.getBody(mOverlappingPairs.mConcaveProxyShapes2[i]) == bodyEntity) {
concavePairs.add(mOverlappingPairs.mConcavePairIds[i]);
convexPairs.add(mOverlappingPairs.mPairIds[i]);
}
}
}
@ -1598,22 +1551,12 @@ void CollisionDetectionSystem::filterOverlappingPairs(Entity body1Entity, Entity
// TODO : Do not go through all the overlapping pairs here but get all the involded overlapping pairs directly from the bodies
// For each possible collision pair of bodies
for (uint i=0; i < mOverlappingPairs.mConvexPairIds.size(); i++) {
for (uint i=0; i < mOverlappingPairs.getNbPairs(); i++) {
if ((mProxyShapesComponents.getBody(mOverlappingPairs.mConvexProxyShapes1[i]) == body1Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mConvexProxyShapes2[i]) == body2Entity) ||
(mProxyShapesComponents.getBody(mOverlappingPairs.mConvexProxyShapes1[i]) == body2Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mConvexProxyShapes2[i]) == body1Entity)) {
if ((mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes1[i]) == body1Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes1[i]) == body2Entity) ||
(mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes2[i]) == body2Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes2[i]) == body1Entity)) {
convexPairs.add(mOverlappingPairs.mConvexPairIds[i]);
}
}
// For each possible collision pair of bodies
for (uint i=0; i < mOverlappingPairs.mConcavePairIds.size(); i++) {
if ((mProxyShapesComponents.getBody(mOverlappingPairs.mConcaveProxyShapes1[i]) == body1Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mConcaveProxyShapes2[i]) == body2Entity) ||
(mProxyShapesComponents.getBody(mOverlappingPairs.mConcaveProxyShapes1[i]) == body2Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mConcaveProxyShapes2[i]) == body1Entity)) {
concavePairs.add(mOverlappingPairs.mConcavePairIds[i]);
convexPairs.add(mOverlappingPairs.mPairIds[i]);
}
}
}

View File

@ -89,15 +89,15 @@ class CollisionDetectionSystem {
/// Pointer to the physics world
CollisionWorld* mWorld;
/// Set of pair of bodies that cannot collide between each other
Set<bodypair> mNoCollisionPairs;
/// Broad-phase overlapping pairs
OverlappingPairs mOverlappingPairs;
/// Broad-phase system
BroadPhaseSystem mBroadPhaseSystem;
/// Set of pair of bodies that cannot collide between each other
Set<bodypair> mNoCollisionPairs;
/// Map a broad-phase id with the corresponding entity of the proxy-shape
Map<int, Entity> mMapBroadPhaseIdToProxyShapeEntity;
@ -197,10 +197,7 @@ class CollisionDetectionSystem {
void computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) const;
/// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
void updateOverlappingPairs(const List<Pair<int, int>>& overlappingNodes);
/// Set the needToTestOverlap value of each overlapping pair to true
void resetNeedToTestOverlap();
void updateOverlappingPairs(const List<Pair<int32, int32> >& overlappingNodes);
/// Remove pairs that are not overlapping anymore
void removeNonOverlappingPairs();
@ -271,7 +268,7 @@ class CollisionDetectionSystem {
/// Constructor
CollisionDetectionSystem(CollisionWorld* world, ProxyShapeComponents& proxyShapesComponents,
TransformComponents& transformComponents, RigidBodyComponents& rigidBodyComponents,
TransformComponents& transformComponents, CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents,
MemoryManager& memoryManager);
/// Destructor
@ -290,7 +287,7 @@ class CollisionDetectionSystem {
void addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb);
/// Remove a proxy collision shape from the collision detection
void removeProxyCollisionShape(ProxyShape* proxyShape);
void removeProxyCollisionShape(ProxyShape *proxyShape);
/// Update a proxy collision shape (that has moved for instance)
void updateProxyShape(Entity proxyShapeEntity, decimal timeStep);
@ -307,6 +304,9 @@ class CollisionDetectionSystem {
/// Ask for a collision shape to be tested again during broad-phase.
void askForBroadPhaseCollisionCheck(ProxyShape* shape);
/// Notify that the overlapping pairs where a given proxy-shape is involved need to be tested for overlap
void notifyOverlappingPairsToTestOverlap(ProxyShape* proxyShape);
/// Report contacts
void reportContacts();
@ -395,7 +395,7 @@ inline void CollisionDetectionSystem::removeNoCollisionPair(Entity body1Entity,
inline void CollisionDetectionSystem::askForBroadPhaseCollisionCheck(ProxyShape* shape) {
if (shape->getBroadPhaseId() != -1) {
mBroadPhaseSystem.addMovedCollisionShape(shape->getBroadPhaseId());
mBroadPhaseSystem.addMovedCollisionShape(shape->getBroadPhaseId(), shape);
}
}