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