Improve EventListener: add onTrigger() method, add event types, add triggers, ...
This commit is contained in:
parent
a190bba8c0
commit
dcd71ef103
|
@ -20,6 +20,9 @@
|
|||
- The RigidBody::getLocalInertiaTensor() method has been added to retrieve the local-space inertia tensor of a rigid body.
|
||||
- The RigidBody::updateMassFromColliders() method has been added to compute and set the mass of a body using its colliders
|
||||
- A Material nows has a mass density parameter that can be set using the Material::setMassDensity() method. The mass density is used to compute the mass of a collider when computing the mass of a rigid body
|
||||
- A Collider can now be a trigger. This collider will be used to only report collisions with another collider but no collision response will be applied. You can use the Collider::setIsTrigger() method for this.
|
||||
- The EventListener class now has a onTrigger() method that is called when a trigger collider is colling with another collider.
|
||||
- In the EventListener, the onContact() and onTrigger() method now reports the type of event (start, stay, exit) for each contact. This way the user can know whether it's a new contact or not or when two colliders are not in contact anymore.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
|
|
@ -160,6 +160,12 @@ class Collider {
|
|||
/// Set a new material for this collider
|
||||
void setMaterial(const Material& material);
|
||||
|
||||
/// Return true if the collider is a trigger
|
||||
bool getIsTrigger() const;
|
||||
|
||||
/// Set whether the collider is a trigger
|
||||
void setIsTrigger(bool isTrigger) const;
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
/// Set the profiler
|
||||
|
|
|
@ -108,6 +108,22 @@ class CollisionCallback {
|
|||
*/
|
||||
class ContactPair {
|
||||
|
||||
public:
|
||||
|
||||
/// Enumeration EventType that describes the type of contact event
|
||||
enum class EventType {
|
||||
|
||||
/// This contact is a new contact between the two
|
||||
/// colliders (the colliders where not touching in the previous frame)
|
||||
ContactStart,
|
||||
|
||||
/// The two colliders were already touching in the previous frame and this is a new or updated contact
|
||||
ContactStay,
|
||||
|
||||
/// The two colliders were in contact in the previous frame and are not in contact anymore
|
||||
ContactExit
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
@ -120,11 +136,14 @@ class CollisionCallback {
|
|||
/// Reference to the physics world
|
||||
PhysicsWorld& mWorld;
|
||||
|
||||
/// True if this is a lost contact pair (contact pair colliding in previous frame but not in current one)
|
||||
bool mIsLostContactPair;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactPair(const reactphysics3d::ContactPair& contactPair, List<reactphysics3d::ContactPoint>* contactPoints,
|
||||
PhysicsWorld& world);
|
||||
ContactPair(const reactphysics3d::ContactPair& contactPair, List<reactphysics3d::ContactPoint>* contactPoints,
|
||||
PhysicsWorld& world, bool mIsLostContactPair);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -157,6 +176,9 @@ class CollisionCallback {
|
|||
/// Return a pointer to the second collider in contact (in body 2)
|
||||
Collider* getCollider2() const;
|
||||
|
||||
/// Return the corresponding type of event for this contact pair
|
||||
EventType getEventType() const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class CollisionCallback;
|
||||
|
@ -172,7 +194,7 @@ class CollisionCallback {
|
|||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Pointer to the list of contact pairs
|
||||
/// Pointer to the list of contact pairs (contains contacts and triggers events)
|
||||
List<reactphysics3d::ContactPair>* mContactPairs;
|
||||
|
||||
/// Pointer to the list of contact manifolds
|
||||
|
@ -181,6 +203,15 @@ class CollisionCallback {
|
|||
/// Pointer to the contact points
|
||||
List<reactphysics3d::ContactPoint>* mContactPoints;
|
||||
|
||||
/// Pointer to the list of lost contact pairs (contains contacts and triggers events)
|
||||
List<reactphysics3d::ContactPair>& mLostContactPairs;
|
||||
|
||||
/// List of indices of the mContactPairs list that are contact events (not overlap/triggers)
|
||||
List<uint> mContactPairsIndices;
|
||||
|
||||
/// List of indices of the mLostContactPairs list that are contact events (not overlap/triggers)
|
||||
List<uint> mLostContactPairsIndices;
|
||||
|
||||
/// Reference to the physics world
|
||||
PhysicsWorld& mWorld;
|
||||
|
||||
|
@ -188,7 +219,8 @@ class CollisionCallback {
|
|||
|
||||
/// Constructor
|
||||
CallbackData(List<reactphysics3d::ContactPair>* contactPairs, List<ContactManifold>* manifolds,
|
||||
List<reactphysics3d::ContactPoint>* contactPoints, PhysicsWorld& world);
|
||||
List<reactphysics3d::ContactPoint>* contactPoints, List<reactphysics3d::ContactPair>& lostContactPairs,
|
||||
PhysicsWorld& world);
|
||||
|
||||
/// Deleted copy constructor
|
||||
CallbackData(const CallbackData& callbackData) = delete;
|
||||
|
@ -226,7 +258,7 @@ class CollisionCallback {
|
|||
* @return The number of contact pairs
|
||||
*/
|
||||
inline uint CollisionCallback::CallbackData::getNbContactPairs() const {
|
||||
return mContactPairs->size();
|
||||
return mContactPairsIndices.size() + mLostContactPairsIndices.size();
|
||||
}
|
||||
|
||||
// Return the number of contact points in the contact pair
|
||||
|
|
|
@ -80,15 +80,21 @@ struct ContactPair {
|
|||
/// Total number of contact points in all the manifolds of the contact pair
|
||||
uint nbToTalContactPoints;
|
||||
|
||||
/// True if the colliders of the pair were already colliding in the previous frame
|
||||
bool collidingInPreviousFrame;
|
||||
|
||||
/// True if one of the two involved colliders is a trigger
|
||||
bool isTrigger;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactPair(uint64 pairId, Entity body1Entity, Entity body2Entity, Entity collider1Entity,
|
||||
Entity collider2Entity, uint contactPairIndex, MemoryAllocator& allocator)
|
||||
Entity collider2Entity, uint contactPairIndex, bool collidingInPreviousFrame, bool isTrigger, MemoryAllocator& allocator)
|
||||
: pairId(pairId), potentialContactManifoldsIndices(allocator), body1Entity(body1Entity), body2Entity(body2Entity),
|
||||
collider1Entity(collider1Entity), collider2Entity(collider2Entity),
|
||||
isAlreadyInIsland(false), contactPairIndex(contactPairIndex), contactManifoldsIndex(0), nbContactManifolds(0),
|
||||
contactPointsIndex(0), nbToTalContactPoints(0) {
|
||||
contactPointsIndex(0), nbToTalContactPoints(0), collidingInPreviousFrame(collidingInPreviousFrame), isTrigger(isTrigger) {
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
// Libraries
|
||||
#include <reactphysics3d/containers/List.h>
|
||||
#include <reactphysics3d/collision/ContactPair.h>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
@ -53,20 +54,39 @@ class OverlapCallback {
|
|||
*/
|
||||
class OverlapPair {
|
||||
|
||||
public:
|
||||
|
||||
/// Enumeration EventType that describes the type of overlapping event
|
||||
enum class EventType {
|
||||
|
||||
/// This overlap is a new overlap between the two
|
||||
/// colliders (the colliders where not overlapping in the previous frame)
|
||||
OverlapStart,
|
||||
|
||||
/// The two colliders were already overlapping in the previous frame and this is a new or updated overlap
|
||||
OverlapStay,
|
||||
|
||||
/// The two colliders were overlapping in the previous frame and are not overlapping anymore
|
||||
OverlapExit
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Pair of overlapping body entities
|
||||
Pair<Entity, Entity>& mOverlapPair;
|
||||
/// Contact pair
|
||||
ContactPair& mContactPair;
|
||||
|
||||
/// Reference to the physics world
|
||||
PhysicsWorld& mWorld;
|
||||
|
||||
/// True if the pair were overlapping in the previous frame but not in the current one
|
||||
bool mIsLostOverlapPair;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
OverlapPair(Pair<Entity, Entity>& overlapPair, reactphysics3d::PhysicsWorld& world);
|
||||
OverlapPair(ContactPair& contactPair, reactphysics3d::PhysicsWorld& world, bool isLostOverlappingPair);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -81,12 +101,21 @@ class OverlapCallback {
|
|||
/// Destructor
|
||||
~OverlapPair() = default;
|
||||
|
||||
/// Return a pointer to the first collider in contact
|
||||
Collider* getCollider1() const;
|
||||
|
||||
/// Return a pointer to the second collider in contact
|
||||
Collider* getCollider2() const;
|
||||
|
||||
/// Return a pointer to the first body in contact
|
||||
CollisionBody* getBody1() const;
|
||||
|
||||
/// Return a pointer to the second body in contact
|
||||
CollisionBody* getBody2() const;
|
||||
|
||||
/// Return the corresponding type of event for this overlapping pair
|
||||
EventType getEventType() const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class OverlapCallback;
|
||||
|
@ -102,7 +131,17 @@ class OverlapCallback {
|
|||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
List<Pair<Entity, Entity>>& mOverlapBodies;
|
||||
/// Reference to the list of contact pairs (contains contacts and triggers events)
|
||||
List<ContactPair>& mContactPairs;
|
||||
|
||||
/// Reference to the list of lost contact pairs (contains contacts and triggers events)
|
||||
List<ContactPair>& mLostContactPairs;
|
||||
|
||||
/// List of indices of the mContactPairs list that are overlap/triggers events (not contact events)
|
||||
List<uint> mContactPairsIndices;
|
||||
|
||||
/// List of indices of the mLostContactPairs list that are overlap/triggers events (not contact events)
|
||||
List<uint> mLostContactPairsIndices;
|
||||
|
||||
/// Reference to the physics world
|
||||
PhysicsWorld& mWorld;
|
||||
|
@ -110,7 +149,7 @@ class OverlapCallback {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
CallbackData(List<Pair<Entity, Entity>>& overlapColliders, PhysicsWorld& world);
|
||||
CallbackData(List<ContactPair>& contactPairs, List<ContactPair>& lostContactPairs, PhysicsWorld& world);
|
||||
|
||||
/// Deleted copy constructor
|
||||
CallbackData(const CallbackData& callbackData) = delete;
|
||||
|
@ -147,7 +186,7 @@ class OverlapCallback {
|
|||
|
||||
// Return the number of overlapping pairs of bodies
|
||||
inline uint OverlapCallback::CallbackData::getNbOverlappingPairs() const {
|
||||
return mOverlapBodies.size();
|
||||
return mContactPairsIndices.size() + mLostContactPairsIndices.size();
|
||||
}
|
||||
|
||||
// Return a given overlapping pair of bodies
|
||||
|
@ -158,7 +197,15 @@ inline OverlapCallback::OverlapPair OverlapCallback::CallbackData::getOverlappin
|
|||
|
||||
assert(index < getNbOverlappingPairs());
|
||||
|
||||
return OverlapPair(mOverlapBodies[index], mWorld);
|
||||
if (index < mContactPairsIndices.size()) {
|
||||
// Return a contact pair
|
||||
return OverlapCallback::OverlapPair((mContactPairs)[mContactPairsIndices[index]], mWorld, false);
|
||||
}
|
||||
else {
|
||||
|
||||
// Return a lost contact pair
|
||||
return OverlapCallback::OverlapPair(mLostContactPairs[mLostContactPairsIndices[index - mContactPairsIndices.size()]], mWorld, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ class CapsuleVsCapsuleAlgorithm : public NarrowPhaseAlgorithm {
|
|||
|
||||
/// Compute the narrow-phase collision detection between two capsules
|
||||
bool testCollision(CapsuleVsCapsuleNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
|
||||
uint batchNbItems, bool reportContacts, MemoryAllocator& memoryAllocator);
|
||||
uint batchNbItems, MemoryAllocator& memoryAllocator);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -58,18 +58,18 @@ struct CapsuleVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
|
|||
CapsuleVsCapsuleNarrowPhaseInfoBatch(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
|
||||
|
||||
/// Destructor
|
||||
virtual ~CapsuleVsCapsuleNarrowPhaseInfoBatch() = default;
|
||||
virtual ~CapsuleVsCapsuleNarrowPhaseInfoBatch() override = default;
|
||||
|
||||
/// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
CollisionShape* shape2, const Transform& shape1Transform,
|
||||
const Transform& shape2Transform);
|
||||
const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator& shapeAllocator) override;
|
||||
|
||||
// Initialize the containers using cached capacity
|
||||
virtual void reserveMemory();
|
||||
virtual void reserveMemory() override;
|
||||
|
||||
/// Clear all the objects in the batch
|
||||
virtual void clear();
|
||||
virtual void clear() override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ class CapsuleVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm {
|
|||
|
||||
/// Compute the narrow-phase collision detection between a capsule and a polyhedron
|
||||
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
|
||||
uint batchNbItems, bool reportContacts, bool clipWithPreviousAxisIfStillColliding,
|
||||
uint batchNbItems, bool clipWithPreviousAxisIfStillColliding,
|
||||
MemoryAllocator& memoryAllocator);
|
||||
};
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ class ConvexPolyhedronVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm
|
|||
ConvexPolyhedronVsConvexPolyhedronAlgorithm& operator=(const ConvexPolyhedronVsConvexPolyhedronAlgorithm& algorithm) = delete;
|
||||
|
||||
/// Compute the narrow-phase collision detection between two convex polyhedra
|
||||
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems, bool reportContacts,
|
||||
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
|
||||
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator);
|
||||
};
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ class GJKAlgorithm {
|
|||
|
||||
/// Compute a contact info if the two bounding volumes collide.
|
||||
void testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
|
||||
uint batchNbItems, List<GJKResult>& gjkResults, bool reportContacts);
|
||||
uint batchNbItems, List<GJKResult>& gjkResults);
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
|
|
|
@ -81,6 +81,9 @@ struct NarrowPhaseInfoBatch {
|
|||
/// List of transforms that maps from collision shape 2 local-space to world-space
|
||||
List<Transform> shape2ToWorldTransforms;
|
||||
|
||||
/// True for each pair of objects that we need to report contacts (false for triggers for instance)
|
||||
List<bool> reportContacts;
|
||||
|
||||
/// Result of the narrow-phase collision detection test
|
||||
List<bool> isColliding;
|
||||
|
||||
|
@ -103,9 +106,9 @@ struct NarrowPhaseInfoBatch {
|
|||
uint getNbObjects() const;
|
||||
|
||||
/// 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,
|
||||
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
CollisionShape* shape2, const Transform& shape1Transform,
|
||||
const Transform& shape2Transform, MemoryAllocator& shapeAllocator);
|
||||
const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator& shapeAllocator);
|
||||
|
||||
/// Add a new contact point
|
||||
virtual void addContactPoint(uint index, const Vector3& contactNormal, decimal penDepth,
|
||||
|
|
|
@ -61,6 +61,7 @@ class NarrowPhaseInput {
|
|||
NarrowPhaseInfoBatch mSphereVsConvexPolyhedronBatch;
|
||||
NarrowPhaseInfoBatch mCapsuleVsConvexPolyhedronBatch;
|
||||
NarrowPhaseInfoBatch mConvexPolyhedronVsConvexPolyhedronBatch;
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
|
@ -69,7 +70,7 @@ class NarrowPhaseInput {
|
|||
/// 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,
|
||||
CollisionShape* shape2, const Transform& shape1Transform,
|
||||
const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType,
|
||||
const Transform& shape2Transform, NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, bool reportContacts,
|
||||
MemoryAllocator& shapeAllocator);
|
||||
|
||||
/// Get a reference to the sphere vs sphere batch
|
||||
|
@ -98,32 +99,32 @@ class NarrowPhaseInput {
|
|||
};
|
||||
|
||||
|
||||
// Get a reference to the sphere vs sphere batch
|
||||
// Get a reference to the sphere vs sphere batch contacts
|
||||
inline SphereVsSphereNarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsSphereBatch() {
|
||||
return mSphereVsSphereBatch;
|
||||
}
|
||||
|
||||
// Get a reference to the sphere vs capsule batch
|
||||
// Get a reference to the sphere vs capsule batch contacts
|
||||
inline SphereVsCapsuleNarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsCapsuleBatch() {
|
||||
return mSphereVsCapsuleBatch;
|
||||
}
|
||||
|
||||
// Get a reference to the capsule vs capsule batch
|
||||
// Get a reference to the capsule vs capsule batch contacts
|
||||
inline CapsuleVsCapsuleNarrowPhaseInfoBatch& NarrowPhaseInput::getCapsuleVsCapsuleBatch() {
|
||||
return mCapsuleVsCapsuleBatch;
|
||||
}
|
||||
|
||||
// Get a reference to the sphere vs convex polyhedron batch
|
||||
// Get a reference to the sphere vs convex polyhedron batch contacts
|
||||
inline NarrowPhaseInfoBatch& NarrowPhaseInput::getSphereVsConvexPolyhedronBatch() {
|
||||
return mSphereVsConvexPolyhedronBatch;
|
||||
}
|
||||
|
||||
// Get a reference to the capsule vs convex polyhedron batch
|
||||
// Get a reference to the capsule vs convex polyhedron batch contacts
|
||||
inline NarrowPhaseInfoBatch& NarrowPhaseInput::getCapsuleVsConvexPolyhedronBatch() {
|
||||
return mCapsuleVsConvexPolyhedronBatch;
|
||||
}
|
||||
|
||||
// Get a reference to the convex polyhedron vs convex polyhedron batch
|
||||
// Get a reference to the convex polyhedron vs convex polyhedron batch contacts
|
||||
inline NarrowPhaseInfoBatch& NarrowPhaseInput::getConvexPolyhedronVsConvexPolyhedronBatch() {
|
||||
return mConvexPolyhedronVsConvexPolyhedronBatch;
|
||||
}
|
||||
|
|
|
@ -154,11 +154,10 @@ class SATAlgorithm {
|
|||
|
||||
/// Test collision between a sphere and a convex mesh
|
||||
bool testCollisionSphereVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch,
|
||||
uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts) const;
|
||||
uint batchStartIndex, uint batchNbItems) const;
|
||||
|
||||
/// Test collision between a capsule and a convex mesh
|
||||
bool testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex, bool reportContacts) const;
|
||||
bool testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex) const;
|
||||
|
||||
/// Compute the two contact points between a polyhedron and a capsule when the separating axis is a face normal of the polyhedron
|
||||
bool computeCapsulePolyhedronFaceContactPoints(uint referenceFaceIndex, decimal capsuleRadius, const ConvexPolyhedronShape* polyhedron,
|
||||
|
@ -172,8 +171,7 @@ class SATAlgorithm {
|
|||
const Vector3& edgeAdjacentFace2Normal) const;
|
||||
|
||||
/// Test collision between two convex meshes
|
||||
bool testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
|
||||
uint batchNbItems, bool reportContacts) const;
|
||||
bool testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems) const;
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ class SphereVsCapsuleAlgorithm : public NarrowPhaseAlgorithm {
|
|||
|
||||
/// Compute the narrow-phase collision detection between a sphere and a capsule
|
||||
bool testCollision(SphereVsCapsuleNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
|
||||
uint batchNbItems, bool reportContacts, MemoryAllocator& memoryAllocator);
|
||||
uint batchNbItems, MemoryAllocator& memoryAllocator);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -58,18 +58,18 @@ struct SphereVsCapsuleNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
|
|||
SphereVsCapsuleNarrowPhaseInfoBatch(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs);
|
||||
|
||||
/// Destructor
|
||||
virtual ~SphereVsCapsuleNarrowPhaseInfoBatch() = default;
|
||||
virtual ~SphereVsCapsuleNarrowPhaseInfoBatch() override = default;
|
||||
|
||||
/// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
CollisionShape* shape2, const Transform& shape1Transform,
|
||||
const Transform& shape2Transform);
|
||||
const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator& shapeAllocator) override;
|
||||
|
||||
// Initialize the containers using cached capacity
|
||||
virtual void reserveMemory();
|
||||
virtual void reserveMemory() override;
|
||||
|
||||
/// Clear all the objects in the batch
|
||||
virtual void clear();
|
||||
virtual void clear() override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ class SphereVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm {
|
|||
SphereVsConvexPolyhedronAlgorithm& operator=(const SphereVsConvexPolyhedronAlgorithm& algorithm) = delete;
|
||||
|
||||
/// Compute the narrow-phase collision detection between a sphere and a convex polyhedron
|
||||
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems, bool reportContacts,
|
||||
bool testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
|
||||
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator);
|
||||
};
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
|
|||
|
||||
/// Compute a contact info if the two bounding volume collide
|
||||
bool testCollision(SphereVsSphereNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
|
||||
uint batchNbItems, bool reportContacts, MemoryAllocator& memoryAllocator);
|
||||
uint batchNbItems, MemoryAllocator& memoryAllocator);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -55,9 +55,9 @@ struct SphereVsSphereNarrowPhaseInfoBatch : public NarrowPhaseInfoBatch {
|
|||
virtual ~SphereVsSphereNarrowPhaseInfoBatch() override = default;
|
||||
|
||||
/// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
virtual void addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
virtual void addNarrowPhaseInfo(uint64 airId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1,
|
||||
CollisionShape* shape2, const Transform& shape1Transform,
|
||||
const Transform& shape2Transform);
|
||||
const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator& shapeAllocator) override;
|
||||
|
||||
// Initialize the containers using cached capacity
|
||||
virtual void reserveMemory() override;
|
||||
|
|
|
@ -96,6 +96,9 @@ class ColliderComponents : public Components {
|
|||
/// has been changed by the user
|
||||
bool* mHasCollisionShapeChangedSize;
|
||||
|
||||
/// True if the collider is a trigger
|
||||
bool* mIsTrigger;
|
||||
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
|
@ -192,9 +195,15 @@ class ColliderComponents : public Components {
|
|||
/// Return true if the size of collision shape of the collider has been changed by the user
|
||||
bool getHasCollisionShapeChangedSize(Entity colliderEntity) const;
|
||||
|
||||
/// Return true if the size of collision shape of the collider has been changed by the user
|
||||
/// Set whether the size of collision shape of the collider has been changed by the user
|
||||
void setHasCollisionShapeChangedSize(Entity colliderEntity, bool hasCollisionShapeChangedSize);
|
||||
|
||||
/// Return true if a collider is a trigger
|
||||
bool getIsTrigger(Entity colliderEntity) const;
|
||||
|
||||
/// Set whether a collider is a trigger
|
||||
void setIsTrigger(Entity colliderEntity, bool isTrigger);
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class BroadPhaseSystem;
|
||||
|
@ -331,6 +340,23 @@ inline void ColliderComponents::setHasCollisionShapeChangedSize(Entity colliderE
|
|||
mHasCollisionShapeChangedSize[mMapEntityToComponentIndex[colliderEntity]] = hasCollisionShapeChangedSize;
|
||||
}
|
||||
|
||||
|
||||
// Return true if a collider is a trigger
|
||||
inline bool ColliderComponents::getIsTrigger(Entity colliderEntity) const {
|
||||
|
||||
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
|
||||
|
||||
return mIsTrigger[mMapEntityToComponentIndex[colliderEntity]];
|
||||
}
|
||||
|
||||
// Set whether a collider is a trigger
|
||||
inline void ColliderComponents::setIsTrigger(Entity colliderEntity, bool isTrigger) {
|
||||
|
||||
assert(mMapEntityToComponentIndex.containsKey(colliderEntity));
|
||||
|
||||
mIsTrigger[mMapEntityToComponentIndex[colliderEntity]] = isTrigger;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -110,7 +110,6 @@ class RigidBodyComponents : public Components {
|
|||
Vector3* mLocalInertiaTensors;
|
||||
|
||||
/// Array with the inverse of the inertia tensor of each component
|
||||
// TODO : We should use a Vector3 here for the diagonal instead of a Matrix3x3
|
||||
Vector3* mInverseInertiaTensorsLocal;
|
||||
|
||||
/// Array with the constrained linear velocity of each component
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
// Libraries
|
||||
#include <reactphysics3d/collision/CollisionCallback.h>
|
||||
#include <reactphysics3d/collision/OverlapCallback.h>
|
||||
|
||||
namespace reactphysics3d {
|
||||
|
||||
|
@ -54,6 +55,12 @@ class EventListener : public CollisionCallback {
|
|||
* @param collisionInfo Information about the contacts
|
||||
*/
|
||||
virtual void onContact(const CollisionCallback::CallbackData& callbackData) override {}
|
||||
|
||||
/// Called when some trigger events occur
|
||||
virtual void onTrigger(const OverlapCallback::CallbackData& callbackData) {}
|
||||
|
||||
/// Called to report rigid bodies that started to sleep or has woken up in the previous frame
|
||||
virtual void onSleep() {}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -173,6 +173,12 @@ class OverlappingPairs {
|
|||
/// 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;
|
||||
|
||||
/// Reference to the colliders components
|
||||
ColliderComponents& mColliderComponents;
|
||||
|
||||
|
@ -276,12 +282,21 @@ class OverlappingPairs {
|
|||
/// Delete all the obsolete last frame collision info
|
||||
void clearObsoleteLastFrameCollisionInfos();
|
||||
|
||||
/// Set the collidingInPreviousFrame value with the collidinginCurrentFrame value for each pair
|
||||
void updateCollidingInPreviousFrame();
|
||||
|
||||
/// Return the pair of bodies index of the pair
|
||||
static bodypair computeBodiesIndexPair(Entity body1Entity, Entity body2Entity);
|
||||
|
||||
/// 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);
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
/// Set the profiler
|
||||
|
@ -380,6 +395,18 @@ inline void OverlappingPairs::setNeedToTestOverlap(uint64 pairId, bool needToTes
|
|||
mNeedToTestOverlap[mMapPairIdToPairIndex[pairId]] = needToTestOverlap;
|
||||
}
|
||||
|
||||
// Return true if the two colliders of the pair were already colliding the previous frame
|
||||
inline bool OverlappingPairs::getCollidingInPreviousFrame(uint64 pairId) const {
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
return mCollidingInPreviousFrame[mMapPairIdToPairIndex[pairId]];
|
||||
}
|
||||
|
||||
// Set to true if the two colliders of the pair were already colliding the previous frame
|
||||
inline void OverlappingPairs::setCollidingInPreviousFrame(uint64 pairId, bool wereCollidingInPreviousFrame) {
|
||||
assert(mMapPairIdToPairIndex.containsKey(pairId));
|
||||
mCollidingInPreviousFrame[mMapPairIdToPairIndex[pairId]] = wereCollidingInPreviousFrame;
|
||||
}
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
// Set the profiler
|
||||
|
|
|
@ -481,6 +481,8 @@ class PhysicsWorld {
|
|||
friend class FixedJoint;
|
||||
friend class HingeJoint;
|
||||
friend class SliderJoint;
|
||||
friend class CollisionCallback::CallbackData;
|
||||
friend class OverlapCallback::CallbackData;
|
||||
};
|
||||
|
||||
// Set the collision dispatch configuration
|
||||
|
|
|
@ -122,6 +122,9 @@ class CollisionDetectionSystem {
|
|||
/// Pointer to the list of contact pairs of the current frame (either mContactPairs1 or mContactPairs2)
|
||||
List<ContactPair>* mCurrentContactPairs;
|
||||
|
||||
/// List of lost contact pairs (contact pairs in contact in previous frame but not in the current one)
|
||||
List<ContactPair> mLostContactPairs;
|
||||
|
||||
/// First map of overlapping pair id to the index of the corresponding pair contact
|
||||
Map<uint64, uint> mMapPairIdToContactPairIndex1;
|
||||
|
||||
|
@ -176,10 +179,11 @@ class CollisionDetectionSystem {
|
|||
void computeBroadPhase();
|
||||
|
||||
/// Compute the middle-phase collision detection
|
||||
void computeMiddlePhase(NarrowPhaseInput& narrowPhaseInput);
|
||||
void computeMiddlePhase(NarrowPhaseInput& narrowPhaseInput, bool needToReportContacts);
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
void computeMiddlePhaseCollisionSnapshot(List<uint64>& convexPairs, List<uint64>& concavePairs, NarrowPhaseInput& narrowPhaseInput);
|
||||
void computeMiddlePhaseCollisionSnapshot(List<uint64>& convexPairs, List<uint64>& concavePairs, NarrowPhaseInput& narrowPhaseInput,
|
||||
bool reportContacts);
|
||||
|
||||
/// Compute the narrow-phase collision detection
|
||||
void computeNarrowPhase();
|
||||
|
@ -191,10 +195,11 @@ class CollisionDetectionSystem {
|
|||
bool computeNarrowPhaseCollisionSnapshot(NarrowPhaseInput& narrowPhaseInput, CollisionCallback& callback);
|
||||
|
||||
/// Process the potential contacts after narrow-phase collision detection
|
||||
void computeSnapshotContactPairs(NarrowPhaseInput& narrowPhaseInput, List<Pair<Entity, Entity>>& overlapPairs) const;
|
||||
void computeOverlapSnapshotContactPairs(NarrowPhaseInput& narrowPhaseInput, List<ContactPair>& contactPairs) const;
|
||||
|
||||
/// Convert the potential contact into actual contacts
|
||||
void computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) const;
|
||||
void computeOverlapSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<ContactPair>& contactPairs,
|
||||
Set<uint64>& setOverlapContactPairId) const;
|
||||
|
||||
/// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
|
||||
void updateOverlappingPairs(const List<Pair<int32, int32> >& overlappingNodes);
|
||||
|
@ -202,8 +207,11 @@ class CollisionDetectionSystem {
|
|||
/// Remove pairs that are not overlapping anymore
|
||||
void removeNonOverlappingPairs();
|
||||
|
||||
/// Add a lost contact pair (pair of colliders that are not in contact anymore)
|
||||
void addLostContactPair(uint64 overlappingPairIndex);
|
||||
|
||||
/// Execute the narrow-phase collision detection algorithm on batches
|
||||
bool testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool reportContacts, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator);
|
||||
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,
|
||||
|
@ -222,7 +230,7 @@ class CollisionDetectionSystem {
|
|||
/// Process the potential contacts after narrow-phase collision detection
|
||||
void processAllPotentialContacts(NarrowPhaseInput& narrowPhaseInput, bool updateLastFrameInfo, List<ContactPointInfo>& potentialContactPoints,
|
||||
Map<uint64, uint>* mapPairIdToContactPairIndex,
|
||||
List<ContactManifoldInfo> &potentialContactManifolds, List<ContactPair>* contactPairs,
|
||||
List<ContactManifoldInfo>& potentialContactManifolds, List<ContactPair>* contactPairs,
|
||||
Map<Entity, List<uint>>& mapBodyToContactPairs);
|
||||
|
||||
/// Reduce the potential contact manifolds and contact points of the overlapping pair contacts
|
||||
|
@ -232,6 +240,9 @@ class CollisionDetectionSystem {
|
|||
/// Create the actual contact manifolds and contacts points (from potential contacts) for a given contact pair
|
||||
void createContacts();
|
||||
|
||||
/// Compute the lost contact pairs (contact pairs in contact in the previous frame but not in the current one)
|
||||
void computeLostContactPairs();
|
||||
|
||||
/// Create the actual contact manifolds and contacts points for testCollision() methods
|
||||
void createSnapshotContacts(List<ContactPair>& contactPairs, List<ContactManifold> &contactManifolds,
|
||||
List<ContactPoint>& contactPoints,
|
||||
|
@ -247,7 +258,10 @@ class CollisionDetectionSystem {
|
|||
|
||||
/// Report contacts
|
||||
void reportContacts(CollisionCallback& callback, List<ContactPair>* contactPairs,
|
||||
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints);
|
||||
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints, List<ContactPair>& lostContactPairs);
|
||||
|
||||
/// Report all triggers
|
||||
void reportTriggers(EventListener& eventListener, List<ContactPair>* contactPairs, List<ContactPair>& lostContactPairs);
|
||||
|
||||
/// Return the largest depth of all the contact points of a potential manifold
|
||||
decimal computePotentialManifoldLargestContactDepth(const ContactManifoldInfo& manifold,
|
||||
|
@ -307,8 +321,8 @@ class CollisionDetectionSystem {
|
|||
/// Notify that the overlapping pairs where a given collider is involved need to be tested for overlap
|
||||
void notifyOverlappingPairsToTestOverlap(Collider* collider);
|
||||
|
||||
/// Report contacts
|
||||
void reportContacts();
|
||||
/// Report contacts and triggers
|
||||
void reportContactsAndTriggers();
|
||||
|
||||
/// Compute the collision detection
|
||||
void computeCollisionDetection();
|
||||
|
|
|
@ -224,6 +224,16 @@ const Transform Collider::getLocalToWorldTransform() const {
|
|||
return mBody->mWorld.mCollidersComponents.getLocalToWorldTransform(mEntity);
|
||||
}
|
||||
|
||||
// Return true if the collider is a trigger
|
||||
bool Collider::getIsTrigger() const {
|
||||
return mBody->mWorld.mCollidersComponents.getIsTrigger(mEntity);
|
||||
}
|
||||
|
||||
// Set whether the collider is a trigger
|
||||
void Collider::setIsTrigger(bool isTrigger) const {
|
||||
mBody->mWorld.mCollidersComponents.setIsTrigger(mEntity, isTrigger);
|
||||
}
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
// Set the profiler
|
||||
|
|
|
@ -39,9 +39,9 @@ CollisionCallback::ContactPoint::ContactPoint(const reactphysics3d::ContactPoint
|
|||
|
||||
// Contact Pair Constructor
|
||||
CollisionCallback::ContactPair::ContactPair(const reactphysics3d::ContactPair& contactPair,
|
||||
List<reactphysics3d::ContactPoint>* contactPoints, PhysicsWorld& world)
|
||||
List<reactphysics3d::ContactPoint>* contactPoints, PhysicsWorld& world, bool isLostContactPair)
|
||||
:mContactPair(contactPair), mContactPoints(contactPoints),
|
||||
mWorld(world) {
|
||||
mWorld(world), mIsLostContactPair(isLostContactPair) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -65,11 +65,38 @@ Collider* CollisionCallback::ContactPair::getCollider2() const {
|
|||
return mWorld.mCollidersComponents.getCollider(mContactPair.collider2Entity);
|
||||
}
|
||||
|
||||
// Return the corresponding type of event for this contact pair
|
||||
CollisionCallback::ContactPair::EventType CollisionCallback::ContactPair::getEventType() const {
|
||||
|
||||
if (mIsLostContactPair) return EventType::ContactExit;
|
||||
|
||||
if (mContactPair.collidingInPreviousFrame) return EventType::ContactStay;
|
||||
|
||||
return EventType::ContactStart;
|
||||
}
|
||||
|
||||
// CollisionCallbackInfo Constructor
|
||||
CollisionCallback::CallbackData::CallbackData(List<reactphysics3d::ContactPair>* contactPairs, List<ContactManifold>* manifolds,
|
||||
List<reactphysics3d::ContactPoint>* contactPoints, PhysicsWorld &world)
|
||||
:mContactPairs(contactPairs), mContactManifolds(manifolds), mContactPoints(contactPoints), mWorld(world) {
|
||||
List<reactphysics3d::ContactPoint>* contactPoints, List<reactphysics3d::ContactPair>& lostContactPairs, PhysicsWorld& world)
|
||||
:mContactPairs(contactPairs), mContactManifolds(manifolds), mContactPoints(contactPoints), mLostContactPairs(lostContactPairs),
|
||||
mContactPairsIndices(world.mMemoryManager.getHeapAllocator()), mLostContactPairsIndices(world.mMemoryManager.getHeapAllocator()), mWorld(world) {
|
||||
|
||||
// Filter the contact pairs to only keep the contact events (not the overlap/trigger events)
|
||||
for (uint i=0; i < mContactPairs->size(); i++) {
|
||||
|
||||
// If the contact pair contains contacts (and is therefore not an overlap/trigger event)
|
||||
if (!(*mContactPairs)[i].isTrigger) {
|
||||
mContactPairsIndices.add(i);
|
||||
}
|
||||
}
|
||||
// Filter the lost contact pairs to only keep the contact events (not the overlap/trigger events)
|
||||
for (uint i=0; i < mLostContactPairs.size(); i++) {
|
||||
|
||||
// If the contact pair contains contacts (and is therefore not an overlap/trigger event)
|
||||
if (!mLostContactPairs[i].isTrigger) {
|
||||
mLostContactPairsIndices.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return a given contact point of the contact pair
|
||||
|
@ -91,5 +118,13 @@ CollisionCallback::ContactPair CollisionCallback::CallbackData::getContactPair(u
|
|||
|
||||
assert(index < getNbContactPairs());
|
||||
|
||||
return CollisionCallback::ContactPair((*mContactPairs)[index], mContactPoints, mWorld);
|
||||
if (index < mContactPairsIndices.size()) {
|
||||
// Return a contact pair
|
||||
return CollisionCallback::ContactPair((*mContactPairs)[mContactPairsIndices[index]], mContactPoints, mWorld, false);
|
||||
}
|
||||
else {
|
||||
|
||||
// Return a lost contact pair
|
||||
return CollisionCallback::ContactPair(mLostContactPairs[mLostContactPairsIndices[index - mContactPairsIndices.size()]], mContactPoints, mWorld, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,23 +31,60 @@
|
|||
using namespace reactphysics3d;
|
||||
|
||||
// Contact Pair Constructor
|
||||
OverlapCallback::OverlapPair::OverlapPair(Pair<Entity, Entity>& overlapPair, PhysicsWorld& world)
|
||||
: mOverlapPair(overlapPair), mWorld(world) {
|
||||
OverlapCallback::OverlapPair::OverlapPair(ContactPair& contactPair, PhysicsWorld& world, bool isLostOverlappingPair)
|
||||
: mContactPair(contactPair), mWorld(world), mIsLostOverlapPair(isLostOverlappingPair) {
|
||||
|
||||
}
|
||||
|
||||
// Return a pointer to the first collider in contact
|
||||
Collider* OverlapCallback::OverlapPair::getCollider1() const {
|
||||
return static_cast<Collider*>(mWorld.mCollidersComponents.getCollider(mContactPair.collider1Entity));
|
||||
}
|
||||
|
||||
// Return a pointer to the second collider in contact
|
||||
Collider* OverlapCallback::OverlapPair::getCollider2() const {
|
||||
return static_cast<Collider*>(mWorld.mCollidersComponents.getCollider(mContactPair.collider2Entity));
|
||||
}
|
||||
|
||||
// Return a pointer to the first body in contact
|
||||
CollisionBody* OverlapCallback::OverlapPair::getBody1() const {
|
||||
return static_cast<CollisionBody*>(mWorld.mCollisionBodyComponents.getBody(mOverlapPair.first));
|
||||
return static_cast<CollisionBody*>(mWorld.mCollisionBodyComponents.getBody(mContactPair.body1Entity));
|
||||
}
|
||||
|
||||
// Return a pointer to the second body in contact
|
||||
CollisionBody* OverlapCallback::OverlapPair::getBody2() const {
|
||||
return static_cast<CollisionBody*>(mWorld.mCollisionBodyComponents.getBody(mOverlapPair.second));
|
||||
return static_cast<CollisionBody*>(mWorld.mCollisionBodyComponents.getBody(mContactPair.body2Entity));
|
||||
}
|
||||
|
||||
// Return the corresponding type of event for this overlapping pair
|
||||
OverlapCallback::OverlapPair::EventType OverlapCallback::OverlapPair::getEventType() const {
|
||||
|
||||
if (mIsLostOverlapPair) return EventType::OverlapExit;
|
||||
|
||||
if (mContactPair.collidingInPreviousFrame) return EventType::OverlapStay;
|
||||
|
||||
return EventType::OverlapStart;
|
||||
}
|
||||
|
||||
// CollisionCallbackData Constructor
|
||||
OverlapCallback::CallbackData::CallbackData(List<Pair<Entity, Entity>>& overlapColliders, PhysicsWorld& world)
|
||||
:mOverlapBodies(overlapColliders), mWorld(world) {
|
||||
OverlapCallback::CallbackData::CallbackData(List<ContactPair>& contactPairs, List<ContactPair>& lostContactPairs, PhysicsWorld& world)
|
||||
:mContactPairs(contactPairs), mLostContactPairs(lostContactPairs),
|
||||
mContactPairsIndices(world.mMemoryManager.getHeapAllocator()), mLostContactPairsIndices(world.mMemoryManager.getHeapAllocator()), mWorld(world) {
|
||||
|
||||
// Filter the contact pairs to only keep the overlap/trigger events (not the contact events)
|
||||
for (uint i=0; i < mContactPairs.size(); i++) {
|
||||
|
||||
// If the contact pair contains contacts (and is therefore not an overlap/trigger event)
|
||||
if (mContactPairs[i].isTrigger) {
|
||||
mContactPairsIndices.add(i);
|
||||
}
|
||||
}
|
||||
// Filter the lost contact pairs to only keep the overlap/trigger events (not the contact events)
|
||||
for (uint i=0; i < mLostContactPairs.size(); i++) {
|
||||
|
||||
// If the contact pair contains contacts (and is therefore not an overlap/trigger event)
|
||||
if (mLostContactPairs[i].isTrigger) {
|
||||
mLostContactPairsIndices.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ using namespace reactphysics3d;
|
|||
// This technique is based on the "Robust Contact Creation for Physics Simulations" presentation
|
||||
// by Dirk Gregorius.
|
||||
bool CapsuleVsCapsuleAlgorithm::testCollision(CapsuleVsCapsuleNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts, MemoryAllocator& memoryAllocator) {
|
||||
MemoryAllocator& memoryAllocator) {
|
||||
|
||||
bool isCollisionFound = false;
|
||||
|
||||
|
@ -95,7 +95,7 @@ bool CapsuleVsCapsuleAlgorithm::testCollision(CapsuleVsCapsuleNarrowPhaseInfoBat
|
|||
// If the segments were overlapping (the clip segment is valid)
|
||||
if (t1 > decimal(0.0) && t2 > decimal(0.0)) {
|
||||
|
||||
if (reportContacts) {
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// Clip the inner segment of capsule 2
|
||||
if (t1 > decimal(1.0)) t1 = decimal(1.0);
|
||||
|
@ -171,7 +171,7 @@ bool CapsuleVsCapsuleAlgorithm::testCollision(CapsuleVsCapsuleNarrowPhaseInfoBat
|
|||
// If the collision shapes overlap
|
||||
if (closestPointsDistanceSquare < sumRadius * sumRadius) {
|
||||
|
||||
if (reportContacts) {
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// If the distance between the inner segments is not zero
|
||||
if (closestPointsDistanceSquare > MACHINE_EPSILON) {
|
||||
|
|
|
@ -39,7 +39,10 @@ CapsuleVsCapsuleNarrowPhaseInfoBatch::CapsuleVsCapsuleNarrowPhaseInfoBatch(Memor
|
|||
|
||||
// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
|
||||
const Transform& shape1Transform, const Transform& shape2Transform) {
|
||||
const Transform& shape1Transform, const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator &shapeAllocator) {
|
||||
|
||||
NarrowPhaseInfoBatch::addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform,
|
||||
shape2Transform, needToReportContacts, shapeAllocator);
|
||||
|
||||
assert(shape1->getType() == CollisionShapeType::CAPSULE);
|
||||
assert(shape2->getType() == CollisionShapeType::CAPSULE);
|
||||
|
@ -47,34 +50,16 @@ void CapsuleVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uin
|
|||
const CapsuleShape* capsule1 = static_cast<const CapsuleShape*>(shape1);
|
||||
const CapsuleShape* capsule2 = static_cast<const CapsuleShape*>(shape2);
|
||||
|
||||
colliderEntities1.add(collider1);
|
||||
colliderEntities2.add(collider2);
|
||||
capsule1Radiuses.add(capsule1->getRadius());
|
||||
capsule2Radiuses.add(capsule2->getRadius());
|
||||
capsule1Heights.add(capsule1->getHeight());
|
||||
capsule2Heights.add(capsule2->getHeight());
|
||||
shape1ToWorldTransforms.add(shape1Transform);
|
||||
shape2ToWorldTransforms.add(shape2Transform);
|
||||
overlappingPairIds.add(pairId);
|
||||
contactPoints.add(List<ContactPointInfo*>(mMemoryAllocator));
|
||||
isColliding.add(false);
|
||||
|
||||
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
|
||||
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
|
||||
lastFrameCollisionInfos.add(lastFrameInfo);
|
||||
}
|
||||
|
||||
// Initialize the containers using cached capacity
|
||||
void CapsuleVsCapsuleNarrowPhaseInfoBatch::reserveMemory() {
|
||||
|
||||
overlappingPairIds.reserve(mCachedCapacity);
|
||||
colliderEntities1.reserve(mCachedCapacity);
|
||||
colliderEntities2.reserve(mCachedCapacity);
|
||||
shape1ToWorldTransforms.reserve(mCachedCapacity);
|
||||
shape2ToWorldTransforms.reserve(mCachedCapacity);
|
||||
lastFrameCollisionInfos.reserve(mCachedCapacity);
|
||||
isColliding.reserve(mCachedCapacity);
|
||||
contactPoints.reserve(mCachedCapacity);
|
||||
NarrowPhaseInfoBatch::reserveMemory();
|
||||
|
||||
capsule1Radiuses.reserve(mCachedCapacity);
|
||||
capsule2Radiuses.reserve(mCachedCapacity);
|
||||
|
@ -90,16 +75,7 @@ void CapsuleVsCapsuleNarrowPhaseInfoBatch::clear() {
|
|||
// allocated in the next frame at a possibly different location in memory (remember that the
|
||||
// location of the allocated memory of a single frame allocator might change between two frames)
|
||||
|
||||
mCachedCapacity = overlappingPairIds.size();
|
||||
|
||||
overlappingPairIds.clear(true);
|
||||
colliderEntities1.clear(true);
|
||||
colliderEntities2.clear(true);
|
||||
shape1ToWorldTransforms.clear(true);
|
||||
shape2ToWorldTransforms.clear(true);
|
||||
lastFrameCollisionInfos.clear(true);
|
||||
isColliding.clear(true);
|
||||
contactPoints.clear(true);
|
||||
NarrowPhaseInfoBatch::clear();
|
||||
|
||||
capsule1Radiuses.clear(true);
|
||||
capsule2Radiuses.clear(true);
|
||||
|
|
|
@ -41,7 +41,7 @@ using namespace reactphysics3d;
|
|||
// by Dirk Gregorius.
|
||||
bool CapsuleVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch,
|
||||
uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts, bool clipWithPreviousAxisIfStillColliding,
|
||||
bool clipWithPreviousAxisIfStillColliding,
|
||||
MemoryAllocator& memoryAllocator) {
|
||||
|
||||
bool isCollisionFound = false;
|
||||
|
@ -59,7 +59,7 @@ bool CapsuleVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& nar
|
|||
|
||||
// Run the GJK algorithm
|
||||
List<GJKAlgorithm::GJKResult> gjkResults(memoryAllocator);
|
||||
gjkAlgorithm.testCollision(narrowPhaseInfoBatch, batchStartIndex, batchNbItems, gjkResults, reportContacts);
|
||||
gjkAlgorithm.testCollision(narrowPhaseInfoBatch, batchStartIndex, batchNbItems, gjkResults);
|
||||
assert(gjkResults.size() == batchNbItems);
|
||||
|
||||
for (uint batchIndex = batchStartIndex; batchIndex < batchStartIndex + batchNbItems; batchIndex++) {
|
||||
|
@ -78,7 +78,8 @@ bool CapsuleVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& nar
|
|||
// If we have found a contact point inside the margins (shallow penetration)
|
||||
if (gjkResults[batchIndex] == GJKAlgorithm::GJKResult::COLLIDE_IN_MARGIN) {
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
bool noContact = false;
|
||||
|
||||
|
@ -173,7 +174,7 @@ bool CapsuleVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& nar
|
|||
if (gjkResults[batchIndex] == GJKAlgorithm::GJKResult::INTERPENETRATE) {
|
||||
|
||||
// Run the SAT algorithm to find the separating axis and compute contact point
|
||||
narrowPhaseInfoBatch.isColliding[batchIndex] = satAlgorithm.testCollisionCapsuleVsConvexPolyhedron(narrowPhaseInfoBatch, batchIndex, reportContacts);
|
||||
narrowPhaseInfoBatch.isColliding[batchIndex] = satAlgorithm.testCollisionCapsuleVsConvexPolyhedron(narrowPhaseInfoBatch, batchIndex);
|
||||
|
||||
lastFrameCollisionInfo->wasUsingGJK = false;
|
||||
lastFrameCollisionInfo->wasUsingSAT = true;
|
||||
|
|
|
@ -37,7 +37,7 @@ using namespace reactphysics3d;
|
|||
// by Dirk Gregorius.
|
||||
bool ConvexPolyhedronVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch,
|
||||
uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator) {
|
||||
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator) {
|
||||
|
||||
// Run the SAT algorithm to find the separating axis and compute contact point
|
||||
SATAlgorithm satAlgorithm(clipWithPreviousAxisIfStillColliding, memoryAllocator);
|
||||
|
@ -48,8 +48,7 @@ bool ConvexPolyhedronVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoB
|
|||
|
||||
#endif
|
||||
|
||||
bool isCollisionFound = satAlgorithm.testCollisionConvexPolyhedronVsConvexPolyhedron(narrowPhaseInfoBatch, batchStartIndex,
|
||||
batchNbItems, reportContacts);
|
||||
bool isCollisionFound = satAlgorithm.testCollisionConvexPolyhedronVsConvexPolyhedron(narrowPhaseInfoBatch, batchStartIndex, batchNbItems);
|
||||
|
||||
for (uint batchIndex = batchStartIndex; batchIndex < batchStartIndex + batchNbItems; batchIndex++) {
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ using namespace reactphysics3d;
|
|||
/// origin, they we give that simplex polytope to the EPA algorithm which will compute
|
||||
/// the correct penetration depth and contact points between the enlarged objects.
|
||||
void GJKAlgorithm::testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex,
|
||||
uint batchNbItems, List<GJKResult>& gjkResults, bool reportContacts) {
|
||||
uint batchNbItems, List<GJKResult>& gjkResults) {
|
||||
|
||||
RP3D_PROFILE("GJKAlgorithm::testCollision()", mProfiler);
|
||||
|
||||
|
@ -214,7 +214,8 @@ void GJKAlgorithm::testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uin
|
|||
continue;
|
||||
}
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// Compute smooth triangle mesh contact if one of the two collision shapes is a triangle
|
||||
TriangleShape::computeSmoothTriangleMeshContact(shape1, shape2, pA, pB, transform1, transform2,
|
||||
|
|
|
@ -36,7 +36,7 @@ using namespace reactphysics3d;
|
|||
NarrowPhaseInfoBatch::NarrowPhaseInfoBatch(MemoryAllocator& allocator, OverlappingPairs& overlappingPairs)
|
||||
: mMemoryAllocator(allocator), mOverlappingPairs(overlappingPairs), overlappingPairIds(allocator),
|
||||
colliderEntities1(allocator), colliderEntities2(allocator), collisionShapes1(allocator), collisionShapes2(allocator),
|
||||
shape1ToWorldTransforms(allocator), shape2ToWorldTransforms(allocator),
|
||||
shape1ToWorldTransforms(allocator), shape2ToWorldTransforms(allocator), reportContacts(allocator),
|
||||
isColliding(allocator), contactPoints(allocator), collisionShapeAllocators(allocator),
|
||||
lastFrameCollisionInfos(allocator) {
|
||||
|
||||
|
@ -49,7 +49,7 @@ NarrowPhaseInfoBatch::~NarrowPhaseInfoBatch() {
|
|||
|
||||
// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
|
||||
const Transform& shape1Transform, const Transform& shape2Transform,
|
||||
const Transform& shape1Transform, const Transform& shape2Transform, bool needToReportContacts,
|
||||
MemoryAllocator& shapeAllocator) {
|
||||
|
||||
overlappingPairIds.add(pairId);
|
||||
|
@ -59,6 +59,7 @@ void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, E
|
|||
collisionShapes2.add(shape2);
|
||||
shape1ToWorldTransforms.add(shape1Transform);
|
||||
shape2ToWorldTransforms.add(shape2Transform);
|
||||
reportContacts.add(needToReportContacts);
|
||||
collisionShapeAllocators.add(&shapeAllocator);
|
||||
contactPoints.add(List<ContactPointInfo*>(mMemoryAllocator));
|
||||
isColliding.add(false);
|
||||
|
@ -72,6 +73,7 @@ void NarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, E
|
|||
void NarrowPhaseInfoBatch::addContactPoint(uint index, const Vector3& contactNormal, decimal penDepth,
|
||||
const Vector3& localPt1, const Vector3& localPt2) {
|
||||
|
||||
assert(reportContacts[index]);
|
||||
assert(penDepth > decimal(0.0));
|
||||
|
||||
// Get the memory allocator
|
||||
|
@ -116,6 +118,7 @@ void NarrowPhaseInfoBatch::reserveMemory() {
|
|||
collisionShapes2.reserve(mCachedCapacity);
|
||||
shape1ToWorldTransforms.reserve(mCachedCapacity);
|
||||
shape2ToWorldTransforms.reserve(mCachedCapacity);
|
||||
reportContacts.reserve(mCachedCapacity);
|
||||
collisionShapeAllocators.reserve(mCachedCapacity);
|
||||
lastFrameCollisionInfos.reserve(mCachedCapacity);
|
||||
isColliding.reserve(mCachedCapacity);
|
||||
|
@ -155,6 +158,7 @@ void NarrowPhaseInfoBatch::clear() {
|
|||
collisionShapes2.clear(true);
|
||||
shape1ToWorldTransforms.clear(true);
|
||||
shape2ToWorldTransforms.clear(true);
|
||||
reportContacts.clear(true);
|
||||
collisionShapeAllocators.clear(true);
|
||||
lastFrameCollisionInfos.clear(true);
|
||||
isColliding.clear(true);
|
||||
|
|
|
@ -41,26 +41,26 @@ NarrowPhaseInput::NarrowPhaseInput(MemoryAllocator& allocator, OverlappingPairs&
|
|||
// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
void NarrowPhaseInput::addNarrowPhaseTest(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
|
||||
const Transform& shape1Transform, const Transform& shape2Transform,
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, MemoryAllocator& shapeAllocator) {
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType, bool reportContacts, MemoryAllocator& shapeAllocator) {
|
||||
|
||||
switch (narrowPhaseAlgorithmType) {
|
||||
case NarrowPhaseAlgorithmType::SphereVsSphere:
|
||||
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform);
|
||||
mSphereVsSphereBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::SphereVsCapsule:
|
||||
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform);
|
||||
mSphereVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::CapsuleVsCapsule:
|
||||
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform);
|
||||
mCapsuleVsCapsuleBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::SphereVsConvexPolyhedron:
|
||||
mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
|
||||
mSphereVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::CapsuleVsConvexPolyhedron:
|
||||
mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
|
||||
mCapsuleVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::ConvexPolyhedronVsConvexPolyhedron:
|
||||
mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, shapeAllocator);
|
||||
mConvexPolyhedronVsConvexPolyhedronBatch.addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform, shape2Transform, reportContacts, shapeAllocator);
|
||||
break;
|
||||
case NarrowPhaseAlgorithmType::None:
|
||||
// Must never happen
|
||||
|
|
|
@ -55,8 +55,7 @@ SATAlgorithm::SATAlgorithm(bool clipWithPreviousAxisIfStillColliding, MemoryAllo
|
|||
|
||||
// Test collision between a sphere and a convex mesh
|
||||
bool SATAlgorithm::testCollisionSphereVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch,
|
||||
uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts) const {
|
||||
uint batchStartIndex, uint batchNbItems) const {
|
||||
|
||||
bool isCollisionFound = false;
|
||||
|
||||
|
@ -114,7 +113,8 @@ bool SATAlgorithm::testCollisionSphereVsConvexPolyhedron(NarrowPhaseInfoBatch& n
|
|||
continue;
|
||||
}
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
const Vector3 minFaceNormal = polyhedron->getFaceNormal(minFaceIndex);
|
||||
Vector3 minFaceNormalWorld = polyhedronToWorldTransform.getOrientation() * minFaceNormal;
|
||||
|
@ -162,7 +162,7 @@ decimal SATAlgorithm::computePolyhedronFaceVsSpherePenetrationDepth(uint faceInd
|
|||
}
|
||||
|
||||
// Test collision between a capsule and a convex mesh
|
||||
bool SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex, bool reportContacts) const {
|
||||
bool SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchIndex) const {
|
||||
|
||||
RP3D_PROFILE("SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron()", mProfiler);
|
||||
|
||||
|
@ -277,7 +277,8 @@ bool SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch&
|
|||
// We need to clip the inner capsule segment with the adjacent faces of the separating face
|
||||
if (isMinPenetrationFaceNormal) {
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
return computeCapsulePolyhedronFaceContactPoints(minFaceIndex, capsuleRadius, polyhedron, minPenetrationDepth,
|
||||
polyhedronToCapsuleTransform, normalWorld, separatingAxisCapsuleSpace,
|
||||
|
@ -287,7 +288,8 @@ bool SATAlgorithm::testCollisionCapsuleVsConvexPolyhedron(NarrowPhaseInfoBatch&
|
|||
}
|
||||
else { // The separating axis is the cross product of a polyhedron edge and the inner capsule segment
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// Compute the closest points between the inner capsule segment and the
|
||||
// edge of the polyhedron in polyhedron local-space
|
||||
|
@ -475,7 +477,7 @@ bool SATAlgorithm::isMinkowskiFaceCapsuleVsEdge(const Vector3& capsuleSegment, c
|
|||
}
|
||||
|
||||
// Test collision between two convex polyhedrons
|
||||
bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems, bool reportContacts) const {
|
||||
bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems) const {
|
||||
|
||||
RP3D_PROFILE("SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron()", mProfiler);
|
||||
|
||||
|
@ -485,6 +487,7 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
|
|||
|
||||
assert(narrowPhaseInfoBatch.collisionShapes1[batchIndex]->getType() == CollisionShapeType::CONVEX_POLYHEDRON);
|
||||
assert(narrowPhaseInfoBatch.collisionShapes2[batchIndex]->getType() == CollisionShapeType::CONVEX_POLYHEDRON);
|
||||
assert(narrowPhaseInfoBatch.contactPoints[batchIndex].size() == 0);
|
||||
|
||||
const ConvexPolyhedronShape* polyhedron1 = static_cast<const ConvexPolyhedronShape*>(narrowPhaseInfoBatch.collisionShapes1[batchIndex]);
|
||||
const ConvexPolyhedronShape* polyhedron2 = static_cast<const ConvexPolyhedronShape*>(narrowPhaseInfoBatch.collisionShapes2[batchIndex]);
|
||||
|
@ -646,32 +649,37 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
|
|||
decimal t2 = vec2.dot(edge1Direction) / edge1LengthSquare;
|
||||
if (t1 >= decimal(0.0) && t1 <= decimal(1) && t2 >= decimal(0.0) && t2 <= decimal(1.0)) {
|
||||
|
||||
// Compute the contact point on polyhedron 1 edge in the local-space of polyhedron 1
|
||||
Vector3 closestPointPolyhedron1EdgeLocalSpace = polyhedron2ToPolyhedron1 * closestPointPolyhedron1Edge;
|
||||
// If we need to report contact points
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// Compute the contact point on polyhedron 1 edge in the local-space of polyhedron 1
|
||||
Vector3 closestPointPolyhedron1EdgeLocalSpace = polyhedron2ToPolyhedron1 * closestPointPolyhedron1Edge;
|
||||
|
||||
// Compute the world normal
|
||||
// We use the direction from the centroid to the edge of the shape that is not a triangle
|
||||
// to avoid possible degeneracies when axis direction is orthogonal to triangle normal
|
||||
Vector3 normal;
|
||||
if (isShape1Triangle) {
|
||||
normal = polyhedron2->getCentroid() - closestPointPolyhedron2Edge;
|
||||
}
|
||||
else {
|
||||
normal = polyhedron1ToPolyhedron2.getOrientation() * ((polyhedron2ToPolyhedron1 * closestPointPolyhedron1Edge) - polyhedron1->getCentroid());
|
||||
}
|
||||
|
||||
//Vector3 normalWorld = narrowPhaseInfo->shape2ToWorldTransform.getOrientation() * minEdgeVsEdgeSeparatingAxisPolyhedron2Space;
|
||||
Vector3 normalWorld = narrowPhaseInfoBatch.shape2ToWorldTransforms[batchIndex].getOrientation() * normal.getUnit();
|
||||
|
||||
// Compute smooth triangle mesh contact if one of the two collision shapes is a triangle
|
||||
TriangleShape::computeSmoothTriangleMeshContact(narrowPhaseInfoBatch.collisionShapes1[batchIndex], narrowPhaseInfoBatch.collisionShapes2[batchIndex],
|
||||
closestPointPolyhedron1EdgeLocalSpace, closestPointPolyhedron2Edge,
|
||||
narrowPhaseInfoBatch.shape1ToWorldTransforms[batchIndex], narrowPhaseInfoBatch.shape2ToWorldTransforms[batchIndex],
|
||||
penetrationDepth, normalWorld);
|
||||
|
||||
// Create the contact point
|
||||
narrowPhaseInfoBatch.addContactPoint(batchIndex, normalWorld, penetrationDepth,
|
||||
closestPointPolyhedron1EdgeLocalSpace, closestPointPolyhedron2Edge);
|
||||
|
||||
// Compute the world normal
|
||||
// We use the direction from the centroid to the edge of the shape that is not a triangle
|
||||
// to avoid possible degeneracies when axis direction is orthogonal to triangle normal
|
||||
Vector3 normal;
|
||||
if (isShape1Triangle) {
|
||||
normal = polyhedron2->getCentroid() - closestPointPolyhedron2Edge;
|
||||
}
|
||||
else {
|
||||
normal = polyhedron1ToPolyhedron2.getOrientation() * ((polyhedron2ToPolyhedron1 * closestPointPolyhedron1Edge) - polyhedron1->getCentroid());
|
||||
}
|
||||
|
||||
//Vector3 normalWorld = narrowPhaseInfo->shape2ToWorldTransform.getOrientation() * minEdgeVsEdgeSeparatingAxisPolyhedron2Space;
|
||||
Vector3 normalWorld = narrowPhaseInfoBatch.shape2ToWorldTransforms[batchIndex].getOrientation() * normal.getUnit();
|
||||
|
||||
// Compute smooth triangle mesh contact if one of the two collision shapes is a triangle
|
||||
TriangleShape::computeSmoothTriangleMeshContact(narrowPhaseInfoBatch.collisionShapes1[batchIndex], narrowPhaseInfoBatch.collisionShapes2[batchIndex],
|
||||
closestPointPolyhedron1EdgeLocalSpace, closestPointPolyhedron2Edge,
|
||||
narrowPhaseInfoBatch.shape1ToWorldTransforms[batchIndex], narrowPhaseInfoBatch.shape2ToWorldTransforms[batchIndex],
|
||||
penetrationDepth, normalWorld);
|
||||
|
||||
// Create the contact point
|
||||
narrowPhaseInfoBatch.addContactPoint(batchIndex, normalWorld, penetrationDepth,
|
||||
closestPointPolyhedron1EdgeLocalSpace, closestPointPolyhedron2Edge);
|
||||
|
||||
// The shapes are overlapping on the previous axis (the contact manifold is not empty). Therefore
|
||||
// we return without running the whole SAT algorithm
|
||||
|
@ -819,24 +827,21 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
|
|||
// If the minimum separating axis is a face normal
|
||||
if (isMinPenetrationFaceNormal) {
|
||||
|
||||
if (reportContacts) {
|
||||
// Compute the contact points between two faces of two convex polyhedra.
|
||||
bool contactsFound = computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1,
|
||||
polyhedron2, polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1,
|
||||
minFaceIndex, narrowPhaseInfoBatch, batchIndex);
|
||||
|
||||
// Compute the contact points between two faces of two convex polyhedra.
|
||||
bool contactsFound = computePolyhedronVsPolyhedronFaceContactPoints(isMinPenetrationFaceNormalPolyhedron1, polyhedron1,
|
||||
polyhedron2, polyhedron1ToPolyhedron2, polyhedron2ToPolyhedron1,
|
||||
minFaceIndex, narrowPhaseInfoBatch, batchIndex);
|
||||
// There should be clipping points here. If it is not the case, it might be
|
||||
// because of a numerical issue
|
||||
if (!contactsFound) {
|
||||
|
||||
// There should be clipping points here. If it is not the case, it might be
|
||||
// because of a numerical issue
|
||||
if (!contactsFound) {
|
||||
lastFrameCollisionInfo->satIsAxisFacePolyhedron1 = isMinPenetrationFaceNormalPolyhedron1;
|
||||
lastFrameCollisionInfo->satIsAxisFacePolyhedron2 = !isMinPenetrationFaceNormalPolyhedron1;
|
||||
lastFrameCollisionInfo->satMinAxisFaceIndex = minFaceIndex;
|
||||
|
||||
lastFrameCollisionInfo->satIsAxisFacePolyhedron1 = isMinPenetrationFaceNormalPolyhedron1;
|
||||
lastFrameCollisionInfo->satIsAxisFacePolyhedron2 = !isMinPenetrationFaceNormalPolyhedron1;
|
||||
lastFrameCollisionInfo->satMinAxisFaceIndex = minFaceIndex;
|
||||
|
||||
// Return no collision
|
||||
continue;
|
||||
}
|
||||
// Return no collision
|
||||
continue;
|
||||
}
|
||||
|
||||
lastFrameCollisionInfo->satIsAxisFacePolyhedron1 = isMinPenetrationFaceNormalPolyhedron1;
|
||||
|
@ -845,7 +850,8 @@ bool SATAlgorithm::testCollisionConvexPolyhedronVsConvexPolyhedron(NarrowPhaseIn
|
|||
}
|
||||
else { // If we have an edge vs edge contact
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// Compute the closest points between the two edges (in the local-space of poylhedron 2)
|
||||
Vector3 closestPointPolyhedron1Edge, closestPointPolyhedron2Edge;
|
||||
|
@ -981,25 +987,29 @@ bool SATAlgorithm::computePolyhedronVsPolyhedronFaceContactPoints(bool isMinPene
|
|||
|
||||
contactPointsFound = true;
|
||||
|
||||
Vector3 outWorldNormal = normalWorld;
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// Convert the clip incident polyhedron vertex into the incident polyhedron local-space
|
||||
Vector3 contactPointIncidentPolyhedron = referenceToIncidentTransform * clipPolygonVertices[i];
|
||||
Vector3 outWorldNormal = normalWorld;
|
||||
|
||||
// Project the contact point onto the reference face
|
||||
Vector3 contactPointReferencePolyhedron = projectPointOntoPlane(clipPolygonVertices[i], axisReferenceSpace, referenceFaceVertex);
|
||||
// Convert the clip incident polyhedron vertex into the incident polyhedron local-space
|
||||
Vector3 contactPointIncidentPolyhedron = referenceToIncidentTransform * clipPolygonVertices[i];
|
||||
|
||||
// Compute smooth triangle mesh contact if one of the two collision shapes is a triangle
|
||||
TriangleShape::computeSmoothTriangleMeshContact(narrowPhaseInfoBatch.collisionShapes1[batchIndex], narrowPhaseInfoBatch.collisionShapes2[batchIndex],
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointReferencePolyhedron : contactPointIncidentPolyhedron,
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointIncidentPolyhedron : contactPointReferencePolyhedron,
|
||||
narrowPhaseInfoBatch.shape1ToWorldTransforms[batchIndex], narrowPhaseInfoBatch.shape2ToWorldTransforms[batchIndex],
|
||||
penetrationDepth, outWorldNormal);
|
||||
// Project the contact point onto the reference face
|
||||
Vector3 contactPointReferencePolyhedron = projectPointOntoPlane(clipPolygonVertices[i], axisReferenceSpace, referenceFaceVertex);
|
||||
|
||||
// Create a new contact point
|
||||
narrowPhaseInfoBatch.addContactPoint(batchIndex, outWorldNormal, penetrationDepth,
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointReferencePolyhedron : contactPointIncidentPolyhedron,
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointIncidentPolyhedron : contactPointReferencePolyhedron);
|
||||
// Compute smooth triangle mesh contact if one of the two collision shapes is a triangle
|
||||
TriangleShape::computeSmoothTriangleMeshContact(narrowPhaseInfoBatch.collisionShapes1[batchIndex], narrowPhaseInfoBatch.collisionShapes2[batchIndex],
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointReferencePolyhedron : contactPointIncidentPolyhedron,
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointIncidentPolyhedron : contactPointReferencePolyhedron,
|
||||
narrowPhaseInfoBatch.shape1ToWorldTransforms[batchIndex], narrowPhaseInfoBatch.shape2ToWorldTransforms[batchIndex],
|
||||
penetrationDepth, outWorldNormal);
|
||||
|
||||
// Create a new contact point
|
||||
narrowPhaseInfoBatch.addContactPoint(batchIndex, outWorldNormal, penetrationDepth,
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointReferencePolyhedron : contactPointIncidentPolyhedron,
|
||||
isMinPenetrationFaceNormalPolyhedron1 ? contactPointIncidentPolyhedron : contactPointReferencePolyhedron);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ using namespace reactphysics3d;
|
|||
// This technique is based on the "Robust Contact Creation for Physics Simulations" presentation
|
||||
// by Dirk Gregorius.
|
||||
bool SphereVsCapsuleAlgorithm::testCollision(SphereVsCapsuleNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts, MemoryAllocator& memoryAllocator) {
|
||||
MemoryAllocator& memoryAllocator) {
|
||||
|
||||
bool isCollisionFound = false;
|
||||
|
||||
|
@ -79,7 +79,8 @@ bool SphereVsCapsuleAlgorithm::testCollision(SphereVsCapsuleNarrowPhaseInfoBatch
|
|||
Vector3 contactPointSphereLocal;
|
||||
Vector3 contactPointCapsuleLocal;
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
// If the sphere center is not on the capsule inner segment
|
||||
if (sphereSegmentDistanceSquare > MACHINE_EPSILON) {
|
||||
|
|
|
@ -40,7 +40,11 @@ SphereVsCapsuleNarrowPhaseInfoBatch::SphereVsCapsuleNarrowPhaseInfoBatch(MemoryA
|
|||
|
||||
// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
|
||||
const Transform& shape1Transform, const Transform& shape2Transform) {
|
||||
const Transform& shape1Transform, const Transform& shape2Transform,
|
||||
bool needToReportContacts, MemoryAllocator& shapeAllocator) {
|
||||
|
||||
NarrowPhaseInfoBatch::addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform,
|
||||
shape2Transform, needToReportContacts, shapeAllocator);
|
||||
|
||||
bool isSphereShape1 = shape1->getType() == CollisionShapeType::SPHERE;
|
||||
isSpheresShape1.add(isSphereShape1);
|
||||
|
@ -54,30 +58,12 @@ void SphereVsCapsuleNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint
|
|||
sphereRadiuses.add(sphereShape->getRadius());
|
||||
capsuleRadiuses.add(capsuleShape->getRadius());
|
||||
capsuleHeights.add(capsuleShape->getHeight());
|
||||
shape1ToWorldTransforms.add(shape1Transform);
|
||||
shape2ToWorldTransforms.add(shape2Transform);
|
||||
overlappingPairIds.add(pairId);
|
||||
colliderEntities1.add(collider1);
|
||||
colliderEntities2.add(collider2);
|
||||
contactPoints.add(List<ContactPointInfo*>(mMemoryAllocator));
|
||||
isColliding.add(false);
|
||||
|
||||
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
|
||||
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
|
||||
lastFrameCollisionInfos.add(lastFrameInfo);
|
||||
}
|
||||
|
||||
// Initialize the containers using cached capacity
|
||||
void SphereVsCapsuleNarrowPhaseInfoBatch::reserveMemory() {
|
||||
|
||||
overlappingPairIds.reserve(mCachedCapacity);
|
||||
colliderEntities1.reserve(mCachedCapacity);
|
||||
colliderEntities2.reserve(mCachedCapacity);
|
||||
shape1ToWorldTransforms.reserve(mCachedCapacity);
|
||||
shape2ToWorldTransforms.reserve(mCachedCapacity);
|
||||
lastFrameCollisionInfos.reserve(mCachedCapacity);
|
||||
isColliding.reserve(mCachedCapacity);
|
||||
contactPoints.reserve(mCachedCapacity);
|
||||
NarrowPhaseInfoBatch::reserveMemory();
|
||||
|
||||
isSpheresShape1.reserve(mCachedCapacity);
|
||||
sphereRadiuses.reserve(mCachedCapacity);
|
||||
|
@ -93,16 +79,7 @@ void SphereVsCapsuleNarrowPhaseInfoBatch::clear() {
|
|||
// allocated in the next frame at a possibly different location in memory (remember that the
|
||||
// location of the allocated memory of a single frame allocator might change between two frames)
|
||||
|
||||
mCachedCapacity = overlappingPairIds.size();
|
||||
|
||||
overlappingPairIds.clear(true);
|
||||
colliderEntities1.clear(true);
|
||||
colliderEntities2.clear(true);
|
||||
shape1ToWorldTransforms.clear(true);
|
||||
shape2ToWorldTransforms.clear(true);
|
||||
lastFrameCollisionInfos.clear(true);
|
||||
isColliding.clear(true);
|
||||
contactPoints.clear(true);
|
||||
NarrowPhaseInfoBatch::clear();
|
||||
|
||||
isSpheresShape1.clear(true);
|
||||
sphereRadiuses.clear(true);
|
||||
|
|
|
@ -36,7 +36,7 @@ using namespace reactphysics3d;
|
|||
// This technique is based on the "Robust Contact Creation for Physics Simulations" presentation
|
||||
// by Dirk Gregorius.
|
||||
bool SphereVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts, bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator) {
|
||||
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& memoryAllocator) {
|
||||
|
||||
// First, we run the GJK algorithm
|
||||
GJKAlgorithm gjkAlgorithm;
|
||||
|
@ -50,7 +50,7 @@ bool SphereVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& narr
|
|||
#endif
|
||||
|
||||
List<GJKAlgorithm::GJKResult> gjkResults(memoryAllocator);
|
||||
gjkAlgorithm.testCollision(narrowPhaseInfoBatch, batchStartIndex, batchNbItems, gjkResults, reportContacts);
|
||||
gjkAlgorithm.testCollision(narrowPhaseInfoBatch, batchStartIndex, batchNbItems, gjkResults);
|
||||
assert(gjkResults.size() == batchNbItems);
|
||||
|
||||
// For each item in the batch
|
||||
|
@ -88,7 +88,7 @@ bool SphereVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfoBatch& narr
|
|||
|
||||
#endif
|
||||
|
||||
isCollisionFound |= satAlgorithm.testCollisionSphereVsConvexPolyhedron(narrowPhaseInfoBatch, batchIndex, 1, reportContacts);
|
||||
isCollisionFound |= satAlgorithm.testCollisionSphereVsConvexPolyhedron(narrowPhaseInfoBatch, batchIndex, 1);
|
||||
|
||||
lastFrameCollisionInfo->wasUsingGJK = false;
|
||||
lastFrameCollisionInfo->wasUsingSAT = true;
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace reactphysics3d;
|
||||
|
||||
bool SphereVsSphereAlgorithm::testCollision(SphereVsSphereNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems,
|
||||
bool reportContacts, MemoryAllocator& memoryAllocator) {
|
||||
bool SphereVsSphereAlgorithm::testCollision(SphereVsSphereNarrowPhaseInfoBatch& narrowPhaseInfoBatch, uint batchStartIndex, uint batchNbItems, MemoryAllocator& memoryAllocator) {
|
||||
|
||||
bool isCollisionFound = false;
|
||||
|
||||
|
@ -59,10 +58,11 @@ bool SphereVsSphereAlgorithm::testCollision(SphereVsSphereNarrowPhaseInfoBatch&
|
|||
// If the sphere collision shapes intersect
|
||||
if (squaredDistanceBetweenCenters < sumRadiusesProducts) {
|
||||
|
||||
if (reportContacts) {
|
||||
// If we need to report contacts
|
||||
if (narrowPhaseInfoBatch.reportContacts[batchIndex]) {
|
||||
|
||||
Transform transform1Inverse = transform1.getInverse();
|
||||
Transform transform2Inverse = transform2.getInverse();
|
||||
const Transform transform1Inverse = transform1.getInverse();
|
||||
const Transform transform2Inverse = transform2.getInverse();
|
||||
|
||||
decimal penetrationDepth = sumRadiuses - std::sqrt(squaredDistanceBetweenCenters);
|
||||
Vector3 intersectionOnBody1;
|
||||
|
|
|
@ -37,7 +37,10 @@ SphereVsSphereNarrowPhaseInfoBatch::SphereVsSphereNarrowPhaseInfoBatch(MemoryAll
|
|||
|
||||
// Add shapes to be tested during narrow-phase collision detection into the batch
|
||||
void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint64 pairIndex, Entity collider1, Entity collider2, CollisionShape* shape1, CollisionShape* shape2,
|
||||
const Transform& shape1Transform, const Transform& shape2Transform) {
|
||||
const Transform& shape1Transform, const Transform& shape2Transform, bool needToReportContacts, MemoryAllocator &shapeAllocator) {
|
||||
|
||||
NarrowPhaseInfoBatch::addNarrowPhaseInfo(pairId, pairIndex, collider1, collider2, shape1, shape2, shape1Transform,
|
||||
shape2Transform, needToReportContacts, shapeAllocator);
|
||||
|
||||
assert(shape1->getType() == CollisionShapeType::SPHERE);
|
||||
assert(shape2->getType() == CollisionShapeType::SPHERE);
|
||||
|
@ -47,30 +50,12 @@ void SphereVsSphereNarrowPhaseInfoBatch::addNarrowPhaseInfo(uint64 pairId, uint6
|
|||
|
||||
sphere1Radiuses.add(sphere1->getRadius());
|
||||
sphere2Radiuses.add(sphere2->getRadius());
|
||||
colliderEntities1.add(collider1);
|
||||
colliderEntities2.add(collider2);
|
||||
shape1ToWorldTransforms.add(shape1Transform);
|
||||
shape2ToWorldTransforms.add(shape2Transform);
|
||||
overlappingPairIds.add(pairId);
|
||||
contactPoints.add(List<ContactPointInfo*>(mMemoryAllocator));
|
||||
isColliding.add(false);
|
||||
|
||||
// Add a collision info for the two collision shapes into the overlapping pair (if not present yet)
|
||||
LastFrameCollisionInfo* lastFrameInfo = mOverlappingPairs.addLastFrameInfoIfNecessary(pairIndex, shape1->getId(), shape2->getId());
|
||||
lastFrameCollisionInfos.add(lastFrameInfo);
|
||||
}
|
||||
|
||||
// Initialize the containers using cached capacity
|
||||
void SphereVsSphereNarrowPhaseInfoBatch::reserveMemory() {
|
||||
|
||||
overlappingPairIds.reserve(mCachedCapacity);
|
||||
colliderEntities1.reserve(mCachedCapacity);
|
||||
colliderEntities2.reserve(mCachedCapacity);
|
||||
shape1ToWorldTransforms.reserve(mCachedCapacity);
|
||||
shape2ToWorldTransforms.reserve(mCachedCapacity);
|
||||
lastFrameCollisionInfos.reserve(mCachedCapacity);
|
||||
isColliding.reserve(mCachedCapacity);
|
||||
contactPoints.reserve(mCachedCapacity);
|
||||
NarrowPhaseInfoBatch::reserveMemory();
|
||||
|
||||
sphere1Radiuses.reserve(mCachedCapacity);
|
||||
sphere2Radiuses.reserve(mCachedCapacity);
|
||||
|
@ -84,16 +69,7 @@ void SphereVsSphereNarrowPhaseInfoBatch::clear() {
|
|||
// allocated in the next frame at a possibly different location in memory (remember that the
|
||||
// location of the allocated memory of a single frame allocator might change between two frames)
|
||||
|
||||
mCachedCapacity = overlappingPairIds.size();
|
||||
|
||||
overlappingPairIds.clear(true);
|
||||
colliderEntities1.clear(true);
|
||||
colliderEntities2.clear(true);
|
||||
shape1ToWorldTransforms.clear(true);
|
||||
shape2ToWorldTransforms.clear(true);
|
||||
lastFrameCollisionInfos.clear(true);
|
||||
isColliding.clear(true);
|
||||
contactPoints.clear(true);
|
||||
NarrowPhaseInfoBatch::clear();
|
||||
|
||||
sphere1Radiuses.clear(true);
|
||||
sphere2Radiuses.clear(true);
|
||||
|
|
|
@ -37,7 +37,8 @@ using namespace reactphysics3d;
|
|||
ColliderComponents::ColliderComponents(MemoryAllocator& allocator)
|
||||
:Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(Collider*) + sizeof(int32) +
|
||||
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(unsigned short) +
|
||||
sizeof(unsigned short) + sizeof(Transform) + sizeof(List<uint64>) + sizeof(bool)) {
|
||||
sizeof(unsigned short) + sizeof(Transform) + sizeof(List<uint64>) + sizeof(bool) +
|
||||
sizeof(bool)) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
|
@ -67,6 +68,7 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
Transform* newLocalToWorldTransforms = reinterpret_cast<Transform*>(newCollideWithMaskBits + nbComponentsToAllocate);
|
||||
List<uint64>* newOverlappingPairs = reinterpret_cast<List<uint64>*>(newLocalToWorldTransforms + nbComponentsToAllocate);
|
||||
bool* hasCollisionShapeChangedSize = reinterpret_cast<bool*>(newOverlappingPairs + nbComponentsToAllocate);
|
||||
bool* isTrigger = reinterpret_cast<bool*>(hasCollisionShapeChangedSize + nbComponentsToAllocate);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
@ -83,6 +85,7 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
memcpy(newLocalToWorldTransforms, mLocalToWorldTransforms, mNbComponents * sizeof(Transform));
|
||||
memcpy(newOverlappingPairs, mOverlappingPairs, mNbComponents * sizeof(List<uint64>));
|
||||
memcpy(hasCollisionShapeChangedSize, mHasCollisionShapeChangedSize, mNbComponents * sizeof(bool));
|
||||
memcpy(isTrigger, mIsTrigger, mNbComponents * sizeof(bool));
|
||||
|
||||
// Deallocate previous memory
|
||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize);
|
||||
|
@ -101,6 +104,7 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
mLocalToWorldTransforms = newLocalToWorldTransforms;
|
||||
mOverlappingPairs = newOverlappingPairs;
|
||||
mHasCollisionShapeChangedSize = hasCollisionShapeChangedSize;
|
||||
mIsTrigger = isTrigger;
|
||||
|
||||
mNbAllocatedComponents = nbComponentsToAllocate;
|
||||
}
|
||||
|
@ -123,6 +127,7 @@ void ColliderComponents::addComponent(Entity colliderEntity, bool isSleeping, co
|
|||
new (mLocalToWorldTransforms + index) Transform(component.localToWorldTransform);
|
||||
new (mOverlappingPairs + index) List<uint64>(mMemoryAllocator);
|
||||
mHasCollisionShapeChangedSize[index] = false;
|
||||
mIsTrigger[index] = false;
|
||||
|
||||
// Map the entity with the new component lookup index
|
||||
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(colliderEntity, index));
|
||||
|
@ -150,6 +155,7 @@ void ColliderComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex)
|
|||
new (mLocalToWorldTransforms + destIndex) Transform(mLocalToWorldTransforms[srcIndex]);
|
||||
new (mOverlappingPairs + destIndex) List<uint64>(mOverlappingPairs[srcIndex]);
|
||||
mHasCollisionShapeChangedSize[destIndex] = mHasCollisionShapeChangedSize[srcIndex];
|
||||
mIsTrigger[destIndex] = mIsTrigger[srcIndex];
|
||||
|
||||
// Destroy the source component
|
||||
destroyComponent(srcIndex);
|
||||
|
@ -177,6 +183,7 @@ void ColliderComponents::swapComponents(uint32 index1, uint32 index2) {
|
|||
Transform localToWorldTransform1 = mLocalToWorldTransforms[index1];
|
||||
List<uint64> overlappingPairs = mOverlappingPairs[index1];
|
||||
bool hasCollisionShapeChangedSize = mHasCollisionShapeChangedSize[index1];
|
||||
bool isTrigger = mIsTrigger[index1];
|
||||
|
||||
// Destroy component 1
|
||||
destroyComponent(index1);
|
||||
|
@ -195,6 +202,7 @@ void ColliderComponents::swapComponents(uint32 index1, uint32 index2) {
|
|||
new (mLocalToWorldTransforms + index2) Transform(localToWorldTransform1);
|
||||
new (mOverlappingPairs + index2) List<uint64>(overlappingPairs);
|
||||
mHasCollisionShapeChangedSize[index2] = hasCollisionShapeChangedSize;
|
||||
mIsTrigger[index2] = isTrigger;
|
||||
|
||||
// Update the entity to component index mapping
|
||||
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(colliderEntity1, index2));
|
||||
|
|
|
@ -40,7 +40,7 @@ OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, M
|
|||
mNbPairs(0), mConcavePairsStartIndex(0), mPairDataSize(sizeof(uint64) + sizeof(int32) + sizeof(int32) + sizeof(Entity) +
|
||||
sizeof(Entity) + sizeof(Map<uint64, LastFrameCollisionInfo*>) +
|
||||
sizeof(bool) + sizeof(bool) + sizeof(NarrowPhaseAlgorithmType) +
|
||||
sizeof(bool)),
|
||||
sizeof(bool) + sizeof(bool) + sizeof(bool)),
|
||||
mNbAllocatedPairs(0), mBuffer(nullptr),
|
||||
mMapPairIdToPairIndex(persistentMemoryAllocator),
|
||||
mColliderComponents(colliderComponents), mCollisionBodyComponents(collisionBodyComponents),
|
||||
|
@ -211,6 +211,8 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
|
|||
bool* newIsActive = reinterpret_cast<bool*>(newNeedToTestOverlap + nbPairsToAllocate);
|
||||
NarrowPhaseAlgorithmType* newNarrowPhaseAlgorithmType = reinterpret_cast<NarrowPhaseAlgorithmType*>(newIsActive + nbPairsToAllocate);
|
||||
bool* newIsShape1Convex = reinterpret_cast<bool*>(newNarrowPhaseAlgorithmType + nbPairsToAllocate);
|
||||
bool* wereCollidingInPreviousFrame = reinterpret_cast<bool*>(newIsShape1Convex + nbPairsToAllocate);
|
||||
bool* areCollidingInCurrentFrame = reinterpret_cast<bool*>(wereCollidingInPreviousFrame + nbPairsToAllocate);
|
||||
|
||||
// If there was already pairs before
|
||||
if (mNbPairs > 0) {
|
||||
|
@ -226,6 +228,8 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
|
|||
memcpy(newIsActive, mIsActive, 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));
|
||||
|
||||
// Deallocate previous memory
|
||||
mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize);
|
||||
|
@ -242,6 +246,8 @@ void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
|
|||
mIsActive = newIsActive;
|
||||
mNarrowPhaseAlgorithmType = newNarrowPhaseAlgorithmType;
|
||||
mIsShape1Convex = newIsShape1Convex;
|
||||
mCollidingInPreviousFrame = wereCollidingInPreviousFrame;
|
||||
mCollidingInCurrentFrame = areCollidingInCurrentFrame;
|
||||
|
||||
mNbAllocatedPairs = nbPairsToAllocate;
|
||||
}
|
||||
|
@ -298,6 +304,8 @@ uint64 OverlappingPairs::addPair(Collider* shape1, Collider* shape2) {
|
|||
new (mIsActive + index) bool(true);
|
||||
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));
|
||||
|
@ -335,6 +343,8 @@ void OverlappingPairs::movePairToIndex(uint64 srcIndex, uint64 destIndex) {
|
|||
mIsActive[destIndex] = mIsActive[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);
|
||||
|
@ -361,6 +371,8 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
|
|||
bool isActive = mIsActive[index1];
|
||||
NarrowPhaseAlgorithmType narrowPhaseAlgorithmType = mNarrowPhaseAlgorithmType[index1];
|
||||
bool isShape1Convex = mIsShape1Convex[index1];
|
||||
bool wereCollidingInPreviousFrame = mCollidingInPreviousFrame[index1];
|
||||
bool areCollidingInCurrentFrame = mCollidingInCurrentFrame[index1];
|
||||
|
||||
// Destroy pair 1
|
||||
destroyPair(index1);
|
||||
|
@ -378,6 +390,8 @@ void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
|
|||
mIsActive[index2] = isActive;
|
||||
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));
|
||||
|
@ -476,7 +490,7 @@ void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() {
|
|||
|
||||
RP3D_PROFILE("OverlappingPairs::clearObsoleteLastFrameCollisionInfos()", mProfiler);
|
||||
|
||||
// For each convex vs convex overlapping pair
|
||||
// For each overlapping pair
|
||||
for (uint64 i=0; i < mNbPairs; i++) {
|
||||
|
||||
// For each collision info
|
||||
|
@ -501,3 +515,13 @@ void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
|
||||
mCollidingInPreviousFrame[i] = mCollidingInCurrentFrame[i];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ void PhysicsWorld::update(decimal timeStep) {
|
|||
createIslands();
|
||||
|
||||
// Report the contacts to the user
|
||||
mCollisionDetection.reportContacts();
|
||||
mCollisionDetection.reportContactsAndTriggers();
|
||||
|
||||
// Disable the joints for pair of sleeping bodies
|
||||
disableJointsOfSleepingBodies();
|
||||
|
@ -718,9 +718,6 @@ void PhysicsWorld::addJointToBodies(Entity body1, Entity body2, Entity joint) {
|
|||
/// it). Then, we create an island with this group of connected bodies.
|
||||
void PhysicsWorld::createIslands() {
|
||||
|
||||
// list of contact pairs involving a non-rigid body
|
||||
List<uint> nonRigidBodiesContactPairs(mMemoryManager.getSingleFrameAllocator());
|
||||
|
||||
RP3D_PROFILE("PhysicsWorld::createIslands()", mProfiler);
|
||||
|
||||
// Reset all the isAlreadyInIsland variables of bodies and joints
|
||||
|
@ -783,14 +780,15 @@ void PhysicsWorld::createIslands() {
|
|||
for (uint p=0; p < contactPairs.size(); p++) {
|
||||
|
||||
ContactPair& pair = (*mCollisionDetection.mCurrentContactPairs)[contactPairs[p]];
|
||||
assert(pair.potentialContactManifoldsIndices.size() > 0);
|
||||
|
||||
// Check if the current contact pair has already been added into an island
|
||||
if (pair.isAlreadyInIsland) continue;
|
||||
|
||||
// If the colliding body is a RigidBody (and not a CollisionBody instead)
|
||||
if (mRigidBodyComponents.hasComponent(pair.body1Entity) && mRigidBodyComponents.hasComponent(pair.body2Entity)) {
|
||||
// If the colliding body is a RigidBody (and not a CollisionBody) and is not a trigger
|
||||
if (mRigidBodyComponents.hasComponent(pair.body1Entity) && mRigidBodyComponents.hasComponent(pair.body2Entity)
|
||||
&& !mCollidersComponents.getIsTrigger(pair.collider1Entity) && !mCollidersComponents.getIsTrigger(pair.collider2Entity)) {
|
||||
|
||||
assert(pair.potentialContactManifoldsIndices.size() > 0);
|
||||
nbTotalManifolds += pair.potentialContactManifoldsIndices.size();
|
||||
|
||||
// Add the contact manifold into the island
|
||||
|
@ -809,7 +807,6 @@ void PhysicsWorld::createIslands() {
|
|||
else {
|
||||
|
||||
// Add the contact pair index in the list of contact pairs that won't be part of islands
|
||||
nonRigidBodiesContactPairs.add(pair.contactPairIndex);
|
||||
pair.isAlreadyInIsland = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,10 +61,10 @@ CollisionDetectionSystem::CollisionDetectionSystem(PhysicsWorld* world, Collider
|
|||
mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator(), mOverlappingPairs), mPotentialContactPoints(mMemoryManager.getSingleFrameAllocator()),
|
||||
mPotentialContactManifolds(mMemoryManager.getSingleFrameAllocator()), mContactPairs1(mMemoryManager.getPoolAllocator()),
|
||||
mContactPairs2(mMemoryManager.getPoolAllocator()), mPreviousContactPairs(&mContactPairs1), mCurrentContactPairs(&mContactPairs2),
|
||||
mMapPairIdToContactPairIndex1(mMemoryManager.getPoolAllocator()), mMapPairIdToContactPairIndex2(mMemoryManager.getPoolAllocator()),
|
||||
mPreviousMapPairIdToContactPairIndex(&mMapPairIdToContactPairIndex1), mCurrentMapPairIdToContactPairIndex(&mMapPairIdToContactPairIndex2),
|
||||
mContactManifolds1(mMemoryManager.getPoolAllocator()), mContactManifolds2(mMemoryManager.getPoolAllocator()),
|
||||
mPreviousContactManifolds(&mContactManifolds1), mCurrentContactManifolds(&mContactManifolds2),
|
||||
mLostContactPairs(mMemoryManager.getSingleFrameAllocator()), mMapPairIdToContactPairIndex1(mMemoryManager.getPoolAllocator()),
|
||||
mMapPairIdToContactPairIndex2(mMemoryManager.getPoolAllocator()), mPreviousMapPairIdToContactPairIndex(&mMapPairIdToContactPairIndex1),
|
||||
mCurrentMapPairIdToContactPairIndex(&mMapPairIdToContactPairIndex2), mContactManifolds1(mMemoryManager.getPoolAllocator()),
|
||||
mContactManifolds2(mMemoryManager.getPoolAllocator()), mPreviousContactManifolds(&mContactManifolds1), mCurrentContactManifolds(&mContactManifolds2),
|
||||
mContactPoints1(mMemoryManager.getPoolAllocator()),
|
||||
mContactPoints2(mMemoryManager.getPoolAllocator()), mPreviousContactPoints(&mContactPoints1),
|
||||
mCurrentContactPoints(&mContactPoints2), mMapBodyToContactPairs(mMemoryManager.getSingleFrameAllocator()) {
|
||||
|
@ -88,7 +88,7 @@ void CollisionDetectionSystem::computeCollisionDetection() {
|
|||
computeBroadPhase();
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
computeMiddlePhase(mNarrowPhaseInput);
|
||||
computeMiddlePhase(mNarrowPhaseInput, true);
|
||||
|
||||
// Compute the narrow-phase collision detection
|
||||
computeNarrowPhase();
|
||||
|
@ -117,7 +117,6 @@ void CollisionDetectionSystem::removeNonOverlappingPairs() {
|
|||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::removeNonOverlappingPairs()", mProfiler);
|
||||
|
||||
// For each possible convex vs convex pair of bodies
|
||||
for (uint64 i=0; i < mOverlappingPairs.getNbPairs(); i++) {
|
||||
|
||||
// Check if we need to test overlap. If so, test if the two shapes are still overlapping.
|
||||
|
@ -128,6 +127,14 @@ void CollisionDetectionSystem::removeNonOverlappingPairs() {
|
|||
mOverlappingPairs.mNeedToTestOverlap[i] = false;
|
||||
}
|
||||
else {
|
||||
|
||||
// If the two colliders of the pair were colliding in the previous frame
|
||||
if (mOverlappingPairs.mCollidingInPreviousFrame[i]) {
|
||||
|
||||
// Create a new lost contact pair
|
||||
addLostContactPair(i);
|
||||
}
|
||||
|
||||
mOverlappingPairs.removePair(mOverlappingPairs.mPairIds[i]);
|
||||
i--;
|
||||
}
|
||||
|
@ -135,6 +142,25 @@ void CollisionDetectionSystem::removeNonOverlappingPairs() {
|
|||
}
|
||||
}
|
||||
|
||||
// Add a lost contact pair (pair of colliders that are not in contact anymore)
|
||||
void CollisionDetectionSystem::addLostContactPair(uint64 overlappingPairIndex) {
|
||||
|
||||
const Entity collider1Entity = mOverlappingPairs.mColliders1[overlappingPairIndex];
|
||||
const Entity collider2Entity = mOverlappingPairs.mColliders2[overlappingPairIndex];
|
||||
|
||||
const Entity body1Entity = mCollidersComponents.getBody(collider1Entity);
|
||||
const Entity body2Entity = mCollidersComponents.getBody(collider2Entity);
|
||||
|
||||
const bool isCollider1Trigger = mCollidersComponents.getIsTrigger(collider1Entity);
|
||||
const bool isCollider2Trigger = mCollidersComponents.getIsTrigger(collider2Entity);
|
||||
const bool isTrigger = isCollider1Trigger || isCollider2Trigger;
|
||||
|
||||
// Create a lost contact pair
|
||||
ContactPair lostContactPair(mOverlappingPairs.mPairIds[overlappingPairIndex], body1Entity, body2Entity, collider1Entity, collider2Entity, mLostContactPairs.size(),
|
||||
true, isTrigger, mMemoryManager.getHeapAllocator());
|
||||
mLostContactPairs.add(lostContactPair);
|
||||
}
|
||||
|
||||
// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
|
||||
void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int32>>& overlappingNodes) {
|
||||
|
||||
|
@ -204,7 +230,7 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int
|
|||
}
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
void CollisionDetectionSystem::computeMiddlePhase(NarrowPhaseInput& narrowPhaseInput) {
|
||||
void CollisionDetectionSystem::computeMiddlePhase(NarrowPhaseInput& narrowPhaseInput, bool needToReportContacts) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::computeMiddlePhase()", mProfiler);
|
||||
|
||||
|
@ -235,12 +261,18 @@ void CollisionDetectionSystem::computeMiddlePhase(NarrowPhaseInput& narrowPhaseI
|
|||
|
||||
NarrowPhaseAlgorithmType algorithmType = mOverlappingPairs.mNarrowPhaseAlgorithmType[i];
|
||||
|
||||
const bool isCollider1Trigger = mCollidersComponents.mIsTrigger[collider1Index];
|
||||
const bool isCollider2Trigger = mCollidersComponents.mIsTrigger[collider2Index];
|
||||
const bool reportContacts = needToReportContacts && !isCollider1Trigger && !isCollider2Trigger;
|
||||
|
||||
// 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, mMemoryManager.getSingleFrameAllocator());
|
||||
algorithmType, reportContacts, mMemoryManager.getSingleFrameAllocator());
|
||||
|
||||
mOverlappingPairs.mCollidingInCurrentFrame[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,12 +288,15 @@ void CollisionDetectionSystem::computeMiddlePhase(NarrowPhaseInput& narrowPhaseI
|
|||
if (mOverlappingPairs.mIsActive[i]) {
|
||||
|
||||
computeConvexVsConcaveMiddlePhase(i, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
|
||||
|
||||
mOverlappingPairs.mCollidingInCurrentFrame[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>& convexPairs, List<uint64>& concavePairs, NarrowPhaseInput& narrowPhaseInput) {
|
||||
void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>& convexPairs, List<uint64>& concavePairs, NarrowPhaseInput& narrowPhaseInput,
|
||||
bool reportContacts) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::computeMiddlePhase()", mProfiler);
|
||||
|
||||
|
@ -299,7 +334,7 @@ void CollisionDetectionSystem::computeMiddlePhaseCollisionSnapshot(List<uint64>&
|
|||
narrowPhaseInput.addNarrowPhaseTest(pairId, pairIndex, collider1Entity, collider2Entity, collisionShape1, collisionShape2,
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider1Index],
|
||||
mCollidersComponents.mLocalToWorldTransforms[collider2Index],
|
||||
algorithmType, mMemoryManager.getSingleFrameAllocator());
|
||||
algorithmType, reportContacts, mMemoryManager.getSingleFrameAllocator());
|
||||
|
||||
}
|
||||
|
||||
|
@ -365,6 +400,10 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairInde
|
|||
assert(triangleVertices.size() % 3 == 0);
|
||||
assert(triangleVerticesNormals.size() % 3 == 0);
|
||||
|
||||
const bool isCollider1Trigger = mCollidersComponents.mIsTrigger[collider1Index];
|
||||
const bool isCollider2Trigger = mCollidersComponents.mIsTrigger[collider2Index];
|
||||
const bool reportContacts = !isCollider1Trigger && !isCollider2Trigger;
|
||||
|
||||
// For each overlapping triangle
|
||||
for (uint i=0; i < shapeIds.size(); i++)
|
||||
{
|
||||
|
@ -384,13 +423,13 @@ void CollisionDetectionSystem::computeConvexVsConcaveMiddlePhase(uint64 pairInde
|
|||
narrowPhaseInput.addNarrowPhaseTest(mOverlappingPairs.mPairIds[pairIndex], pairIndex, collider1, collider2, isShape1Convex ? convexShape : triangleShape,
|
||||
isShape1Convex ? triangleShape : convexShape,
|
||||
shape1LocalToWorldTransform, shape2LocalToWorldTransform,
|
||||
mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex], allocator);
|
||||
mOverlappingPairs.mNarrowPhaseAlgorithmType[pairIndex], reportContacts, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the narrow-phase collision detection algorithm on batches
|
||||
bool CollisionDetectionSystem::testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput, bool reportContacts,
|
||||
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator) {
|
||||
bool CollisionDetectionSystem::testNarrowPhaseCollision(NarrowPhaseInput& narrowPhaseInput,
|
||||
bool clipWithPreviousAxisIfStillColliding, MemoryAllocator& allocator) {
|
||||
|
||||
bool contactFound = false;
|
||||
|
||||
|
@ -402,32 +441,32 @@ bool CollisionDetectionSystem::testNarrowPhaseCollision(NarrowPhaseInput& narrow
|
|||
CapsuleVsConvexPolyhedronAlgorithm* capsuleVsConvexPolyAlgo = mCollisionDispatch.getCapsuleVsConvexPolyhedronAlgorithm();
|
||||
ConvexPolyhedronVsConvexPolyhedronAlgorithm* convexPolyVsConvexPolyAlgo = mCollisionDispatch.getConvexPolyhedronVsConvexPolyhedronAlgorithm();
|
||||
|
||||
// get the narrow-phase batches to test for collision
|
||||
SphereVsSphereNarrowPhaseInfoBatch& sphereVsSphereBatch = narrowPhaseInput.getSphereVsSphereBatch();
|
||||
SphereVsCapsuleNarrowPhaseInfoBatch& sphereVsCapsuleBatch = narrowPhaseInput.getSphereVsCapsuleBatch();
|
||||
CapsuleVsCapsuleNarrowPhaseInfoBatch& capsuleVsCapsuleBatch = narrowPhaseInput.getCapsuleVsCapsuleBatch();
|
||||
NarrowPhaseInfoBatch& sphereVsConvexPolyhedronBatch = narrowPhaseInput.getSphereVsConvexPolyhedronBatch();
|
||||
NarrowPhaseInfoBatch& capsuleVsConvexPolyhedronBatch = narrowPhaseInput.getCapsuleVsConvexPolyhedronBatch();
|
||||
NarrowPhaseInfoBatch& convexPolyhedronVsConvexPolyhedronBatch = narrowPhaseInput.getConvexPolyhedronVsConvexPolyhedronBatch();
|
||||
// get the narrow-phase batches to test for collision for contacts
|
||||
SphereVsSphereNarrowPhaseInfoBatch& sphereVsSphereBatchContacts = narrowPhaseInput.getSphereVsSphereBatch();
|
||||
SphereVsCapsuleNarrowPhaseInfoBatch& sphereVsCapsuleBatchContacts = narrowPhaseInput.getSphereVsCapsuleBatch();
|
||||
CapsuleVsCapsuleNarrowPhaseInfoBatch& capsuleVsCapsuleBatchContacts = narrowPhaseInput.getCapsuleVsCapsuleBatch();
|
||||
NarrowPhaseInfoBatch& sphereVsConvexPolyhedronBatchContacts = narrowPhaseInput.getSphereVsConvexPolyhedronBatch();
|
||||
NarrowPhaseInfoBatch& capsuleVsConvexPolyhedronBatchContacts = narrowPhaseInput.getCapsuleVsConvexPolyhedronBatch();
|
||||
NarrowPhaseInfoBatch& convexPolyhedronVsConvexPolyhedronBatchContacts = narrowPhaseInput.getConvexPolyhedronVsConvexPolyhedronBatch();
|
||||
|
||||
// Compute the narrow-phase collision detection for each kind of collision shapes
|
||||
if (sphereVsSphereBatch.getNbObjects() > 0) {
|
||||
contactFound |= sphereVsSphereAlgo->testCollision(sphereVsSphereBatch, 0, sphereVsSphereBatch.getNbObjects(), reportContacts, allocator);
|
||||
// Compute the narrow-phase collision detection for each kind of collision shapes (for contacts)
|
||||
if (sphereVsSphereBatchContacts.getNbObjects() > 0) {
|
||||
contactFound |= sphereVsSphereAlgo->testCollision(sphereVsSphereBatchContacts, 0, sphereVsSphereBatchContacts.getNbObjects(), allocator);
|
||||
}
|
||||
if (sphereVsCapsuleBatch.getNbObjects() > 0) {
|
||||
contactFound |= sphereVsCapsuleAlgo->testCollision(sphereVsCapsuleBatch, 0, sphereVsCapsuleBatch.getNbObjects(), reportContacts, allocator);
|
||||
if (sphereVsCapsuleBatchContacts.getNbObjects() > 0) {
|
||||
contactFound |= sphereVsCapsuleAlgo->testCollision(sphereVsCapsuleBatchContacts, 0, sphereVsCapsuleBatchContacts.getNbObjects(), allocator);
|
||||
}
|
||||
if (capsuleVsCapsuleBatch.getNbObjects() > 0) {
|
||||
contactFound |= capsuleVsCapsuleAlgo->testCollision(capsuleVsCapsuleBatch, 0, capsuleVsCapsuleBatch.getNbObjects(), reportContacts, allocator);
|
||||
if (capsuleVsCapsuleBatchContacts.getNbObjects() > 0) {
|
||||
contactFound |= capsuleVsCapsuleAlgo->testCollision(capsuleVsCapsuleBatchContacts, 0, capsuleVsCapsuleBatchContacts.getNbObjects(), allocator);
|
||||
}
|
||||
if (sphereVsConvexPolyhedronBatch.getNbObjects() > 0) {
|
||||
contactFound |= sphereVsConvexPolyAlgo->testCollision(sphereVsConvexPolyhedronBatch, 0, sphereVsConvexPolyhedronBatch.getNbObjects(), reportContacts, clipWithPreviousAxisIfStillColliding, allocator);
|
||||
if (sphereVsConvexPolyhedronBatchContacts.getNbObjects() > 0) {
|
||||
contactFound |= sphereVsConvexPolyAlgo->testCollision(sphereVsConvexPolyhedronBatchContacts, 0, sphereVsConvexPolyhedronBatchContacts.getNbObjects(), clipWithPreviousAxisIfStillColliding, allocator);
|
||||
}
|
||||
if (capsuleVsConvexPolyhedronBatch.getNbObjects() > 0) {
|
||||
contactFound |= capsuleVsConvexPolyAlgo->testCollision(capsuleVsConvexPolyhedronBatch, 0, capsuleVsConvexPolyhedronBatch.getNbObjects(), reportContacts, clipWithPreviousAxisIfStillColliding, allocator);
|
||||
if (capsuleVsConvexPolyhedronBatchContacts.getNbObjects() > 0) {
|
||||
contactFound |= capsuleVsConvexPolyAlgo->testCollision(capsuleVsConvexPolyhedronBatchContacts, 0, capsuleVsConvexPolyhedronBatchContacts.getNbObjects(), clipWithPreviousAxisIfStillColliding, allocator);
|
||||
}
|
||||
if (convexPolyhedronVsConvexPolyhedronBatch.getNbObjects() > 0) {
|
||||
contactFound |= convexPolyVsConvexPolyAlgo->testCollision(convexPolyhedronVsConvexPolyhedronBatch, 0, convexPolyhedronVsConvexPolyhedronBatch.getNbObjects(), reportContacts, clipWithPreviousAxisIfStillColliding, allocator);
|
||||
if (convexPolyhedronVsConvexPolyhedronBatchContacts.getNbObjects() > 0) {
|
||||
contactFound |= convexPolyVsConvexPolyAlgo->testCollision(convexPolyhedronVsConvexPolyhedronBatchContacts, 0, convexPolyhedronVsConvexPolyhedronBatchContacts.getNbObjects(), clipWithPreviousAxisIfStillColliding, allocator);
|
||||
}
|
||||
|
||||
return contactFound;
|
||||
|
@ -478,7 +517,7 @@ void CollisionDetectionSystem::computeNarrowPhase() {
|
|||
swapPreviousAndCurrentContacts();
|
||||
|
||||
// Test the narrow-phase collision detection on the batches to be tested
|
||||
testNarrowPhaseCollision(mNarrowPhaseInput, true, true, allocator);
|
||||
testNarrowPhaseCollision(mNarrowPhaseInput, true, allocator);
|
||||
|
||||
// Process all the potential contacts after narrow-phase collision
|
||||
processAllPotentialContacts(mNarrowPhaseInput, true, mPotentialContactPoints, mCurrentMapPairIdToContactPairIndex,
|
||||
|
@ -505,15 +544,16 @@ bool CollisionDetectionSystem::computeNarrowPhaseOverlapSnapshot(NarrowPhaseInpu
|
|||
MemoryAllocator& allocator = mMemoryManager.getPoolAllocator();
|
||||
|
||||
// Test the narrow-phase collision detection on the batches to be tested
|
||||
bool collisionFound = testNarrowPhaseCollision(narrowPhaseInput, false, false, allocator);
|
||||
bool collisionFound = testNarrowPhaseCollision(narrowPhaseInput, false, allocator);
|
||||
if (collisionFound && callback != nullptr) {
|
||||
|
||||
// Compute the overlapping bodies
|
||||
List<Pair<Entity, Entity>> overlapBodies(allocator);
|
||||
computeSnapshotContactPairs(narrowPhaseInput, overlapBodies);
|
||||
// Compute the overlapping colliders
|
||||
List<ContactPair> contactPairs(allocator);
|
||||
List<ContactPair> lostContactPairs(allocator); // Always empty in this case (snapshot)
|
||||
computeOverlapSnapshotContactPairs(narrowPhaseInput, contactPairs);
|
||||
|
||||
// Report overlapping bodies
|
||||
OverlapCallback::CallbackData callbackData(overlapBodies, *mWorld);
|
||||
// Report overlapping colliders
|
||||
OverlapCallback::CallbackData callbackData(contactPairs, lostContactPairs, *mWorld);
|
||||
(*callback).onOverlap(callbackData);
|
||||
}
|
||||
|
||||
|
@ -521,7 +561,9 @@ bool CollisionDetectionSystem::computeNarrowPhaseOverlapSnapshot(NarrowPhaseInpu
|
|||
}
|
||||
|
||||
// Process the potential overlapping bodies for the testOverlap() methods
|
||||
void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInput& narrowPhaseInput, List<Pair<Entity, Entity>>& overlapPairs) const {
|
||||
void CollisionDetectionSystem::computeOverlapSnapshotContactPairs(NarrowPhaseInput& narrowPhaseInput, List<ContactPair>& contactPairs) const {
|
||||
|
||||
Set<uint64> setOverlapContactPairId(mMemoryManager.getHeapAllocator());
|
||||
|
||||
// get the narrow-phase batches to test for collision
|
||||
NarrowPhaseInfoBatch& sphereVsSphereBatch = narrowPhaseInput.getSphereVsSphereBatch();
|
||||
|
@ -532,12 +574,12 @@ void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInput& nar
|
|||
NarrowPhaseInfoBatch& convexPolyhedronVsConvexPolyhedronBatch = narrowPhaseInput.getConvexPolyhedronVsConvexPolyhedronBatch();
|
||||
|
||||
// Process the potential contacts
|
||||
computeSnapshotContactPairs(sphereVsSphereBatch, overlapPairs);
|
||||
computeSnapshotContactPairs(sphereVsCapsuleBatch, overlapPairs);
|
||||
computeSnapshotContactPairs(capsuleVsCapsuleBatch, overlapPairs);
|
||||
computeSnapshotContactPairs(sphereVsConvexPolyhedronBatch, overlapPairs);
|
||||
computeSnapshotContactPairs(capsuleVsConvexPolyhedronBatch, overlapPairs);
|
||||
computeSnapshotContactPairs(convexPolyhedronVsConvexPolyhedronBatch, overlapPairs);
|
||||
computeOverlapSnapshotContactPairs(sphereVsSphereBatch, contactPairs, setOverlapContactPairId);
|
||||
computeOverlapSnapshotContactPairs(sphereVsCapsuleBatch, contactPairs, setOverlapContactPairId);
|
||||
computeOverlapSnapshotContactPairs(capsuleVsCapsuleBatch, contactPairs, setOverlapContactPairId);
|
||||
computeOverlapSnapshotContactPairs(sphereVsConvexPolyhedronBatch, contactPairs, setOverlapContactPairId);
|
||||
computeOverlapSnapshotContactPairs(capsuleVsConvexPolyhedronBatch, contactPairs, setOverlapContactPairId);
|
||||
computeOverlapSnapshotContactPairs(convexPolyhedronVsConvexPolyhedronBatch, contactPairs, setOverlapContactPairId);
|
||||
}
|
||||
|
||||
// Notify that the overlapping pairs where a given collider is involved need to be tested for overlap
|
||||
|
@ -554,19 +596,38 @@ void CollisionDetectionSystem::notifyOverlappingPairsToTestOverlap(Collider* col
|
|||
}
|
||||
|
||||
// Convert the potential overlapping bodies for the testOverlap() methods
|
||||
void CollisionDetectionSystem::computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) const {
|
||||
void CollisionDetectionSystem::computeOverlapSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<ContactPair>& contactPairs,
|
||||
Set<uint64>& setOverlapContactPairId) const {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::computeSnapshotContactPairs()", mProfiler);
|
||||
|
||||
// For each narrow phase info object
|
||||
for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) {
|
||||
|
||||
// If there is a contact
|
||||
// If there is a collision
|
||||
if (narrowPhaseInfoBatch.isColliding[i]) {
|
||||
|
||||
// Add the pair of bodies in contact into the list
|
||||
overlapPairs.add(Pair<Entity, Entity>(mCollidersComponents.getBody(narrowPhaseInfoBatch.colliderEntities1[i]),
|
||||
mCollidersComponents.getBody(narrowPhaseInfoBatch.colliderEntities2[i])));
|
||||
// If the contact pair does not already exist
|
||||
if (!setOverlapContactPairId.contains(narrowPhaseInfoBatch.overlappingPairIds[i])) {
|
||||
|
||||
const Entity collider1Entity = narrowPhaseInfoBatch.colliderEntities1[i];
|
||||
const Entity collider2Entity = narrowPhaseInfoBatch.colliderEntities2[i];
|
||||
|
||||
const uint32 collider1Index = mCollidersComponents.getEntityIndex(collider1Entity);
|
||||
const uint32 collider2Index = mCollidersComponents.getEntityIndex(collider2Entity);
|
||||
|
||||
const Entity body1Entity = mCollidersComponents.mBodiesEntities[collider1Index];
|
||||
const Entity body2Entity = mCollidersComponents.mBodiesEntities[collider2Index];
|
||||
|
||||
const bool isTrigger = mCollidersComponents.mIsTrigger[collider1Index] || mCollidersComponents.mIsTrigger[collider2Index];
|
||||
|
||||
// Create a new contact pair
|
||||
ContactPair contactPair(narrowPhaseInfoBatch.overlappingPairIds[i], body1Entity, body2Entity, collider1Entity, collider2Entity,
|
||||
contactPairs.size(), isTrigger, false, mMemoryManager.getHeapAllocator());
|
||||
contactPairs.add(contactPair);
|
||||
|
||||
setOverlapContactPairId.add(narrowPhaseInfoBatch.overlappingPairIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
narrowPhaseInfoBatch.resetContactPoints(i);
|
||||
|
@ -582,7 +643,7 @@ bool CollisionDetectionSystem::computeNarrowPhaseCollisionSnapshot(NarrowPhaseIn
|
|||
MemoryAllocator& allocator = mMemoryManager.getHeapAllocator();
|
||||
|
||||
// Test the narrow-phase collision detection on the batches to be tested
|
||||
bool collisionFound = testNarrowPhaseCollision(narrowPhaseInput, true, false, allocator);
|
||||
bool collisionFound = testNarrowPhaseCollision(narrowPhaseInput, false, allocator);
|
||||
|
||||
// If collision has been found, create contacts
|
||||
if (collisionFound) {
|
||||
|
@ -591,6 +652,7 @@ bool CollisionDetectionSystem::computeNarrowPhaseCollisionSnapshot(NarrowPhaseIn
|
|||
List<ContactManifoldInfo> potentialContactManifolds(allocator);
|
||||
Map<uint64, uint> mapPairIdToContactPairIndex(allocator);
|
||||
List<ContactPair> contactPairs(allocator);
|
||||
List<ContactPair> lostContactPairs(allocator); // Not used during collision snapshots
|
||||
List<ContactManifold> contactManifolds(allocator);
|
||||
List<ContactPoint> contactPoints(allocator);
|
||||
Map<Entity, List<uint>> mapBodyToContactPairs(allocator);
|
||||
|
@ -607,7 +669,7 @@ bool CollisionDetectionSystem::computeNarrowPhaseCollisionSnapshot(NarrowPhaseIn
|
|||
potentialContactPoints);
|
||||
|
||||
// Report the contacts to the user
|
||||
reportContacts(callback, &contactPairs, &contactManifolds, &contactPoints);
|
||||
reportContacts(callback, &contactPairs, &contactManifolds, &contactPoints, lostContactPairs);
|
||||
}
|
||||
|
||||
return collisionFound;
|
||||
|
@ -654,7 +716,6 @@ void CollisionDetectionSystem::createContacts() {
|
|||
for (uint p=0; p < (*mCurrentContactPairs).size(); p++) {
|
||||
|
||||
ContactPair& contactPair = (*mCurrentContactPairs)[p];
|
||||
assert(contactPair.potentialContactManifoldsIndices.size() > 0);
|
||||
|
||||
contactPair.contactManifoldsIndex = mCurrentContactManifolds->size();
|
||||
contactPair.nbContactManifolds = contactPair.potentialContactManifoldsIndices.size();
|
||||
|
@ -696,16 +757,38 @@ void CollisionDetectionSystem::createContacts() {
|
|||
// Initialize the current contacts with the contacts from the previous frame (for warmstarting)
|
||||
initContactsWithPreviousOnes();
|
||||
|
||||
// Report contacts to the user
|
||||
if (mWorld->mEventListener != nullptr) {
|
||||
reportContacts(*(mWorld->mEventListener), mCurrentContactPairs, mCurrentContactManifolds, mCurrentContactPoints);
|
||||
}
|
||||
// Compute the lost contacts (contact pairs that were colliding in previous frame but not in this one)
|
||||
computeLostContactPairs();
|
||||
|
||||
mPreviousContactPoints->clear();
|
||||
mPreviousContactManifolds->clear();
|
||||
mPreviousContactPairs->clear();
|
||||
mPreviousMapPairIdToContactPairIndex->clear();
|
||||
|
||||
// Reset the potential contacts
|
||||
mPotentialContactPoints.clear(true);
|
||||
mPotentialContactManifolds.clear(true);
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
|
||||
// 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 both bodies still exist
|
||||
if (mCollidersComponents.hasComponent(mOverlappingPairs.mColliders1[i]) && mCollidersComponents.hasComponent(mOverlappingPairs.mColliders2[i])) {
|
||||
|
||||
// Create a lost contact pair
|
||||
addLostContactPair(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the actual contact manifolds and contacts points for testCollision() methods
|
||||
void CollisionDetectionSystem::createSnapshotContacts(List<ContactPair>& contactPairs,
|
||||
List<ContactManifold>& contactManifolds,
|
||||
|
@ -784,7 +867,7 @@ void CollisionDetectionSystem::initContactsWithPreviousOnes() {
|
|||
const uint contactManifoldsIndex = currentContactPair.contactManifoldsIndex;
|
||||
const uint nbContactManifolds = currentContactPair.nbContactManifolds;
|
||||
|
||||
// For each current contact manifold of the contact pair
|
||||
// For each current contact manifold of the current contact pair
|
||||
for (uint m=contactManifoldsIndex; m < contactManifoldsIndex + nbContactManifolds; m++) {
|
||||
|
||||
assert(m < mCurrentContactManifolds->size());
|
||||
|
@ -823,7 +906,7 @@ void CollisionDetectionSystem::initContactsWithPreviousOnes() {
|
|||
const uint contactPointsIndex = currentContactPair.contactPointsIndex;
|
||||
const uint nbTotalContactPoints = currentContactPair.nbToTalContactPoints;
|
||||
|
||||
// For each current contact point of the contact pair
|
||||
// For each current contact point of the current contact pair
|
||||
for (uint c=contactPointsIndex; c < contactPointsIndex + nbTotalContactPoints; c++) {
|
||||
|
||||
assert(c < mCurrentContactPoints->size());
|
||||
|
@ -850,11 +933,6 @@ void CollisionDetectionSystem::initContactsWithPreviousOnes() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mPreviousContactPoints->clear();
|
||||
mPreviousContactManifolds->clear();
|
||||
mPreviousContactPairs->clear();
|
||||
mPreviousMapPairIdToContactPairIndex->clear();
|
||||
}
|
||||
|
||||
// Remove a body from the collision detection
|
||||
|
@ -897,11 +975,11 @@ void CollisionDetectionSystem::raycast(RaycastCallback* raycastCallback,
|
|||
|
||||
// Convert the potential contact into actual contacts
|
||||
void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, bool updateLastFrameInfo,
|
||||
List<ContactPointInfo>& potentialContactPoints,
|
||||
Map<uint64, uint>* mapPairIdToContactPairIndex,
|
||||
List<ContactManifoldInfo>& potentialContactManifolds,
|
||||
List<ContactPair>* contactPairs,
|
||||
Map<Entity, List<uint>>& mapBodyToContactPairs) {
|
||||
List<ContactPointInfo>& potentialContactPoints,
|
||||
Map<uint64, uint>* mapPairIdToContactPairIndex,
|
||||
List<ContactManifoldInfo>& potentialContactManifolds,
|
||||
List<ContactPair>* contactPairs,
|
||||
Map<Entity, List<uint>>& mapBodyToContactPairs) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::processPotentialContacts()", mProfiler);
|
||||
|
||||
|
@ -915,32 +993,82 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
|
|||
narrowPhaseInfoBatch.lastFrameCollisionInfos[i]->isValid = true;
|
||||
}
|
||||
|
||||
// Add the potential contacts
|
||||
for (uint j=0; j < narrowPhaseInfoBatch.contactPoints[i].size(); j++) {
|
||||
const uint64 pairId = narrowPhaseInfoBatch.overlappingPairIds[i];
|
||||
const uint64 pairIndex = mOverlappingPairs.mMapPairIdToPairIndex[pairId];
|
||||
|
||||
assert(narrowPhaseInfoBatch.isColliding[i]);
|
||||
// If the two colliders are colliding
|
||||
if (narrowPhaseInfoBatch.isColliding[i]) {
|
||||
|
||||
const ContactPointInfo& contactPoint = *(narrowPhaseInfoBatch.contactPoints[i][j]);
|
||||
mOverlappingPairs.mCollidingInCurrentFrame[pairIndex] = true;
|
||||
|
||||
// Add the contact point to the list of potential contact points
|
||||
const uint contactPointIndex = static_cast<uint>(potentialContactPoints.size());
|
||||
|
||||
potentialContactPoints.add(contactPoint);
|
||||
|
||||
bool similarManifoldFound = false;
|
||||
|
||||
// If there is already a contact pair for this overlapping pair
|
||||
const uint64 pairId = narrowPhaseInfoBatch.overlappingPairIds[i];
|
||||
// If there is not already a contact pair for this overlapping pair
|
||||
auto it = mapPairIdToContactPairIndex->find(pairId);
|
||||
ContactPair* pairContact = nullptr;
|
||||
if (it != mapPairIdToContactPairIndex->end()) {
|
||||
if (it == mapPairIdToContactPairIndex->end()) {
|
||||
|
||||
// Create a new ContactPair
|
||||
|
||||
const Entity collider1Entity = narrowPhaseInfoBatch.colliderEntities1[i];
|
||||
const Entity collider2Entity = narrowPhaseInfoBatch.colliderEntities2[i];
|
||||
|
||||
const uint32 collider1Index = mCollidersComponents.getEntityIndex(collider1Entity);
|
||||
const uint32 collider2Index = mCollidersComponents.getEntityIndex(collider2Entity);
|
||||
|
||||
const Entity body1Entity = mCollidersComponents.mBodiesEntities[collider1Index];
|
||||
const Entity body2Entity = mCollidersComponents.mBodiesEntities[collider2Index];
|
||||
|
||||
const bool isTrigger = mCollidersComponents.mIsTrigger[collider1Index] || mCollidersComponents.mIsTrigger[collider2Index];
|
||||
|
||||
assert(!mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) || !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity));
|
||||
|
||||
const uint newContactPairIndex = contactPairs->size();
|
||||
ContactPair overlappingPairContact(pairId, body1Entity, body2Entity,
|
||||
collider1Entity, collider2Entity,
|
||||
newContactPairIndex, mOverlappingPairs.getCollidingInPreviousFrame(pairId), isTrigger, mMemoryManager.getHeapAllocator());
|
||||
contactPairs->add(overlappingPairContact);
|
||||
pairContact = &((*contactPairs)[newContactPairIndex]);
|
||||
mapPairIdToContactPairIndex->add(Pair<uint64, uint>(pairId, newContactPairIndex));
|
||||
|
||||
auto itbodyContactPairs = mapBodyToContactPairs.find(body1Entity);
|
||||
if (itbodyContactPairs != mapBodyToContactPairs.end()) {
|
||||
itbodyContactPairs->second.add(newContactPairIndex);
|
||||
}
|
||||
else {
|
||||
List<uint> contactPairs(mMemoryManager.getPoolAllocator(), 1);
|
||||
contactPairs.add(newContactPairIndex);
|
||||
mapBodyToContactPairs.add(Pair<Entity, List<uint>>(body1Entity, contactPairs));
|
||||
}
|
||||
itbodyContactPairs = mapBodyToContactPairs.find(body2Entity);
|
||||
if (itbodyContactPairs != mapBodyToContactPairs.end()) {
|
||||
itbodyContactPairs->second.add(newContactPairIndex);
|
||||
}
|
||||
else {
|
||||
List<uint> contactPairs(mMemoryManager.getPoolAllocator(), 1);
|
||||
contactPairs.add(newContactPairIndex);
|
||||
mapBodyToContactPairs.add(Pair<Entity, List<uint>>(body2Entity, contactPairs));
|
||||
}
|
||||
}
|
||||
else { // If a ContactPair already exists for this overlapping pair, we use this one
|
||||
|
||||
assert(it->first == pairId);
|
||||
|
||||
const uint pairContactIndex = it->second;
|
||||
pairContact = &((*contactPairs)[pairContactIndex]);
|
||||
}
|
||||
|
||||
assert(pairContact->potentialContactManifoldsIndices.size() > 0);
|
||||
assert(pairContact != nullptr);
|
||||
|
||||
// Add the potential contacts
|
||||
for (uint j=0; j < narrowPhaseInfoBatch.contactPoints[i].size(); j++) {
|
||||
|
||||
const ContactPointInfo& contactPoint = *(narrowPhaseInfoBatch.contactPoints[i][j]);
|
||||
|
||||
// Add the contact point to the list of potential contact points
|
||||
const uint contactPointIndex = static_cast<uint>(potentialContactPoints.size());
|
||||
|
||||
potentialContactPoints.add(contactPoint);
|
||||
|
||||
bool similarManifoldFound = false;
|
||||
|
||||
// For each contact manifold of the overlapping pair
|
||||
for (uint m=0; m < pairContact->potentialContactManifoldsIndices.size(); m++) {
|
||||
|
@ -964,71 +1092,32 @@ void CollisionDetectionSystem::processPotentialContacts(NarrowPhaseInfoBatch& na
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have not found a manifold with a similar contact normal for the contact point
|
||||
if (!similarManifoldFound) {
|
||||
// If we have not found a manifold with a similar contact normal for the contact point
|
||||
if (!similarManifoldFound) {
|
||||
|
||||
// Create a new contact manifold for the overlapping pair
|
||||
ContactManifoldInfo contactManifoldInfo(pairId, mMemoryManager.getPoolAllocator());
|
||||
// Create a new contact manifold for the overlapping pair
|
||||
ContactManifoldInfo contactManifoldInfo(pairId, mMemoryManager.getPoolAllocator());
|
||||
|
||||
// Add the contact point to the manifold
|
||||
contactManifoldInfo.potentialContactPointsIndices.add(contactPointIndex);
|
||||
// Add the contact point to the manifold
|
||||
contactManifoldInfo.potentialContactPointsIndices.add(contactPointIndex);
|
||||
|
||||
// If the overlapping pair contact does not exists yet
|
||||
if (pairContact == nullptr) {
|
||||
assert(pairContact != nullptr);
|
||||
|
||||
const Entity collider1Entity = narrowPhaseInfoBatch.colliderEntities1[i];
|
||||
const Entity collider2Entity = narrowPhaseInfoBatch.colliderEntities2[i];
|
||||
// Add the potential contact manifold
|
||||
uint contactManifoldIndex = static_cast<uint>(potentialContactManifolds.size());
|
||||
potentialContactManifolds.add(contactManifoldInfo);
|
||||
|
||||
const Entity body1Entity = mCollidersComponents.getBody(collider1Entity);
|
||||
const Entity body2Entity = mCollidersComponents.getBody(collider2Entity);
|
||||
|
||||
assert(!mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) || !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity));
|
||||
|
||||
const uint newContactPairIndex = contactPairs->size();
|
||||
ContactPair overlappingPairContact(pairId, body1Entity, body2Entity,
|
||||
collider1Entity, collider2Entity,
|
||||
newContactPairIndex, mMemoryManager.getHeapAllocator());
|
||||
contactPairs->add(overlappingPairContact);
|
||||
pairContact = &((*contactPairs)[newContactPairIndex]);
|
||||
mapPairIdToContactPairIndex->add(Pair<uint64, uint>(pairId, newContactPairIndex));
|
||||
|
||||
auto itbodyContactPairs = mapBodyToContactPairs.find(body1Entity);
|
||||
if (itbodyContactPairs != mapBodyToContactPairs.end()) {
|
||||
itbodyContactPairs->second.add(newContactPairIndex);
|
||||
}
|
||||
else {
|
||||
List<uint> contactPairs(mMemoryManager.getPoolAllocator(), 1);
|
||||
contactPairs.add(newContactPairIndex);
|
||||
mapBodyToContactPairs.add(Pair<Entity, List<uint>>(body1Entity, contactPairs));
|
||||
}
|
||||
itbodyContactPairs = mapBodyToContactPairs.find(body2Entity);
|
||||
if (itbodyContactPairs != mapBodyToContactPairs.end()) {
|
||||
itbodyContactPairs->second.add(newContactPairIndex);
|
||||
}
|
||||
else {
|
||||
List<uint> contactPairs(mMemoryManager.getPoolAllocator(), 1);
|
||||
contactPairs.add(newContactPairIndex);
|
||||
mapBodyToContactPairs.add(Pair<Entity, List<uint>>(body2Entity, contactPairs));
|
||||
}
|
||||
// Add the contact manifold to the overlapping pair contact
|
||||
assert(pairContact->pairId == contactManifoldInfo.pairId);
|
||||
pairContact->potentialContactManifoldsIndices.add(contactManifoldIndex);
|
||||
}
|
||||
|
||||
assert(pairContact != nullptr);
|
||||
|
||||
// Add the potential contact manifold
|
||||
uint contactManifoldIndex = static_cast<uint>(potentialContactManifolds.size());
|
||||
potentialContactManifolds.add(contactManifoldInfo);
|
||||
|
||||
// Add the contact manifold to the overlapping pair contact
|
||||
assert(pairContact->pairId == contactManifoldInfo.pairId);
|
||||
pairContact->potentialContactManifoldsIndices.add(contactManifoldIndex);
|
||||
assert(pairContact->potentialContactManifoldsIndices.size() > 0);
|
||||
}
|
||||
|
||||
assert(pairContact->potentialContactManifoldsIndices.size() > 0);
|
||||
narrowPhaseInfoBatch.resetContactPoints(i);
|
||||
}
|
||||
|
||||
narrowPhaseInfoBatch.resetContactPoints(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1044,8 +1133,6 @@ void CollisionDetectionSystem::reducePotentialContactManifolds(List<ContactPair>
|
|||
|
||||
ContactPair& contactPair = (*contactPairs)[i];
|
||||
|
||||
assert(contactPair.potentialContactManifoldsIndices.size() > 0);
|
||||
|
||||
// While there are too many manifolds in the contact pair
|
||||
while(contactPair.potentialContactManifoldsIndices.size() > mWorld->mConfig.nbMaxContactManifolds) {
|
||||
|
||||
|
@ -1296,31 +1383,51 @@ void CollisionDetectionSystem::reduceContactPoints(ContactManifoldInfo& manifold
|
|||
manifold.potentialContactPointsIndices.add(pointsToKeepIndices[3]);
|
||||
}
|
||||
|
||||
// Report contacts
|
||||
void CollisionDetectionSystem::reportContacts() {
|
||||
// Report contacts and triggers
|
||||
void CollisionDetectionSystem::reportContactsAndTriggers() {
|
||||
|
||||
if (mWorld->mEventListener != nullptr) {
|
||||
reportContacts(*(mWorld->mEventListener), mCurrentContactPairs, mCurrentContactManifolds,
|
||||
mCurrentContactPoints);
|
||||
}
|
||||
if (mWorld->mEventListener != nullptr) {
|
||||
|
||||
reportContacts(*(mWorld->mEventListener), mCurrentContactPairs, mCurrentContactManifolds, mCurrentContactPoints, mLostContactPairs);
|
||||
reportTriggers(*(mWorld->mEventListener), mCurrentContactPairs, mLostContactPairs);
|
||||
}
|
||||
|
||||
mOverlappingPairs.updateCollidingInPreviousFrame();
|
||||
|
||||
mLostContactPairs.clear(true);
|
||||
}
|
||||
|
||||
// Report all contacts
|
||||
void CollisionDetectionSystem::reportContacts(CollisionCallback& callback, List<ContactPair>* contactPairs,
|
||||
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints) {
|
||||
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints, List<ContactPair>& lostContactPairs) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::reportContacts()", mProfiler);
|
||||
|
||||
// If there are contacts
|
||||
if (contactPairs->size() > 0) {
|
||||
if (contactPairs->size() + lostContactPairs.size() > 0) {
|
||||
|
||||
CollisionCallback::CallbackData callbackData(contactPairs, manifolds, contactPoints, *mWorld);
|
||||
CollisionCallback::CallbackData callbackData(contactPairs, manifolds, contactPoints, lostContactPairs, *mWorld);
|
||||
|
||||
// Call the callback method to report the contacts
|
||||
callback.onContact(callbackData);
|
||||
}
|
||||
}
|
||||
|
||||
// Report all triggers
|
||||
void CollisionDetectionSystem::reportTriggers(EventListener& eventListener, List<ContactPair>* contactPairs, List<ContactPair>& lostContactPairs) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::reportTriggers()", mProfiler);
|
||||
|
||||
// If there are contacts
|
||||
if (contactPairs->size() + lostContactPairs.size() > 0) {
|
||||
|
||||
OverlapCallback::CallbackData callbackData(*contactPairs, lostContactPairs, *mWorld);
|
||||
|
||||
// Call the callback method to report the overlapping shapes
|
||||
eventListener.onTrigger(callbackData);
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if two bodies overlap (collide)
|
||||
bool CollisionDetectionSystem::testOverlap(CollisionBody* body1, CollisionBody* body2) {
|
||||
|
||||
|
@ -1337,7 +1444,7 @@ bool CollisionDetectionSystem::testOverlap(CollisionBody* body1, CollisionBody*
|
|||
if (convexPairs.size() > 0 || concavePairs.size() > 0) {
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput);
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput, false);
|
||||
|
||||
// Compute the narrow-phase collision detection
|
||||
return computeNarrowPhaseOverlapSnapshot(narrowPhaseInput, nullptr);
|
||||
|
@ -1355,7 +1462,7 @@ void CollisionDetectionSystem::testOverlap(OverlapCallback& callback) {
|
|||
computeBroadPhase();
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
computeMiddlePhase(narrowPhaseInput);
|
||||
computeMiddlePhase(narrowPhaseInput, false);
|
||||
|
||||
// Compute the narrow-phase collision detection and report overlapping shapes
|
||||
computeNarrowPhaseOverlapSnapshot(narrowPhaseInput, &callback);
|
||||
|
@ -1377,7 +1484,7 @@ void CollisionDetectionSystem::testOverlap(CollisionBody* body, OverlapCallback&
|
|||
if (convexPairs.size() > 0 || concavePairs.size() > 0) {
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput);
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput, false);
|
||||
|
||||
// Compute the narrow-phase collision detection
|
||||
computeNarrowPhaseOverlapSnapshot(narrowPhaseInput, &callback);
|
||||
|
@ -1400,7 +1507,7 @@ void CollisionDetectionSystem::testCollision(CollisionBody* body1, CollisionBody
|
|||
if (convexPairs.size() > 0 || concavePairs.size() > 0) {
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput);
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput, true);
|
||||
|
||||
// Compute the narrow-phase collision detection and report contacts
|
||||
computeNarrowPhaseCollisionSnapshot(narrowPhaseInput, callback);
|
||||
|
@ -1423,7 +1530,7 @@ void CollisionDetectionSystem::testCollision(CollisionBody* body, CollisionCallb
|
|||
if (convexPairs.size() > 0 || concavePairs.size() > 0) {
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput);
|
||||
computeMiddlePhaseCollisionSnapshot(convexPairs, concavePairs, narrowPhaseInput, true);
|
||||
|
||||
// Compute the narrow-phase collision detection and report contacts
|
||||
computeNarrowPhaseCollisionSnapshot(narrowPhaseInput, callback);
|
||||
|
@ -1439,7 +1546,7 @@ void CollisionDetectionSystem::testCollision(CollisionCallback& callback) {
|
|||
computeBroadPhase();
|
||||
|
||||
// Compute the middle-phase collision detection
|
||||
computeMiddlePhase(narrowPhaseInput);
|
||||
computeMiddlePhase(narrowPhaseInput, true);
|
||||
|
||||
// Compute the narrow-phase collision detection and report contacts
|
||||
computeNarrowPhaseCollisionSnapshot(narrowPhaseInput, callback);
|
||||
|
|
|
@ -207,3 +207,7 @@ void Scene::onContact(const rp3d::CollisionCallback::CallbackData& callbackData)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData) {
|
||||
|
||||
}
|
||||
|
|
|
@ -238,6 +238,8 @@ class Scene : public rp3d::EventListener {
|
|||
|
||||
/// Called when some contacts occur
|
||||
virtual void onContact(const rp3d::CollisionCallback::CallbackData& callbackData) override;
|
||||
|
||||
virtual void onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData) override;
|
||||
};
|
||||
|
||||
// Called when a keyboard event occurs
|
||||
|
|
Loading…
Reference in New Issue
Block a user