Working on middle-phase collision detection

This commit is contained in:
Daniel Chappuis 2019-11-19 18:35:22 +01:00
parent 7dcc86d746
commit d894a40d2e
17 changed files with 200 additions and 225 deletions

View File

@ -98,6 +98,9 @@ void RigidBody::setType(BodyType type) {
// Awake the body
setIsSleeping(false);
// Update the active status of currently overlapping pairs
updateOverlappingPairs();
// Ask the broad-phase to test again the collision shapes of the body for collision
// detection (as if the body has moved)
askForBroadPhaseCollisionCheck();
@ -683,6 +686,9 @@ void RigidBody::setIsSleeping(bool isSleeping) {
// Notify all the components
mWorld.setBodyDisabled(mEntity, isSleeping);
// Update the currently overlapping pairs
updateOverlappingPairs();
if (isSleeping) {
mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, Vector3::zero());
@ -696,6 +702,23 @@ void RigidBody::setIsSleeping(bool isSleeping) {
(isSleeping ? "true" : "false"));
}
// Update whether the current overlapping pairs where this body is involed are active or not
void RigidBody::updateOverlappingPairs() {
// For each proxy-shape of the body
const List<Entity>& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
// Get the currently overlapping pairs for this proxy-shape
List<uint64> overlappingPairs = mWorld.mProxyShapesComponents.getOverlappingPairs(proxyShapesEntities[i]);
for (uint j=0; j < overlappingPairs.size(); j++) {
mWorld.mCollisionDetection.mOverlappingPairs.updateOverlappingPairIsActive(overlappingPairs[j]);
}
}
}
/// Return the inverse of the inertia tensor in world coordinates.
const Matrix3x3 RigidBody::getInertiaTensorInverseWorld(CollisionWorld& world, Entity bodyEntity) {

View File

@ -73,6 +73,9 @@ class RigidBody : public CollisionBody {
/// Set the variable to know whether or not the body is sleeping
void setIsSleeping(bool isSleeping);
/// Update whether the current overlapping pairs where this body is involed are active or not
void updateOverlappingPairs();
/// Return the inverse of the inertia tensor in world coordinates.
static const Matrix3x3 getInertiaTensorInverseWorld(CollisionWorld& world, Entity bodyEntity);

View File

@ -38,7 +38,7 @@ CapsuleVsCapsuleNarrowPhaseInfoBatch::CapsuleVsCapsuleNarrowPhaseInfoBatch(Memor
}
// Add shapes to be tested during narrow-phase collision detection into the batch
void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
const Transform& shape1Transform, const Transform& shape2Transform) {
assert(shape1->getType() == CollisionShapeType::CAPSULE);
@ -60,7 +60,7 @@ void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Ent
isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId());
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
lastFrameCollisionInfos.add(lastFrameInfo);
}

View File

@ -61,7 +61,7 @@ struct CapsuleVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
virtual ~CapsuleVsCapsuleNarrowPhaseInfoBatch() = default;
/// Add shapes to be tested during narrow-phase collision detection into the batch
virtual void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform);

View File

@ -48,7 +48,7 @@ NarrowPhaseInfoBatch::~NarrowPhaseInfoBatch() {
}
// Add shapes to be tested during narrow-phase collision detection into the batch
void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
const Transform& shape1Transform, const Transform& shape2Transform,
MemoryAllocator& shapeAllocator) {
@ -64,7 +64,7 @@ void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1,
isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId());
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
lastFrameCollisionInfos.add(lastFrameInfo);
}

View File

@ -103,7 +103,7 @@ struct NarrowPhaseInfoBatch {
uint getNbObjects() const;
/// Add shapes to be tested during narrow-phase collision detection into the batch
void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform, MemoryAllocator& shapeAllocator);

View File

@ -39,28 +39,28 @@ NarrowPhaseInput::NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs&
}
// Add shapes to be tested during narrow-phase collision detection into the batch
void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
const Transform& shape1Transform, const Transform& shape2Transform,
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, MemoryAllocator& shapeAllocator) {
switch (narrowPhaseAlgorithmType) {
case NarrowPhaseAlgorithmType::SphereVsSphere:
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
break;
case NarrowPhaseAlgorithmType::SphereVsCapsule:
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
break;
case NarrowPhaseAlgorithmType::CapsuleVsCapsule:
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
break;
case NarrowPhaseAlgorithmType::SphereVsConvexPolyhedron:
mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::CapsuleVsConvexPolyhedron:
mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::ConvexPolyhedronVsConvexPolyhedron:
mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
break;
case NarrowPhaseAlgorithmType::None:
// Must never happen

View File

@ -67,7 +67,7 @@ class NarrowPhaseInput {
NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
/// Add shapes to be tested during narrow-phase collision detection into the batch
void addNarrowPhaseTest(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
void addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType,
MemoryAllocator& shapeAllocator);

View File

@ -39,7 +39,7 @@ SphereVsCapsuleNarrowPhaseInfoBatch::SphereVsCapsuleNarrowPhaseInfoBatch(MemoryA
}
// Add shapes to be tested during narrow-phase collision detection into the batch
void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
const Transform& shape1Transform, const Transform& shape2Transform) {
bool isSphereShape1 = shape1->getType() == CollisionShapeType::SPHERE;
@ -63,7 +63,7 @@ void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Enti
isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId());
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
lastFrameCollisionInfos.add(lastFrameInfo);
}

View File

@ -61,7 +61,7 @@ struct SphereVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
virtual ~SphereVsCapsuleNarrowPhaseInfoBatch() = default;
/// Add shapes to be tested during narrow-phase collision detection into the batch
virtual void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform);

View File

@ -36,7 +36,7 @@ SphereVsSphereNarrowPhaseInfoBatch::SphereVsSphereNarrowPhaseInfoBatch(MemoryAll
}
// Add shapes to be tested during narrow-phase collision detection into the batch
void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1, CollisionShape* shape2,
const Transform& shape1Transform, const Transform& shape2Transform) {
assert(shape1->getType() == CollisionShapeType::SPHERE);
@ -56,7 +56,7 @@ void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entit
isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairId, shape1->getId(), shape2->getId());
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
lastFrameCollisionInfos.add(lastFrameInfo);
}

View File

@ -55,7 +55,7 @@ struct SphereVsSphereNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
virtual ~SphereVsSphereNarrowPhaseInfoBatch() override = default;
/// Add shapes to be tested during narrow-phase collision detection into the batch
virtual void addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity proxyShape1, Entity proxyShape2, CollisionShape* shape1,
CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform);

View File

@ -73,7 +73,7 @@ class CollisionShape {
CollisionShapeName mName;
/// Unique identifier of the shape inside an overlapping pair
uint mId;
uint32 mId;
#ifdef IS_PROFILING_ACTIVE
@ -125,7 +125,7 @@ class CollisionShape {
virtual void getLocalBounds(Vector3& min, Vector3& max) const=0;
/// Return the id of the shape
uint getId() const;
uint32 getId() const;
/// Return the local inertia tensor of the collision shapes
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const=0;
@ -166,7 +166,7 @@ inline CollisionShapeType CollisionShape::getType() const {
}
// Return the id of the shape
inline uint CollisionShape::getId() const {
inline uint32 CollisionShape::getId() const {
return mId;
}

View File

@ -38,8 +38,9 @@ OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, M
CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, Set<bodypair> &noCollisionPairs, CollisionDispatch &collisionDispatch)
: 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) + sizeof(NarrowPhaseAlgorithmType)),
sizeof(Entity) + sizeof(Map<uint64, LastFrameCollisionInfo*>) +
sizeof(bool) + sizeof(bool) + sizeof(NarrowPhaseAlgorithmType) +
sizeof(bool)),
mNbAllocatedPairs(0), mBuffer(nullptr),
mMapPairIdToPairIndex(persistentMemoryAllocator),
mProxyShapeComponents(proxyShapeComponents), mCollisionBodyComponents(collisionBodyComponents),
@ -205,10 +206,11 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
int32* newPairBroadPhaseId2 = reinterpret_cast<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);
Map<uint64, LastFrameCollisionInfo*>* newLastFrameCollisionInfos = reinterpret_cast<Map<uint64, LastFrameCollisionInfo*>*>(newProxyShapes2 + nbPairsToAllocate);
bool* newNeedToTestOverlap = reinterpret_cast<bool*>(newLastFrameCollisionInfos + nbPairsToAllocate);
bool* newIsActive = reinterpret_cast<bool*>(newNeedToTestOverlap + nbPairsToAllocate);
NarrowPhaseAlgorithmType* newNarrowPhaseAlgorithmType = reinterpret_cast<NarrowPhaseAlgorithmType*>(newIsActive + nbPairsToAllocate);
bool* newIsShape1Convex = reinterpret_cast<bool*>(newNarrowPhaseAlgorithmType + nbPairsToAllocate);
// If there was already pairs before
if (mNbPairs > 0) {
@ -219,10 +221,11 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
memcpy(newPairBroadPhaseId2, mPairBroadPhaseId2, mNbPairs * sizeof(int32));
memcpy(newProxyShapes1, mProxyShapes1, mNbPairs * sizeof(Entity));
memcpy(newProxyShapes2, mProxyShapes2, mNbPairs * sizeof(Entity));
memcpy(newLastFrameCollisionInfos, mLastFrameCollisionInfos, mNbPairs * sizeof(Map<ShapeIdPair, LastFrameCollisionInfo*>));
memcpy(newLastFrameCollisionInfos, mLastFrameCollisionInfos, mNbPairs * sizeof(Map<uint64, LastFrameCollisionInfo*>));
memcpy(newNeedToTestOverlap, mNeedToTestOverlap, mNbPairs * sizeof(bool));
memcpy(newIsActive, mIsActive, mNbPairs * sizeof(bool));
memcpy(newNarrowPhaseAlgorithmType, mNarrowPhaseAlgorithmType, mNbPairs * sizeof(NarrowPhaseAlgorithmType));
memcpy(newIsShape1Convex, mIsShape1Convex, mNbPairs * sizeof(bool));
// Deallocate previous memory
mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize);
@ -238,43 +241,57 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
mNeedToTestOverlap = newNeedToTestOverlap;
mIsActive = newIsActive;
mNarrowPhaseAlgorithmType = newNarrowPhaseAlgorithmType;
mIsShape1Convex = newIsShape1Convex;
mNbAllocatedPairs = nbPairsToAllocate;
}
// Add an overlapping pair
uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2, bool isActive) {
uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2) {
RP3D_PROFILE("OverlappingPairs::addPair()", mProfiler);
const CollisionShape* collisionShape1 = mProxyShapeComponents.getCollisionShape(shape1->getEntity());
const CollisionShape* collisionShape2 = mProxyShapeComponents.getCollisionShape(shape2->getEntity());
// Prepare to add new pair (allocate memory if necessary and compute insertion index)
uint64 index = prepareAddPair(collisionShape1->isConvex() && collisionShape2->isConvex());
const bool isShape1Convex = collisionShape1->isConvex();
const bool isShape2Convex = collisionShape2->isConvex();
const bool isConvexVsConvex = isShape1Convex && isShape2Convex;
const uint32 shape1Id = static_cast<uint32>(shape1->getBroadPhaseId());
const uint32 shape2Id = static_cast<uint32>(shape2->getBroadPhaseId());
// Prepare to add new pair (allocate memory if necessary and compute insertion index)
uint64 index = prepareAddPair(isConvexVsConvex);
const uint32 broadPhase1Id = static_cast<uint32>(shape1->getBroadPhaseId());
const uint32 broadPhase2Id = 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));
const uint64 pairId = pairNumbers(std::max(broadPhase1Id, broadPhase2Id), std::min(broadPhase1Id, broadPhase2Id));
assert(!mMapPairIdToPairIndex.containsKey(pairId));
// Select the narrow phase algorithm to use according to the two collision shapes
NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(),
collisionShape2->getType());
NarrowPhaseAlgorithmType algorithmType;
if (isConvexVsConvex) {
algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(), collisionShape2->getType());
}
else {
algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(isShape1Convex ? collisionShape1->getType() : collisionShape2->getType(),
CollisionShapeType::CONVEX_POLYHEDRON);
}
// Insert the new component data
new (mPairIds + index) uint64(pairId);
new (mPairBroadPhaseId1 + index) int32(shape1->getBroadPhaseId());
new (mPairBroadPhaseId2 + index) int32(shape2->getBroadPhaseId());
new (mProxyShapes1 + index) Entity(shape1->getEntity());
new (mProxyShapes2 + index) Entity(shape2->getEntity());
new (mLastFrameCollisionInfos + index) Map<ShapeIdPair, LastFrameCollisionInfo*>(mPersistentAllocator);
new (mLastFrameCollisionInfos + index) Map<uint64, LastFrameCollisionInfo*>(mPersistentAllocator);
new (mNeedToTestOverlap + index) bool(false);
new (mIsActive + index) bool(isActive);
new (mIsActive + index) bool(true);
new (mNarrowPhaseAlgorithmType + index) NarrowPhaseAlgorithmType(algorithmType);
new (mIsShape1Convex + index) bool(isShape1Convex);
// Map the entity with the new component lookup index
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index));
@ -290,6 +307,8 @@ uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2, bool is
assert(mConcavePairsStartIndex <= mNbPairs);
assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
updateOverlappingPairIsActive(pairId);
return pairId;
}
@ -305,10 +324,11 @@ void OverlappingPairs::movePairToIndex(uint64 srcIndex, uint64 destIndex) {
mPairBroadPhaseId2[destIndex] = mPairBroadPhaseId2[srcIndex];
new (mProxyShapes1 + destIndex) Entity(mProxyShapes1[srcIndex]);
new (mProxyShapes2 + destIndex) Entity(mProxyShapes2[srcIndex]);
new (mLastFrameCollisionInfos + destIndex) Map<ShapeIdPair, LastFrameCollisionInfo*>(mLastFrameCollisionInfos[srcIndex]);
new (mLastFrameCollisionInfos + destIndex) Map<uint64, LastFrameCollisionInfo*>(mLastFrameCollisionInfos[srcIndex]);
mNeedToTestOverlap[destIndex] = mNeedToTestOverlap[srcIndex];
mIsActive[destIndex] = mIsActive[srcIndex];
new (mNarrowPhaseAlgorithmType + destIndex) NarrowPhaseAlgorithmType(mNarrowPhaseAlgorithmType[srcIndex]);
mIsShape1Convex[destIndex] = mIsShape1Convex[srcIndex];
// Destroy the source pair
destroyPair(srcIndex);
@ -330,10 +350,11 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
int32 pairBroadPhaseId2 = mPairBroadPhaseId2[index1];
Entity proxyShape1 = mProxyShapes1[index1];
Entity proxyShape2 = mProxyShapes2[index1];
Map<ShapeIdPair, LastFrameCollisionInfo*> lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]);
Map<uint64, LastFrameCollisionInfo*> lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]);
bool needTestOverlap = mNeedToTestOverlap[index1];
bool isActive = mIsActive[index1];
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType = mNarrowPhaseAlgorithmType[index1];
bool isShape1Convex = mIsShape1Convex[index1];
// Destroy pair 1
destroyPair(index1);
@ -346,10 +367,11 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
mPairBroadPhaseId2[index2] = pairBroadPhaseId2;
new (mProxyShapes1 + index2) Entity(proxyShape1);
new (mProxyShapes2 + index2) Entity(proxyShape2);
new (mLastFrameCollisionInfos + index2) Map<ShapeIdPair, LastFrameCollisionInfo*>(lastFrameCollisionInfo);
new (mLastFrameCollisionInfos + index2) Map<uint64, LastFrameCollisionInfo*>(lastFrameCollisionInfo);
mNeedToTestOverlap[index2] = needTestOverlap;
mIsActive[index2] = isActive;
new (mNarrowPhaseAlgorithmType + index2) NarrowPhaseAlgorithmType(narrowPhaseAlgorithmType);
mIsShape1Convex[index2] = isShape1Convex;
// Update the pairID to pair index mapping
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index2));
@ -370,33 +392,60 @@ void OverlappingPairs::destroyPair(uint64 index) {
mProxyShapes1[index].~Entity();
mProxyShapes2[index].~Entity();
mLastFrameCollisionInfos[index].~Map<ShapeIdPair, LastFrameCollisionInfo*>();
mLastFrameCollisionInfos[index].~Map<uint64, LastFrameCollisionInfo*>();
mNarrowPhaseAlgorithmType[index].~NarrowPhaseAlgorithmType();
}
// Add a new last frame collision info if it does not exist for the given shapes already
LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pairId, uint shapeId1, uint shapeId2) {
RP3D_PROFILE("OverlappingPairs::addLastFrameInfoIfNecessary()", mProfiler);
// Update whether a given overlapping pair is active or not
void OverlappingPairs::updateOverlappingPairIsActive(uint64 pairId) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
const uint64 index = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs);
const uint64 pairIndex = mMapPairIdToPairIndex[pairId];
const Entity proxyShape1 = mProxyShapes1[pairIndex];
const Entity proxyShape2 = mProxyShapes2[pairIndex];
const Entity body1 = mProxyShapeComponents.getBody(proxyShape1);
const Entity body2 = mProxyShapeComponents.getBody(proxyShape2);
const bool isBody1Enabled = !mCollisionBodyComponents.getIsEntityDisabled(body1);
const bool isBody2Enabled = !mCollisionBodyComponents.getIsEntityDisabled(body2);
const bool isBody1Static = mRigidBodyComponents.hasComponent(body1) &&
mRigidBodyComponents.getBodyType(body1) == BodyType::STATIC;
const bool isBody2Static = mRigidBodyComponents.hasComponent(body2) &&
mRigidBodyComponents.getBodyType(body2) == BodyType::STATIC;
const bool isBody1Active = isBody1Enabled && !isBody1Static;
const bool isBody2Active = isBody2Enabled && !isBody2Static;
// Check if the bodies are in the set of bodies that cannot collide between each other
bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1, body2);
bool bodiesCanCollide = !mNoCollisionPairs.contains(bodiesIndex);
mIsActive[pairIndex] = bodiesCanCollide && (isBody1Active || isBody2Active);
}
// Add a new last frame collision info if it does not exist for the given shapes already
LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2) {
RP3D_PROFILE("OverlappingPairs::addLastFrameInfoIfNecessary()", mProfiler);
assert(pairIndex < mNbPairs);
// Try to get the corresponding last frame collision info
const ShapeIdPair shapeIdPair(shapeId1, shapeId2);
const uint64 shapesId = pairNumbers(std::max(shapeId1, shapeId2), std::min(shapeId1, shapeId2));
// If there is no collision info for those two shapes already
auto it = mLastFrameCollisionInfos[index].find(shapeIdPair);
if (it == mLastFrameCollisionInfos[index].end()) {
auto it = mLastFrameCollisionInfos[pairIndex].find(shapesId);
if (it == mLastFrameCollisionInfos[pairIndex].end()) {
// Create a new collision info
LastFrameCollisionInfo* collisionInfo = new (mPersistentAllocator.allocate(sizeof(LastFrameCollisionInfo)))
LastFrameCollisionInfo();
// Add it into the map of collision infos
mLastFrameCollisionInfos[index].add(Pair<ShapeIdPair, LastFrameCollisionInfo*>(shapeIdPair, collisionInfo));
mLastFrameCollisionInfos[pairIndex].add(Pair<uint64, LastFrameCollisionInfo*>(shapesId, collisionInfo));
return collisionInfo;
}
@ -439,28 +488,3 @@ void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() {
}
}
}
// Return true if the overlapping pair between two shapes is active
bool OverlappingPairs::computeIsPairActive(ProxyShape* shape1, ProxyShape* shape2) {
const Entity body1Entity = mProxyShapeComponents.getBody(shape1->getEntity());
const Entity body2Entity = mProxyShapeComponents.getBody(shape2->getEntity());
const bool isStaticRigidBody1 = mRigidBodyComponents.hasComponent(body1Entity) &&
mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
const bool isStaticRigidBody2 = mRigidBodyComponents.hasComponent(body2Entity) &&
mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC;
// Check that at least one body is enabled (active and awake) and not static
// TODO : Do not test this every frame
bool isBody1Active = !mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
bool isBody2Active = !mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
if (!isBody1Active && !isBody2Active) return false;
// Check if the bodies are in the set of bodies that cannot collide between each other
// TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation
bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity);
if (mNoCollisionPairs.contains(bodiesIndex) > 0) return false;
return true;
}

View File

@ -104,11 +104,6 @@ struct LastFrameCollisionInfo {
*/
class OverlappingPairs {
public:
// TODO : Try to use a pairing function like pairNumbers() here
using ShapeIdPair = Pair<uint, uint>;
private:
// -------------------- Constants -------------------- //
@ -165,7 +160,7 @@ class OverlappingPairs {
/// If two convex shapes overlap, we have a single collision data but if one shape is concave,
/// we might have collision data for several overlapping triangles. The key in the map is the
/// shape Ids of the two collision shapes.
Map<ShapeIdPair, LastFrameCollisionInfo*>* mLastFrameCollisionInfos;
Map<uint64, LastFrameCollisionInfo*>* mLastFrameCollisionInfos;
/// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
bool* mNeedToTestOverlap;
@ -176,6 +171,9 @@ class OverlappingPairs {
/// Array with the pointer to the narrow-phase algorithm for each overlapping pair
NarrowPhaseAlgorithmType* mNarrowPhaseAlgorithmType;
/// True if the first shape of the pair is convex
bool* mIsShape1Convex;
/// Reference to the proxy-shapes components
ProxyShapeComponents& mProxyShapeComponents;
@ -235,7 +233,7 @@ class OverlappingPairs {
OverlappingPairs& operator=(const OverlappingPairs& pair) = delete;
/// Add an overlapping pair
uint64 addPair(ProxyShape* shape1, ProxyShape* shape2, bool isActive);
uint64 addPair(ProxyShape* shape1, ProxyShape* shape2);
/// Remove a component at a given index
void removePair(uint64 pairId);
@ -261,14 +259,20 @@ class OverlappingPairs {
/// Notify if a given pair is active or not
void setIsPairActive(uint64 pairId, bool isActive);
/// Return the index of a given overlapping pair in the internal array
uint64 getPairIndex(uint64 pairId) const;
/// Return the last frame collision info
LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, ShapeIdPair& shapeIds);
LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, uint64 shapesId);
/// Return a reference to the temporary memory allocator
MemoryAllocator& getTemporaryAllocator();
/// Add a new last frame collision info if it does not exist for the given shapes already
LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint64 pairId, uint shapeId1, uint shapeId2);
LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2);
/// Update whether a given overlapping pair is active or not
void updateOverlappingPairIsActive(uint64 pairId);
/// Delete all the obsolete last frame collision info
void clearObsoleteLastFrameCollisionInfos();
@ -276,9 +280,6 @@ class OverlappingPairs {
/// Return the pair of bodies index of the pair
static bodypair computeBodiesIndexPair(Entity body1Entity, Entity body2Entity);
/// Return true if the overlapping pair between two shapes is active
bool computeIsPairActive(ProxyShape* shape1, ProxyShape* shape2);
/// Set if we need to test a given pair for overlap
void setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap);
@ -317,14 +318,20 @@ inline void OverlappingPairs::setIsPairActive(uint64 pairId, bool isActive) {
mIsActive[mMapPairIdToPairIndex[pairId]] = isActive;
}
// Return the index of a given overlapping pair in the internal array
inline uint64 OverlappingPairs::getPairIndex(uint64 pairId) const {
assert(mMapPairIdToPairIndex.containsKey(pairId));
return mMapPairIdToPairIndex[pairId];
}
// Return the last frame collision info for a given shape id or nullptr if none is found
inline LastFrameCollisionInfo* OverlappingPairs::getLastFrameCollisionInfo(uint64 pairId, ShapeIdPair& shapeIds) {
inline LastFrameCollisionInfo* OverlappingPairs::getLastFrameCollisionInfo(uint64 pairId, uint64 shapesId) {
assert(mMapPairIdToPairIndex.containsKey(pairId));
const uint64 index = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs);
Map<ShapeIdPair, LastFrameCollisionInfo*>::Iterator it = mLastFrameCollisionInfos[index].find(shapeIds);
Map<uint64, LastFrameCollisionInfo*>::Iterator it = mLastFrameCollisionInfos[index].find(shapesId);
if (it != mLastFrameCollisionInfos[index].end()) {
return it->second;
}

View File

@ -189,7 +189,7 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int
if (shape1->getCollisionShape()->isConvex() || shape2->getCollisionShape()->isConvex()) {
// Add the new overlapping pair
mOverlappingPairs.addPair(shape1, shape2, mOverlappingPairs.computeIsPairActive(shape1, shape2));
mOverlappingPairs.addPair(shape1, shape2);
}
}
}
@ -217,84 +217,47 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairs& overlappingP
// For each possible convex vs convex pair of bodies
for (uint64 i=0; i < overlappingPairs.getNbConvexVsConvexPairs(); i++) {
const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i];
const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i];
const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1Entity);
const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2Entity);
assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != -1);
assert(mProxyShapesComponents.mBroadPhaseId[proxyShape2Index] != -1);
assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != mProxyShapesComponents.mBroadPhaseId[proxyShape2Index]);
const Entity body1Entity = mProxyShapesComponents.mBodiesEntities[proxyShape1Index];
const Entity body2Entity = mProxyShapesComponents.mBodiesEntities[proxyShape2Index];
const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC;
assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i]) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i]));
// Check that at least one body is enabled (active and awake) and not static
// TODO : Do not test this every frame
bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
if (!isBody1Active && !isBody2Active) continue;
if (mOverlappingPairs.mIsActive[i]) {
// Check if the bodies are in the set of bodies that cannot collide between each other
// TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation
bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity);
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i];
const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i];
CollisionShape* collisionShape1 = mProxyShapesComponents.mCollisionShapes[proxyShape1Index];
CollisionShape* collisionShape2 = mProxyShapesComponents.mCollisionShapes[proxyShape2Index];
const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1Entity);
const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2Entity);
NarrowPhaseAlgorithmType algorithmType = overlappingPairs.mNarrowPhaseAlgorithmType[i];
CollisionShape* collisionShape1 = mProxyShapesComponents.mCollisionShapes[proxyShape1Index];
CollisionShape* collisionShape2 = mProxyShapesComponents.mCollisionShapes[proxyShape2Index];
// No middle-phase is necessary, simply create a narrow phase info
// for the narrow-phase collision detection
narrowPhaseInput.addNarrowPhaseTest(overlappingPairs.mPairIds[i], proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2,
mProxyShapesComponents.mLocalToWorldTransforms[proxyShape1Index],
mProxyShapesComponents.mLocalToWorldTransforms[proxyShape2Index],
algorithmType, mMemoryManager.getSingleFrameAllocator());
NarrowPhaseAlgorithmType algorithmType = overlappingPairs.mNarrowPhaseAlgorithmType[i];
// No middle-phase is necessary, simply create a narrow phase info
// for the narrow-phase collision detection
narrowPhaseInput.addNarrowPhaseTest(overlappingPairs.mPairIds[i], i, proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2,
mProxyShapesComponents.mLocalToWorldTransforms[proxyShape1Index],
mProxyShapesComponents.mLocalToWorldTransforms[proxyShape2Index],
algorithmType, mMemoryManager.getSingleFrameAllocator());
}
}
// For each possible convex vs concave pair of bodies
uint64 convexVsConcaveStartIndex = overlappingPairs.getConvexVsConcavePairsStartIndex();
const uint64 convexVsConcaveStartIndex = overlappingPairs.getConvexVsConcavePairsStartIndex();
for (uint64 i=convexVsConcaveStartIndex; i < convexVsConcaveStartIndex + overlappingPairs.getNbConvexVsConcavePairs(); i++) {
const Entity proxyShape1Entity = overlappingPairs.mProxyShapes1[i];
const Entity proxyShape2Entity = overlappingPairs.mProxyShapes2[i];
const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1Entity);
const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2Entity);
assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != -1);
assert(mProxyShapesComponents.mBroadPhaseId[proxyShape2Index] != -1);
assert(mProxyShapesComponents.mBroadPhaseId[proxyShape1Index] != mProxyShapesComponents.mBroadPhaseId[proxyShape2Index]);
const Entity body1Entity = mProxyShapesComponents.mBodiesEntities[proxyShape1Index];
const Entity body2Entity = mProxyShapesComponents.mBodiesEntities[proxyShape2Index];
const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC;
assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i]) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes1[i]) != mProxyShapesComponents.getBroadPhaseId(overlappingPairs.mProxyShapes2[i]));
// Check that at least one body is enabled (active and awake) and not static
// TODO : Do not test this every frame
bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
if (!isBody1Active && !isBody2Active) continue;
if (mOverlappingPairs.mIsActive[i]) {
// Check if the bodies are in the set of bodies that cannot collide between each other
// TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation
bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity);
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
computeConvexVsConcaveMiddlePhase(overlappingPairs.mPairIds[i], proxyShape1Entity, proxyShape2Entity,
mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
computeConvexVsConcaveMiddlePhase(i, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
}
}
}
@ -324,25 +287,6 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity));
const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC;
// Check that at least one body is enabled (active and awake) and not static
// TODO : Do not test this every frame
bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
if (!isBody1Active && !isBody2Active) continue;
// Check if the bodies are in the set of bodies that cannot collide between each other
// TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation
bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity);
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
CollisionShape* collisionShape1 = mProxyShapesComponents.getCollisionShape(proxyShape1Entity);
CollisionShape* collisionShape2 = mProxyShapesComponents.getCollisionShape(proxyShape2Entity);
@ -350,7 +294,7 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
// No middle-phase is necessary, simply create a narrow phase info
// for the narrow-phase collision detection
narrowPhaseInput.addNarrowPhaseTest(pairId, proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2,
narrowPhaseInput.addNarrowPhaseTest(pairId, pairIndex, proxyShape1Entity, proxyShape2Entity, collisionShape1, collisionShape2,
mProxyShapesComponents.getLocalToWorldTransform(proxyShape1Entity),
mProxyShapesComponents.getLocalToWorldTransform(proxyShape2Entity),
algorithmType, mMemoryManager.getSingleFrameAllocator());
@ -361,78 +305,52 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
for (uint p=0; p < concavePairs.size(); p++) {
const uint64 pairId = concavePairs[p];
const uint64 pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
const uint pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
assert(mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes1[pairIndex]) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes2[pairIndex]) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes1[pairIndex]) != mProxyShapesComponents.getBroadPhaseId(mOverlappingPairs.mProxyShapes2[pairIndex]));
const Entity proxyShape1Entity = mOverlappingPairs.mProxyShapes1[pairIndex];
const Entity proxyShape2Entity = mOverlappingPairs.mProxyShapes2[pairIndex];
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity));
const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC;
// Check that at least one body is enabled (active and awake) and not static
// TODO : Do not test this every frame
bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
if (!isBody1Active && !isBody2Active) continue;
// Check if the bodies are in the set of bodies that cannot collide between each other
// TODO : Do not check this every frame but remove and do not create overlapping pairs of bodies in this situation
bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1Entity, body2Entity);
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
computeConvexVsConcaveMiddlePhase(pairId, proxyShape1Entity, proxyShape2Entity,
mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
computeConvexVsConcaveMiddlePhase(pairIndex, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
}
}
// Compute the concave vs convex middle-phase algorithm for a given pair of bodies
void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairId, Entity proxyShape1, Entity proxyShape2,
MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput) {
void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairIndex, MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput) {
RP3D_PROFILE("CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase()", mProfiler);
ProxyShape* shape1 = mProxyShapesComponents.getProxyShape(proxyShape1);
ProxyShape* shape2 = mProxyShapesComponents.getProxyShape(proxyShape2);
const Entity proxyShape1 = mOverlappingPairs.mProxyShapes1[pairIndex];
const Entity proxyShape2 = mOverlappingPairs.mProxyShapes2[pairIndex];
const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1);
const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2);
ProxyShape* shape1 = mProxyShapesComponents.mProxyShapes[proxyShape1Index];
ProxyShape* shape2 = mProxyShapesComponents.mProxyShapes[proxyShape2Index];
ProxyShape* convexProxyShape;
ProxyShape* concaveProxyShape;
ConvexShape* convexShape;
ConcaveShape* concaveShape;
const bool isShape1Convex = shape1->getCollisionShape()->isConvex();
const bool isShape1Convex = mOverlappingPairs.mIsShape1Convex[pairIndex];
// Collision shape 1 is convex, collision shape 2 is concave
if (isShape1Convex) {
convexProxyShape = shape1;
convexShape = static_cast<ConvexShape*>(shape1->getCollisionShape());
concaveProxyShape = shape2;
concaveShape = static_cast<ConcaveShape*>(shape2->getCollisionShape());
}
else { // Collision shape 2 is convex, collision shape 1 is concave
convexProxyShape = shape2;
convexShape = static_cast<ConvexShape*>(shape2->getCollisionShape());
concaveProxyShape = shape1;
concaveShape = static_cast<ConcaveShape*>(shape1->getCollisionShape());
}
// Select the narrow phase algorithm to use according to the two collision shapes
NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(convexShape->getType(),
CollisionShapeType::CONVEX_POLYHEDRON);
assert(mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex] != NarrowPhaseAlgorithmType::None);
assert(algorithmType != NarrowPhaseAlgorithmType::None);
Transform& shape1LocalToWorldTransform = mProxyShapesComponents.mLocalToWorldTransforms[proxyShape1Index];
Transform& shape2LocalToWorldTransform = mProxyShapesComponents.mLocalToWorldTransforms[proxyShape2Index];
// Compute the convex shape AABB in the local-space of the convex shape
const Transform convexToConcaveTransform = mProxyShapesComponents.getLocalToWorldTransform(concaveProxyShape->getEntity()).getInverse() *
mProxyShapesComponents.getLocalToWorldTransform(convexProxyShape->getEntity());
const Transform convexToConcaveTransform = (isShape1Convex ? shape2LocalToWorldTransform : shape1LocalToWorldTransform).getInverse() *
(isShape1Convex ? shape1LocalToWorldTransform : shape2LocalToWorldTransform);
AABB aabb;
convexShape->computeAABB(aabb, convexToConcaveTransform);
@ -463,11 +381,10 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairId,
#endif
// Create a narrow phase info for the narrow-phase collision detection
narrowPhaseInput.addNarrowPhaseTest(pairId, proxyShape1, proxyShape2, isShape1Convex ? convexShape : triangleShape,
narrowPhaseInput.addNarrowPhaseTest(mOverlappingPairs.mPairIds[pairIndex], pairIndex, proxyShape1, proxyShape2, isShape1Convex ? convexShape : triangleShape,
isShape1Convex ? triangleShape : convexShape,
mProxyShapesComponents.getLocalToWorldTransform(proxyShape1),
mProxyShapesComponents.getLocalToWorldTransform(proxyShape2),
algorithmType, allocator);
shape1LocalToWorldTransform, shape2LocalToWorldTransform,
mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex], allocator);
}
}

View File

@ -206,7 +206,7 @@ class CollisionDetectionSystem {
bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool reportContacts, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator);
/// Compute the concave vs convex middle-phase algorithm for a given pair of bodies
void computeConvexVsConcaveMiddlePhase(uint64 pairId, Entity proxyShape1, Entity proxyShape2, MemoryAllocator& allocator,
void computeConvexVsConcaveMiddlePhase(uint64 pairIndex, MemoryAllocator& allocator,
NarrowPhaseInput& narrowPhaseInput);
/// Swap the previous and current contacts lists
@ -358,6 +358,7 @@ class CollisionDetectionSystem {
friend class DynamicsWorld;
friend class ConvexMeshShape;
friend class RigidBody;
};
// Return a reference to the collision dispatch configuration