Report narrow-phase contacts to the collision detection in a more generic way
This commit is contained in:
parent
ec5e41c19e
commit
c7846d4a29
|
@ -175,7 +175,6 @@ void CollisionDetection::computeNarrowPhase() {
|
|||
// For each possible collision pair of bodies
|
||||
map<overlappingpairid, OverlappingPair*>::iterator it;
|
||||
for (it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ) {
|
||||
ContactPointInfo* contactInfo = NULL;
|
||||
|
||||
OverlappingPair* pair = it->second;
|
||||
|
||||
|
@ -239,27 +238,9 @@ void CollisionDetection::computeNarrowPhase() {
|
|||
pair, shape2->getCachedCollisionData());
|
||||
|
||||
// Use the narrow-phase collision detection algorithm to check
|
||||
// if there really is a collision
|
||||
if (narrowPhaseAlgorithm->testCollision(shape1Info, shape2Info, contactInfo)) {
|
||||
assert(contactInfo != NULL);
|
||||
|
||||
// If it is the first contact since the pair are overlapping
|
||||
if (pair->getNbContactPoints() == 0) {
|
||||
|
||||
// Trigger a callback event
|
||||
if (mWorld->mEventListener != NULL) mWorld->mEventListener->beginContact(*contactInfo);
|
||||
}
|
||||
|
||||
// Create a new contact
|
||||
createContact(pair, contactInfo);
|
||||
|
||||
// Trigger a callback event for the new contact
|
||||
if (mWorld->mEventListener != NULL) mWorld->mEventListener->newContact(*contactInfo);
|
||||
|
||||
// Delete and remove the contact info from the memory allocator
|
||||
contactInfo->~ContactPointInfo();
|
||||
mWorld->mMemoryAllocator.release(contactInfo, sizeof(ContactPointInfo));
|
||||
}
|
||||
// if there really is a collision. If a collision occurs, the
|
||||
// notifyContact() callback method will be called.
|
||||
narrowPhaseAlgorithm->testCollision(shape1Info, shape2Info, this);
|
||||
}
|
||||
|
||||
// Add all the contact manifolds (between colliding bodies) to the bodies
|
||||
|
@ -361,19 +342,7 @@ void CollisionDetection::computeNarrowPhaseBetweenShapes(CollisionCallback* call
|
|||
|
||||
// Use the narrow-phase collision detection algorithm to check
|
||||
// if there really is a collision
|
||||
if (narrowPhaseAlgorithm->testCollision(shape1Info, shape2Info, contactInfo)) {
|
||||
assert(contactInfo != NULL);
|
||||
|
||||
// Create a new contact
|
||||
createContact(pair, contactInfo);
|
||||
|
||||
// Notify the collision callback about this new contact
|
||||
if (callback != NULL) callback->notifyContact(*contactInfo);
|
||||
|
||||
// Delete and remove the contact info from the memory allocator
|
||||
contactInfo->~ContactPointInfo();
|
||||
mWorld->mMemoryAllocator.release(contactInfo, sizeof(ContactPointInfo));
|
||||
}
|
||||
narrowPhaseAlgorithm->testCollision(shape1Info, shape2Info, this);
|
||||
}
|
||||
|
||||
// Add all the contact manifolds (between colliding bodies) to the bodies
|
||||
|
@ -443,6 +412,30 @@ void CollisionDetection::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
|||
mBroadPhaseAlgorithm.removeProxyCollisionShape(proxyShape);
|
||||
}
|
||||
|
||||
// Called by a narrow-phase collision algorithm when a new contact has been found
|
||||
void CollisionDetection::notifyContact(OverlappingPair* overlappingPair, ContactPointInfo* contactInfo) {
|
||||
assert(contactInfo != NULL);
|
||||
|
||||
// If it is the first contact since the pairs are overlapping
|
||||
if (overlappingPair->getNbContactPoints() == 0) {
|
||||
|
||||
// Trigger a callback event
|
||||
if (mWorld->mEventListener != NULL) mWorld->mEventListener->beginContact(*contactInfo);
|
||||
}
|
||||
|
||||
// TODO : Try not to allocate ContactPointInfo dynamically
|
||||
|
||||
// Create a new contact
|
||||
createContact(overlappingPair, contactInfo);
|
||||
|
||||
// Trigger a callback event for the new contact
|
||||
if (mWorld->mEventListener != NULL) mWorld->mEventListener->newContact(*contactInfo);
|
||||
|
||||
// Delete and remove the contact info from the memory allocator
|
||||
contactInfo->~ContactPointInfo();
|
||||
mWorld->mMemoryAllocator.release(contactInfo, sizeof(ContactPointInfo));
|
||||
}
|
||||
|
||||
// Create a new contact
|
||||
void CollisionDetection::createContact(OverlappingPair* overlappingPair,
|
||||
const ContactPointInfo* contactInfo) {
|
||||
|
|
|
@ -54,7 +54,7 @@ class CollisionCallback;
|
|||
* collide and then we run a narrow-phase algorithm to compute the
|
||||
* collision contacts between bodies.
|
||||
*/
|
||||
class CollisionDetection {
|
||||
class CollisionDetection : public NarrowPhaseCallback {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -203,6 +203,9 @@ class CollisionDetection {
|
|||
/// Return a reference to the world memory allocator
|
||||
MemoryAllocator& getWorldMemoryAllocator();
|
||||
|
||||
/// Called by a narrow-phase collision algorithm when a new contact has been found
|
||||
virtual void notifyContact(OverlappingPair* overlappingPair, ContactPointInfo* contactInfo);
|
||||
|
||||
/// Create a new contact
|
||||
void createContact(OverlappingPair* overlappingPair, const ContactPointInfo* contactInfo);
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ ConcaveVsConvexAlgorithm::~ConcaveVsConvexAlgorithm() {
|
|||
// Return true and compute a contact info if the two bounding volumes collide
|
||||
bool ConcaveVsConvexAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
ContactPointInfo*& contactInfo) {
|
||||
NarrowPhaseCallback* narrowPhaseCallback) {
|
||||
|
||||
ProxyShape* convexProxyShape;
|
||||
ProxyShape* concaveProxyShape;
|
||||
|
@ -67,6 +67,7 @@ bool ConcaveVsConvexAlgorithm::testCollision(const CollisionShapeInfo& shape1Inf
|
|||
}
|
||||
|
||||
// Set the parameters of the callback object
|
||||
mConvexVsTriangleCallback.setNarrowPhaseCallback(narrowPhaseCallback);
|
||||
mConvexVsTriangleCallback.setCollisionDetection(mCollisionDetection);
|
||||
mConvexVsTriangleCallback.setConvexShape(convexShape);
|
||||
mConvexVsTriangleCallback.setProxyShapes(convexProxyShape, concaveProxyShape);
|
||||
|
@ -102,29 +103,5 @@ void ConvexVsTriangleCallback::reportTriangle(const Vector3* trianglePoints) {
|
|||
mOverlappingPair, mConcaveProxyShape->getCachedCollisionData());
|
||||
|
||||
// Use the collision algorithm to test collision between the triangle and the other convex shape
|
||||
ContactPointInfo* contactInfo = NULL;
|
||||
if (algo->testCollision(shapeConvexInfo, shapeConcaveInfo, contactInfo)) {
|
||||
assert(contactInfo != NULL);
|
||||
|
||||
// If it is the first contact since the pair are overlapping
|
||||
if (mOverlappingPair->getNbContactPoints() == 0) {
|
||||
|
||||
// Trigger a callback event
|
||||
if (mCollisionDetection->getWorldEventListener() != NULL) {
|
||||
mCollisionDetection->getWorldEventListener()->beginContact(*contactInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new contact
|
||||
mCollisionDetection->createContact(mOverlappingPair, contactInfo);
|
||||
|
||||
// Trigger a callback event for the new contact
|
||||
if (mCollisionDetection->getWorldEventListener() != NULL) {
|
||||
mCollisionDetection->getWorldEventListener()->newContact(*contactInfo);
|
||||
}
|
||||
|
||||
// Delete and remove the contact info from the memory allocator
|
||||
contactInfo->~ContactPointInfo();
|
||||
mCollisionDetection->getWorldMemoryAllocator().release(contactInfo, sizeof(ContactPointInfo));
|
||||
}
|
||||
algo->testCollision(shapeConvexInfo, shapeConcaveInfo, mNarrowPhaseCallback);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ class ConvexVsTriangleCallback : public TriangleCallback {
|
|||
/// Pointer to the collision detection object
|
||||
CollisionDetection* mCollisionDetection;
|
||||
|
||||
/// Narrow-phase collision callback
|
||||
NarrowPhaseCallback* mNarrowPhaseCallback;
|
||||
|
||||
/// Convex collision shape to test collision with
|
||||
const ConvexShape* mConvexShape;
|
||||
|
||||
|
@ -66,6 +69,11 @@ class ConvexVsTriangleCallback : public TriangleCallback {
|
|||
mCollisionDetection = collisionDetection;
|
||||
}
|
||||
|
||||
/// Set the narrow-phase collision callback
|
||||
void setNarrowPhaseCallback(NarrowPhaseCallback* callback) {
|
||||
mNarrowPhaseCallback = callback;
|
||||
}
|
||||
|
||||
/// Set the convex collision shape to test collision with
|
||||
void setConvexShape(const ConvexShape* convexShape) {
|
||||
mConvexShape = convexShape;
|
||||
|
@ -124,7 +132,7 @@ class ConcaveVsConvexAlgorithm : public NarrowPhaseAlgorithm {
|
|||
/// Return true and compute a contact info if the two bounding volume collide
|
||||
virtual bool testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
ContactPointInfo*& contactInfo);
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -86,7 +86,8 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simple
|
|||
const Transform& transform1,
|
||||
CollisionShapeInfo shape2Info,
|
||||
const Transform& transform2,
|
||||
Vector3& v, ContactPointInfo*& contactInfo) {
|
||||
Vector3& v,
|
||||
NarrowPhaseCallback* narrowPhaseCallback) {
|
||||
|
||||
assert(shape1Info.collisionShape->isConvex());
|
||||
assert(shape2Info.collisionShape->isConvex());
|
||||
|
@ -426,9 +427,11 @@ bool EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simple
|
|||
assert(penetrationDepth > 0.0);
|
||||
|
||||
// Create the contact info object
|
||||
contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo* contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo(shape1Info.proxyShape, shape2Info.proxyShape, normal,
|
||||
penetrationDepth, pALocal, pBLocal);
|
||||
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "collision/shapes/CollisionShape.h"
|
||||
#include "collision/CollisionShapeInfo.h"
|
||||
#include "constraint/ContactPoint.h"
|
||||
#include "collision/narrowphase/NarrowPhaseAlgorithm.h"
|
||||
#include "mathematics/mathematics.h"
|
||||
#include "TriangleEPA.h"
|
||||
#include "memory/MemoryAllocator.h"
|
||||
|
@ -127,7 +128,8 @@ class EPAAlgorithm {
|
|||
const Transform& transform1,
|
||||
CollisionShapeInfo shape2Info,
|
||||
const Transform& transform2,
|
||||
Vector3& v, ContactPointInfo*& contactInfo);
|
||||
Vector3& v,
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
};
|
||||
|
||||
// Add a triangle face in the candidate triangle heap in the EPA algorithm
|
||||
|
|
|
@ -58,7 +58,7 @@ GJKAlgorithm::~GJKAlgorithm() {
|
|||
/// the correct penetration depth and contact points between the enlarged objects.
|
||||
bool GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
ContactPointInfo*& contactInfo) {
|
||||
NarrowPhaseCallback* narrowPhaseCallback) {
|
||||
|
||||
Vector3 suppA; // Support point of object A
|
||||
Vector3 suppB; // Support point of object B
|
||||
|
@ -147,10 +147,12 @@ bool GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
|||
if (penetrationDepth <= 0.0) return false;
|
||||
|
||||
// Create the contact info object
|
||||
contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo* contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo(shape1Info.proxyShape, shape2Info.proxyShape, normal,
|
||||
penetrationDepth, pA, pB);
|
||||
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
|
||||
// There is an intersection, therefore we return true
|
||||
return true;
|
||||
}
|
||||
|
@ -179,10 +181,12 @@ bool GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
|||
if (penetrationDepth <= 0.0) return false;
|
||||
|
||||
// Create the contact info object
|
||||
contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo* contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo(shape1Info.proxyShape, shape2Info.proxyShape, normal,
|
||||
penetrationDepth, pA, pB);
|
||||
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
|
||||
// There is an intersection, therefore we return true
|
||||
return true;
|
||||
}
|
||||
|
@ -209,10 +213,12 @@ bool GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
|||
if (penetrationDepth <= 0.0) return false;
|
||||
|
||||
// Create the contact info object
|
||||
contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo* contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo(shape1Info.proxyShape, shape2Info.proxyShape, normal,
|
||||
penetrationDepth, pA, pB);
|
||||
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
|
||||
// There is an intersection, therefore we return true
|
||||
return true;
|
||||
}
|
||||
|
@ -246,10 +252,12 @@ bool GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
|||
if (penetrationDepth <= 0.0) return false;
|
||||
|
||||
// Create the contact info object
|
||||
contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo* contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo(shape1Info.proxyShape, shape2Info.proxyShape, normal,
|
||||
penetrationDepth, pA, pB);
|
||||
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
|
||||
// There is an intersection, therefore we return true
|
||||
return true;
|
||||
}
|
||||
|
@ -261,7 +269,7 @@ bool GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
|||
// the origin. Then, we give that simplex polytope to the EPA algorithm to compute
|
||||
// the correct penetration depth and contact points between the enlarged objects.
|
||||
return computePenetrationDepthForEnlargedObjects(shape1Info, transform1, shape2Info,
|
||||
transform2, contactInfo, v);
|
||||
transform2, narrowPhaseCallback, v);
|
||||
}
|
||||
|
||||
/// This method runs the GJK algorithm on the two enlarged objects (with margin)
|
||||
|
@ -273,7 +281,7 @@ bool GJKAlgorithm::computePenetrationDepthForEnlargedObjects(const CollisionShap
|
|||
const Transform& transform1,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
const Transform& transform2,
|
||||
ContactPointInfo*& contactInfo,
|
||||
NarrowPhaseCallback* narrowPhaseCallback,
|
||||
Vector3& v) {
|
||||
Simplex simplex;
|
||||
Vector3 suppA;
|
||||
|
@ -344,7 +352,7 @@ bool GJKAlgorithm::computePenetrationDepthForEnlargedObjects(const CollisionShap
|
|||
// between the two enlarged objects
|
||||
return mAlgoEPA.computePenetrationDepthAndContactPoints(simplex, shape1Info,
|
||||
transform1, shape2Info, transform2,
|
||||
v, contactInfo);
|
||||
v, narrowPhaseCallback);
|
||||
}
|
||||
|
||||
// Use the GJK Algorithm to find if a point is inside a convex collision shape
|
||||
|
|
|
@ -79,7 +79,8 @@ class GJKAlgorithm : public NarrowPhaseAlgorithm {
|
|||
const Transform& transform1,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
const Transform& transform2,
|
||||
ContactPointInfo*& contactInfo, Vector3& v);
|
||||
NarrowPhaseCallback* narrowPhaseCallback,
|
||||
Vector3& v);
|
||||
|
||||
public :
|
||||
|
||||
|
@ -98,7 +99,7 @@ class GJKAlgorithm : public NarrowPhaseAlgorithm {
|
|||
/// Return true and compute a contact info if the two bounding volumes collide.
|
||||
virtual bool testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
ContactPointInfo*& contactInfo);
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
|
||||
/// Use the GJK Algorithm to find if a point is inside a convex collision shape
|
||||
bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape);
|
||||
|
|
|
@ -38,6 +38,20 @@ namespace reactphysics3d {
|
|||
|
||||
class CollisionDetection;
|
||||
|
||||
// Class NarrowPhaseCallback
|
||||
/**
|
||||
* This abstract class is the base class for a narrow-phase collision
|
||||
* callback class.
|
||||
*/
|
||||
class NarrowPhaseCallback {
|
||||
|
||||
public:
|
||||
|
||||
/// Called by a narrow-phase collision algorithm when a new contact has been found
|
||||
virtual void notifyContact(OverlappingPair* overlappingPair, ContactPointInfo* contactInfo)=0;
|
||||
|
||||
};
|
||||
|
||||
// Class NarrowPhaseAlgorithm
|
||||
/**
|
||||
* This abstract class is the base class for a narrow-phase collision
|
||||
|
@ -86,7 +100,7 @@ class NarrowPhaseAlgorithm {
|
|||
/// Return true and compute a contact info if the two bounding volume collide
|
||||
virtual bool testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
ContactPointInfo*& contactInfo)=0;
|
||||
NarrowPhaseCallback* narrowPhaseCallback)=0;
|
||||
};
|
||||
|
||||
// Set the current overlapping pair of bodies
|
||||
|
|
|
@ -42,7 +42,7 @@ SphereVsSphereAlgorithm::~SphereVsSphereAlgorithm() {
|
|||
|
||||
bool SphereVsSphereAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
ContactPointInfo*& contactInfo) {
|
||||
NarrowPhaseCallback* narrowPhaseCallback) {
|
||||
|
||||
// Get the sphere collision shapes
|
||||
const SphereShape* sphereShape1 = static_cast<const SphereShape*>(shape1Info.collisionShape);
|
||||
|
@ -70,10 +70,13 @@ bool SphereVsSphereAlgorithm::testCollision(const CollisionShapeInfo& shape1Info
|
|||
decimal penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters);
|
||||
|
||||
// Create the contact info object
|
||||
contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo* contactInfo = new (mMemoryAllocator->allocate(sizeof(ContactPointInfo)))
|
||||
ContactPointInfo(shape1Info.proxyShape, shape2Info.proxyShape,
|
||||
vectorBetweenCenters.getUnit(), penetrationDepth,
|
||||
intersectionOnBody1, intersectionOnBody2);
|
||||
|
||||
// Notify about the new contact
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
|
|||
/// Return true and compute a contact info if the two bounding volume collide
|
||||
virtual bool testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
ContactPointInfo*& contactInfo);
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user