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 // Awake the body
setIsSleeping(false); 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 // Ask the broad-phase to test again the collision shapes of the body for collision
// detection (as if the body has moved) // detection (as if the body has moved)
askForBroadPhaseCollisionCheck(); askForBroadPhaseCollisionCheck();
@ -683,6 +686,9 @@ void RigidBody::setIsSleeping(bool isSleeping) {
// Notify all the components // Notify all the components
mWorld.setBodyDisabled(mEntity, isSleeping); mWorld.setBodyDisabled(mEntity, isSleeping);
// Update the currently overlapping pairs
updateOverlappingPairs();
if (isSleeping) { if (isSleeping) {
mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, Vector3::zero()); mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, Vector3::zero());
@ -696,6 +702,23 @@ void RigidBody::setIsSleeping(bool isSleeping) {
(isSleeping ? "true" : "false")); (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. /// Return the inverse of the inertia tensor in world coordinates.
const Matrix3x3 RigidBody::getInertiaTensorInverseWorld(CollisionWorld& world, Entity bodyEntity) { 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 /// Set the variable to know whether or not the body is sleeping
void setIsSleeping(bool isSleeping); 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. /// Return the inverse of the inertia tensor in world coordinates.
static const Matrix3x3 getInertiaTensorInverseWorld(CollisionWorld& world, Entity bodyEntity); 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 // 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) { const Transform& shape1Transform, const Transform& shape2Transform) {
assert(shape1->getType() == CollisionShapeType::CAPSULE); assert(shape1->getType() == CollisionShapeType::CAPSULE);
@ -60,7 +60,7 @@ void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Ent
isColliding.add(false); isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet) // 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); lastFrameCollisionInfos.add(lastFrameInfo);
} }

View File

@ -61,7 +61,7 @@ struct CapsuleVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
virtual ~CapsuleVsCapsuleNarrowPhaseInfoBatch() = default; virtual ~CapsuleVsCapsuleNarrowPhaseInfoBatch() = default;
/// Add shapes to be tested during narrow-phase collision detection into the batch /// 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, CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform); const Transform& shape2Transform);

View File

@ -48,7 +48,7 @@ NarrowPhaseInfoBatch::~NarrowPhaseInfoBatch() {
} }
// Add shapes to be tested during narrow-phase collision detection into the batch // 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, const Transform& shape1Transform, const Transform& shape2Transform,
MemoryAllocator& shapeAllocator) { MemoryAllocator& shapeAllocator) {
@ -64,7 +64,7 @@ void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity proxyShape1,
isColliding.add(false); isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet) // 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); lastFrameCollisionInfos.add(lastFrameInfo);
} }

View File

@ -103,7 +103,7 @@ struct NarrowPhaseInfoBatch {
uint getNbObjects() const; uint getNbObjects() const;
/// Add shapes to be tested during narrow-phase collision detection into the batch /// 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, CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform, MemoryAllocator& shapeAllocator); 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 // 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, const Transform& shape1Transform, const Transform& shape2Transform,
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, MemoryAllocator& shapeAllocator) { NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, MemoryAllocator& shapeAllocator) {
switch (narrowPhaseAlgorithmType) { switch (narrowPhaseAlgorithmType) {
case NarrowPhaseAlgorithmType::SphereVsSphere: case NarrowPhaseAlgorithmType::SphereVsSphere:
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
break; break;
case NarrowPhaseAlgorithmType::SphereVsCapsule: case NarrowPhaseAlgorithmType::SphereVsCapsule:
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
break; break;
case NarrowPhaseAlgorithmType::CapsuleVsCapsule: case NarrowPhaseAlgorithmType::CapsuleVsCapsule:
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform); mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, proxyShape1, proxyShape2, shape1, shape2, shape1Transform, shape2Transform);
break; break;
case NarrowPhaseAlgorithmType::SphereVsConvexPolyhedron: 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; break;
case NarrowPhaseAlgorithmType::CapsuleVsConvexPolyhedron: 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; break;
case NarrowPhaseAlgorithmType::ConvexPolyhedronVsConvexPolyhedron: 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; break;
case NarrowPhaseAlgorithmType::None: case NarrowPhaseAlgorithmType::None:
// Must never happen // Must never happen

View File

@ -67,7 +67,7 @@ class NarrowPhaseInput {
NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs); NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
/// Add shapes to be tested during narrow-phase collision detection into the batch /// 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, CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType,
MemoryAllocator& shapeAllocator); MemoryAllocator& shapeAllocator);

View File

@ -39,7 +39,7 @@ SphereVsCapsuleNarrowPhaseInfoBatch::SphereVsCapsuleNarrowPhaseInfoBatch(MemoryA
} }
// Add shapes to be tested during narrow-phase collision detection into the batch // 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) { const Transform& shape1Transform, const Transform& shape2Transform) {
bool isSphereShape1 = shape1->getType() == CollisionShapeType::SPHERE; bool isSphereShape1 = shape1->getType() == CollisionShapeType::SPHERE;
@ -63,7 +63,7 @@ void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Enti
isColliding.add(false); isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet) // 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); lastFrameCollisionInfos.add(lastFrameInfo);
} }

View File

@ -61,7 +61,7 @@ struct SphereVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
virtual ~SphereVsCapsuleNarrowPhaseInfoBatch() = default; virtual ~SphereVsCapsuleNarrowPhaseInfoBatch() = default;
/// Add shapes to be tested during narrow-phase collision detection into the batch /// 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, CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform); 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 // 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) { const Transform& shape1Transform, const Transform& shape2Transform) {
assert(shape1->getType() == CollisionShapeType::SPHERE); assert(shape1->getType() == CollisionShapeType::SPHERE);
@ -56,7 +56,7 @@ void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entit
isColliding.add(false); isColliding.add(false);
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet) // 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); lastFrameCollisionInfos.add(lastFrameInfo);
} }

View File

@ -55,7 +55,7 @@ struct SphereVsSphereNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
virtual ~SphereVsSphereNarrowPhaseInfoBatch() override = default; virtual ~SphereVsSphereNarrowPhaseInfoBatch() override = default;
/// Add shapes to be tested during narrow-phase collision detection into the batch /// 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, CollisionShape* shape2, const Transform& shape1Transform,
const Transform& shape2Transform); const Transform& shape2Transform);

View File

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

View File

@ -38,8 +38,9 @@ OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, M
CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, Set<bodypair> &noCollisionPairs, CollisionDispatch &collisionDispatch) CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, Set<bodypair> &noCollisionPairs, CollisionDispatch &collisionDispatch)
: mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator), : mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
mNbPairs(0), mConcavePairsStartIndex(0), mPairDataSize(sizeof(uint64) + sizeof(int32) + sizeof(int32) + sizeof(Entity) + mNbPairs(0), mConcavePairsStartIndex(0), mPairDataSize(sizeof(uint64) + sizeof(int32) + sizeof(int32) + sizeof(Entity) +
sizeof(Entity) + sizeof(Map<ShapeIdPair, LastFrameCollisionInfo*>) + sizeof(Entity) + sizeof(Map<uint64, LastFrameCollisionInfo*>) +
sizeof(bool) + sizeof(bool) + sizeof(NarrowPhaseAlgorithmType)), sizeof(bool) + sizeof(bool) + sizeof(NarrowPhaseAlgorithmType) +
sizeof(bool)),
mNbAllocatedPairs(0), mBuffer(nullptr), mNbAllocatedPairs(0), mBuffer(nullptr),
mMapPairIdToPairIndex(persistentMemoryAllocator), mMapPairIdToPairIndex(persistentMemoryAllocator),
mProxyShapeComponents(proxyShapeComponents), mCollisionBodyComponents(collisionBodyComponents), mProxyShapeComponents(proxyShapeComponents), mCollisionBodyComponents(collisionBodyComponents),
@ -205,10 +206,11 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
int32* newPairBroadPhaseId2 = reinterpret_cast<int32*>(newPairBroadPhaseId1 + nbPairsToAllocate); int32* newPairBroadPhaseId2 = reinterpret_cast<int32*>(newPairBroadPhaseId1 + nbPairsToAllocate);
Entity* newProxyShapes1 = reinterpret_cast<Entity*>(newPairBroadPhaseId2 + nbPairsToAllocate); Entity* newProxyShapes1 = reinterpret_cast<Entity*>(newPairBroadPhaseId2 + nbPairsToAllocate);
Entity* newProxyShapes2 = reinterpret_cast<Entity*>(newProxyShapes1 + 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* newNeedToTestOverlap = reinterpret_cast<bool*>(newLastFrameCollisionInfos + nbPairsToAllocate);
bool* newIsActive = reinterpret_cast<bool*>(newNeedToTestOverlap + nbPairsToAllocate); bool* newIsActive = reinterpret_cast<bool*>(newNeedToTestOverlap + nbPairsToAllocate);
NarrowPhaseAlgorithmType* newNarrowPhaseAlgorithmType = reinterpret_cast<NarrowPhaseAlgorithmType*>(newIsActive + nbPairsToAllocate); NarrowPhaseAlgorithmType* newNarrowPhaseAlgorithmType = reinterpret_cast<NarrowPhaseAlgorithmType*>(newIsActive + nbPairsToAllocate);
bool* newIsShape1Convex = reinterpret_cast<bool*>(newNarrowPhaseAlgorithmType + nbPairsToAllocate);
// If there was already pairs before // If there was already pairs before
if (mNbPairs > 0) { if (mNbPairs > 0) {
@ -219,10 +221,11 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
memcpy(newPairBroadPhaseId2, mPairBroadPhaseId2, mNbPairs * sizeof(int32)); memcpy(newPairBroadPhaseId2, mPairBroadPhaseId2, mNbPairs * sizeof(int32));
memcpy(newProxyShapes1, mProxyShapes1, mNbPairs * sizeof(Entity)); memcpy(newProxyShapes1, mProxyShapes1, mNbPairs * sizeof(Entity));
memcpy(newProxyShapes2, mProxyShapes2, 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(newNeedToTestOverlap, mNeedToTestOverlap, mNbPairs * sizeof(bool));
memcpy(newIsActive, mIsActive, mNbPairs * sizeof(bool)); memcpy(newIsActive, mIsActive, mNbPairs * sizeof(bool));
memcpy(newNarrowPhaseAlgorithmType, mNarrowPhaseAlgorithmType, mNbPairs * sizeof(NarrowPhaseAlgorithmType)); memcpy(newNarrowPhaseAlgorithmType, mNarrowPhaseAlgorithmType, mNbPairs * sizeof(NarrowPhaseAlgorithmType));
memcpy(newIsShape1Convex, mIsShape1Convex, mNbPairs * sizeof(bool));
// Deallocate previous memory // Deallocate previous memory
mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize); mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize);
@ -238,43 +241,57 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
mNeedToTestOverlap = newNeedToTestOverlap; mNeedToTestOverlap = newNeedToTestOverlap;
mIsActive = newIsActive; mIsActive = newIsActive;
mNarrowPhaseAlgorithmType = newNarrowPhaseAlgorithmType; mNarrowPhaseAlgorithmType = newNarrowPhaseAlgorithmType;
mIsShape1Convex = newIsShape1Convex;
mNbAllocatedPairs = nbPairsToAllocate; mNbAllocatedPairs = nbPairsToAllocate;
} }
// Add an overlapping pair // 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); RP3D_PROFILE("OverlappingPairs::addPair()", mProfiler);
const CollisionShape* collisionShape1 = mProxyShapeComponents.getCollisionShape(shape1->getEntity()); const CollisionShape* collisionShape1 = mProxyShapeComponents.getCollisionShape(shape1->getEntity());
const CollisionShape* collisionShape2 = mProxyShapeComponents.getCollisionShape(shape2->getEntity()); const CollisionShape* collisionShape2 = mProxyShapeComponents.getCollisionShape(shape2->getEntity());
// Prepare to add new pair (allocate memory if necessary and compute insertion index) const bool isShape1Convex = collisionShape1->isConvex();
uint64 index = prepareAddPair(collisionShape1->isConvex() && collisionShape2->isConvex()); const bool isShape2Convex = collisionShape2->isConvex();
const bool isConvexVsConvex = isShape1Convex && isShape2Convex;
const uint32 shape1Id = static_cast<uint32>(shape1->getBroadPhaseId()); // Prepare to add new pair (allocate memory if necessary and compute insertion index)
const uint32 shape2Id = static_cast<uint32>(shape2->getBroadPhaseId()); 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 // 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)); assert(!mMapPairIdToPairIndex.containsKey(pairId));
// Select the narrow phase algorithm to use according to the two collision shapes // Select the narrow phase algorithm to use according to the two collision shapes
NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(), NarrowPhaseAlgorithmType algorithmType;
collisionShape2->getType()); 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 // Insert the new component data
new (mPairIds + index) uint64(pairId); new (mPairIds + index) uint64(pairId);
new (mPairBroadPhaseId1 + index) int32(shape1->getBroadPhaseId()); new (mPairBroadPhaseId1 + index) int32(shape1->getBroadPhaseId());
new (mPairBroadPhaseId2 + index) int32(shape2->getBroadPhaseId()); new (mPairBroadPhaseId2 + index) int32(shape2->getBroadPhaseId());
new (mProxyShapes1 + index) Entity(shape1->getEntity()); new (mProxyShapes1 + index) Entity(shape1->getEntity());
new (mProxyShapes2 + index) Entity(shape2->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 (mNeedToTestOverlap + index) bool(false);
new (mIsActive + index) bool(isActive); new (mIsActive + index) bool(true);
new (mNarrowPhaseAlgorithmType + index) NarrowPhaseAlgorithmType(algorithmType); new (mNarrowPhaseAlgorithmType + index) NarrowPhaseAlgorithmType(algorithmType);
new (mIsShape1Convex + index) bool(isShape1Convex);
// Map the entity with the new component lookup index // Map the entity with the new component lookup index
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, 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(mConcavePairsStartIndex <= mNbPairs);
assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size())); assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
updateOverlappingPairIsActive(pairId);
return pairId; return pairId;
} }
@ -305,10 +324,11 @@ void OverlappingPairs::movePairToIndex(uint64 srcIndex, uint64 destIndex) {
mPairBroadPhaseId2[destIndex] = mPairBroadPhaseId2[srcIndex]; mPairBroadPhaseId2[destIndex] = mPairBroadPhaseId2[srcIndex];
new (mProxyShapes1 + destIndex) Entity(mProxyShapes1[srcIndex]); new (mProxyShapes1 + destIndex) Entity(mProxyShapes1[srcIndex]);
new (mProxyShapes2 + destIndex) Entity(mProxyShapes2[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]; mNeedToTestOverlap[destIndex] = mNeedToTestOverlap[srcIndex];
mIsActive[destIndex] = mIsActive[srcIndex]; mIsActive[destIndex] = mIsActive[srcIndex];
new (mNarrowPhaseAlgorithmType + destIndex) NarrowPhaseAlgorithmType(mNarrowPhaseAlgorithmType[srcIndex]); new (mNarrowPhaseAlgorithmType + destIndex) NarrowPhaseAlgorithmType(mNarrowPhaseAlgorithmType[srcIndex]);
mIsShape1Convex[destIndex] = mIsShape1Convex[srcIndex];
// Destroy the source pair // Destroy the source pair
destroyPair(srcIndex); destroyPair(srcIndex);
@ -330,10 +350,11 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
int32 pairBroadPhaseId2 = mPairBroadPhaseId2[index1]; int32 pairBroadPhaseId2 = mPairBroadPhaseId2[index1];
Entity proxyShape1 = mProxyShapes1[index1]; Entity proxyShape1 = mProxyShapes1[index1];
Entity proxyShape2 = mProxyShapes2[index1]; Entity proxyShape2 = mProxyShapes2[index1];
Map<ShapeIdPair, LastFrameCollisionInfo*> lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]); Map<uint64, LastFrameCollisionInfo*> lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]);
bool needTestOverlap = mNeedToTestOverlap[index1]; bool needTestOverlap = mNeedToTestOverlap[index1];
bool isActive = mIsActive[index1]; bool isActive = mIsActive[index1];
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType = mNarrowPhaseAlgorithmType[index1]; NarrowPhaseAlgorithmType narrowPhaseAlgorithmType = mNarrowPhaseAlgorithmType[index1];
bool isShape1Convex = mIsShape1Convex[index1];
// Destroy pair 1 // Destroy pair 1
destroyPair(index1); destroyPair(index1);
@ -346,10 +367,11 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
mPairBroadPhaseId2[index2] = pairBroadPhaseId2; mPairBroadPhaseId2[index2] = pairBroadPhaseId2;
new (mProxyShapes1 + index2) Entity(proxyShape1); new (mProxyShapes1 + index2) Entity(proxyShape1);
new (mProxyShapes2 + index2) Entity(proxyShape2); new (mProxyShapes2 + index2) Entity(proxyShape2);
new (mLastFrameCollisionInfos + index2) Map<ShapeIdPair, LastFrameCollisionInfo*>(lastFrameCollisionInfo); new (mLastFrameCollisionInfos + index2) Map<uint64, LastFrameCollisionInfo*>(lastFrameCollisionInfo);
mNeedToTestOverlap[index2] = needTestOverlap; mNeedToTestOverlap[index2] = needTestOverlap;
mIsActive[index2] = isActive; mIsActive[index2] = isActive;
new (mNarrowPhaseAlgorithmType + index2) NarrowPhaseAlgorithmType(narrowPhaseAlgorithmType); new (mNarrowPhaseAlgorithmType + index2) NarrowPhaseAlgorithmType(narrowPhaseAlgorithmType);
mIsShape1Convex[index2] = isShape1Convex;
// Update the pairID to pair index mapping // Update the pairID to pair index mapping
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index2)); mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index2));
@ -370,33 +392,60 @@ void OverlappingPairs::destroyPair(uint64 index) {
mProxyShapes1[index].~Entity(); mProxyShapes1[index].~Entity();
mProxyShapes2[index].~Entity(); mProxyShapes2[index].~Entity();
mLastFrameCollisionInfos[index].~Map<ShapeIdPair, LastFrameCollisionInfo*>(); mLastFrameCollisionInfos[index].~Map<uint64, LastFrameCollisionInfo*>();
mNarrowPhaseAlgorithmType[index].~NarrowPhaseAlgorithmType(); mNarrowPhaseAlgorithmType[index].~NarrowPhaseAlgorithmType();
} }
// Add a new last frame collision info if it does not exist for the given shapes already // Update whether a given overlapping pair is active or not
LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pairId, uint shapeId1, uint shapeId2) { void OverlappingPairs::updateOverlappingPairIsActive(uint64 pairId) {
RP3D_PROFILE("OverlappingPairs::addLastFrameInfoIfNecessary()", mProfiler);
assert(mMapPairIdToPairIndex.containsKey(pairId)); assert(mMapPairIdToPairIndex.containsKey(pairId));
const uint64 index = mMapPairIdToPairIndex[pairId]; const uint64 pairIndex = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs);
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 // 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 // If there is no collision info for those two shapes already
auto it = mLastFrameCollisionInfos[index].find(shapeIdPair); auto it = mLastFrameCollisionInfos[pairIndex].find(shapesId);
if (it == mLastFrameCollisionInfos[index].end()) { if (it == mLastFrameCollisionInfos[pairIndex].end()) {
// Create a new collision info // Create a new collision info
LastFrameCollisionInfo* collisionInfo = new (mPersistentAllocator.allocate(sizeof(LastFrameCollisionInfo))) LastFrameCollisionInfo* collisionInfo = new (mPersistentAllocator.allocate(sizeof(LastFrameCollisionInfo)))
LastFrameCollisionInfo(); LastFrameCollisionInfo();
// Add it into the map of collision infos // 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; 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 { class OverlappingPairs {
public:
// TODO : Try to use a pairing function like pairNumbers() here
using ShapeIdPair = Pair<uint, uint>;
private: private:
// -------------------- Constants -------------------- // // -------------------- Constants -------------------- //
@ -165,7 +160,7 @@ class OverlappingPairs {
/// If two convex shapes overlap, we have a single collision data but if one shape is concave, /// 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 /// we might have collision data for several overlapping triangles. The key in the map is the
/// shape Ids of the two collision shapes. /// 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 /// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
bool* mNeedToTestOverlap; bool* mNeedToTestOverlap;
@ -176,6 +171,9 @@ class OverlappingPairs {
/// Array with the pointer to the narrow-phase algorithm for each overlapping pair /// Array with the pointer to the narrow-phase algorithm for each overlapping pair
NarrowPhaseAlgorithmType* mNarrowPhaseAlgorithmType; NarrowPhaseAlgorithmType* mNarrowPhaseAlgorithmType;
/// True if the first shape of the pair is convex
bool* mIsShape1Convex;
/// Reference to the proxy-shapes components /// Reference to the proxy-shapes components
ProxyShapeComponents& mProxyShapeComponents; ProxyShapeComponents& mProxyShapeComponents;
@ -235,7 +233,7 @@ class OverlappingPairs {
OverlappingPairs& operator=(const OverlappingPairs& pair) = delete; OverlappingPairs& operator=(const OverlappingPairs& pair) = delete;
/// Add an overlapping pair /// 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 /// Remove a component at a given index
void removePair(uint64 pairId); void removePair(uint64 pairId);
@ -261,14 +259,20 @@ class OverlappingPairs {
/// Notify if a given pair is active or not /// Notify if a given pair is active or not
void setIsPairActive(uint64 pairId, bool isActive); 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 /// Return the last frame collision info
LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, ShapeIdPair& shapeIds); LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, uint64 shapesId);
/// Return a reference to the temporary memory allocator /// Return a reference to the temporary memory allocator
MemoryAllocator& getTemporaryAllocator(); MemoryAllocator& getTemporaryAllocator();
/// Add a new last frame collision info if it does not exist for the given shapes already /// 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 /// Delete all the obsolete last frame collision info
void clearObsoleteLastFrameCollisionInfos(); void clearObsoleteLastFrameCollisionInfos();
@ -276,9 +280,6 @@ class OverlappingPairs {
/// Return the pair of bodies index of the pair /// Return the pair of bodies index of the pair
static bodypair computeBodiesIndexPair(Entity body1Entity, Entity body2Entity); 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 /// Set if we need to test a given pair for overlap
void setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap); void setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap);
@ -317,14 +318,20 @@ inline void OverlappingPairs::setIsPairActive(uint64 pairId, bool isActive) {
mIsActive[mMapPairIdToPairIndex[pairId]] = 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 // 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)); assert(mMapPairIdToPairIndex.containsKey(pairId));
const uint64 index = mMapPairIdToPairIndex[pairId]; const uint64 index = mMapPairIdToPairIndex[pairId];
assert(index < mNbPairs); 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()) { if (it != mLastFrameCollisionInfos[index].end()) {
return it->second; return it->second;
} }

View File

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

View File

@ -206,7 +206,7 @@ class CollisionDetectionSystem {
bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool reportContacts, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator); bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool reportContacts, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator);
/// Compute the concave vs convex middle-phase algorithm for a given pair of bodies /// 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); NarrowPhaseInput& narrowPhaseInput);
/// Swap the previous and current contacts lists /// Swap the previous and current contacts lists
@ -358,6 +358,7 @@ class CollisionDetectionSystem {
friend class DynamicsWorld; friend class DynamicsWorld;
friend class ConvexMeshShape; friend class ConvexMeshShape;
friend class RigidBody;
}; };
// Return a reference to the collision dispatch configuration // Return a reference to the collision dispatch configuration