Refactoring

This commit is contained in:
Daniel Chappuis 2019-10-18 07:13:45 +02:00
parent 2c2b75def7
commit 130eb00136
10 changed files with 96 additions and 123 deletions

View File

@ -130,8 +130,7 @@ class DynamicAABBTreeRaycastCallback {
// Class DynamicAABBTree // Class DynamicAABBTree
/** /**
* This class implements a dynamic AABB tree that is used for broad-phase * This class implements a dynamic AABB tree that is used for broad-phase
* collision detection. This data structure is inspired by Nathanael Presson's * collision detection. The following implementation is
* dynamic tree implementation in BulletPhysics. The following implementation is
* based on the one from Erin Catto in Box2D as described in the book * based on the one from Erin Catto in Box2D as described in the book
* "Introduction to Game Physics with Box2D" by Ian Parberry. * "Introduction to Game Physics with Box2D" by Ian Parberry.
*/ */

View File

@ -536,7 +536,7 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
// Compute the contact points between two faces of two convex polyhedra. // Compute the contact points between two faces of two convex polyhedra.
if(computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1, polyhedron2, if(computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1, polyhedron2,
polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1, minFaceIndex, polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1, minFaceIndex,
narrowPhaseInfoBatch, batchIndex, minPenetrationDepth)) { narrowPhaseInfoBatch, batchIndex)) {
lastFrameCollisionInfo->satIsAxisFacePolyhedron1 = isMinPenetrationFaceNormalPolyhedron1; lastFrameCollisionInfo->satIsAxisFacePolyhedron1 = isMinPenetrationFaceNormalPolyhedron1;
lastFrameCollisionInfo->satIsAxisFacePolyhedron2 = !isMinPenetrationFaceNormalPolyhedron1; lastFrameCollisionInfo->satIsAxisFacePolyhedron2 = !isMinPenetrationFaceNormalPolyhedron1;
@ -576,7 +576,7 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
// Compute the contact points between two faces of two convex polyhedra. // Compute the contact points between two faces of two convex polyhedra.
if(computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1, polyhedron2, if(computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1, polyhedron2,
polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1, minFaceIndex, polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1, minFaceIndex,
narrowPhaseInfoBatch, batchIndex, minPenetrationDepth)) { narrowPhaseInfoBatch, batchIndex)) {
lastFrameCollisionInfo->satIsAxisFacePolyhedron1 = isMinPenetrationFaceNormalPolyhedron1; lastFrameCollisionInfo->satIsAxisFacePolyhedron1 = isMinPenetrationFaceNormalPolyhedron1;
lastFrameCollisionInfo->satIsAxisFacePolyhedron2 = !isMinPenetrationFaceNormalPolyhedron1; lastFrameCollisionInfo->satIsAxisFacePolyhedron2 = !isMinPenetrationFaceNormalPolyhedron1;
@ -804,7 +804,7 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
// Compute the contact points between two faces of two convex polyhedra. // Compute the contact points between two faces of two convex polyhedra.
bool contactsFound = computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1, bool contactsFound = computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1,
polyhedron2, polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1, polyhedron2, polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1,
minFaceIndex, narrowPhaseInfoBatch, batchIndex, minPenetrationDepth); minFaceIndex, narrowPhaseInfoBatch, batchIndex);
// There should be clipping points here. If it is not the case, it might be // There should be clipping points here. If it is not the case, it might be
// because of a numerical issue // because of a numerical issue
@ -877,8 +877,7 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
bool SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPenetrationFaceNormalPolyhedron1, bool SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPenetrationFaceNormalPolyhedron1,
const ConvexPolyhedronShape* polyhedron1, const ConvexPolyhedronShape* polyhedron2, const ConvexPolyhedronShape* polyhedron1, const ConvexPolyhedronShape* polyhedron2,
const Transform& polyhedron1ToPolyhedron2, const Transform& polyhedron2ToPolyhedron1, const Transform& polyhedron1ToPolyhedron2, const Transform& polyhedron2ToPolyhedron1,
uint minFaceIndex, NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex, uint minFaceIndex, NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex) const {
decimal minPenetrationDepth) const {
RP3D_PROFILE("SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints", mProfiler); RP3D_PROFILE("SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints", mProfiler);
@ -887,8 +886,6 @@ bool SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPene
const Transform& referenceToIncidentTransform = isMinPenetrationFaceNormalPolyhedron1 ? polyhedron1ToPolyhedron2 : polyhedron2ToPolyhedron1; const Transform& referenceToIncidentTransform = isMinPenetrationFaceNormalPolyhedron1 ? polyhedron1ToPolyhedron2 : polyhedron2ToPolyhedron1;
const Transform& incidentToReferenceTransform = isMinPenetrationFaceNormalPolyhedron1 ? polyhedron2ToPolyhedron1 : polyhedron1ToPolyhedron2; const Transform& incidentToReferenceTransform = isMinPenetrationFaceNormalPolyhedron1 ? polyhedron2ToPolyhedron1 : polyhedron1ToPolyhedron2;
assert(minPenetrationDepth > decimal(0.0));
const Vector3 axisReferenceSpace = referencePolyhedron->getFaceNormal(minFaceIndex); const Vector3 axisReferenceSpace = referencePolyhedron->getFaceNormal(minFaceIndex);
const Vector3 axisIncidentSpace = referenceToIncidentTransform.getOrientation() * axisReferenceSpace; const Vector3 axisIncidentSpace = referenceToIncidentTransform.getOrientation() * axisReferenceSpace;

View File

@ -132,7 +132,7 @@ class SATAlgorithm {
bool computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPenetrationFaceNormalPolyhedron1, const ConvexPolyhedronShape* polyhedron1, bool computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPenetrationFaceNormalPolyhedron1, const ConvexPolyhedronShape* polyhedron1,
const ConvexPolyhedronShape* polyhedron2, const Transform& polyhedron1ToPolyhedron2, const ConvexPolyhedronShape* polyhedron2, const Transform& polyhedron1ToPolyhedron2,
const Transform& polyhedron2ToPolyhedron1, uint minFaceIndex, const Transform& polyhedron2ToPolyhedron1, uint minFaceIndex,
NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex, decimal minPenetrationDepth) const; NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex) const;
public : public :

View File

@ -405,7 +405,7 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) {
if (!jointInfo.isCollisionEnabled) { if (!jointInfo.isCollisionEnabled) {
// Add the pair of bodies in the set of body pairs that cannot collide with each other // Add the pair of bodies in the set of body pairs that cannot collide with each other
mCollisionDetection.addNoCollisionPair(jointInfo.body1, jointInfo.body2); mCollisionDetection.addNoCollisionPair(jointInfo.body1->getEntity(), jointInfo.body2->getEntity());
} }
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Joint, RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Joint,
@ -435,7 +435,7 @@ void DynamicsWorld::destroyJoint(Joint* joint) {
if (!joint->isCollisionEnabled()) { if (!joint->isCollisionEnabled()) {
// Remove the pair of bodies from the set of body pairs that cannot collide with each other // Remove the pair of bodies from the set of body pairs that cannot collide with each other
mCollisionDetection.removeNoCollisionPair(joint->getBody1(), joint->getBody2()); mCollisionDetection.removeNoCollisionPair(joint->getBody1()->getEntity(), joint->getBody2()->getEntity());
} }
RigidBody* body1 = joint->getBody1(); RigidBody* body1 = joint->getBody1();

View File

@ -35,7 +35,7 @@ using namespace reactphysics3d;
OverlappingPair::OverlappingPair(ProxyShape* shape1, ProxyShape* shape2, OverlappingPair::OverlappingPair(ProxyShape* shape1, ProxyShape* shape2,
MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator, MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator,
const WorldSettings& worldSettings) const WorldSettings& worldSettings)
: mPairID(computeID(shape1->getBroadPhaseId(), shape2->getBroadPhaseId())), mProxyShape1(shape1), mProxyShape2(shape2), : mPairID(computeID(shape1->getBroadPhaseId(), shape2->getBroadPhaseId())), mProxyShape1(shape1->getEntity()), mProxyShape2(shape2->getEntity()),
mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator), mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
mLastFrameCollisionInfos(mPersistentAllocator), mWorldSettings(worldSettings) { mLastFrameCollisionInfos(mPersistentAllocator), mWorldSettings(worldSettings) {
@ -99,16 +99,12 @@ void OverlappingPair::clearObsoleteLastFrameCollisionInfos() {
it = mLastFrameCollisionInfos.remove(it); it = mLastFrameCollisionInfos.remove(it);
} }
else { else { // If the collision info is not obsolete
// Do not delete it but mark it as obsolete
it->second->isObsolete = true;
++it; ++it;
} }
} }
} }
// Make all the last frame collision infos obsolete
void OverlappingPair::makeLastFrameCollisionInfosObsolete() {
for (auto it = mLastFrameCollisionInfos.begin(); it != mLastFrameCollisionInfos.end(); ++it) {
it->second->isObsolete = true;
}
}

View File

@ -109,9 +109,11 @@ class OverlappingPair {
/// Pair ID /// Pair ID
OverlappingPairId mPairID; OverlappingPairId mPairID;
// TODO : Replace this by entities /// Entity of the first proxy-shape of the overlapping pair
ProxyShape* mProxyShape1; Entity mProxyShape1;
ProxyShape* mProxyShape2;
/// Entity of the second proxy-shape of the overlapping pair
Entity mProxyShape2;
/// Persistent memory allocator /// Persistent memory allocator
MemoryAllocator& mPersistentAllocator; MemoryAllocator& mPersistentAllocator;
@ -149,11 +151,11 @@ class OverlappingPair {
/// Return the Id of the pair /// Return the Id of the pair
OverlappingPairId getId() const; OverlappingPairId getId() const;
/// Return the pointer to first proxy collision shape /// Return the entity of the first proxy-shape
ProxyShape* getShape1() const; Entity getProxyShape1() const;
/// Return the pointer to second body /// Return the entity of the second proxy-shape
ProxyShape* getShape2() const; Entity getProxyShape2() const;
/// Return the last frame collision info /// Return the last frame collision info
LastFrameCollisionInfo* getLastFrameCollisionInfo(ShapeIdPair& shapeIds); LastFrameCollisionInfo* getLastFrameCollisionInfo(ShapeIdPair& shapeIds);
@ -161,9 +163,6 @@ class OverlappingPair {
/// Return a reference to the temporary memory allocator /// Return a reference to the temporary memory allocator
MemoryAllocator& getTemporaryAllocator(); MemoryAllocator& getTemporaryAllocator();
/// Return true if one of the shapes of the pair is a concave shape
bool hasConcaveShape() const;
/// 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(uint shapeId1, uint shapeId2); LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint shapeId1, uint shapeId2);
@ -173,14 +172,11 @@ class OverlappingPair {
/// Delete all the obsolete last frame collision info /// Delete all the obsolete last frame collision info
void clearObsoleteLastFrameCollisionInfos(); void clearObsoleteLastFrameCollisionInfos();
/// Make all the last frame collision infos obsolete
void makeLastFrameCollisionInfosObsolete();
/// Return the pair of bodies index /// Return the pair of bodies index
static OverlappingPairId computeID(int shape1BroadPhaseId, int shape2BroadPhaseId); static OverlappingPairId computeID(int shape1BroadPhaseId, int shape2BroadPhaseId);
/// Return the pair of bodies index of the pair /// Return the pair of bodies index of the pair
static bodypair computeBodiesIndexPair(CollisionBody* body1, CollisionBody* body2); static bodypair computeBodiesIndexPair(Entity body1Entity, Entity body2Entity);
// -------------------- Friendship -------------------- // // -------------------- Friendship -------------------- //
@ -192,13 +188,13 @@ inline OverlappingPair::OverlappingPairId OverlappingPair::getId() const {
return mPairID; return mPairID;
} }
// Return the pointer to first body // Return the entity of the first proxy-shape
inline ProxyShape* OverlappingPair::getShape1() const { inline Entity OverlappingPair::getProxyShape1() const {
return mProxyShape1; return mProxyShape1;
} }
// Return the pointer to second body // Return the entity of the second proxy-shape
inline ProxyShape* OverlappingPair::getShape2() const { inline Entity OverlappingPair::getProxyShape2() const {
return mProxyShape2; return mProxyShape2;
} }
@ -225,13 +221,12 @@ inline OverlappingPair::OverlappingPairId OverlappingPair::computeID(int shape1B
} }
// Return the pair of bodies index // Return the pair of bodies index
inline bodypair OverlappingPair::computeBodiesIndexPair(CollisionBody* body1, inline bodypair OverlappingPair::computeBodiesIndexPair(Entity body1Entity, Entity body2Entity) {
CollisionBody* body2) {
// Construct the pair of body index // Construct the pair of body index
bodypair indexPair = body1->getEntity().id < body2->getEntity().id ? bodypair indexPair = body1Entity.id < body2Entity.id ?
bodypair(body1->getEntity(), body2->getEntity()) : bodypair(body1Entity, body2Entity) :
bodypair(body2->getEntity(), body1->getEntity()); bodypair(body2Entity, body1Entity);
assert(indexPair.first != indexPair.second); assert(indexPair.first != indexPair.second);
return indexPair; return indexPair;
} }
@ -241,12 +236,6 @@ inline MemoryAllocator& OverlappingPair::getTemporaryAllocator() {
return mTempMemoryAllocator; return mTempMemoryAllocator;
} }
// Return true if one of the shapes of the pair is a concave shape
inline bool OverlappingPair::hasConcaveShape() const {
return !getShape1()->getCollisionShape()->isConvex() ||
!getShape2()->getCollisionShape()->isConvex();
}
// Return the last frame collision info for a given pair of shape ids // Return the last frame collision info for a given pair of shape ids
inline LastFrameCollisionInfo* OverlappingPair::getLastFrameCollisionInfo(uint shapeId1, uint shapeId2) const { inline LastFrameCollisionInfo* OverlappingPair::getLastFrameCollisionInfo(uint shapeId1, uint shapeId2) const {
return mLastFrameCollisionInfos[ShapeIdPair(shapeId1, shapeId2)]; return mLastFrameCollisionInfos[ShapeIdPair(shapeId1, shapeId2)];

View File

@ -51,14 +51,16 @@ BroadPhaseSystem::BroadPhaseSystem(CollisionDetectionSystem& collisionDetection,
} }
// Return true if the two broad-phase collision shapes are overlapping // Return true if the two broad-phase collision shapes are overlapping
// TODO : Use proxy-shape entities in parameters bool BroadPhaseSystem::testOverlappingShapes(Entity proxyShape1Entity, Entity proxyShape2Entity) const {
bool BroadPhaseSystem::testOverlappingShapes(const ProxyShape* shape1, const ProxyShape* shape2) const {
if (shape1->getBroadPhaseId() == -1 || shape2->getBroadPhaseId() == -1) return false; const int32 shape1BroadPhaseId = mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity);
const int32 shape2BroadPhaseId = mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity);
if (shape1BroadPhaseId == -1 || shape2BroadPhaseId == -1) return false;
// Get the two AABBs of the collision shapes // Get the two AABBs of the collision shapes
const AABB& aabb1 = mDynamicAABBTree.getFatAABB(shape1->getBroadPhaseId()); const AABB& aabb1 = mDynamicAABBTree.getFatAABB(shape1BroadPhaseId);
const AABB& aabb2 = mDynamicAABBTree.getFatAABB(shape2->getBroadPhaseId()); const AABB& aabb2 = mDynamicAABBTree.getFatAABB(shape2BroadPhaseId);
// Check if the two AABBs are overlapping // Check if the two AABBs are overlapping
return aabb1.testCollision(aabb2); return aabb1.testCollision(aabb2);

View File

@ -189,7 +189,7 @@ class BroadPhaseSystem {
ProxyShape* getProxyShapeForBroadPhaseId(int broadPhaseId) const; ProxyShape* getProxyShapeForBroadPhaseId(int broadPhaseId) const;
/// Return true if the two broad-phase collision shapes are overlapping /// Return true if the two broad-phase collision shapes are overlapping
bool testOverlappingShapes(const ProxyShape* shape1, const ProxyShape* shape2) const; bool testOverlappingShapes(Entity proxyShape1Entity, Entity proxyShape2Entity) const;
/// Return the fat AABB of a given broad-phase shape /// Return the fat AABB of a given broad-phase shape
const AABB& getFatAABB(int broadPhaseId) const; const AABB& getFatAABB(int broadPhaseId) const;

View File

@ -82,7 +82,7 @@ CollisionDetectionSystem::CollisionDetectionSystem(CollisionWorld* world, ProxyS
// Compute the collision detection // Compute the collision detection
void CollisionDetectionSystem::computeCollisionDetection() { void CollisionDetectionSystem::computeCollisionDetection() {
RP3D_PROFILE("CollisionDetection::computeCollisionDetection()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::computeCollisionDetection()", mProfiler);
// Compute the broad-phase collision detection // Compute the broad-phase collision detection
computeBroadPhase(); computeBroadPhase();
@ -97,7 +97,7 @@ void CollisionDetectionSystem::computeCollisionDetection() {
// Compute the broad-phase collision detection // Compute the broad-phase collision detection
void CollisionDetectionSystem::computeBroadPhase() { void CollisionDetectionSystem::computeBroadPhase() {
RP3D_PROFILE("CollisionDetection::computeBroadPhase()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::computeBroadPhase()", mProfiler);
// Ask the broad-phase to compute all the shapes overlapping the shapes that // Ask the broad-phase to compute all the shapes overlapping the shapes that
// have moved or have been added in the last frame. This call can only add new // have moved or have been added in the last frame. This call can only add new
@ -120,11 +120,8 @@ void CollisionDetectionSystem::removeNonOverlappingPairs() {
OverlappingPair* pair = it->second; OverlappingPair* pair = it->second;
ProxyShape* shape1 = pair->getShape1();
ProxyShape* shape2 = pair->getShape2();
// Check if the two shapes are still overlapping. Otherwise, we destroy the overlapping pair // Check if the two shapes are still overlapping. Otherwise, we destroy the overlapping pair
if (!mBroadPhaseSystem.testOverlappingShapes(shape1, shape2)) { if (!mBroadPhaseSystem.testOverlappingShapes(pair->getProxyShape1(), pair->getProxyShape2())) {
// Destroy the overlapping pair // Destroy the overlapping pair
pair->~OverlappingPair(); pair->~OverlappingPair();
@ -154,12 +151,12 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int, int>>
if (nodePair.first != nodePair.second) { if (nodePair.first != nodePair.second) {
// Get the two proxy-shapes // Get the two proxy-shapes
Entity proxyShape1Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.first]; const Entity proxyShape1Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.first];
Entity proxyShape2Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.second]; const Entity proxyShape2Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.second];
// Get the two bodies // Get the two bodies
Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity); const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity); const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
// If the two proxy collision shapes are from the same body, skip it // If the two proxy collision shapes are from the same body, skip it
if (body1Entity != body2Entity) { if (body1Entity != body2Entity) {
@ -212,14 +209,11 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairMap& overlappin
OverlappingPair* pair = it->second; OverlappingPair* pair = it->second;
// Make all the last frame collision info obsolete // Remove the obsolete last frame collision infos and mark all the others as obsolete
pair->makeLastFrameCollisionInfosObsolete(); pair->clearObsoleteLastFrameCollisionInfos();
const Entity proxyShape1Entity = pair->getShape1()->getEntity(); const Entity proxyShape1Entity = pair->getProxyShape1();
const Entity proxyShape2Entity = pair->getShape2()->getEntity(); const Entity proxyShape2Entity = pair->getProxyShape2();
ProxyShape* shape1 = pair->getShape1();
ProxyShape* shape2 = pair->getShape2();
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1); assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != -1);
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1); assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
@ -229,11 +223,8 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairMap& overlappin
if ((mProxyShapesComponents.getCollideWithMaskBits(proxyShape1Entity) & mProxyShapesComponents.getCollisionCategoryBits(proxyShape2Entity)) != 0 && if ((mProxyShapesComponents.getCollideWithMaskBits(proxyShape1Entity) & mProxyShapesComponents.getCollisionCategoryBits(proxyShape2Entity)) != 0 &&
(mProxyShapesComponents.getCollisionCategoryBits(proxyShape1Entity) & mProxyShapesComponents.getCollideWithMaskBits(proxyShape2Entity)) != 0) { (mProxyShapesComponents.getCollisionCategoryBits(proxyShape1Entity) & mProxyShapesComponents.getCollideWithMaskBits(proxyShape2Entity)) != 0) {
CollisionBody* const body1 = shape1->getBody(); const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
CollisionBody* const body2 = shape2->getBody(); const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
const Entity body1Entity = body1->getEntity();
const Entity body2Entity = body2->getEntity();
const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) && const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) &&
mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC; mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
@ -246,22 +237,25 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairMap& overlappin
if (!isBody1Active && !isBody2Active) continue; if (!isBody1Active && !isBody2Active) continue;
// Check if the bodies are in the set of bodies that cannot collide between each other // Check if the bodies are in the set of bodies that cannot collide between each other
bodypair bodiesIndex = OverlappingPair::computeBodiesIndexPair(body1, body2); bodypair bodiesIndex = OverlappingPair::computeBodiesIndexPair(body1Entity, body2Entity);
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue; if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
bool isShape1Convex = shape1->getCollisionShape()->isConvex(); CollisionShape* collisionShape1 = mProxyShapesComponents.getCollisionShape(proxyShape1Entity);
bool isShape2Convex = shape2->getCollisionShape()->isConvex(); CollisionShape* collisionShape2 = mProxyShapesComponents.getCollisionShape(proxyShape2Entity);
const bool isShape1Convex = collisionShape1->isConvex();
const bool isShape2Convex = collisionShape2->isConvex();
// If both shapes are convex // If both shapes are convex
if (isShape1Convex && isShape2Convex) { if (isShape1Convex && isShape2Convex) {
// 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(shape1->getCollisionShape()->getType(), NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(),
shape2->getCollisionShape()->getType()); collisionShape2->getType());
// 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(pair, shape1->getCollisionShape(), shape2->getCollisionShape(), narrowPhaseInput.addNarrowPhaseTest(pair, collisionShape1, collisionShape2,
mProxyShapesComponents.getLocalToWorldTransform(proxyShape1Entity), mProxyShapesComponents.getLocalToWorldTransform(proxyShape1Entity),
mProxyShapesComponents.getLocalToWorldTransform(proxyShape2Entity), mProxyShapesComponents.getLocalToWorldTransform(proxyShape2Entity),
algorithmType, mMemoryManager.getSingleFrameAllocator()); algorithmType, mMemoryManager.getSingleFrameAllocator());
@ -277,9 +271,6 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairMap& overlappin
// Not handled // Not handled
continue; continue;
} }
// Remove the obsolete last frame collision infos
pair->clearObsoleteLastFrameCollisionInfos();
} }
} }
} }
@ -288,10 +279,10 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairMap& overlappin
void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, MemoryAllocator& allocator, void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, MemoryAllocator& allocator,
NarrowPhaseInput& narrowPhaseInput) { NarrowPhaseInput& narrowPhaseInput) {
RP3D_PROFILE("CollisionDetection::computeConvexVsConcaveMiddlePhase()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase()", mProfiler);
ProxyShape* shape1 = pair->getShape1(); ProxyShape* shape1 = mProxyShapesComponents.getProxyShape(pair->getProxyShape1());
ProxyShape* shape2 = pair->getShape2(); ProxyShape* shape2 = mProxyShapesComponents.getProxyShape(pair->getProxyShape2());
ProxyShape* convexProxyShape; ProxyShape* convexProxyShape;
ProxyShape* concaveProxyShape; ProxyShape* concaveProxyShape;
@ -350,7 +341,7 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(OverlappingPair
#endif #endif
bool isShape1Convex = pair->getShape1()->getCollisionShape()->isConvex(); bool isShape1Convex = mProxyShapesComponents.getCollisionShape(pair->getProxyShape1())->isConvex();
ProxyShape* shape1 = isShape1Convex ? convexProxyShape : concaveProxyShape; ProxyShape* shape1 = isShape1Convex ? convexProxyShape : concaveProxyShape;
ProxyShape* shape2 = isShape1Convex ? concaveProxyShape : convexProxyShape; ProxyShape* shape2 = isShape1Convex ? concaveProxyShape : convexProxyShape;
@ -445,7 +436,7 @@ void CollisionDetectionSystem::processAllPotentialContacts(NarrowPhaseInput& nar
// Compute the narrow-phase collision detection // Compute the narrow-phase collision detection
void CollisionDetectionSystem::computeNarrowPhase() { void CollisionDetectionSystem::computeNarrowPhase() {
RP3D_PROFILE("CollisionDetection::computeNarrowPhase()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::computeNarrowPhase()", mProfiler);
MemoryAllocator& allocator = mMemoryManager.getSingleFrameAllocator(); MemoryAllocator& allocator = mMemoryManager.getSingleFrameAllocator();
@ -475,7 +466,7 @@ void CollisionDetectionSystem::computeNarrowPhase() {
/// This method returns true if contacts are found. /// This method returns true if contacts are found.
bool CollisionDetectionSystem::computeNarrowPhaseOverlapSnapshot(NarrowPhaseInput& narrowPhaseInput, OverlapCallback* callback) { bool CollisionDetectionSystem::computeNarrowPhaseOverlapSnapshot(NarrowPhaseInput& narrowPhaseInput, OverlapCallback* callback) {
RP3D_PROFILE("CollisionDetection::computeNarrowPhaseOverlapSnapshot()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::computeNarrowPhaseOverlapSnapshot()", mProfiler);
MemoryAllocator& allocator = mMemoryManager.getPoolAllocator(); MemoryAllocator& allocator = mMemoryManager.getPoolAllocator();
@ -518,7 +509,7 @@ void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInput& nar
// Convert the potential overlapping bodies for the testOverlap() methods // Convert the potential overlapping bodies for the testOverlap() methods
void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) const { void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) const {
RP3D_PROFILE("CollisionDetection::computeSnapshotContactPairs()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::computeSnapshotContactPairs()", mProfiler);
// For each narrow phase info object // For each narrow phase info object
for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) { for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) {
@ -527,8 +518,8 @@ void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInfoBatch&
if (narrowPhaseInfoBatch.isColliding[i]) { if (narrowPhaseInfoBatch.isColliding[i]) {
// Add the pair of bodies in contact into the list // Add the pair of bodies in contact into the list
overlapPairs.add(Pair<Entity, Entity>(narrowPhaseInfoBatch.overlappingPairs[i]->getShape1()->getBody()->getEntity(), overlapPairs.add(Pair<Entity, Entity>(mProxyShapesComponents.getBody(narrowPhaseInfoBatch.overlappingPairs[i]->getProxyShape1()),
narrowPhaseInfoBatch.overlappingPairs[i]->getShape2()->getBody()->getEntity())); mProxyShapesComponents.getBody(narrowPhaseInfoBatch.overlappingPairs[i]->getProxyShape2())));
} }
narrowPhaseInfoBatch.resetContactPoints(i); narrowPhaseInfoBatch.resetContactPoints(i);
@ -539,7 +530,7 @@ void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInfoBatch&
// This method returns true if contacts are found. // This method returns true if contacts are found.
bool CollisionDetectionSystem::computeNarrowPhaseCollisionSnapshot(NarrowPhaseInput& narrowPhaseInput, CollisionCallback& callback) { bool CollisionDetectionSystem::computeNarrowPhaseCollisionSnapshot(NarrowPhaseInput& narrowPhaseInput, CollisionCallback& callback) {
RP3D_PROFILE("CollisionDetection::computeNarrowPhaseCollisionSnapshot()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::computeNarrowPhaseCollisionSnapshot()", mProfiler);
MemoryAllocator& allocator = mMemoryManager.getPoolAllocator(); MemoryAllocator& allocator = mMemoryManager.getPoolAllocator();
@ -675,7 +666,7 @@ void CollisionDetectionSystem::createSnapshotContacts(List<ContactPair>& contact
List<ContactManifoldInfo>& potentialContactManifolds, List<ContactManifoldInfo>& potentialContactManifolds,
List<ContactPointInfo>& potentialContactPoints) { List<ContactPointInfo>& potentialContactPoints) {
RP3D_PROFILE("CollisionDetection::createSnapshotContacts()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::createSnapshotContacts()", mProfiler);
contactManifolds.reserve(contactPairs.size()); contactManifolds.reserve(contactPairs.size());
contactPoints.reserve(contactManifolds.size()); contactPoints.reserve(contactManifolds.size());
@ -830,8 +821,8 @@ void CollisionDetectionSystem::removeProxyCollisionShape(ProxyShape* proxyShape)
OverlappingPair* pair = it->second; OverlappingPair* pair = it->second;
if (pair->getShape1()->getBroadPhaseId() == proxyShape->getBroadPhaseId()|| if (mProxyShapesComponents.getBroadPhaseId(pair->getProxyShape1()) == proxyShape->getBroadPhaseId() ||
pair->getShape2()->getBroadPhaseId() == proxyShape->getBroadPhaseId()) { mProxyShapesComponents.getBroadPhaseId(pair->getProxyShape2()) == proxyShape->getBroadPhaseId()) {
// TODO : Remove all the contact manifold of the overlapping pair from the contact manifolds list of the two bodies involved // TODO : Remove all the contact manifold of the overlapping pair from the contact manifolds list of the two bodies involved
@ -856,7 +847,7 @@ void CollisionDetectionSystem::raycast(RaycastCallback* raycastCallback,
const Ray& ray, const Ray& ray,
unsigned short raycastWithCategoryMaskBits) const { unsigned short raycastWithCategoryMaskBits) const {
RP3D_PROFILE("CollisionDetection::raycast()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::raycast()", mProfiler);
RaycastTest rayCastTest(raycastCallback); RaycastTest rayCastTest(raycastCallback);
@ -873,7 +864,7 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
List<ContactPair>* contactPairs, List<ContactPair>* contactPairs,
Map<Entity, List<uint>>& mapBodyToContactPairs) { Map<Entity, List<uint>>& mapBodyToContactPairs) {
RP3D_PROFILE("CollisionDetection::processPotentialContacts()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::processPotentialContacts()", mProfiler);
// For each narrow phase info object // For each narrow phase info object
for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) { for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) {
@ -952,16 +943,18 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
// If the overlapping pair contact does not exists yet // If the overlapping pair contact does not exists yet
if (pairContact == nullptr) { if (pairContact == nullptr) {
Entity body1Entity = narrowPhaseInfoBatch.overlappingPairs[i]->getShape1()->getBody()->getEntity(); const Entity proxyShape1Entity = narrowPhaseInfoBatch.overlappingPairs[i]->getProxyShape1();
Entity body2Entity = narrowPhaseInfoBatch.overlappingPairs[i]->getShape2()->getBody()->getEntity(); const Entity proxyShape2Entity = narrowPhaseInfoBatch.overlappingPairs[i]->getProxyShape2();
const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
assert(!mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) || !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity)); assert(!mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) || !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity));
// TODO : We should probably use a single frame allocator here // TODO : We should probably use a single frame allocator here
const uint newContactPairIndex = contactPairs->size(); const uint newContactPairIndex = contactPairs->size();
ContactPair overlappingPairContact(pairId, body1Entity, body2Entity, ContactPair overlappingPairContact(pairId, body1Entity, body2Entity,
narrowPhaseInfoBatch.overlappingPairs[i]->getShape1()->getEntity(), proxyShape1Entity, proxyShape2Entity,
narrowPhaseInfoBatch.overlappingPairs[i]->getShape2()->getEntity(),
newContactPairIndex, mMemoryManager.getPoolAllocator()); newContactPairIndex, mMemoryManager.getPoolAllocator());
contactPairs->add(overlappingPairContact); contactPairs->add(overlappingPairContact);
pairContact = &((*contactPairs)[newContactPairIndex]); pairContact = &((*contactPairs)[newContactPairIndex]);
@ -1010,7 +1003,7 @@ void CollisionDetectionSystem::reducePotentialContactManifolds(List<ContactPair>
List<ContactManifoldInfo>& potentialContactManifolds, List<ContactManifoldInfo>& potentialContactManifolds,
const List<ContactPointInfo>& potentialContactPoints) const { const List<ContactPointInfo>& potentialContactPoints) const {
RP3D_PROFILE("CollisionDetection::reducePotentialContactManifolds()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::reducePotentialContactManifolds()", mProfiler);
// Reduce the number of potential contact manifolds in a contact pair // Reduce the number of potential contact manifolds in a contact pair
for (uint i=0; i < contactPairs->size(); i++) { for (uint i=0; i < contactPairs->size(); i++) {
@ -1057,7 +1050,7 @@ void CollisionDetectionSystem::reducePotentialContactManifolds(List<ContactPair>
// If there are two many contact points in the manifold // If there are two many contact points in the manifold
if (manifold.potentialContactPointsIndices.size() > MAX_CONTACT_POINTS_IN_MANIFOLD) { if (manifold.potentialContactPointsIndices.size() > MAX_CONTACT_POINTS_IN_MANIFOLD) {
Transform shape1LocalToWorldTransoform = mOverlappingPairs[manifold.pairId]->getShape1()->getLocalToWorldTransform(); Transform shape1LocalToWorldTransoform = mProxyShapesComponents.getLocalToWorldTransform(mOverlappingPairs[manifold.pairId]->getProxyShape1());
// Reduce the number of contact points in the manifold // Reduce the number of contact points in the manifold
reduceContactPoints(manifold, shape1LocalToWorldTransoform, potentialContactPoints); reduceContactPoints(manifold, shape1LocalToWorldTransoform, potentialContactPoints);
@ -1280,7 +1273,7 @@ void CollisionDetectionSystem::reportContacts() {
void CollisionDetectionSystem::reportContacts(CollisionCallback& callback, List<ContactPair>* contactPairs, void CollisionDetectionSystem::reportContacts(CollisionCallback& callback, List<ContactPair>* contactPairs,
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints) { List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints) {
RP3D_PROFILE("CollisionDetection::reportContacts()", mProfiler); RP3D_PROFILE("CollisionDetectionSystem::reportContacts()", mProfiler);
// If there are contacts // If there are contacts
if (contactPairs->size() > 0) { if (contactPairs->size() > 0) {
@ -1420,12 +1413,12 @@ void CollisionDetectionSystem::filterOverlappingPairs(Entity bodyEntity, Overlap
OverlappingPair* pair = it->second; OverlappingPair* pair = it->second;
if (pair->getShape1()->getBody()->getEntity() == bodyEntity || pair->getShape2()->getBody()->getEntity() == bodyEntity) { if (mProxyShapesComponents.getBody(pair->getProxyShape1()) == bodyEntity ||
mProxyShapesComponents.getBody(pair->getProxyShape2()) == bodyEntity) {
outFilteredPairs.add(Pair<Pair<uint, uint>, OverlappingPair*>(it->first, pair)); outFilteredPairs.add(Pair<Pair<uint, uint>, OverlappingPair*>(it->first, pair));
} }
} }
} }
// Filter the overlapping pairs to keep only the pairs where two given bodies are involved // Filter the overlapping pairs to keep only the pairs where two given bodies are involved
@ -1436,13 +1429,12 @@ void CollisionDetectionSystem::filterOverlappingPairs(Entity body1Entity, Entity
OverlappingPair* pair = it->second; OverlappingPair* pair = it->second;
if ((pair->getShape1()->getBody()->getEntity() == body1Entity && pair->getShape2()->getBody()->getEntity() == body2Entity) || if ((mProxyShapesComponents.getBody(pair->getProxyShape1()) == body1Entity && mProxyShapesComponents.getBody(pair->getProxyShape2()) == body2Entity) ||
(pair->getShape1()->getBody()->getEntity() == body2Entity && pair->getShape2()->getBody()->getEntity() == body1Entity)) { (mProxyShapesComponents.getBody(pair->getProxyShape1()) == body2Entity && mProxyShapesComponents.getBody(pair->getProxyShape2()) == body1Entity)) {
outFilteredPairs.add(Pair<Pair<uint, uint>, OverlappingPair*>(it->first, pair)); outFilteredPairs.add(Pair<Pair<uint, uint>, OverlappingPair*>(it->first, pair));
} }
} }
} }
// Return the world event listener // Return the world event listener

View File

@ -292,10 +292,10 @@ class CollisionDetectionSystem {
void updateProxyShapes(decimal timeStep); void updateProxyShapes(decimal timeStep);
/// Add a pair of bodies that cannot collide with each other /// Add a pair of bodies that cannot collide with each other
void addNoCollisionPair(CollisionBody* body1, CollisionBody* body2); void addNoCollisionPair(Entity body1Entity, Entity body2Entity);
/// Remove a pair of bodies that cannot collide with each other /// Remove a pair of bodies that cannot collide with each other
void removeNoCollisionPair(CollisionBody* body1, CollisionBody* body2); void removeNoCollisionPair(Entity body1Entity, Entity body2Entity);
/// Ask for a collision shape to be tested again during broad-phase. /// Ask for a collision shape to be tested again during broad-phase.
void askForBroadPhaseCollisionCheck(ProxyShape* shape); void askForBroadPhaseCollisionCheck(ProxyShape* shape);
@ -373,15 +373,13 @@ inline void CollisionDetectionSystem::addProxyCollisionShape(ProxyShape* proxySh
} }
// Add a pair of bodies that cannot collide with each other // Add a pair of bodies that cannot collide with each other
inline void CollisionDetectionSystem::addNoCollisionPair(CollisionBody* body1, inline void CollisionDetectionSystem::addNoCollisionPair(Entity body1Entity, Entity body2Entity) {
CollisionBody* body2) { mNoCollisionPairs.add(OverlappingPair::computeBodiesIndexPair(body1Entity, body2Entity));
mNoCollisionPairs.add(OverlappingPair::computeBodiesIndexPair(body1, body2));
} }
// Remove a pair of bodies that cannot collide with each other // Remove a pair of bodies that cannot collide with each other
inline void CollisionDetectionSystem::removeNoCollisionPair(CollisionBody* body1, inline void CollisionDetectionSystem::removeNoCollisionPair(Entity body1Entity, Entity body2Entity) {
CollisionBody* body2) { mNoCollisionPairs.remove(OverlappingPair::computeBodiesIndexPair(body1Entity, body2Entity));
mNoCollisionPairs.remove(OverlappingPair::computeBodiesIndexPair(body1, body2));
} }
// Ask for a collision shape to be tested again during broad-phase. // Ask for a collision shape to be tested again during broad-phase.