Refactor OverlappingPairs
This commit is contained in:
parent
5dd48c195c
commit
a1e0e0aa94
|
@ -59,7 +59,6 @@ struct NarrowPhaseInfoBatch {
|
|||
Entity colliderEntity2;
|
||||
|
||||
/// Collision info of the previous frame
|
||||
// TODO OPTI : Do we really need to use a pointer here ? why not flat object instead ?
|
||||
LastFrameCollisionInfo* lastFrameCollisionInfo;
|
||||
|
||||
/// Memory allocator for the collision shape (Used to release TriangleShape memory in destructor)
|
||||
|
@ -124,9 +123,9 @@ struct NarrowPhaseInfoBatch {
|
|||
~NarrowPhaseInfoBatch();
|
||||
|
||||
/// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
void addNarrowPhaseInfo(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform,
|
||||
bool needToReportContacts, MemoryAllocator& shapeAllocator);
|
||||
bool needToReportContacts, LastFrameCollisionInfo* lastFrameInfo, MemoryAllocator& shapeAllocator);
|
||||
|
||||
/// Return the number of objects in the batch
|
||||
uint getNbObjects() const;
|
||||
|
@ -151,13 +150,9 @@ RP3D_FORCE_INLINE uint NarrowPhaseInfoBatch::getNbObjects() const {
|
|||
}
|
||||
|
||||
// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
RP3D_FORCE_INLINE void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
RP3D_FORCE_INLINE void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
CollisionShape* shape2, const Transform& shape1Transform, const Transform& shape2Transform,
|
||||
bool needToReportContacts, MemoryAllocator& shapeAllocator) {
|
||||
|
||||
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
|
||||
// TODO OPTI : Can we better manage this
|
||||
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
|
||||
bool needToReportContacts, LastFrameCollisionInfo* lastFrameInfo, MemoryAllocator& shapeAllocator) {
|
||||
|
||||
// Create a meta data object
|
||||
narrowPhaseInfos.emplace(pairId, collider1, collider2, lastFrameInfo, shapeAllocator, shape1Transform, shape2Transform, shape1, shape2, needToReportContacts);
|
||||
|
|
|
@ -66,10 +66,10 @@ class NarrowPhaseInput {
|
|||
NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
|
||||
|
||||
/// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
void addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
void addNarrowPhaseTest(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
CollisionShape* shape2, const Transform& shape1Transform,
|
||||
const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, bool reportContacts,
|
||||
MemoryAllocator& shapeAllocator);
|
||||
LastFrameCollisionInfo* lastFrameInfo, MemoryAllocator& shapeAllocator);
|
||||
|
||||
/// Get a reference to the sphere vs sphere batch
|
||||
NarrowPhaseInfoBatch& getSphereVsSphereBatch();
|
||||
|
@ -128,28 +128,29 @@ RP3D_FORCE_INLINE NarrowPhaseInfoBatch &NarrowPhaseInput::getConvexPolyhedronVsC
|
|||
}
|
||||
|
||||
// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
RP3D_FORCE_INLINE void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
|
||||
RP3D_FORCE_INLINE void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
|
||||
const Transform& shape1Transform, const Transform& shape2Transform,
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, bool reportContacts, MemoryAllocator& shapeAllocator) {
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, bool reportContacts, LastFrameCollisionInfo* lastFrameInfo,
|
||||
MemoryAllocator& shapeAllocator) {
|
||||
|
||||
switch (narrowPhaseAlgorithmType) {
|
||||
case NarrowPhaseAlgorithmType::SphereVsSphere:
|
||||
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::SphereVsCapsule:
|
||||
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::CapsuleVsCapsule:
|
||||
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::SphereVsConvexPolyhedron:
|
||||
mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::CapsuleVsConvexPolyhedron:
|
||||
mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::ConvexPolyhedronVsConvexPolyhedron:
|
||||
mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, lastFrameInfo, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::None:
|
||||
// Must never happen
|
||||
|
|
|
@ -106,77 +106,199 @@ struct LastFrameCollisionInfo {
|
|||
*/
|
||||
class OverlappingPairs {
|
||||
|
||||
public:
|
||||
|
||||
struct OverlappingPair {
|
||||
|
||||
/// Ids of the convex vs convex pairs
|
||||
uint64 pairID;
|
||||
|
||||
/// Broad-phase Id of the first shape
|
||||
// TODO OPTI : Is this used ?
|
||||
int32 broadPhaseId1;
|
||||
|
||||
/// Broad-phase Id of the second shape
|
||||
// TODO OPTI : Is this used ?
|
||||
int32 broadPhaseId2;
|
||||
|
||||
/// Entity of the first collider of the convex vs convex pairs
|
||||
Entity collider1;
|
||||
|
||||
/// Entity of the second collider of the convex vs convex pairs
|
||||
Entity collider2;
|
||||
|
||||
/// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
|
||||
bool needToTestOverlap;
|
||||
|
||||
/// Pointer to the narrow-phase algorithm
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType;
|
||||
|
||||
/// True if the colliders of the overlapping pair were colliding in the previous frame
|
||||
bool collidingInPreviousFrame;
|
||||
|
||||
/// True if the colliders of the overlapping pair are colliding in the current frame
|
||||
bool collidingInCurrentFrame;
|
||||
|
||||
/// Constructor
|
||||
OverlappingPair(uint64 pairId, int32 broadPhaseId1, int32 broadPhaseId2, Entity collider1, Entity collider2,
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType)
|
||||
: pairID(pairId), broadPhaseId1(broadPhaseId1), broadPhaseId2(broadPhaseId2), collider1(collider1) , collider2(collider2),
|
||||
needToTestOverlap(false), narrowPhaseAlgorithmType(narrowPhaseAlgorithmType), collidingInPreviousFrame(false),
|
||||
collidingInCurrentFrame(false) {
|
||||
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~OverlappingPair() = default;
|
||||
};
|
||||
|
||||
// Overlapping pair between two convex colliders
|
||||
struct ConvexOverlappingPair : public OverlappingPair {
|
||||
|
||||
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
|
||||
/// Temporal coherence data store collision information about the last frame.
|
||||
/// If two convex shapes overlap, we have a single collision data but if one shape is concave,
|
||||
/// we might have collision data for several overlapping triangles.
|
||||
LastFrameCollisionInfo lastFrameCollisionInfo;
|
||||
|
||||
/// Constructor
|
||||
ConvexOverlappingPair(uint64 pairId, int32 broadPhaseId1, int32 broadPhaseId2, Entity collider1, Entity collider2,
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType)
|
||||
: OverlappingPair(pairId, broadPhaseId1, broadPhaseId2, collider1, collider2, narrowPhaseAlgorithmType) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Overlapping pair between two a convex collider and a concave collider
|
||||
struct ConcaveOverlappingPair : public OverlappingPair {
|
||||
|
||||
private:
|
||||
|
||||
MemoryAllocator& mPoolAllocator;
|
||||
|
||||
public:
|
||||
|
||||
/// True if the first shape of the pair is convex
|
||||
bool isShape1Convex;
|
||||
|
||||
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
|
||||
/// Temporal coherence data store collision information about the last frame.
|
||||
/// If two convex shapes overlap, we have a single collision data but if one shape is concave,
|
||||
/// we might have collision data for several overlapping triangles. The key in the map is the
|
||||
/// shape Ids of the two collision shapes.
|
||||
Map<uint64, LastFrameCollisionInfo*> lastFrameCollisionInfos;
|
||||
|
||||
/// Constructor
|
||||
ConcaveOverlappingPair(uint64 pairId, int32 broadPhaseId1, int32 broadPhaseId2, Entity collider1, Entity collider2,
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType,
|
||||
bool isShape1Convex, MemoryAllocator& poolAllocator, MemoryAllocator& heapAllocator)
|
||||
: OverlappingPair(pairId, broadPhaseId1, broadPhaseId2, collider1, collider2, narrowPhaseAlgorithmType), mPoolAllocator(poolAllocator),
|
||||
isShape1Convex(isShape1Convex), lastFrameCollisionInfos(heapAllocator, 16) {
|
||||
|
||||
}
|
||||
|
||||
// Destroy all the LastFrameCollisionInfo objects
|
||||
void destroyLastFrameCollisionInfos() {
|
||||
|
||||
for (auto it = lastFrameCollisionInfos.begin(); it != lastFrameCollisionInfos.end(); ++it) {
|
||||
|
||||
// Call the destructor
|
||||
it->second->LastFrameCollisionInfo::~LastFrameCollisionInfo();
|
||||
|
||||
// Release memory
|
||||
mPoolAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
|
||||
}
|
||||
|
||||
lastFrameCollisionInfos.clear();
|
||||
}
|
||||
|
||||
// Add a new last frame collision info if it does not exist for the given shapes already
|
||||
LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint32 shapeId1, uint32 shapeId2) {
|
||||
|
||||
uint32 maxShapeId = shapeId1;
|
||||
uint32 minShapeId = shapeId2;
|
||||
if (shapeId1 < shapeId2) {
|
||||
maxShapeId = shapeId2;
|
||||
minShapeId = shapeId1;
|
||||
}
|
||||
|
||||
// Try to get the corresponding last frame collision info
|
||||
const uint64 shapesId = pairNumbers(maxShapeId, minShapeId);
|
||||
|
||||
// If there is no collision info for those two shapes already
|
||||
auto it = lastFrameCollisionInfos.find(shapesId);
|
||||
if (it == lastFrameCollisionInfos.end()) {
|
||||
|
||||
LastFrameCollisionInfo* lastFrameInfo = new (mPoolAllocator.allocate(sizeof(LastFrameCollisionInfo))) LastFrameCollisionInfo();
|
||||
|
||||
// Add it into the map of collision infos
|
||||
lastFrameCollisionInfos.add(Pair<uint64, LastFrameCollisionInfo*>(shapesId, lastFrameInfo));
|
||||
|
||||
return lastFrameInfo;
|
||||
}
|
||||
else {
|
||||
|
||||
// The existing collision info is not obsolete
|
||||
it->second->isObsolete = false;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear the obsolete LastFrameCollisionInfo objects
|
||||
void clearObsoleteLastFrameInfos() {
|
||||
|
||||
// For each last frame collision info
|
||||
for (auto it = lastFrameCollisionInfos.begin(); it != lastFrameCollisionInfos.end(); ) {
|
||||
|
||||
// If the collision info is obsolete
|
||||
if (it->second->isObsolete) {
|
||||
|
||||
// Call the destructor
|
||||
it->second->LastFrameCollisionInfo::~LastFrameCollisionInfo();
|
||||
|
||||
// Release memory
|
||||
mPoolAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
|
||||
|
||||
it = lastFrameCollisionInfos.remove(it);
|
||||
}
|
||||
else { // If the collision info is not obsolete
|
||||
|
||||
// Do not delete it but mark it as obsolete
|
||||
it->second->isObsolete = true;
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~ConcaveOverlappingPair() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
|
||||
/// Number of pairs to allocated at the beginning
|
||||
const uint32 INIT_NB_ALLOCATED_PAIRS = 10;
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Persistent memory allocator
|
||||
MemoryAllocator& mPersistentAllocator;
|
||||
/// Pool memory allocator
|
||||
MemoryAllocator& mPoolAllocator;
|
||||
|
||||
/// Memory allocator used to allocated memory for the ContactManifoldInfo and ContactPointInfo
|
||||
// TODO OPTI : Do we need to keep this ?
|
||||
MemoryAllocator& mTempMemoryAllocator;
|
||||
/// Heap memory allocator
|
||||
MemoryAllocator& mHeapAllocator;
|
||||
|
||||
/// Current number of components
|
||||
uint64 mNbPairs;
|
||||
/// List of convex vs convex overlapping pairs
|
||||
List<ConvexOverlappingPair> mConvexPairs;
|
||||
|
||||
/// Index in the array of the first convex vs concave pair
|
||||
uint64 mConcavePairsStartIndex;
|
||||
|
||||
/// Size (in bytes) of a single pair
|
||||
size_t mPairDataSize;
|
||||
|
||||
/// Number of allocated pairs
|
||||
uint64 mNbAllocatedPairs;
|
||||
|
||||
/// Allocated memory for all the data of the pairs
|
||||
void* mBuffer;
|
||||
/// List of convex vs concave overlapping pairs
|
||||
List<ConcaveOverlappingPair> mConcavePairs;
|
||||
|
||||
/// Map a pair id to the internal array index
|
||||
Map<uint64, uint64> mMapPairIdToPairIndex;
|
||||
Map<uint64, uint64> mMapConvexPairIdToPairIndex;
|
||||
|
||||
/// Ids of the convex vs convex pairs
|
||||
uint64* mPairIds;
|
||||
|
||||
/// Array with the broad-phase Ids of the first shape
|
||||
int32* mPairBroadPhaseId1;
|
||||
|
||||
/// Array with the broad-phase Ids of the second shape
|
||||
int32* mPairBroadPhaseId2;
|
||||
|
||||
/// Array of Entity of the first collider of the convex vs convex pairs
|
||||
Entity* mColliders1;
|
||||
|
||||
/// Array of Entity of the second collider of the convex vs convex pairs
|
||||
Entity* mColliders2;
|
||||
|
||||
/// Temporal coherence collision data for each overlapping collision shapes of this pair.
|
||||
/// Temporal coherence data store collision information about the last frame.
|
||||
/// If two convex shapes overlap, we have a single collision data but if one shape is concave,
|
||||
/// we might have collision data for several overlapping triangles. The key in the map is the
|
||||
/// shape Ids of the two collision shapes.
|
||||
Map<uint64, LastFrameCollisionInfo*>* mLastFrameCollisionInfos;
|
||||
|
||||
/// True if we need to test if the convex vs convex overlapping pairs of shapes still overlap
|
||||
bool* mNeedToTestOverlap;
|
||||
|
||||
/// Array with the pointer to the narrow-phase algorithm for each overlapping pair
|
||||
NarrowPhaseAlgorithmType* mNarrowPhaseAlgorithmType;
|
||||
|
||||
/// True if the first shape of the pair is convex
|
||||
bool* mIsShape1Convex;
|
||||
|
||||
/// True if the colliders of the overlapping pair were colliding in the previous frame
|
||||
bool* mCollidingInPreviousFrame;
|
||||
|
||||
/// True if the colliders of the overlapping pair are colliding in the current frame
|
||||
bool* mCollidingInCurrentFrame;
|
||||
/// Map a pair id to the internal array index
|
||||
Map<uint64, uint64> mMapConcavePairIdToPairIndex;
|
||||
|
||||
/// Reference to the colliders components
|
||||
ColliderComponents& mColliderComponents;
|
||||
|
@ -202,15 +324,6 @@ class OverlappingPairs {
|
|||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Allocate memory for a given number of pairs
|
||||
void allocate(uint64 nbPairsToAllocate);
|
||||
|
||||
/// Compute the index where we need to insert the new pair
|
||||
uint64 prepareAddPair(bool isConvexVsConvex);
|
||||
|
||||
/// Destroy a pair at a given index
|
||||
void destroyPair(uint64 index);
|
||||
|
||||
// Move a pair from a source to a destination index in the pairs array
|
||||
void movePairToIndex(uint64 srcIndex, uint64 destIndex);
|
||||
|
||||
|
@ -222,8 +335,8 @@ class OverlappingPairs {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator,
|
||||
ColliderComponents& colliderComponents, CollisionBodyComponents& collisionBodyComponents,
|
||||
OverlappingPairs(MemoryManager& memoryManager, ColliderComponents& colliderComponents,
|
||||
CollisionBodyComponents& collisionBodyComponents,
|
||||
RigidBodyComponents& rigidBodyComponents, Set<bodypair>& noCollisionPairs,
|
||||
CollisionDispatch& collisionDispatch);
|
||||
|
||||
|
@ -237,40 +350,13 @@ class OverlappingPairs {
|
|||
OverlappingPairs& operator=(const OverlappingPairs& pair) = delete;
|
||||
|
||||
/// Add an overlapping pair
|
||||
uint64 addPair(Collider* shape1, Collider* shape2);
|
||||
uint64 addPair(uint32 collider1Index, uint32 collider2Index, bool isConvexVsConvex);
|
||||
|
||||
/// Remove a component at a given index
|
||||
void removePair(uint64 pairId);
|
||||
|
||||
/// Return the number of pairs
|
||||
uint64 getNbPairs() const;
|
||||
|
||||
/// Return the number of convex vs convex pairs
|
||||
uint64 getNbConvexVsConvexPairs() const;
|
||||
|
||||
/// Return the number of convex vs concave pairs
|
||||
uint64 getNbConvexVsConcavePairs() const;
|
||||
|
||||
/// Return the starting index of the convex vs concave pairs
|
||||
uint64 getConvexVsConcavePairsStartIndex() const;
|
||||
|
||||
/// Return the entity of the first collider
|
||||
Entity getCollider1(uint64 pairId) const;
|
||||
|
||||
/// Return the entity of the second collider
|
||||
Entity getCollider2(uint64 pairId) const;
|
||||
|
||||
/// Return the index of a given overlapping pair in the internal array
|
||||
uint64 getPairIndex(uint64 pairId) const;
|
||||
|
||||
/// Return the last frame collision info
|
||||
LastFrameCollisionInfo* getLastFrameCollisionInfo(uint64, uint64 shapesId);
|
||||
|
||||
/// Return a reference to the temporary memory allocator
|
||||
MemoryAllocator& getTemporaryAllocator();
|
||||
|
||||
/// Add a new last frame collision info if it does not exist for the given shapes already
|
||||
LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2);
|
||||
/// Remove a pair
|
||||
void removePair(uint64 pairIndex, bool isConvexVsConvex);
|
||||
|
||||
/// Delete all the obsolete last frame collision info
|
||||
void clearObsoleteLastFrameCollisionInfos();
|
||||
|
@ -284,11 +370,8 @@ class OverlappingPairs {
|
|||
/// Set if we need to test a given pair for overlap
|
||||
void setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap);
|
||||
|
||||
/// Return true if the two colliders of the pair were already colliding the previous frame
|
||||
bool getCollidingInPreviousFrame(uint64 pairId) const;
|
||||
|
||||
/// Set to true if the two colliders of the pair were already colliding the previous frame
|
||||
void setCollidingInPreviousFrame(uint64 pairId, bool wereCollidingInPreviousFrame);
|
||||
/// Return a reference to an overlapping pair
|
||||
OverlappingPair* getOverlappingPair(uint64 pairId);
|
||||
|
||||
#ifdef IS_RP3D_PROFILING_ENABLED
|
||||
|
||||
|
@ -303,41 +386,6 @@ class OverlappingPairs {
|
|||
friend class CollisionDetectionSystem;
|
||||
};
|
||||
|
||||
// Return the entity of the first collider
|
||||
RP3D_FORCE_INLINE Entity OverlappingPairs::getCollider1(uint64 pairId) const {
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
|
||||
return mColliders1[mMapPairIdToPairIndex[pairId]];
|
||||
}
|
||||
|
||||
// Return the entity of the second collider
|
||||
RP3D_FORCE_INLINE Entity OverlappingPairs::getCollider2(uint64 pairId) const {
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
assert(mMapPairIdToPairIndex[pairId] < mNbPairs);
|
||||
return mColliders2[mMapPairIdToPairIndex[pairId]];
|
||||
}
|
||||
|
||||
// Return the index of a given overlapping pair in the internal array
|
||||
RP3D_FORCE_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
|
||||
RP3D_FORCE_INLINE LastFrameCollisionInfo* OverlappingPairs::getLastFrameCollisionInfo(uint64 pairId, uint64 shapesId) {
|
||||
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
const uint64 index = mMapPairIdToPairIndex[pairId];
|
||||
assert(index < mNbPairs);
|
||||
|
||||
Map<uint64, LastFrameCollisionInfo*>::Iterator it = mLastFrameCollisionInfos[index].find(shapesId);
|
||||
if (it != mLastFrameCollisionInfos[index].end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return the pair of bodies index
|
||||
RP3D_FORCE_INLINE bodypair OverlappingPairs::computeBodiesIndexPair(Entity body1Entity, Entity body2Entity) {
|
||||
|
||||
|
@ -349,47 +397,33 @@ RP3D_FORCE_INLINE bodypair OverlappingPairs::computeBodiesIndexPair(Entity body1
|
|||
return indexPair;
|
||||
}
|
||||
|
||||
// Return the number of pairs
|
||||
RP3D_FORCE_INLINE uint64 OverlappingPairs::getNbPairs() const {
|
||||
return mNbPairs;
|
||||
}
|
||||
|
||||
// Return the number of convex vs convex pairs
|
||||
RP3D_FORCE_INLINE uint64 OverlappingPairs::getNbConvexVsConvexPairs() const {
|
||||
return mConcavePairsStartIndex;
|
||||
}
|
||||
|
||||
// Return the number of convex vs concave pairs
|
||||
RP3D_FORCE_INLINE uint64 OverlappingPairs::getNbConvexVsConcavePairs() const {
|
||||
return mNbPairs - mConcavePairsStartIndex;
|
||||
}
|
||||
|
||||
// Return the starting index of the convex vs concave pairs
|
||||
RP3D_FORCE_INLINE uint64 OverlappingPairs::getConvexVsConcavePairsStartIndex() const {
|
||||
return mConcavePairsStartIndex;
|
||||
}
|
||||
|
||||
// Return a reference to the temporary memory allocator
|
||||
RP3D_FORCE_INLINE MemoryAllocator& OverlappingPairs::getTemporaryAllocator() {
|
||||
return mTempMemoryAllocator;
|
||||
}
|
||||
|
||||
// Set if we need to test a given pair for overlap
|
||||
RP3D_FORCE_INLINE void OverlappingPairs::setNeedToTestOverlap(uint64 pairId, bool needToTestOverlap) {
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
mNeedToTestOverlap[mMapPairIdToPairIndex[pairId]] = needToTestOverlap;
|
||||
|
||||
assert(mMapConvexPairIdToPairIndex.containsKey(pairId) || mMapConcavePairIdToPairIndex.containsKey(pairId));
|
||||
|
||||
auto it = mMapConvexPairIdToPairIndex.find(pairId);
|
||||
if (it != mMapConvexPairIdToPairIndex.end()) {
|
||||
mConvexPairs[it->second].needToTestOverlap = needToTestOverlap;
|
||||
}
|
||||
else {
|
||||
mConcavePairs[mMapConcavePairIdToPairIndex[pairId]].needToTestOverlap = needToTestOverlap;
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if the two colliders of the pair were already colliding the previous frame
|
||||
RP3D_FORCE_INLINE bool OverlappingPairs::getCollidingInPreviousFrame(uint64 pairId) const {
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
return mCollidingInPreviousFrame[mMapPairIdToPairIndex[pairId]];
|
||||
}
|
||||
// Return a reference to an overlapping pair
|
||||
RP3D_FORCE_INLINE OverlappingPairs::OverlappingPair* OverlappingPairs::getOverlappingPair(uint64 pairId) {
|
||||
|
||||
// Set to true if the two colliders of the pair were already colliding the previous frame
|
||||
RP3D_FORCE_INLINE void OverlappingPairs::setCollidingInPreviousFrame(uint64 pairId, bool wereCollidingInPreviousFrame) {
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
mCollidingInPreviousFrame[mMapPairIdToPairIndex[pairId]] = wereCollidingInPreviousFrame;
|
||||
auto it = mMapConvexPairIdToPairIndex.find(pairId);
|
||||
if (it != mMapConvexPairIdToPairIndex.end()) {
|
||||
return &(mConvexPairs[it->second]);
|
||||
}
|
||||
it = mMapConcavePairIdToPairIndex.find(pairId);
|
||||
if (it != mMapConcavePairIdToPairIndex.end()) {
|
||||
return &(mConcavePairs[it->second]);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef IS_RP3D_PROFILING_ENABLED
|
||||
|
|
|
@ -198,13 +198,13 @@ class CollisionDetectionSystem {
|
|||
void removeNonOverlappingPairs();
|
||||
|
||||
/// Add a lost contact pair (pair of colliders that are not in contact anymore)
|
||||
void addLostContactPair(uint64 overlappingPairIndex);
|
||||
void addLostContactPair(OverlappingPairs::OverlappingPair& overlappingPair);
|
||||
|
||||
/// Execute the narrow-phase collision detection algorithm on batches
|
||||
bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator);
|
||||
|
||||
/// Compute the concave vs convex middle-phase algorithm for a given pair of bodies
|
||||
void computeConvexVsConcaveMiddlePhase(uint64 pairIndex, MemoryAllocator& allocator,
|
||||
void computeConvexVsConcaveMiddlePhase(OverlappingPairs::ConcaveOverlappingPair& overlappingPair, MemoryAllocator& allocator,
|
||||
NarrowPhaseInput& narrowPhaseInput);
|
||||
|
||||
/// Swap the previous and current contacts lists
|
||||
|
|
|
@ -640,6 +640,9 @@ void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb, List<
|
|||
// Get the next node ID to visit
|
||||
const int32 nodeIDToVisit = stack.pop();
|
||||
|
||||
assert(nodeIDToVisit >= 0);
|
||||
assert(nodeIDToVisit < mNbAllocatedNodes);
|
||||
|
||||
// Skip it if it is a null node
|
||||
if (nodeIDToVisit == TreeNode::NULL_TREE_NODE) continue;
|
||||
|
||||
|
|
|
@ -52,11 +52,12 @@ void NarrowPhaseInfoBatch::reserveMemory() {
|
|||
// Clear all the objects in the batch
|
||||
void NarrowPhaseInfoBatch::clear() {
|
||||
|
||||
// TODO OPTI : Better manage this
|
||||
for (uint i=0; i < narrowPhaseInfos.size(); i++) {
|
||||
|
||||
assert(narrowPhaseInfos[i].nbContactPoints == 0);
|
||||
|
||||
// TODO OPTI : Better manage this
|
||||
|
||||
// Release the memory of the TriangleShape (this memory was allocated in the
|
||||
// MiddlePhaseTriangleCallback::testTriangle() method)
|
||||
if (narrowPhaseInfos[i].collisionShape1->getName() == CollisionShapeName::TRIANGLE) {
|
||||
|
|
|
@ -139,7 +139,7 @@ void ConcaveMeshShape::computeOverlappingTriangles(const AABB& localAABB, List<V
|
|||
aabb.applyScale(Vector3(decimal(1.0) / mScale.x, decimal(1.0) / mScale.y, decimal(1.0) / mScale.z));
|
||||
|
||||
// Compute the nodes of the internal AABB tree that are overlapping with the AABB
|
||||
List<int> overlappingNodes(allocator);
|
||||
List<int> overlappingNodes(allocator, 64);
|
||||
mDynamicAABBTree.reportAllShapesOverlappingWithAABB(aabb, overlappingNodes);
|
||||
|
||||
const uint nbOverlappingNodes = overlappingNodes.size();
|
||||
|
|
|
@ -236,9 +236,9 @@ bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collide
|
|||
const AABB rayAABB(Vector3::min(ray.point1, rayEnd), Vector3::max(ray.point1, rayEnd));
|
||||
|
||||
// Compute the triangles overlapping with the ray AABB
|
||||
List<Vector3> triangleVertices(allocator);
|
||||
List<Vector3> triangleVerticesNormals(allocator);
|
||||
List<uint> shapeIds(allocator);
|
||||
List<Vector3> triangleVertices(allocator, 64);
|
||||
List<Vector3> triangleVerticesNormals(allocator, 64);
|
||||
List<uint> shapeIds(allocator, 64);
|
||||
computeOverlappingTriangles(rayAABB, triangleVertices, triangleVerticesNormals, shapeIds, allocator);
|
||||
|
||||
assert(triangleVertices.size() == triangleVerticesNormals.size());
|
||||
|
|
|
@ -30,459 +30,194 @@
|
|||
#include <reactphysics3d/collision/ContactPointInfo.h>
|
||||
#include <reactphysics3d/collision/narrowphase/NarrowPhaseAlgorithm.h>
|
||||
#include <reactphysics3d/collision/narrowphase/CollisionDispatch.h>
|
||||
#include <reactphysics3d/memory/MemoryManager.h>
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator, ColliderComponents &colliderComponents,
|
||||
OverlappingPairs::OverlappingPairs(MemoryManager& memoryManager, ColliderComponents& colliderComponents,
|
||||
CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, Set<bodypair> &noCollisionPairs, CollisionDispatch &collisionDispatch)
|
||||
: mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
|
||||
mNbPairs(0), mConcavePairsStartIndex(0), mPairDataSize(sizeof(uint64) + sizeof(int32) + sizeof(int32) + sizeof(Entity) +
|
||||
sizeof(Entity) + sizeof(Map<uint64, LastFrameCollisionInfo*>) +
|
||||
sizeof(bool) + sizeof(NarrowPhaseAlgorithmType) +
|
||||
sizeof(bool) + sizeof(bool) + sizeof(bool)),
|
||||
mNbAllocatedPairs(0), mBuffer(nullptr),
|
||||
mMapPairIdToPairIndex(persistentMemoryAllocator),
|
||||
: mPoolAllocator(memoryManager.getPoolAllocator()), mHeapAllocator(memoryManager.getHeapAllocator()), mConvexPairs(memoryManager.getHeapAllocator()),
|
||||
mConcavePairs(memoryManager.getHeapAllocator()), mMapConvexPairIdToPairIndex(memoryManager.getHeapAllocator()), mMapConcavePairIdToPairIndex(memoryManager.getHeapAllocator()),
|
||||
mColliderComponents(colliderComponents), mCollisionBodyComponents(collisionBodyComponents),
|
||||
mRigidBodyComponents(rigidBodyComponents), mNoCollisionPairs(noCollisionPairs), mCollisionDispatch(collisionDispatch) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_PAIRS);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
OverlappingPairs::~OverlappingPairs() {
|
||||
|
||||
// If there are allocated pairs
|
||||
if (mNbAllocatedPairs > 0) {
|
||||
// Destroy the convex pairs
|
||||
while (mConvexPairs.size() > 0) {
|
||||
|
||||
// Destroy all the remaining pairs
|
||||
for (uint32 i = 0; i < mNbPairs; i++) {
|
||||
|
||||
// Remove all the remaining last frame collision info
|
||||
for (auto it = mLastFrameCollisionInfos[i].begin(); it != mLastFrameCollisionInfos[i].end(); ++it) {
|
||||
|
||||
// Call the constructor
|
||||
it->second->~LastFrameCollisionInfo();
|
||||
|
||||
// Release memory
|
||||
mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
|
||||
}
|
||||
|
||||
// Remove the involved overlapping pair to the two colliders
|
||||
assert(mColliderComponents.getOverlappingPairs(mColliders1[i]).find(mPairIds[i]) != mColliderComponents.getOverlappingPairs(mColliders1[i]).end());
|
||||
assert(mColliderComponents.getOverlappingPairs(mColliders2[i]).find(mPairIds[i]) != mColliderComponents.getOverlappingPairs(mColliders2[i]).end());
|
||||
mColliderComponents.getOverlappingPairs(mColliders1[i]).remove(mPairIds[i]);
|
||||
mColliderComponents.getOverlappingPairs(mColliders2[i]).remove(mPairIds[i]);
|
||||
|
||||
destroyPair(i);
|
||||
}
|
||||
|
||||
// Size for the data of a single pair (in bytes)
|
||||
const size_t totalSizeBytes = mNbAllocatedPairs * mPairDataSize;
|
||||
|
||||
// Release the allocated memory
|
||||
mPersistentAllocator.release(mBuffer, totalSizeBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the index where we need to insert the new pair
|
||||
uint64 OverlappingPairs::prepareAddPair(bool isConvexVsConvex) {
|
||||
|
||||
// If we need to allocate more components
|
||||
if (mNbPairs == mNbAllocatedPairs) {
|
||||
allocate(mNbAllocatedPairs * 2);
|
||||
removePair(mConvexPairs.size() - 1, true);
|
||||
}
|
||||
|
||||
uint64 index;
|
||||
// Destroy the concave pairs
|
||||
while (mConcavePairs.size() > 0) {
|
||||
|
||||
// If the pair to add is not convex vs convex or there are no concave pairs yet
|
||||
if (!isConvexVsConvex) {
|
||||
|
||||
// Add the component at the end of the array
|
||||
index = mNbPairs;
|
||||
removePair(mConcavePairs.size() - 1, false);
|
||||
}
|
||||
// If the pair to add is convex vs convex
|
||||
else {
|
||||
|
||||
// If there already are convex vs concave pairs
|
||||
if (mConcavePairsStartIndex != mNbPairs) {
|
||||
|
||||
// Move the first convex vs concave pair to the end of the array
|
||||
movePairToIndex(mConcavePairsStartIndex, mNbPairs);
|
||||
}
|
||||
|
||||
index = mConcavePairsStartIndex;
|
||||
|
||||
mConcavePairsStartIndex++;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
// Remove a component at a given index
|
||||
void OverlappingPairs::removePair(uint64 pairId) {
|
||||
|
||||
RP3D_PROFILE("OverlappingPairs::removePair()", mProfiler);
|
||||
assert(mMapConvexPairIdToPairIndex.containsKey(pairId) || mMapConcavePairIdToPairIndex.containsKey(pairId));
|
||||
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
|
||||
uint64 index = mMapPairIdToPairIndex[pairId];
|
||||
assert(index < mNbPairs);
|
||||
|
||||
// We want to keep the arrays tightly packed. Therefore, when a pair is removed,
|
||||
// we replace it with the last element of the array. But we need to make sure that convex
|
||||
// and concave pairs stay grouped together.
|
||||
|
||||
// Remove all the remaining last frame collision info
|
||||
for (auto it = mLastFrameCollisionInfos[index].begin(); it != mLastFrameCollisionInfos[index].end(); ++it) {
|
||||
|
||||
// Call the constructor
|
||||
it->second->~LastFrameCollisionInfo();
|
||||
|
||||
// Release memory
|
||||
mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
|
||||
auto it = mMapConvexPairIdToPairIndex.find(pairId);
|
||||
if (it != mMapConvexPairIdToPairIndex.end()) {
|
||||
removePair(it->second, true);
|
||||
}
|
||||
|
||||
// Remove the involved overlapping pair to the two colliders
|
||||
assert(mColliderComponents.getOverlappingPairs(mColliders1[index]).find(pairId) != mColliderComponents.getOverlappingPairs(mColliders1[index]).end());
|
||||
assert(mColliderComponents.getOverlappingPairs(mColliders2[index]).find(pairId) != mColliderComponents.getOverlappingPairs(mColliders2[index]).end());
|
||||
mColliderComponents.getOverlappingPairs(mColliders1[index]).remove(pairId);
|
||||
mColliderComponents.getOverlappingPairs(mColliders2[index]).remove(pairId);
|
||||
|
||||
// Destroy the pair
|
||||
destroyPair(index);
|
||||
|
||||
// If the pair to remove is convex vs concave
|
||||
if (index >= mConcavePairsStartIndex) {
|
||||
|
||||
// If the pair is not the last one
|
||||
if (index != mNbPairs - 1) {
|
||||
|
||||
// We replace it by the last convex vs concave pair
|
||||
movePairToIndex(mNbPairs - 1, index);
|
||||
}
|
||||
else {
|
||||
removePair(mMapConcavePairIdToPairIndex[pairId], false);
|
||||
}
|
||||
else { // If the pair to remove is convex vs convex
|
||||
|
||||
// If it not the last convex vs convex pair
|
||||
if (index != mConcavePairsStartIndex - 1) {
|
||||
|
||||
// We replace it by the last convex vs convex pair
|
||||
movePairToIndex(mConcavePairsStartIndex - 1, index);
|
||||
}
|
||||
|
||||
// If there are convex vs concave pairs at the end
|
||||
if (mConcavePairsStartIndex != mNbPairs) {
|
||||
|
||||
// We replace the last convex vs convex pair by the last convex vs concave pair
|
||||
movePairToIndex(mNbPairs - 1, mConcavePairsStartIndex - 1);
|
||||
}
|
||||
|
||||
mConcavePairsStartIndex--;
|
||||
}
|
||||
|
||||
mNbPairs--;
|
||||
|
||||
assert(mConcavePairsStartIndex <= mNbPairs);
|
||||
assert(mNbPairs == static_cast<uint32>(mMapPairIdToPairIndex.size()));
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of pairs
|
||||
void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
|
||||
// Remove a component at a given index
|
||||
void OverlappingPairs::removePair(uint64 pairIndex, bool isConvexVsConvex) {
|
||||
|
||||
assert(nbPairsToAllocate > mNbAllocatedPairs);
|
||||
RP3D_PROFILE("OverlappingPairs::removePair()", mProfiler);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbPairsToAllocate * mPairDataSize;
|
||||
if (isConvexVsConvex) {
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mPersistentAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
const uint nbConvexPairs = mConvexPairs.size();
|
||||
|
||||
// New pointers to components data
|
||||
uint64* newPairIds = static_cast<uint64*>(newBuffer);
|
||||
int32* newPairBroadPhaseId1 = reinterpret_cast<int32*>(newPairIds + nbPairsToAllocate);
|
||||
int32* newPairBroadPhaseId2 = reinterpret_cast<int32*>(newPairBroadPhaseId1 + nbPairsToAllocate);
|
||||
Entity* newColliders1 = reinterpret_cast<Entity*>(newPairBroadPhaseId2 + nbPairsToAllocate);
|
||||
Entity* newColliders2 = reinterpret_cast<Entity*>(newColliders1 + nbPairsToAllocate);
|
||||
Map<uint64, LastFrameCollisionInfo*>* newLastFrameCollisionInfos = reinterpret_cast<Map<uint64, LastFrameCollisionInfo*>*>(newColliders2 + nbPairsToAllocate);
|
||||
bool* newNeedToTestOverlap = reinterpret_cast<bool*>(newLastFrameCollisionInfos + nbPairsToAllocate);
|
||||
NarrowPhaseAlgorithmType* newNarrowPhaseAlgorithmType = reinterpret_cast<NarrowPhaseAlgorithmType*>(newNeedToTestOverlap + nbPairsToAllocate);
|
||||
bool* newIsShape1Convex = reinterpret_cast<bool*>(newNarrowPhaseAlgorithmType + nbPairsToAllocate);
|
||||
bool* wereCollidingInPreviousFrame = reinterpret_cast<bool*>(newIsShape1Convex + nbPairsToAllocate);
|
||||
bool* areCollidingInCurrentFrame = reinterpret_cast<bool*>(wereCollidingInPreviousFrame + nbPairsToAllocate);
|
||||
assert(pairIndex < nbConvexPairs);
|
||||
|
||||
// If there was already pairs before
|
||||
if (mNbPairs > 0) {
|
||||
// Remove the involved overlapping pair from the two colliders
|
||||
assert(mColliderComponents.getOverlappingPairs(mConvexPairs[pairIndex].collider1).find(mConvexPairs[pairIndex].pairID) != mColliderComponents.getOverlappingPairs(mConvexPairs[pairIndex].collider1).end());
|
||||
assert(mColliderComponents.getOverlappingPairs(mConvexPairs[pairIndex].collider2).find(mConvexPairs[pairIndex].pairID) != mColliderComponents.getOverlappingPairs(mConvexPairs[pairIndex].collider2).end());
|
||||
mColliderComponents.getOverlappingPairs(mConvexPairs[pairIndex].collider1).remove(mConvexPairs[pairIndex].pairID);
|
||||
mColliderComponents.getOverlappingPairs(mConvexPairs[pairIndex].collider2).remove(mConvexPairs[pairIndex].pairID);
|
||||
|
||||
// Copy component data from the previous buffer to the new one
|
||||
memcpy(newPairIds, mPairIds, mNbPairs * sizeof(uint64));
|
||||
memcpy(newPairBroadPhaseId1, mPairBroadPhaseId1, mNbPairs * sizeof(int32));
|
||||
memcpy(newPairBroadPhaseId2, mPairBroadPhaseId2, mNbPairs * sizeof(int32));
|
||||
memcpy(newColliders1, mColliders1, mNbPairs * sizeof(Entity));
|
||||
memcpy(newColliders2, mColliders2, mNbPairs * sizeof(Entity));
|
||||
memcpy(newLastFrameCollisionInfos, mLastFrameCollisionInfos, mNbPairs * sizeof(Map<uint64, LastFrameCollisionInfo*>));
|
||||
memcpy(newNeedToTestOverlap, mNeedToTestOverlap, mNbPairs * sizeof(bool));
|
||||
memcpy(newNarrowPhaseAlgorithmType, mNarrowPhaseAlgorithmType, mNbPairs * sizeof(NarrowPhaseAlgorithmType));
|
||||
memcpy(newIsShape1Convex, mIsShape1Convex, mNbPairs * sizeof(bool));
|
||||
memcpy(wereCollidingInPreviousFrame, mCollidingInPreviousFrame, mNbPairs * sizeof(bool));
|
||||
memcpy(areCollidingInCurrentFrame, mCollidingInCurrentFrame, mNbPairs * sizeof(bool));
|
||||
assert(mMapConvexPairIdToPairIndex[mConvexPairs[pairIndex].pairID] == pairIndex);
|
||||
mMapConvexPairIdToPairIndex.remove(mConvexPairs[pairIndex].pairID);
|
||||
|
||||
// Deallocate previous memory
|
||||
mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize);
|
||||
// Change the mapping between the pairId and the index in the convex pairs array if we swap the last item with the one to remove
|
||||
if (mConvexPairs.size() > 1 && pairIndex < (nbConvexPairs - 1)) {
|
||||
|
||||
mMapConvexPairIdToPairIndex[mConvexPairs[nbConvexPairs - 1].pairID] = pairIndex;
|
||||
}
|
||||
|
||||
// We want to keep the arrays tightly packed. Therefore, when a pair is removed,
|
||||
// we replace it with the last element of the array.
|
||||
mConvexPairs.removeAtAndReplaceByLast(pairIndex);
|
||||
}
|
||||
else {
|
||||
|
||||
mBuffer = newBuffer;
|
||||
mPairIds = newPairIds;
|
||||
mPairBroadPhaseId1 = newPairBroadPhaseId1;
|
||||
mPairBroadPhaseId2 = newPairBroadPhaseId2;
|
||||
mColliders1 = newColliders1;
|
||||
mColliders2 = newColliders2;
|
||||
mLastFrameCollisionInfos = newLastFrameCollisionInfos;
|
||||
mNeedToTestOverlap = newNeedToTestOverlap;
|
||||
mNarrowPhaseAlgorithmType = newNarrowPhaseAlgorithmType;
|
||||
mIsShape1Convex = newIsShape1Convex;
|
||||
mCollidingInPreviousFrame = wereCollidingInPreviousFrame;
|
||||
mCollidingInCurrentFrame = areCollidingInCurrentFrame;
|
||||
const uint nbConcavePairs = mConcavePairs.size();
|
||||
|
||||
mNbAllocatedPairs = nbPairsToAllocate;
|
||||
assert(pairIndex < nbConcavePairs);
|
||||
|
||||
// Remove the involved overlapping pair to the two colliders
|
||||
assert(mColliderComponents.getOverlappingPairs(mConcavePairs[pairIndex].collider1).find(mConcavePairs[pairIndex].pairID) != mColliderComponents.getOverlappingPairs(mConcavePairs[pairIndex].collider1).end());
|
||||
assert(mColliderComponents.getOverlappingPairs(mConcavePairs[pairIndex].collider2).find(mConcavePairs[pairIndex].pairID) != mColliderComponents.getOverlappingPairs(mConcavePairs[pairIndex].collider2).end());
|
||||
mColliderComponents.getOverlappingPairs(mConcavePairs[pairIndex].collider1).remove(mConcavePairs[pairIndex].pairID);
|
||||
mColliderComponents.getOverlappingPairs(mConcavePairs[pairIndex].collider2).remove(mConcavePairs[pairIndex].pairID);
|
||||
|
||||
assert(mMapConcavePairIdToPairIndex[mConcavePairs[pairIndex].pairID] == pairIndex);
|
||||
mMapConcavePairIdToPairIndex.remove(mConcavePairs[pairIndex].pairID);
|
||||
|
||||
// Destroy all the LastFrameCollisionInfo objects
|
||||
mConcavePairs[pairIndex].destroyLastFrameCollisionInfos();
|
||||
|
||||
// Change the mapping between the pairId and the index in the convex pairs array if we swap the last item with the one to remove
|
||||
if (mConcavePairs.size() > 1 && pairIndex < (nbConcavePairs - 1)) {
|
||||
|
||||
mMapConcavePairIdToPairIndex[mConcavePairs[nbConcavePairs - 1].pairID] = pairIndex;
|
||||
}
|
||||
|
||||
// We want to keep the arrays tightly packed. Therefore, when a pair is removed,
|
||||
// we replace it with the last element of the array.
|
||||
mConcavePairs.removeAtAndReplaceByLast(pairIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Add an overlapping pair
|
||||
uint64 OverlappingPairs::addPair(Collider* shape1, Collider* shape2) {
|
||||
uint64 OverlappingPairs::addPair(uint32 collider1Index, uint32 collider2Index, bool isConvexVsConvex) {
|
||||
|
||||
RP3D_PROFILE("OverlappingPairs::addPair()", mProfiler);
|
||||
|
||||
const Entity collider1 = shape1->getEntity();
|
||||
const Entity collider2 = shape2->getEntity();
|
||||
|
||||
const uint collider1Index = mColliderComponents.getEntityIndex(collider1);
|
||||
const uint collider2Index = mColliderComponents.getEntityIndex(collider2);
|
||||
assert(mColliderComponents.mBroadPhaseIds[collider1Index] >= 0 && mColliderComponents.mBroadPhaseIds[collider2Index] >= 0);
|
||||
|
||||
const CollisionShape* collisionShape1 = mColliderComponents.mCollisionShapes[collider1Index];
|
||||
const CollisionShape* collisionShape2 = mColliderComponents.mCollisionShapes[collider2Index];
|
||||
|
||||
const bool isShape1Convex = collisionShape1->isConvex();
|
||||
const bool isShape2Convex = collisionShape2->isConvex();
|
||||
const bool isConvexVsConvex = isShape1Convex && isShape2Convex;
|
||||
const Entity collider1Entity = mColliderComponents.mCollidersEntities[collider1Index];
|
||||
const Entity collider2Entity = mColliderComponents.mCollidersEntities[collider2Index];
|
||||
|
||||
// Prepare to add new pair (allocate memory if necessary and compute insertion index)
|
||||
uint64 index = prepareAddPair(isConvexVsConvex);
|
||||
|
||||
const uint32 broadPhase1Id = static_cast<uint32>(shape1->getBroadPhaseId());
|
||||
const uint32 broadPhase2Id = static_cast<uint32>(shape2->getBroadPhaseId());
|
||||
const uint32 broadPhase1Id = static_cast<uint32>(mColliderComponents.mBroadPhaseIds[collider1Index]);
|
||||
const uint32 broadPhase2Id = static_cast<uint32>(mColliderComponents.mBroadPhaseIds[collider2Index]);
|
||||
|
||||
// Compute a unique id for the overlapping pair
|
||||
const uint64 pairId = pairNumbers(std::max(broadPhase1Id, broadPhase2Id), std::min(broadPhase1Id, broadPhase2Id));
|
||||
|
||||
assert(!mMapPairIdToPairIndex.containsKey(pairId));
|
||||
|
||||
// Select the narrow phase algorithm to use according to the two collision shapes
|
||||
NarrowPhaseAlgorithmType algorithmType;
|
||||
if (isConvexVsConvex) {
|
||||
|
||||
algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(), collisionShape2->getType());
|
||||
assert(!mMapConvexPairIdToPairIndex.containsKey(pairId));
|
||||
NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(), collisionShape2->getType());
|
||||
|
||||
// Map the entity with the new component lookup index
|
||||
mMapConvexPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, mConvexPairs.size()));
|
||||
|
||||
// Create and add a new convex pair
|
||||
mConvexPairs.emplace(pairId, broadPhase1Id, broadPhase2Id, collider1Entity, collider2Entity, algorithmType);
|
||||
}
|
||||
else {
|
||||
|
||||
algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(isShape1Convex ? collisionShape1->getType() : collisionShape2->getType(),
|
||||
const bool isShape1Convex = collisionShape1->isConvex();
|
||||
|
||||
assert(!mMapConcavePairIdToPairIndex.containsKey(pairId));
|
||||
NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(isShape1Convex ? collisionShape1->getType() : collisionShape2->getType(),
|
||||
CollisionShapeType::CONVEX_POLYHEDRON);
|
||||
// Map the entity with the new component lookup index
|
||||
mMapConcavePairIdToPairIndex.add(Pair<uint64, uint64>(pairId, mConcavePairs.size()));
|
||||
|
||||
// Create and add a new concave pair
|
||||
mConcavePairs.emplace(pairId, broadPhase1Id, broadPhase2Id, collider1Entity, collider2Entity, algorithmType,
|
||||
isShape1Convex, mPoolAllocator, mHeapAllocator);
|
||||
}
|
||||
|
||||
// Insert the new component data
|
||||
new (mPairIds + index) uint64(pairId);
|
||||
new (mPairBroadPhaseId1 + index) int32(shape1->getBroadPhaseId());
|
||||
new (mPairBroadPhaseId2 + index) int32(shape2->getBroadPhaseId());
|
||||
new (mColliders1 + index) Entity(shape1->getEntity());
|
||||
new (mColliders2 + index) Entity(shape2->getEntity());
|
||||
new (mLastFrameCollisionInfos + index) Map<uint64, LastFrameCollisionInfo*>(mPersistentAllocator);
|
||||
new (mNeedToTestOverlap + index) bool(false);
|
||||
new (mNarrowPhaseAlgorithmType + index) NarrowPhaseAlgorithmType(algorithmType);
|
||||
new (mIsShape1Convex + index) bool(isShape1Convex);
|
||||
new (mCollidingInPreviousFrame + index) bool(false);
|
||||
new (mCollidingInCurrentFrame + index) bool(false);
|
||||
|
||||
// Map the entity with the new component lookup index
|
||||
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index));
|
||||
|
||||
// Add the involved overlapping pair to the two colliders
|
||||
assert(mColliderComponents.mOverlappingPairs[collider1Index].find(pairId) == mColliderComponents.mOverlappingPairs[collider1Index].end());
|
||||
assert(mColliderComponents.mOverlappingPairs[collider2Index].find(pairId) == mColliderComponents.mOverlappingPairs[collider2Index].end());
|
||||
mColliderComponents.mOverlappingPairs[collider1Index].add(pairId);
|
||||
mColliderComponents.mOverlappingPairs[collider2Index].add(pairId);
|
||||
|
||||
mNbPairs++;
|
||||
|
||||
assert(mConcavePairsStartIndex <= mNbPairs);
|
||||
assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
|
||||
|
||||
return pairId;
|
||||
}
|
||||
|
||||
// Move a pair from a source to a destination index in the pairs array
|
||||
// The destination location must contain a constructed object
|
||||
void OverlappingPairs::movePairToIndex(uint64 srcIndex, uint64 destIndex) {
|
||||
|
||||
const uint64 pairId = mPairIds[srcIndex];
|
||||
|
||||
// Copy the data of the source pair to the destination location
|
||||
mPairIds[destIndex] = mPairIds[srcIndex];
|
||||
mPairBroadPhaseId1[destIndex] = mPairBroadPhaseId1[srcIndex];
|
||||
mPairBroadPhaseId2[destIndex] = mPairBroadPhaseId2[srcIndex];
|
||||
new (mColliders1 + destIndex) Entity(mColliders1[srcIndex]);
|
||||
new (mColliders2 + destIndex) Entity(mColliders2[srcIndex]);
|
||||
new (mLastFrameCollisionInfos + destIndex) Map<uint64, LastFrameCollisionInfo*>(mLastFrameCollisionInfos[srcIndex]);
|
||||
mNeedToTestOverlap[destIndex] = mNeedToTestOverlap[srcIndex];
|
||||
new (mNarrowPhaseAlgorithmType + destIndex) NarrowPhaseAlgorithmType(mNarrowPhaseAlgorithmType[srcIndex]);
|
||||
mIsShape1Convex[destIndex] = mIsShape1Convex[srcIndex];
|
||||
mCollidingInPreviousFrame[destIndex] = mCollidingInPreviousFrame[srcIndex];
|
||||
mCollidingInCurrentFrame[destIndex] = mCollidingInCurrentFrame[srcIndex];
|
||||
|
||||
// Destroy the source pair
|
||||
destroyPair(srcIndex);
|
||||
|
||||
assert(!mMapPairIdToPairIndex.containsKey(pairId));
|
||||
|
||||
// Update the pairId to pair index mapping
|
||||
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, destIndex));
|
||||
|
||||
assert(mMapPairIdToPairIndex[mPairIds[destIndex]] == destIndex);
|
||||
}
|
||||
|
||||
// Swap two pairs in the array
|
||||
void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
|
||||
|
||||
// Copy pair 1 data
|
||||
uint64 pairId = mPairIds[index1];
|
||||
int32 pairBroadPhaseId1 = mPairBroadPhaseId1[index1];
|
||||
int32 pairBroadPhaseId2 = mPairBroadPhaseId2[index1];
|
||||
Entity collider1 = mColliders1[index1];
|
||||
Entity collider2 = mColliders2[index1];
|
||||
Map<uint64, LastFrameCollisionInfo*> lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]);
|
||||
bool needTestOverlap = mNeedToTestOverlap[index1];
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType = mNarrowPhaseAlgorithmType[index1];
|
||||
bool isShape1Convex = mIsShape1Convex[index1];
|
||||
bool wereCollidingInPreviousFrame = mCollidingInPreviousFrame[index1];
|
||||
bool areCollidingInCurrentFrame = mCollidingInCurrentFrame[index1];
|
||||
|
||||
// Destroy pair 1
|
||||
destroyPair(index1);
|
||||
|
||||
movePairToIndex(index2, index1);
|
||||
|
||||
// Reconstruct pair 1 at pair 2 location
|
||||
mPairIds[index2] = pairId;
|
||||
mPairBroadPhaseId1[index2] = pairBroadPhaseId1;
|
||||
mPairBroadPhaseId2[index2] = pairBroadPhaseId2;
|
||||
new (mColliders1 + index2) Entity(collider1);
|
||||
new (mColliders2 + index2) Entity(collider2);
|
||||
new (mLastFrameCollisionInfos + index2) Map<uint64, LastFrameCollisionInfo*>(lastFrameCollisionInfo);
|
||||
mNeedToTestOverlap[index2] = needTestOverlap;
|
||||
new (mNarrowPhaseAlgorithmType + index2) NarrowPhaseAlgorithmType(narrowPhaseAlgorithmType);
|
||||
mIsShape1Convex[index2] = isShape1Convex;
|
||||
mCollidingInPreviousFrame[index2] = wereCollidingInPreviousFrame;
|
||||
mCollidingInCurrentFrame[index2] = areCollidingInCurrentFrame;
|
||||
|
||||
// Update the pairID to pair index mapping
|
||||
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index2));
|
||||
|
||||
assert(mMapPairIdToPairIndex[mPairIds[index1]] == index1);
|
||||
assert(mMapPairIdToPairIndex[mPairIds[index2]] == index2);
|
||||
assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
|
||||
}
|
||||
|
||||
// Destroy a pair at a given index
|
||||
void OverlappingPairs::destroyPair(uint64 index) {
|
||||
|
||||
assert(index < mNbPairs);
|
||||
|
||||
assert(mMapPairIdToPairIndex[mPairIds[index]] == index);
|
||||
|
||||
mMapPairIdToPairIndex.remove(mPairIds[index]);
|
||||
|
||||
mColliders1[index].~Entity();
|
||||
mColliders2[index].~Entity();
|
||||
mLastFrameCollisionInfos[index].~Map<uint64, LastFrameCollisionInfo*>();
|
||||
mNarrowPhaseAlgorithmType[index].~NarrowPhaseAlgorithmType();
|
||||
}
|
||||
|
||||
// Add a new last frame collision info if it does not exist for the given shapes already
|
||||
LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2) {
|
||||
|
||||
RP3D_PROFILE("OverlappingPairs::addLastFrameInfoIfNecessary()", mProfiler);
|
||||
|
||||
assert(pairIndex < mNbPairs);
|
||||
|
||||
uint32 maxShapeId = shapeId1;
|
||||
uint32 minShapeId = shapeId2;
|
||||
if (shapeId1 < shapeId2) {
|
||||
maxShapeId = shapeId2;
|
||||
minShapeId = shapeId1;
|
||||
}
|
||||
|
||||
// Try to get the corresponding last frame collision info
|
||||
const uint64 shapesId = pairNumbers(maxShapeId, minShapeId);
|
||||
|
||||
// If there is no collision info for those two shapes already
|
||||
auto it = mLastFrameCollisionInfos[pairIndex].find(shapesId);
|
||||
if (it == mLastFrameCollisionInfos[pairIndex].end()) {
|
||||
|
||||
// Create a new collision info
|
||||
LastFrameCollisionInfo* collisionInfo = new (mPersistentAllocator.allocate(sizeof(LastFrameCollisionInfo)))
|
||||
LastFrameCollisionInfo();
|
||||
|
||||
// Add it into the map of collision infos
|
||||
mLastFrameCollisionInfos[pairIndex].add(Pair<uint64, LastFrameCollisionInfo*>(shapesId, collisionInfo));
|
||||
|
||||
return collisionInfo;
|
||||
}
|
||||
else {
|
||||
|
||||
// The existing collision info is not obsolete
|
||||
it->second->isObsolete = false;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all the obsolete last frame collision info
|
||||
void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() {
|
||||
|
||||
RP3D_PROFILE("OverlappingPairs::clearObsoleteLastFrameCollisionInfos()", mProfiler);
|
||||
|
||||
// For each overlapping pair
|
||||
for (uint64 i=0; i < mNbPairs; i++) {
|
||||
// For each concave overlapping pair
|
||||
const uint64 nbConcavePairs = mConcavePairs.size();
|
||||
for (uint64 i=0; i < nbConcavePairs; i++) {
|
||||
|
||||
// For each collision info
|
||||
for (auto it = mLastFrameCollisionInfos[i].begin(); it != mLastFrameCollisionInfos[i].end(); ) {
|
||||
|
||||
// If the collision info is obsolete
|
||||
if (it->second->isObsolete) {
|
||||
|
||||
// Delete it
|
||||
it->second->~LastFrameCollisionInfo();
|
||||
mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
|
||||
|
||||
it = mLastFrameCollisionInfos[i].remove(it);
|
||||
}
|
||||
else { // If the collision info is not obsolete
|
||||
|
||||
// Do not delete it but mark it as obsolete
|
||||
it->second->isObsolete = true;
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
mConcavePairs[i].clearObsoleteLastFrameInfos();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the collidingInPreviousFrame value with the collidinginCurrentFrame value for each pair
|
||||
void OverlappingPairs::updateCollidingInPreviousFrame() {
|
||||
|
||||
// For each overlapping pair
|
||||
for (uint64 i=0; i < mNbPairs; i++) {
|
||||
RP3D_PROFILE("OverlappingPairs::updateCollidingInPreviousFrame()", mProfiler);
|
||||
|
||||
mCollidingInPreviousFrame[i] = mCollidingInCurrentFrame[i];
|
||||
// For each convex overlapping pair
|
||||
const uint64 nbConvexPairs = mConvexPairs.size();
|
||||
for (uint64 i=0; i < nbConvexPairs; i++) {
|
||||
|
||||
mConvexPairs[i].collidingInPreviousFrame = mConvexPairs[i].collidingInCurrentFrame;
|
||||
}
|
||||
|
||||
// For each concave overlapping pair
|
||||
const uint64 nbConcavePairs = mConcavePairs.size();
|
||||
for (uint64 i=0; i < nbConcavePairs; i++) {
|
||||
|
||||
mConcavePairs[i].collidingInPreviousFrame = mConcavePairs[i].collidingInCurrentFrame;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,9 +37,9 @@ using namespace reactphysics3d;
|
|||
// Constructor
|
||||
BroadPhaseSystem::BroadPhaseSystem(CollisionDetectionSystem& collisionDetection, ColliderComponents& collidersComponents,
|
||||
TransformComponents& transformComponents, RigidBodyComponents& rigidBodyComponents)
|
||||
:mDynamicAABBTree(collisionDetection.getMemoryManager().getPoolAllocator(), DYNAMIC_TREE_FAT_AABB_INFLATE_PERCENTAGE),
|
||||
:mDynamicAABBTree(collisionDetection.getMemoryManager().getHeapAllocator(), DYNAMIC_TREE_FAT_AABB_INFLATE_PERCENTAGE),
|
||||
mCollidersComponents(collidersComponents), mTransformsComponents(transformComponents),
|
||||
mRigidBodyComponents(rigidBodyComponents), mMovedShapes(collisionDetection.getMemoryManager().getPoolAllocator()),
|
||||
mRigidBodyComponents(rigidBodyComponents), mMovedShapes(collisionDetection.getMemoryManager().getHeapAllocator()),
|
||||
mCollisionDetection(collisionDetection) {
|
||||
|
||||
#ifdef IS_RP3D_PROFILING_ENABLED
|
||||
|
@ -211,7 +211,7 @@ void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager, Lis
|
|||
RP3D_PROFILE("BroadPhaseSystem::computeOverlappingPairs()", mProfiler);
|
||||
|
||||
// Get the list of the colliders that have moved or have been created in the last frame
|
||||
List<int> shapesToTest = mMovedShapes.toList(memoryManager.getPoolAllocator());
|
||||
List<int> shapesToTest = mMovedShapes.toList(memoryManager.getHeapAllocator());
|
||||
|
||||
// Ask the dynamic AABB tree to report all collision shapes that overlap with the shapes to test
|
||||
mDynamicAABBTree.reportAllShapesOverlappingWithShapes(shapesToTest, 0, shapesToTest.size(), overlappingNodes);
|
||||
|
|
|
@ -55,8 +55,8 @@ CollisionDetectionSystem::CollisionDetectionSystem(PhysicsWorld* world, Collider
|
|||
: mMemoryManager(memoryManager), mCollidersComponents(collidersComponents), mRigidBodyComponents(rigidBodyComponents),
|
||||
mCollisionDispatch(mMemoryManager.getPoolAllocator()), mWorld(world),
|
||||
mNoCollisionPairs(mMemoryManager.getPoolAllocator()),
|
||||
mOverlappingPairs(mMemoryManager.getPoolAllocator(), mMemoryManager.getSingleFrameAllocator(), mCollidersComponents,
|
||||
collisionBodyComponents, rigidBodyComponents, mNoCollisionPairs, mCollisionDispatch),
|
||||
mOverlappingPairs(mMemoryManager, mCollidersComponents, collisionBodyComponents, rigidBodyComponents,
|
||||
mNoCollisionPairs, mCollisionDispatch),
|
||||
mBroadPhaseSystem(*this, mCollidersComponents, transformComponents, rigidBodyComponents),
|
||||
mMapBroadPhaseIdToColliderEntity(memoryManager.getPoolAllocator()),
|
||||
mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator(), mOverlappingPairs), mPotentialContactPoints(mMemoryManager.getSingleFrameAllocator()),
|
||||
|
@ -102,7 +102,7 @@ void CollisionDetectionSystem::computeBroadPhase() {
|
|||
// Ask the broad-phase to compute all the shapes overlapping with the shapes that
|
||||
// have moved or have been added in the last frame. This call can only add new
|
||||
// overlapping pairs in the collision detection.
|
||||
List<Pair<int32, int32>> overlappingNodes(mMemoryManager.getPoolAllocator(), 32);
|
||||
List<Pair<int32, int32>> overlappingNodes(mMemoryManager.getHeapAllocator(), 32);
|
||||
mBroadPhaseSystem.computeOverlappingPairs(mMemoryManager, overlappingNodes);
|
||||
|
||||
// Create new overlapping pairs if necessary
|
||||
|
@ -117,25 +117,55 @@ void CollisionDetectionSystem::removeNonOverlappingPairs() {
|
|||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::removeNonOverlappingPairs()", mProfiler);
|
||||
|
||||
for (uint64 i=0; i < mOverlappingPairs.getNbPairs(); i++) {
|
||||
// For each convex pairs
|
||||
for (uint64 i=0; i < mOverlappingPairs.mConvexPairs.size(); i++) {
|
||||
|
||||
OverlappingPairs::ConvexOverlappingPair& overlappingPair = mOverlappingPairs.mConvexPairs[i];
|
||||
|
||||
// Check if we need to test overlap. If so, test if the two shapes are still overlapping.
|
||||
// Otherwise, we destroy the overlapping pair
|
||||
if (mOverlappingPairs.mNeedToTestOverlap[i]) {
|
||||
if (overlappingPair.needToTestOverlap) {
|
||||
|
||||
if(mBroadPhaseSystem.testOverlappingShapes(mOverlappingPairs.mPairBroadPhaseId1[i], mOverlappingPairs.mPairBroadPhaseId2[i])) {
|
||||
mOverlappingPairs.mNeedToTestOverlap[i] = false;
|
||||
if(mBroadPhaseSystem.testOverlappingShapes(overlappingPair.broadPhaseId1, overlappingPair.broadPhaseId2)) {
|
||||
overlappingPair.needToTestOverlap = false;
|
||||
}
|
||||
else {
|
||||
|
||||
// If the two colliders of the pair were colliding in the previous frame
|
||||
if (mOverlappingPairs.mCollidingInPreviousFrame[i]) {
|
||||
if (overlappingPair.collidingInPreviousFrame) {
|
||||
|
||||
// Create a new lost contact pair
|
||||
addLostContactPair(i);
|
||||
addLostContactPair(overlappingPair);
|
||||
}
|
||||
|
||||
mOverlappingPairs.removePair(mOverlappingPairs.mPairIds[i]);
|
||||
mOverlappingPairs.removePair(i, true);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each concave pairs
|
||||
for (uint64 i=0; i < mOverlappingPairs.mConcavePairs.size(); i++) {
|
||||
|
||||
OverlappingPairs::ConcaveOverlappingPair& overlappingPair = mOverlappingPairs.mConcavePairs[i];
|
||||
|
||||
// Check if we need to test overlap. If so, test if the two shapes are still overlapping.
|
||||
// Otherwise, we destroy the overlapping pair
|
||||
if (overlappingPair.needToTestOverlap) {
|
||||
|
||||
if(mBroadPhaseSystem.testOverlappingShapes(overlappingPair.broadPhaseId1, overlappingPair.broadPhaseId2)) {
|
||||
overlappingPair.needToTestOverlap = false;
|
||||
}
|
||||
else {
|
||||
|
||||
// If the two colliders of the pair were colliding in the previous frame
|
||||
if (overlappingPair.collidingInPreviousFrame) {
|
||||
|
||||
// Create a new lost contact pair
|
||||
addLostContactPair(overlappingPair);
|
||||
}
|
||||
|
||||
mOverlappingPairs.removePair(i, false);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
@ -143,20 +173,20 @@ void CollisionDetectionSystem::removeNonOverlappingPairs() {
|
|||
}
|
||||
|
||||
// Add a lost contact pair (pair of colliders that are not in contact anymore)
|
||||
void CollisionDetectionSystem::addLostContactPair(uint64 overlappingPairIndex) {
|
||||
void CollisionDetectionSystem::addLostContactPair(OverlappingPairs::OverlappingPair& overlappingPair) {
|
||||
|
||||
const Entity collider1Entity = mOverlappingPairs.mColliders1[overlappingPairIndex];
|
||||
const Entity collider2Entity = mOverlappingPairs.mColliders2[overlappingPairIndex];
|
||||
const uint32 collider1Index = mCollidersComponents.getEntityIndex(overlappingPair.collider1);
|
||||
const uint32 collider2Index = mCollidersComponents.getEntityIndex(overlappingPair.collider2);
|
||||
|
||||
const Entity body1Entity = mCollidersComponents.getBody(collider1Entity);
|
||||
const Entity body2Entity = mCollidersComponents.getBody(collider2Entity);
|
||||
const Entity body1Entity = mCollidersComponents.mBodiesEntities[collider1Index];
|
||||
const Entity body2Entity = mCollidersComponents.mBodiesEntities[collider2Index];
|
||||
|
||||
const bool isCollider1Trigger = mCollidersComponents.getIsTrigger(collider1Entity);
|
||||
const bool isCollider2Trigger = mCollidersComponents.getIsTrigger(collider2Entity);
|
||||
const bool isCollider1Trigger = mCollidersComponents.mIsTrigger[collider1Index];
|
||||
const bool isCollider2Trigger = mCollidersComponents.mIsTrigger[collider2Index];
|
||||
const bool isTrigger = isCollider1Trigger || isCollider2Trigger;
|
||||
|
||||
// Create a lost contact pair
|
||||
ContactPair lostContactPair(mOverlappingPairs.mPairIds[overlappingPairIndex], body1Entity, body2Entity, collider1Entity, collider2Entity, mLostContactPairs.size(),
|
||||
ContactPair lostContactPair(overlappingPair.pairID, body1Entity, body2Entity, overlappingPair.collider1, overlappingPair.collider2, mLostContactPairs.size(),
|
||||
true, isTrigger);
|
||||
mLostContactPairs.add(lostContactPair);
|
||||
}
|
||||
|
@ -219,8 +249,8 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int
|
|||
const uint64 pairId = pairNumbers(std::max(nodePair.first, nodePair.second), std::min(nodePair.first, nodePair.second));
|
||||
|
||||
// Check if the overlapping pair already exists
|
||||
auto it = mOverlappingPairs.mMapPairIdToPairIndex.find(pairId);
|
||||
if (it == mOverlappingPairs.mMapPairIdToPairIndex.end()) {
|
||||
OverlappingPairs::OverlappingPair* overlappingPair = mOverlappingPairs.getOverlappingPair(pairId);
|
||||
if (overlappingPair == nullptr) {
|
||||
|
||||
const unsigned short shape1CollideWithMaskBits = mCollidersComponents.mCollideWithMaskBits[collider1Index];
|
||||
const unsigned short shape2CollideWithMaskBits = mCollidersComponents.mCollideWithMaskBits[collider2Index];
|
||||
|
@ -236,17 +266,19 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int
|
|||
Collider* shape2 = mCollidersComponents.mColliders[collider2Index];
|
||||
|
||||
// Check that at least one collision shape is convex
|
||||
if (shape1->getCollisionShape()->isConvex() || shape2->getCollisionShape()->isConvex()) {
|
||||
const bool isShape1Convex = shape1->getCollisionShape()->isConvex();
|
||||
const bool isShape2Convex = shape2->getCollisionShape()->isConvex();
|
||||
if (isShape1Convex || isShape2Convex) {
|
||||
|
||||
// Add the new overlapping pair
|
||||
mOverlappingPairs.addPair(shape1, shape2);
|
||||
mOverlappingPairs.addPair(collider1Index, collider2Index, isShape1Convex && isShape2Convex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// We do not need to test the pair for overlap because it has just been reported that they still overlap
|
||||
mOverlappingPairs.mNeedToTestOverlap[it->second] = false;
|
||||
overlappingPair->needToTestOverlap = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,16 +299,18 @@ void CollisionDetectionSystem::computeMiddlePhase(NarrowPhaseInput& narrowPhaseI
|
|||
mOverlappingPairs.clearObsoleteLastFrameCollisionInfos();
|
||||
|
||||
// For each possible convex vs convex pair of bodies
|
||||
const uint64 nbConvexVsConvexPairs = mOverlappingPairs.getNbConvexVsConvexPairs();
|
||||
const uint64 nbConvexVsConvexPairs = mOverlappingPairs.mConvexPairs.size();
|
||||
for (uint64 i=0; i < nbConvexVsConvexPairs; i++) {
|
||||
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders1[i]) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders2[i]) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders1[i]) != mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders2[i]));
|
||||
OverlappingPairs::ConvexOverlappingPair& overlappingPair = mOverlappingPairs.mConvexPairs[i];
|
||||
|
||||
assert(mCollidersComponents.getBroadPhaseId(overlappingPair.collider1) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(overlappingPair.collider2) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(overlappingPair.collider1) != mCollidersComponents.getBroadPhaseId(overlappingPair.collider2));
|
||||
|
||||
|
||||
const Entity collider1Entity = mOverlappingPairs.mColliders1[i];
|
||||
const Entity collider2Entity = mOverlappingPairs.mColliders2[i];
|
||||
const Entity collider1Entity = overlappingPair.collider1;
|
||||
const Entity collider2Entity = overlappingPair.collider2;
|
||||
|
||||
const uint collider1Index = mCollidersComponents.getEntityIndex(collider1Entity);
|
||||
const uint collider2Index = mCollidersComponents.getEntityIndex(collider2Entity);
|
||||
|
@ -284,7 +318,7 @@ void CollisionDetectionSystem::computeMiddlePhase(NarrowPhaseInput& narrowPhaseI
|
|||
CollisionShape* collisionShape1 = mCollidersComponents.mCollisionShapes[collider1Index];
|
||||
CollisionShape* collisionShape2 = mCollidersComponents.mCollisionShapes[collider2Index];
|
||||
|
||||
NarrowPhaseAlgorithmType algorithmType = mOverlappingPairs.mNarrowPhaseAlgorithmType[i];
|
||||
NarrowPhaseAlgorithmType algorithmType = overlappingPair.narrowPhaseAlgorithmType;
|
||||
|
||||
const bool isCollider1Trigger = mCollidersComponents.mIsTrigger[collider1Index];
|
||||
const bool isCollider2Trigger = mCollidersComponents.mIsTrigger[collider2Index];
|
||||
|
@ -292,32 +326,34 @@ void CollisionDetectionSystem::computeMiddlePhase(NarrowPhaseInput& narrowPhaseI
|
|||
|
||||
// No middle-phase is necessary, simply create a narrow phase info
|
||||
// for the narrow-phase collision detection
|
||||
narrowPhaseInput.addNarrowPhaseTest(mOverlappingPairs.mPairIds[i], i, collider1Entity, collider2Entity, collisionShape1, collisionShape2,
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider1Index],
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider2Index],
|
||||
algorithmType, reportContacts, mMemoryManager.getSingleFrameAllocator());
|
||||
narrowPhaseInput.addNarrowPhaseTest(overlappingPair.pairID, collider1Entity, collider2Entity, collisionShape1, collisionShape2,
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider1Index],
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider2Index],
|
||||
algorithmType, reportContacts, &overlappingPair.lastFrameCollisionInfo,
|
||||
mMemoryManager.getSingleFrameAllocator());
|
||||
|
||||
mOverlappingPairs.mCollidingInCurrentFrame[i] = false;
|
||||
overlappingPair.collidingInCurrentFrame = false;
|
||||
}
|
||||
|
||||
// For each possible convex vs concave pair of bodies
|
||||
const uint64 convexVsConcaveStartIndex = mOverlappingPairs.getConvexVsConcavePairsStartIndex();
|
||||
const uint64 nbConvexVsConcavePairs = mOverlappingPairs.getNbConvexVsConcavePairs();
|
||||
for (uint64 i=convexVsConcaveStartIndex; i < convexVsConcaveStartIndex + nbConvexVsConcavePairs; i++) {
|
||||
const uint64 nbConcavePairs = mOverlappingPairs.mConcavePairs.size();
|
||||
for (uint64 i=0; i < nbConcavePairs; i++) {
|
||||
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders1[i]) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders2[i]) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders1[i]) != mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders2[i]));
|
||||
OverlappingPairs::ConcaveOverlappingPair& overlappingPair = mOverlappingPairs.mConcavePairs[i];
|
||||
|
||||
computeConvexVsConcaveMiddlePhase(i, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
|
||||
assert(mCollidersComponents.getBroadPhaseId(overlappingPair.collider1) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(overlappingPair.collider2) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(overlappingPair.collider1) != mCollidersComponents.getBroadPhaseId(overlappingPair.collider2));
|
||||
|
||||
mOverlappingPairs.mCollidingInCurrentFrame[i] = false;
|
||||
computeConvexVsConcaveMiddlePhase(overlappingPair, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
|
||||
|
||||
overlappingPair.collidingInCurrentFrame = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>& convexPairs, List<uint64>& concavePairs, NarrowPhaseInput& narrowPhaseInput,
|
||||
bool reportContacts) {
|
||||
void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>& convexPairs, List<uint64>& concavePairs,
|
||||
NarrowPhaseInput& narrowPhaseInput, bool reportContacts) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::computeMiddlePhase()", mProfiler);
|
||||
|
||||
|
@ -333,11 +369,11 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
|
|||
|
||||
const uint64 pairId = convexPairs[p];
|
||||
|
||||
const uint64 pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
|
||||
assert(pairIndex < mOverlappingPairs.getNbPairs());
|
||||
const uint64 pairIndex = mOverlappingPairs.mMapConvexPairIdToPairIndex[pairId];
|
||||
assert(pairIndex < mOverlappingPairs.mConvexPairs.size());
|
||||
|
||||
const Entity collider1Entity = mOverlappingPairs.mColliders1[pairIndex];
|
||||
const Entity collider2Entity = mOverlappingPairs.mColliders2[pairIndex];
|
||||
const Entity collider1Entity = mOverlappingPairs.mConvexPairs[pairIndex].collider1;
|
||||
const Entity collider2Entity = mOverlappingPairs.mConvexPairs[pairIndex].collider2;
|
||||
|
||||
const uint collider1Index = mCollidersComponents.getEntityIndex(collider1Entity);
|
||||
const uint collider2Index = mCollidersComponents.getEntityIndex(collider2Entity);
|
||||
|
@ -349,14 +385,14 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
|
|||
CollisionShape* collisionShape1 = mCollidersComponents.mCollisionShapes[collider1Index];
|
||||
CollisionShape* collisionShape2 = mCollidersComponents.mCollisionShapes[collider2Index];
|
||||
|
||||
NarrowPhaseAlgorithmType algorithmType = mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex];
|
||||
NarrowPhaseAlgorithmType algorithmType = mOverlappingPairs.mConvexPairs[pairIndex].narrowPhaseAlgorithmType;
|
||||
|
||||
// No middle-phase is necessary, simply create a narrow phase info
|
||||
// for the narrow-phase collision detection
|
||||
narrowPhaseInput.addNarrowPhaseTest(pairId, pairIndex, collider1Entity, collider2Entity, collisionShape1, collisionShape2,
|
||||
narrowPhaseInput.addNarrowPhaseTest(pairId, collider1Entity, collider2Entity, collisionShape1, collisionShape2,
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider1Index],
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider2Index],
|
||||
algorithmType, reportContacts, mMemoryManager.getSingleFrameAllocator());
|
||||
algorithmType, reportContacts, &mOverlappingPairs.mConvexPairs[pairIndex].lastFrameCollisionInfo, mMemoryManager.getSingleFrameAllocator());
|
||||
|
||||
}
|
||||
|
||||
|
@ -365,23 +401,23 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
|
|||
for (uint p=0; p < nbConcavePairs; p++) {
|
||||
|
||||
const uint64 pairId = concavePairs[p];
|
||||
const uint64 pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
|
||||
const uint64 pairIndex = mOverlappingPairs.mMapConcavePairIdToPairIndex[pairId];
|
||||
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders1[pairIndex]) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders2[pairIndex]) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders1[pairIndex]) != mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mColliders2[pairIndex]));
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mConcavePairs[pairIndex].collider1) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mConcavePairs[pairIndex].collider2) != -1);
|
||||
assert(mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mConcavePairs[pairIndex].collider1) != mCollidersComponents.getBroadPhaseId(mOverlappingPairs.mConcavePairs[pairIndex].collider2));
|
||||
|
||||
computeConvexVsConcaveMiddlePhase(pairIndex, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
|
||||
computeConvexVsConcaveMiddlePhase(mOverlappingPairs.mConcavePairs[pairIndex], mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the concave vs convex middle-phase algorithm for a given pair of bodies
|
||||
void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairIndex, MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput) {
|
||||
void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(OverlappingPairs::ConcaveOverlappingPair& overlappingPair, MemoryAllocator& allocator, NarrowPhaseInput& narrowPhaseInput) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase()", mProfiler);
|
||||
|
||||
const Entity collider1 = mOverlappingPairs.mColliders1[pairIndex];
|
||||
const Entity collider2 = mOverlappingPairs.mColliders2[pairIndex];
|
||||
const Entity collider1 = overlappingPair.collider1;
|
||||
const Entity collider2 = overlappingPair.collider2;
|
||||
|
||||
const uint collider1Index = mCollidersComponents.getEntityIndex(collider1);
|
||||
const uint collider2Index = mCollidersComponents.getEntityIndex(collider2);
|
||||
|
@ -394,8 +430,7 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairInde
|
|||
// Collision shape 1 is convex, collision shape 2 is concave
|
||||
ConvexShape* convexShape;
|
||||
ConcaveShape* concaveShape;
|
||||
const bool isShape1Convex = mOverlappingPairs.mIsShape1Convex[pairIndex];
|
||||
if (isShape1Convex) {
|
||||
if (overlappingPair.isShape1Convex) {
|
||||
convexShape = static_cast<ConvexShape*>(mCollidersComponents.mCollisionShapes[collider1Index]);
|
||||
concaveShape = static_cast<ConcaveShape*>(mCollidersComponents.mCollisionShapes[collider2Index]);
|
||||
convexToConcaveTransform = shape2LocalToWorldTransform.getInverse() * shape1LocalToWorldTransform;
|
||||
|
@ -408,16 +443,16 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairInde
|
|||
|
||||
assert(convexShape->isConvex());
|
||||
assert(!concaveShape->isConvex());
|
||||
assert(mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex] != NarrowPhaseAlgorithmType::None);
|
||||
assert(overlappingPair.narrowPhaseAlgorithmType != NarrowPhaseAlgorithmType::None);
|
||||
|
||||
// Compute the convex shape AABB in the local-space of the convex shape
|
||||
AABB aabb;
|
||||
convexShape->computeAABB(aabb, convexToConcaveTransform);
|
||||
|
||||
// Compute the concave shape triangles that are overlapping with the convex mesh AABB
|
||||
List<Vector3> triangleVertices(allocator);
|
||||
List<Vector3> triangleVerticesNormals(allocator);
|
||||
List<uint> shapeIds(allocator);
|
||||
List<Vector3> triangleVertices(allocator, 64);
|
||||
List<Vector3> triangleVerticesNormals(allocator, 64);
|
||||
List<uint> shapeIds(allocator, 64);
|
||||
concaveShape->computeOverlappingTriangles(aabb, triangleVertices, triangleVerticesNormals, shapeIds, allocator);
|
||||
|
||||
assert(triangleVertices.size() == triangleVerticesNormals.size());
|
||||
|
@ -429,10 +464,20 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairInde
|
|||
const bool isCollider2Trigger = mCollidersComponents.mIsTrigger[collider2Index];
|
||||
const bool reportContacts = !isCollider1Trigger && !isCollider2Trigger;
|
||||
|
||||
CollisionShape* shape1;
|
||||
CollisionShape* shape2;
|
||||
|
||||
if (overlappingPair.isShape1Convex) {
|
||||
shape1 = convexShape;
|
||||
}
|
||||
else {
|
||||
shape2 = convexShape;
|
||||
}
|
||||
|
||||
// For each overlapping triangle
|
||||
const uint nbShapeIds = shapeIds.size();
|
||||
for (uint i=0; i < nbShapeIds; i++)
|
||||
{
|
||||
for (uint i=0; i < nbShapeIds; i++) {
|
||||
|
||||
// Create a triangle collision shape (the allocated memory for the TriangleShape will be released in the
|
||||
// destructor of the corresponding NarrowPhaseInfo.
|
||||
TriangleShape* triangleShape = new (allocator.allocate(sizeof(TriangleShape)))
|
||||
|
@ -446,11 +491,20 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairInde
|
|||
|
||||
#endif
|
||||
|
||||
if (overlappingPair.isShape1Convex) {
|
||||
shape2 = triangleShape;
|
||||
}
|
||||
else {
|
||||
shape1 = triangleShape;
|
||||
}
|
||||
|
||||
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
|
||||
LastFrameCollisionInfo* lastFrameInfo = overlappingPair.addLastFrameInfoIfNecessary(shape1->getId(), shape2->getId());
|
||||
|
||||
// Create a narrow phase info for the narrow-phase collision detection
|
||||
narrowPhaseInput.addNarrowPhaseTest(mOverlappingPairs.mPairIds[pairIndex], pairIndex, collider1, collider2, isShape1Convex ? convexShape : triangleShape,
|
||||
isShape1Convex ? triangleShape : convexShape,
|
||||
shape1LocalToWorldTransform, shape2LocalToWorldTransform,
|
||||
mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex], reportContacts, allocator);
|
||||
narrowPhaseInput.addNarrowPhaseTest(overlappingPair.pairID, collider1, collider2, shape1, shape2,
|
||||
shape1LocalToWorldTransform, shape2LocalToWorldTransform,
|
||||
overlappingPair.narrowPhaseAlgorithmType, reportContacts, lastFrameInfo, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,7 +678,8 @@ void CollisionDetectionSystem::notifyOverlappingPairsToTestOverlap(Collider* col
|
|||
// Get the overlapping pairs involved with this collider
|
||||
List<uint64>& overlappingPairs = mCollidersComponents.getOverlappingPairs(collider->getEntity());
|
||||
|
||||
for (uint i=0; i < overlappingPairs.size(); i++) {
|
||||
const uint nbPairs = overlappingPairs.size();
|
||||
for (uint i=0; i < nbPairs; i++) {
|
||||
|
||||
// Notify that the overlapping pair needs to be testbed for overlap
|
||||
mOverlappingPairs.setNeedToTestOverlap(overlappingPairs[i], true);
|
||||
|
@ -802,17 +857,34 @@ void CollisionDetectionSystem::createContacts() {
|
|||
// Compute the lost contact pairs (contact pairs in contact in the previous frame but not in the current one)
|
||||
void CollisionDetectionSystem::computeLostContactPairs() {
|
||||
|
||||
// For each overlapping pair
|
||||
for (uint i=0; i < mOverlappingPairs.getNbPairs(); i++) {
|
||||
// For each convex pair
|
||||
const uint nbConvexPairs = mOverlappingPairs.mConvexPairs.size();
|
||||
for (uint i=0; i < nbConvexPairs; i++) {
|
||||
|
||||
// If the two colliders of the pair were colliding in the previous frame but not in the current one
|
||||
if (mOverlappingPairs.mCollidingInPreviousFrame[i] && !mOverlappingPairs.mCollidingInCurrentFrame[i]) {
|
||||
if (mOverlappingPairs.mConvexPairs[i].collidingInPreviousFrame && !mOverlappingPairs.mConvexPairs[i].collidingInCurrentFrame) {
|
||||
|
||||
// If both bodies still exist
|
||||
if (mCollidersComponents.hasComponent(mOverlappingPairs.mColliders1[i]) && mCollidersComponents.hasComponent(mOverlappingPairs.mColliders2[i])) {
|
||||
if (mCollidersComponents.hasComponent(mOverlappingPairs.mConvexPairs[i].collider1) && mCollidersComponents.hasComponent(mOverlappingPairs.mConvexPairs[i].collider2)) {
|
||||
|
||||
// Create a lost contact pair
|
||||
addLostContactPair(i);
|
||||
addLostContactPair(mOverlappingPairs.mConvexPairs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each convex pair
|
||||
const uint nbConcavePairs = mOverlappingPairs.mConcavePairs.size();
|
||||
for (uint i=0; i < nbConcavePairs; i++) {
|
||||
|
||||
// If the two colliders of the pair were colliding in the previous frame but not in the current one
|
||||
if (mOverlappingPairs.mConcavePairs[i].collidingInPreviousFrame && !mOverlappingPairs.mConcavePairs[i].collidingInCurrentFrame) {
|
||||
|
||||
// If both bodies still exist
|
||||
if (mCollidersComponents.hasComponent(mOverlappingPairs.mConcavePairs[i].collider1) && mCollidersComponents.hasComponent(mOverlappingPairs.mConcavePairs[i].collider2)) {
|
||||
|
||||
// Create a lost contact pair
|
||||
addLostContactPair(mOverlappingPairs.mConcavePairs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1025,13 +1097,14 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
|
|||
// For each narrow phase info object
|
||||
for(uint i=0; i < nbObjects; i++) {
|
||||
|
||||
const uint64 pairId = narrowPhaseInfoBatch.narrowPhaseInfos[i].overlappingPairId;
|
||||
const uint64 pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
|
||||
|
||||
// If the two colliders are colliding
|
||||
if (narrowPhaseInfoBatch.narrowPhaseInfos[i].isColliding) {
|
||||
|
||||
mOverlappingPairs.mCollidingInCurrentFrame[pairIndex] = true;
|
||||
const uint64 pairId = narrowPhaseInfoBatch.narrowPhaseInfos[i].overlappingPairId;
|
||||
OverlappingPairs::OverlappingPair* overlappingPair = mOverlappingPairs.getOverlappingPair(pairId);
|
||||
assert(overlappingPair != nullptr);
|
||||
|
||||
overlappingPair->collidingInCurrentFrame = true;
|
||||
|
||||
const Entity collider1Entity = narrowPhaseInfoBatch.narrowPhaseInfos[i].colliderEntity1;
|
||||
const Entity collider2Entity = narrowPhaseInfoBatch.narrowPhaseInfos[i].colliderEntity2;
|
||||
|
@ -1043,8 +1116,7 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
|
|||
const Entity body2Entity = mCollidersComponents.mBodiesEntities[collider2Index];
|
||||
|
||||
// If we have a convex vs convex collision (if we consider the base collision shapes of the colliders)
|
||||
if (mCollidersComponents.mCollisionShapes[collider1Index]->isConvex() &&
|
||||
mCollidersComponents.mCollisionShapes[collider2Index]->isConvex()) {
|
||||
if (mCollidersComponents.mCollisionShapes[collider1Index]->isConvex() && mCollidersComponents.mCollisionShapes[collider2Index]->isConvex()) {
|
||||
|
||||
// Create a new ContactPair
|
||||
|
||||
|
@ -1055,7 +1127,7 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
|
|||
const uint newContactPairIndex = contactPairs->size();
|
||||
|
||||
contactPairs->emplace(pairId, body1Entity, body2Entity, collider1Entity, collider2Entity,
|
||||
newContactPairIndex, mOverlappingPairs.getCollidingInPreviousFrame(pairId), isTrigger);
|
||||
newContactPairIndex, overlappingPair->collidingInPreviousFrame, isTrigger);
|
||||
|
||||
ContactPair* pairContact = &((*contactPairs)[newContactPairIndex]);
|
||||
|
||||
|
@ -1102,7 +1174,7 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
|
|||
|
||||
const uint newContactPairIndex = contactPairs->size();
|
||||
contactPairs->emplace(pairId, body1Entity, body2Entity, collider1Entity, collider2Entity,
|
||||
newContactPairIndex, mOverlappingPairs.getCollidingInPreviousFrame(pairId), isTrigger);
|
||||
newContactPairIndex, overlappingPair->collidingInPreviousFrame , isTrigger);
|
||||
pairContact = &((*contactPairs)[newContactPairIndex]);
|
||||
mapPairIdToContactPairIndex.add(Pair<uint64, uint>(pairId, newContactPairIndex));
|
||||
|
||||
|
@ -1236,9 +1308,7 @@ void CollisionDetectionSystem::reducePotentialContactManifolds(List<ContactPair>
|
|||
// If there are two many contact points in the manifold
|
||||
if (manifold.nbPotentialContactPoints > MAX_CONTACT_POINTS_IN_MANIFOLD) {
|
||||
|
||||
Entity collider1 = mOverlappingPairs.mColliders1[mOverlappingPairs.mMapPairIdToPairIndex[manifold.pairId]];
|
||||
|
||||
Transform shape1LocalToWorldTransoform = mCollidersComponents.getLocalToWorldTransform(collider1);
|
||||
Transform shape1LocalToWorldTransoform = mCollidersComponents.getLocalToWorldTransform(pairContact.collider1Entity);
|
||||
|
||||
// Reduce the number of contact points in the manifold
|
||||
reduceContactPoints(manifold, shape1LocalToWorldTransoform, potentialContactPoints);
|
||||
|
@ -1655,18 +1725,25 @@ void CollisionDetectionSystem::testCollision(CollisionCallback& callback) {
|
|||
// Filter the overlapping pairs to keep only the pairs where a given body is involved
|
||||
void CollisionDetectionSystem::filterOverlappingPairs(Entity bodyEntity, List<uint64>& convexPairs, List<uint64>& concavePairs) const {
|
||||
|
||||
// For each possible collision pair of bodies
|
||||
for (uint i=0; i < mOverlappingPairs.getNbPairs(); i++) {
|
||||
// For each convex pairs
|
||||
const uint nbConvexPairs = mOverlappingPairs.mConvexPairs.size();
|
||||
for (uint i=0; i < nbConvexPairs; i++) {
|
||||
|
||||
if (mCollidersComponents.getBody(mOverlappingPairs.mColliders1[i]) == bodyEntity ||
|
||||
mCollidersComponents.getBody(mOverlappingPairs.mColliders2[i]) == bodyEntity) {
|
||||
if (mCollidersComponents.getBody(mOverlappingPairs.mConvexPairs[i].collider1) == bodyEntity ||
|
||||
mCollidersComponents.getBody(mOverlappingPairs.mConvexPairs[i].collider2) == bodyEntity) {
|
||||
|
||||
if (i < mOverlappingPairs.getNbConvexVsConvexPairs()) {
|
||||
convexPairs.add(mOverlappingPairs.mPairIds[i]);
|
||||
}
|
||||
else {
|
||||
concavePairs.add(mOverlappingPairs.mPairIds[i]);
|
||||
}
|
||||
convexPairs.add(mOverlappingPairs.mConvexPairs[i].pairID);
|
||||
}
|
||||
}
|
||||
|
||||
// For each concave pairs
|
||||
const uint nbConcavePairs = mOverlappingPairs.mConcavePairs.size();
|
||||
for (uint i=0; i < nbConcavePairs; i++) {
|
||||
|
||||
if (mCollidersComponents.getBody(mOverlappingPairs.mConcavePairs[i].collider1) == bodyEntity ||
|
||||
mCollidersComponents.getBody(mOverlappingPairs.mConcavePairs[i].collider2) == bodyEntity) {
|
||||
|
||||
concavePairs.add(mOverlappingPairs.mConcavePairs[i].pairID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1674,21 +1751,31 @@ void CollisionDetectionSystem::filterOverlappingPairs(Entity bodyEntity, List<ui
|
|||
// Filter the overlapping pairs to keep only the pairs where two given bodies are involved
|
||||
void CollisionDetectionSystem::filterOverlappingPairs(Entity body1Entity, Entity body2Entity, List<uint64>& convexPairs, List<uint64>& concavePairs) const {
|
||||
|
||||
// For each possible collision pair of bodies
|
||||
for (uint i=0; i < mOverlappingPairs.getNbPairs(); i++) {
|
||||
// For each convex pair
|
||||
const uint nbConvexPairs = mOverlappingPairs.mConvexPairs.size();
|
||||
for (uint i=0; i < nbConvexPairs; i++) {
|
||||
|
||||
const Entity collider1Body = mCollidersComponents.getBody(mOverlappingPairs.mColliders1[i]);
|
||||
const Entity collider2Body = mCollidersComponents.getBody(mOverlappingPairs.mColliders2[i]);
|
||||
const Entity collider1Body = mCollidersComponents.getBody(mOverlappingPairs.mConvexPairs[i].collider1);
|
||||
const Entity collider2Body = mCollidersComponents.getBody(mOverlappingPairs.mConvexPairs[i].collider2);
|
||||
|
||||
if ((collider1Body == body1Entity && collider2Body == body2Entity) ||
|
||||
(collider1Body == body2Entity && collider2Body == body1Entity)) {
|
||||
|
||||
if (i < mOverlappingPairs.getNbConvexVsConvexPairs()) {
|
||||
convexPairs.add(mOverlappingPairs.mPairIds[i]);
|
||||
}
|
||||
else {
|
||||
concavePairs.add(mOverlappingPairs.mPairIds[i]);
|
||||
}
|
||||
convexPairs.add(mOverlappingPairs.mConvexPairs[i].pairID);
|
||||
}
|
||||
}
|
||||
|
||||
// For each concave pair
|
||||
const uint nbConcavePairs = mOverlappingPairs.mConcavePairs.size();
|
||||
for (uint i=0; i < nbConcavePairs; i++) {
|
||||
|
||||
const Entity collider1Body = mCollidersComponents.getBody(mOverlappingPairs.mConcavePairs[i].collider1);
|
||||
const Entity collider2Body = mCollidersComponents.getBody(mOverlappingPairs.mConcavePairs[i].collider2);
|
||||
|
||||
if ((collider1Body == body1Entity && collider2Body == body2Entity) ||
|
||||
(collider1Body == body2Entity && collider2Body == body1Entity)) {
|
||||
|
||||
concavePairs.add(mOverlappingPairs.mConcavePairs[i].pairID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user