Working on testCollision() and testOverlap() methods

This commit is contained in:
Daniel Chappuis 2019-06-25 23:26:06 +02:00
parent 3f5916a280
commit 74b442077f
38 changed files with 1136 additions and 878 deletions

View File

@ -6,6 +6,12 @@
- The CollisionWorld::testCollision() methods do not have the 'categoryMaskBits' parameter anymore. - The CollisionWorld::testCollision() methods do not have the 'categoryMaskBits' parameter anymore.
- The CollisionWorld::testOverlap() methods do not have the 'categoryMaskBits' parameter anymore. - The CollisionWorld::testOverlap() methods do not have the 'categoryMaskBits' parameter anymore.
- Many methods in the EventListener class have changed. Check the user manual for more information.
- The way to retrieve contacts from a CollisionCallbackInfo object has changed. Check the user manual for more information.
### Removed
- DynamicsWorld::getContactsList(). You need to use the EventListener class to retrieve contacts now.
## Release Candidate ## Release Candidate

View File

@ -239,6 +239,7 @@ SET (REACTPHYSICS3D_SOURCES
"src/components/ProxyShapeComponents.cpp" "src/components/ProxyShapeComponents.cpp"
"src/components/DynamicsComponents.cpp" "src/components/DynamicsComponents.cpp"
"src/collision/CollisionCallback.cpp" "src/collision/CollisionCallback.cpp"
"src/collision/OverlapCallback.cpp"
"src/mathematics/mathematics_functions.cpp" "src/mathematics/mathematics_functions.cpp"
"src/mathematics/Matrix2x2.cpp" "src/mathematics/Matrix2x2.cpp"
"src/mathematics/Matrix3x3.cpp" "src/mathematics/Matrix3x3.cpp"

View File

@ -140,6 +140,8 @@ class Body {
void setLogger(Logger* logger); void setLogger(Logger* logger);
#endif #endif
// TODO : Check if those operators are still used
/// Smaller than operator /// Smaller than operator
bool operator<(const Body& body2) const; bool operator<(const Body& body2) const;

View File

@ -25,66 +25,71 @@
// Libraries // Libraries
#include "collision/CollisionCallback.h" #include "collision/CollisionCallback.h"
#include "engine/OverlappingPair.h" #include "collision/ContactPair.h"
#include "memory/MemoryAllocator.h" #include "constraint/ContactPoint.h"
#include "collision/ContactManifold.h" #include "engine/CollisionWorld.h"
#include "memory/MemoryManager.h"
// We want to use the ReactPhysics3D namespace // We want to use the ReactPhysics3D namespace
using namespace reactphysics3d; using namespace reactphysics3d;
// Constructor // Constructor
CollisionCallback::CollisionCallbackInfo::CollisionCallbackInfo(OverlappingPair* pair, MemoryManager& memoryManager) : CollisionCallback::ContactPoint::ContactPoint(const reactphysics3d::ContactPoint& contactPoint) : mContactPoint(contactPoint) {
contactManifoldElements(nullptr), body1(pair->getShape1()->getBody()),
body2(pair->getShape2()->getBody()),
proxyShape1(pair->getShape1()), proxyShape2(pair->getShape2()),
mMemoryManager(memoryManager) {
assert(pair != nullptr);
// TODO : Rework how to report contacts
/*
const ContactManifoldSet& manifoldSet = pair->getContactManifoldSet();
// For each contact manifold in the set of manifolds in the pair
ContactManifold* contactManifold = manifoldSet.getContactManifolds();
assert(contactManifold != nullptr);
while (contactManifold != nullptr) {
assert(contactManifold->getNbContactPoints() > 0);
// Add the contact manifold at the beginning of the linked
// list of contact manifolds of the first body
ContactManifoldListElement* element = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(ContactManifoldListElement)))
ContactManifoldListElement(contactManifold,
contactManifoldElements);
contactManifoldElements = element;
contactManifold = contactManifold->getNext();
}
*/
} }
// Destructor // Contact Pair Constructor
CollisionCallback::CollisionCallbackInfo::~CollisionCallbackInfo() { CollisionCallback::ContactPair::ContactPair(const reactphysics3d::ContactPair& contactPair,
List<reactphysics3d::ContactPoint>* contactPoints, CollisionWorld& world)
:mContactPair(contactPair), mContactPoints(contactPoints),
mWorld(world) {
// TODO : Rework how to report contacts
/*
// Release memory allocator for the contact manifold list elements
ContactManifoldListElement* element = contactManifoldElements;
while (element != nullptr) {
ContactManifoldListElement* nextElement = element->getNext();
// Delete and release memory
element->~ContactManifoldListElement();
mMemoryManager.release(MemoryManager::AllocationType::Pool, element,
sizeof(ContactManifoldListElement));
element = nextElement;
}
*/
} }
// Return a pointer to the first body in contact
CollisionBody* CollisionCallback::ContactPair::getBody1() const {
return static_cast<CollisionBody*>(mWorld.mBodyComponents.getBody(mContactPair.body1Entity));
}
// Return a pointer to the second body in contact
CollisionBody* CollisionCallback::ContactPair::getBody2() const {
return static_cast<CollisionBody*>(mWorld.mBodyComponents.getBody(mContactPair.body2Entity));
}
// Return a pointer to the first proxy-shape in contact (in body 1)
ProxyShape* CollisionCallback::ContactPair::getProxyShape1() const {
return mWorld.mProxyShapesComponents.getProxyShape(mContactPair.proxyShape1Entity);
}
// Return a pointer to the second proxy-shape in contact (in body 1)
ProxyShape* CollisionCallback::ContactPair::getProxyShape2() const {
return mWorld.mProxyShapesComponents.getProxyShape(mContactPair.proxyShape2Entity);
}
// CollisionCallbackInfo Constructor
CollisionCallback::CallbackData::CallbackData(List<reactphysics3d::ContactPair>* contactPairs, List<ContactManifold>* manifolds,
List<reactphysics3d::ContactPoint>* contactPoints, CollisionWorld& world)
:mContactPairs(contactPairs), mContactManifolds(manifolds), mContactPoints(contactPoints), mWorld(world) {
}
// Return a given contact point of the contact pair
/// Note that the returned ContactPoint object is only valid during the call of the CollisionCallback::onContact()
/// method. Therefore, you need to get contact data from it and make a copy. Do not make a copy of the ContactPoint
/// object itself because it won't be valid after the CollisionCallback::onContact() call.
CollisionCallback::ContactPoint CollisionCallback::ContactPair::getContactPoint(uint index) const {
assert(index < getNbContactPoints());
return CollisionCallback::ContactPoint((*mContactPoints)[mContactPair.contactPointsIndex + index]);
}
// Return a given contact pair
/// Note that the returned ContactPair object is only valid during the call of the CollisionCallback::onContact()
/// method. Therefore, you need to get contact data from it and make a copy. Do not make a copy of the ContactPair
/// object itself because it won't be valid after the CollisionCallback::onContact() call.
CollisionCallback::ContactPair CollisionCallback::CallbackData::getContactPair(uint index) const {
assert(index < getNbContactPairs());
return CollisionCallback::ContactPair((*mContactPairs)[index], mContactPoints, mWorld);
}

View File

@ -26,6 +26,11 @@
#ifndef REACTPHYSICS3D_COLLISION_CALLBACK_H #ifndef REACTPHYSICS3D_COLLISION_CALLBACK_H
#define REACTPHYSICS3D_COLLISION_CALLBACK_H #define REACTPHYSICS3D_COLLISION_CALLBACK_H
// Libraries
#include "containers/List.h"
#include "collision/ContactPair.h"
#include "constraint/ContactPoint.h"
/// ReactPhysics3D namespace /// ReactPhysics3D namespace
namespace reactphysics3d { namespace reactphysics3d {
@ -36,10 +41,11 @@ struct ContactManifoldListElement;
class CollisionBody; class CollisionBody;
class ProxyShape; class ProxyShape;
class MemoryManager; class MemoryManager;
class CollisionCallbackInfo;
// Class CollisionCallback // Class CollisionCallback
/** /**
* This class can be used to register a callback for collision test queries. * This abstract class can be used to register a callback for collision test queries.
* You should implement your own class inherited from this one and implement * You should implement your own class inherited from this one and implement
* the notifyContact() method. This method will called each time a contact * the notifyContact() method. This method will called each time a contact
* point is reported. * point is reported.
@ -48,47 +54,221 @@ class CollisionCallback {
public: public:
// Structure CollisionCallbackInfo // Class ContactPoint
/** /**
* This structure represents the contact information between two collision * This class represents a contact point between two bodies of the physics world.
* shapes of two bodies
*/ */
struct CollisionCallbackInfo { class ContactPoint {
private:
// -------------------- Attributes -------------------- //
const reactphysics3d::ContactPoint& mContactPoint;
// -------------------- Methods -------------------- //
/// Constructor
ContactPoint(const reactphysics3d::ContactPoint& contactPoint);
public: public:
/// Pointer to the first element of the linked-list that contains contact manifolds // -------------------- Methods -------------------- //
ContactManifoldListElement* contactManifoldElements;
/// Pointer to the first body of the contact /// Copy constructor
CollisionBody* body1; ContactPoint(const ContactPoint& contactPoint) = default;
/// Pointer to the second body of the contact /// Assignment operator
CollisionBody* body2; ContactPoint& operator=(const ContactPoint& contactPoint) = default;
/// Pointer to the proxy shape of first body /// Destructor
const ProxyShape* proxyShape1; ~ContactPoint() = default;
/// Pointer to the proxy shape of second body /// Return the penetration depth
const ProxyShape* proxyShape2; decimal getPenetrationDepth() const;
/// Memory manager /// Return the world-space contact normal
MemoryManager& mMemoryManager; const Vector3& getWorldNormal() const;
// Constructor /// Return the contact point on the first proxy shape in the local-space of the first proxy shape
CollisionCallbackInfo(OverlappingPair* pair, MemoryManager& memoryManager); const Vector3& getLocalPointOnShape1() const;
// Destructor /// Return the contact point on the second proxy shape in the local-space of the second proxy shape
~CollisionCallbackInfo(); const Vector3& getLocalPointOnShape2() const;
// -------------------- Friendship -------------------- //
friend class CollisionCallback;
};
// Class ContactPair
/**
* This class represents the contact between two bodies of the physics world.
* A contact pair contains a list of contact points.
*/
class ContactPair {
private:
// -------------------- Attributes -------------------- //
const reactphysics3d::ContactPair& mContactPair;
/// Pointer to the contact points
List<reactphysics3d::ContactPoint>* mContactPoints;
/// Reference to the physics world
CollisionWorld& mWorld;
// -------------------- Methods -------------------- //
/// Constructor
ContactPair(const reactphysics3d::ContactPair& contactPair, List<reactphysics3d::ContactPoint>* contactPoints,
CollisionWorld& world);
public:
// -------------------- Methods -------------------- //
/// Copy constructor
ContactPair(const ContactPair& contactPair) = default;
/// Assignment operator
ContactPair& operator=(const ContactPair& contactPair) = default;
/// Destructor
~ContactPair() = default;
/// Return the number of contact points in the contact pair
uint getNbContactPoints() const;
/// Return a given contact point
ContactPoint getContactPoint(uint index) const;
/// Return a pointer to the first body in contact
CollisionBody* getBody1() const;
/// Return a pointer to the second body in contact
CollisionBody* getBody2() const;
/// Return a pointer to the first proxy-shape in contact (in body 1)
ProxyShape* getProxyShape1() const;
/// Return a pointer to the second proxy-shape in contact (in body 2)
ProxyShape* getProxyShape2() const;
// -------------------- Friendship -------------------- //
friend class CollisionCallback;
};
// Class CallbackData
/**
* This class contains data about contacts between bodies
*/
class CallbackData {
private:
// -------------------- Attributes -------------------- //
/// Pointer to the list of contact pairs
List<reactphysics3d::ContactPair>* mContactPairs;
/// Pointer to the list of contact manifolds
List<ContactManifold>* mContactManifolds;
/// Pointer to the contact points
List<reactphysics3d::ContactPoint>* mContactPoints;
/// Reference to the physics world
CollisionWorld& mWorld;
// -------------------- Methods -------------------- //
/// Constructor
CallbackData(List<reactphysics3d::ContactPair>* contactPairs, List<ContactManifold>* manifolds,
List<reactphysics3d::ContactPoint>* contactPoints, CollisionWorld& world);
/// Deleted copy constructor
CallbackData(const CallbackData& callbackData) = delete;
/// Deleted assignment operator
CallbackData& operator=(const CallbackData& callbackData) = delete;
/// Destructor
~CallbackData() = default;
public:
// -------------------- Methods -------------------- //
/// Return the number of contact pairs
uint getNbContactPairs() const;
/// Return a given contact pair
ContactPair getContactPair(uint index) const;
// -------------------- Friendship -------------------- //
friend class CollisionDetection;
}; };
/// Destructor /// Destructor
virtual ~CollisionCallback() = default; virtual ~CollisionCallback() = default;
/// This method will be called for each reported contact point /// This method is called when some contacts occur
virtual void notifyContact(const CollisionCallbackInfo& collisionCallbackInfo)=0; virtual void onContact(const CallbackData& callbackData)=0;
}; };
// Return the number of contact pairs (there is a single contact pair between two bodies in contact)
/**
* @return The number of contact pairs
*/
inline uint CollisionCallback::CallbackData::getNbContactPairs() const {
return mContactPairs->size();
}
// Return the number of contact points in the contact pair
/**
* @return The number of contact points
*/
inline uint CollisionCallback::ContactPair::getNbContactPoints() const {
return mContactPair.nbToTalContactPoints;
}
// Return the penetration depth between the two bodies in contact
/**
* @return The penetration depth (larger than zero)
*/
inline decimal CollisionCallback::ContactPoint::getPenetrationDepth() const {
return mContactPoint.getPenetrationDepth();
}
// Return the world-space contact normal (vector from first body toward second body)
/**
* @return The contact normal direction at the contact point (in world-space)
*/
inline const Vector3& CollisionCallback::ContactPoint::getWorldNormal() const {
return mContactPoint.getNormal();
}
// Return the contact point on the first proxy shape in the local-space of the first proxy shape
/**
* @return The contact point in the local-space of the first proxy-shape (from body1) in contact
*/
inline const Vector3& CollisionCallback::ContactPoint::getLocalPointOnShape1() const {
return mContactPoint.getLocalPointOnShape1();
}
// Return the contact point on the second proxy shape in the local-space of the second proxy shape
/**
* @return The contact point in the local-space of the second proxy-shape (from body2) in contact
*/
inline const Vector3& CollisionCallback::ContactPoint::getLocalPointOnShape2() const {
return mContactPoint.getLocalPointOnShape2();
}
} }
#endif #endif

View File

@ -43,6 +43,7 @@
#include "engine/EventListener.h" #include "engine/EventListener.h"
#include "collision/RaycastInfo.h" #include "collision/RaycastInfo.h"
#include "engine/Islands.h" #include "engine/Islands.h"
#include "containers/Pair.h"
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
@ -431,9 +432,6 @@ void CollisionDetection::computeNarrowPhase() {
// Reduce the number of contact points in the manifolds // Reduce the number of contact points in the manifolds
reducePotentialContactManifolds(mCurrentContactPairs, mPotentialContactManifolds, mPotentialContactPoints); reducePotentialContactManifolds(mCurrentContactPairs, mPotentialContactManifolds, mPotentialContactPoints);
// Report contacts to the user
reportAllContacts();
assert(mCurrentContactManifolds->size() == 0); assert(mCurrentContactManifolds->size() == 0);
assert(mCurrentContactPoints->size() == 0); assert(mCurrentContactPoints->size() == 0);
@ -442,32 +440,105 @@ void CollisionDetection::computeNarrowPhase() {
mNarrowPhaseInput.clear(); mNarrowPhaseInput.clear();
} }
// Compute the narrow-phase collision detection for the testCollision() methods. // Compute the narrow-phase collision detection for the testOverlap() methods.
// This method returns true if contacts are found. /// This method returns true if contacts are found.
bool CollisionDetection::computeNarrowPhaseSnapshot(NarrowPhaseInput& narrowPhaseInput, bool reportContacts) { bool CollisionDetection::computeNarrowPhaseOverlapSnapshot(NarrowPhaseInput& narrowPhaseInput, OverlapCallback* callback) {
RP3D_PROFILE("CollisionDetection::computeNarrowPhaseSnapshot()", mProfiler); RP3D_PROFILE("CollisionDetection::computeNarrowPhaseOverlapSnapshot()", mProfiler);
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, reportContacts, allocator); bool collisionFound = testNarrowPhaseCollision(narrowPhaseInput, false, allocator);
if (!reportContacts) { if (collisionFound && callback != nullptr) {
return collisionFound;
// Compute the overlapping bodies
List<Pair<Entity, Entity>> overlapBodies(allocator);
computeSnapshotContactPairs(narrowPhaseInput, overlapBodies);
// Report overlapping bodies
OverlapCallback::CallbackData callbackData(overlapBodies, *mWorld);
(*callback).onOverlap(callbackData);
} }
List<ContactPointInfo> potentialContactPoints(allocator); return collisionFound;
List<ContactManifoldInfo> potentialContactManifolds(allocator); }
Map<OverlappingPair::OverlappingPairId, uint> mapPairIdToContactPairIndex(allocator);
List<ContactPair> contactPairs(allocator);
Map<Entity, List<uint>> mapBodyToContactPairs(allocator);
// Process all the potential contacts after narrow-phase collision // Process the potential overlapping bodies for the testOverlap() methods
processAllPotentialContacts(narrowPhaseInput, true, potentialContactPoints, &mapPairIdToContactPairIndex, potentialContactManifolds, void CollisionDetection::computeSnapshotContactPairs(NarrowPhaseInput& narrowPhaseInput, List<Pair<Entity, Entity>>& overlapPairs) const {
&contactPairs, mapBodyToContactPairs);
// Reduce the number of contact points in the manifolds // get the narrow-phase batches to test for collision
reducePotentialContactManifolds(&contactPairs, potentialContactManifolds, potentialContactPoints); NarrowPhaseInfoBatch& sphereVsSphereBatch = narrowPhaseInput.getSphereVsSphereBatch();
NarrowPhaseInfoBatch& sphereVsCapsuleBatch = narrowPhaseInput.getSphereVsCapsuleBatch();
NarrowPhaseInfoBatch& capsuleVsCapsuleBatch = narrowPhaseInput.getCapsuleVsCapsuleBatch();
NarrowPhaseInfoBatch& sphereVsConvexPolyhedronBatch = narrowPhaseInput.getSphereVsConvexPolyhedronBatch();
NarrowPhaseInfoBatch& capsuleVsConvexPolyhedronBatch = narrowPhaseInput.getCapsuleVsConvexPolyhedronBatch();
NarrowPhaseInfoBatch& convexPolyhedronVsConvexPolyhedronBatch = narrowPhaseInput.getConvexPolyhedronVsConvexPolyhedronBatch();
// Process the potential contacts
computeSnapshotContactPairs(sphereVsSphereBatch, overlapPairs);
computeSnapshotContactPairs(sphereVsCapsuleBatch, overlapPairs);
computeSnapshotContactPairs(capsuleVsCapsuleBatch, overlapPairs);
computeSnapshotContactPairs(sphereVsConvexPolyhedronBatch, overlapPairs);
computeSnapshotContactPairs(capsuleVsConvexPolyhedronBatch, overlapPairs);
computeSnapshotContactPairs(convexPolyhedronVsConvexPolyhedronBatch, overlapPairs);
}
// Convert the potential overlapping bodies for the testOverlap() methods
void CollisionDetection::computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) const {
RP3D_PROFILE("CollisionDetection::computeSnapshotContactPairs()", mProfiler);
// For each narrow phase info object
for(uint i=0; i < narrowPhaseInfoBatch.getNbObjects(); i++) {
// If there is a contact
if (narrowPhaseInfoBatch.isColliding[i]) {
// Add the pair of bodies in contact into the list
overlapPairs.add(Pair<Entity, Entity>(narrowPhaseInfoBatch.overlappingPairs[i]->getShape1()->getBody()->getEntity(),
narrowPhaseInfoBatch.overlappingPairs[i]->getShape2()->getBody()->getEntity()));
}
narrowPhaseInfoBatch.resetContactPoints(i);
}
}
// Compute the narrow-phase collision detection for the testCollision() methods.
// This method returns true if contacts are found.
bool CollisionDetection::computeNarrowPhaseCollisionSnapshot(NarrowPhaseInput& narrowPhaseInput, CollisionCallback& callback) {
RP3D_PROFILE("CollisionDetection::computeNarrowPhaseCollisionSnapshot()", mProfiler);
MemoryAllocator& allocator = mMemoryManager.getPoolAllocator();
// Test the narrow-phase collision detection on the batches to be tested
bool collisionFound = testNarrowPhaseCollision(narrowPhaseInput, true, allocator);
// If collision has been found, create contacts
if (collisionFound) {
List<ContactPointInfo> potentialContactPoints(allocator);
List<ContactManifoldInfo> potentialContactManifolds(allocator);
Map<OverlappingPair::OverlappingPairId, uint> mapPairIdToContactPairIndex(allocator);
List<ContactPair> contactPairs(allocator);
List<ContactManifold> contactManifolds(allocator);
List<ContactPoint> contactPoints(allocator);
Map<Entity, List<uint>> mapBodyToContactPairs(allocator);
// Process all the potential contacts after narrow-phase collision
processAllPotentialContacts(narrowPhaseInput, true, potentialContactPoints, &mapPairIdToContactPairIndex, potentialContactManifolds,
&contactPairs, mapBodyToContactPairs);
// Reduce the number of contact points in the manifolds
reducePotentialContactManifolds(&contactPairs, potentialContactManifolds, potentialContactPoints);
// Create the actual contact manifolds and contact points
createSnapshotContacts(contactPairs, contactManifolds, contactPoints, potentialContactManifolds,
potentialContactPoints);
// Report the contacts to the user
reportContacts(callback, &contactPairs, &contactManifolds, &contactPoints);
}
return collisionFound; return collisionFound;
} }
@ -502,10 +573,6 @@ void CollisionDetection::swapPreviousAndCurrentContacts() {
} }
// Create the actual contact manifolds and contacts points // Create the actual contact manifolds and contacts points
/// List of the indices of the contact pairs (in mCurrentContacPairs array) with contact pairs of
/// same islands packed together linearly and contact pairs that are not part of islands at the end.
/// This is used when we create contact manifolds and contact points so that there are also packed
/// together linearly if they are part of the same island.
void CollisionDetection::createContacts() { void CollisionDetection::createContacts() {
RP3D_PROFILE("CollisionDetection::createContacts()", mProfiler); RP3D_PROFILE("CollisionDetection::createContacts()", mProfiler);
@ -561,12 +628,73 @@ void CollisionDetection::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
if (mWorld->mEventListener != nullptr) {
reportContacts(*(mWorld->mEventListener), mCurrentContactPairs, mCurrentContactManifolds, mCurrentContactPoints);
}
// Reset the potential contacts // Reset the potential contacts
mPotentialContactPoints.clear(true); mPotentialContactPoints.clear(true);
mPotentialContactManifolds.clear(true); mPotentialContactManifolds.clear(true);
mContactPairsIndicesOrderingForContacts.clear(true); mContactPairsIndicesOrderingForContacts.clear(true);
} }
// Create the actual contact manifolds and contacts points for testCollision() methods
void CollisionDetection::createSnapshotContacts(List<ContactPair>& contactPairs,
List<ContactManifold>& contactManifolds,
List<ContactPoint>& contactPoints,
List<ContactManifoldInfo>& potentialContactManifolds,
List<ContactPointInfo>& potentialContactPoints) {
RP3D_PROFILE("CollisionDetection::createSnapshotContacts()", mProfiler);
contactManifolds.reserve(contactPairs.size());
contactPoints.reserve(contactManifolds.size());
// For each contact pair
for (uint p=0; p < contactPairs.size(); p++) {
ContactPair& contactPair = contactPairs[p];
assert(contactPair.potentialContactManifoldsIndices.size() > 0);
contactPair.contactManifoldsIndex = contactManifolds.size();
contactPair.nbContactManifolds = contactPair.potentialContactManifoldsIndices.size();
contactPair.contactPointsIndex = contactPoints.size();
// For each potential contact manifold of the pair
for (uint m=0; m < contactPair.potentialContactManifoldsIndices.size(); m++) {
ContactManifoldInfo& potentialManifold = potentialContactManifolds[contactPair.potentialContactManifoldsIndices[m]];
// Start index and number of contact points for this manifold
const uint contactPointsIndex = contactPoints.size();
const int8 nbContactPoints = static_cast<int8>(potentialManifold.potentialContactPointsIndices.size());
contactPair.nbToTalContactPoints += nbContactPoints;
// We create a new contact manifold
ContactManifold contactManifold(contactPair.body1Entity, contactPair.body2Entity, contactPair.proxyShape1Entity,
contactPair.proxyShape2Entity, contactPointsIndex, nbContactPoints);
// Add the contact manifold
contactManifolds.add(contactManifold);
assert(potentialManifold.potentialContactPointsIndices.size() > 0);
// For each contact point of the manifold
for (uint c=0; c < potentialManifold.potentialContactPointsIndices.size(); c++) {
ContactPointInfo& potentialContactPoint = potentialContactPoints[potentialManifold.potentialContactPointsIndices[c]];
// Create a new contact point
ContactPoint contactPoint(potentialContactPoint, mWorld->mConfig);
// Add the contact point
contactPoints.add(contactPoint);
}
}
}
}
// 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)
void CollisionDetection::initContactsWithPreviousOnes() { void CollisionDetection::initContactsWithPreviousOnes() {
@ -660,46 +788,6 @@ void CollisionDetection::initContactsWithPreviousOnes() {
mPreviousContactManifolds->clear(); mPreviousContactManifolds->clear();
mPreviousContactPairs->clear(); mPreviousContactPairs->clear();
mPreviousMapPairIdToContactPairIndex->clear(); mPreviousMapPairIdToContactPairIndex->clear();
/*
// TODO : DELETE THIS
std::cout << "_______________ RECAP ACTUAL CONTACTS___________________" << std::endl;
std::cout << "ContactPairs :" << std::endl;
for (uint i=0; i < mCurrentContactPairs->size(); i++) {
ContactPair& pair = (*mCurrentContactPairs)[i];
std::cout << " PairId : (" << pair.pairId.first << ", " << pair.pairId.second << std::endl;
std::cout << " Index : " << i << std::endl;
std::cout << " ContactManifoldsIndex : " << pair.contactManifoldsIndex << std::endl;
std::cout << " nbManifolds : " << pair.nbContactManifolds << std::endl;
std::cout << " ContactPointsIndex : " << pair.contactPointsIndex << std::endl;
std::cout << " nbTotalPoints : " << pair.nbToTalContactPoints << std::endl;
}
std::cout << "ContactManifolds :" << std::endl;
for (uint i=0; i < mCurrentContactManifolds->size(); i++) {
ContactManifold& manifold = (*mCurrentContactManifolds)[i];
std::cout << " Index : " << i << std::endl;
std::cout << " >>ContactPointsIndex : " << manifold.mContactPointsIndex << std::endl;
std::cout << " >>Nb Contact Points : " << manifold.mNbContactPoints << std::endl;
}
std::cout << "ContactPoints :" << std::endl;
for (uint i=0; i < mCurrentContactPoints->size(); i++) {
ContactPoint& contactPoint = (*mCurrentContactPoints)[i];
std::cout << " Index : " << i << std::endl;
std::cout << " Point : (" << contactPoint.getLocalPointOnShape1().x << ", " << contactPoint.getLocalPointOnShape1().y << ", " << contactPoint.getLocalPointOnShape1().z << std::endl;
}
std::cout << "mCurrentMapPairIdToContactPairIndex :" << std::endl;
for (auto it = mCurrentMapPairIdToContactPairIndex->begin(); it != mCurrentMapPairIdToContactPairIndex->end(); ++it) {
OverlappingPair::OverlappingPairId pairId = it->first;
uint index = it->second;
std::cout << " PairId : " << pairId.first << ", " << pairId.second << std::endl;
std::cout << " ContactPair Index : " << index << std::endl;
}
*/
} }
// Remove a body from the collision detection // Remove a body from the collision detection
@ -902,7 +990,7 @@ void CollisionDetection::reducePotentialContactManifolds(List<ContactPair>* cont
assert(contactPair.potentialContactManifoldsIndices.size() > 0); assert(contactPair.potentialContactManifoldsIndices.size() > 0);
// While there are too many manifolds // While there are too many manifolds in the contact pair
while(contactPair.potentialContactManifoldsIndices.size() > mWorld->mConfig.nbMaxContactManifolds) { while(contactPair.potentialContactManifoldsIndices.size() > mWorld->mConfig.nbMaxContactManifolds) {
// Look for a manifold with the smallest contact penetration depth. // Look for a manifold with the smallest contact penetration depth.
@ -1150,32 +1238,32 @@ void CollisionDetection::reduceContactPoints(ContactManifoldInfo& manifold, cons
manifold.potentialContactPointsIndices.add(pointsToKeepIndices[3]); manifold.potentialContactPointsIndices.add(pointsToKeepIndices[3]);
} }
// Report contacts for all the colliding overlapping pairs // Report contacts
// TODO : What do we do with this method void CollisionDetection::reportContacts() {
void CollisionDetection::reportAllContacts() {
RP3D_PROFILE("CollisionDetection::reportAllContacts()", mProfiler); if (mWorld->mEventListener != nullptr) {
reportContacts(*(mWorld->mEventListener), mCurrentContactPairs, mCurrentContactManifolds,
// TODO : Rework how we report contacts mCurrentContactPoints);
/*
// For each overlapping pairs in contact during the narrow-phase
for (auto it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ++it) {
OverlappingPair* pair = it->second;
// If there is a user callback
if (mWorld->mEventListener != nullptr && pair->hasContacts()) {
CollisionCallback::CollisionCallbackInfo collisionInfo(pair, mMemoryManager);
// Trigger a callback event to report the new contact to the user
mWorld->mEventListener->newContact(collisionInfo);
}
} }
*/
} }
// Return true if two bodies overlap // Report all contacts
void CollisionDetection::reportContacts(CollisionCallback& callback, List<ContactPair>* contactPairs,
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints) {
RP3D_PROFILE("CollisionDetection::reportContacts()", mProfiler);
// If there are contacts
if (contactPairs->size() > 0) {
CollisionCallback::CallbackData callbackData(contactPairs, manifolds, contactPoints, *mWorld);
// Call the callback method to report the contacts
callback.onContact(callbackData);
}
}
// Return true if two bodies overlap (collide)
bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) { bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) {
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
@ -1193,16 +1281,14 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2)
computeMiddlePhase(overlappingPairs, narrowPhaseInput); computeMiddlePhase(overlappingPairs, narrowPhaseInput);
// Compute the narrow-phase collision detection // Compute the narrow-phase collision detection
return computeNarrowPhaseSnapshot(narrowPhaseInput, true); return computeNarrowPhaseOverlapSnapshot(narrowPhaseInput, nullptr);
} }
return false; return false;
} }
// Report all the bodies that overlap in the world // Report all the bodies that overlap (collide) in the world
void CollisionDetection::testOverlap(OverlapCallback* callback) { void CollisionDetection::testOverlap(OverlapCallback& callback) {
assert(callback != nullptr);
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
@ -1212,16 +1298,12 @@ void CollisionDetection::testOverlap(OverlapCallback* callback) {
// Compute the middle-phase collision detection // Compute the middle-phase collision detection
computeMiddlePhase(mOverlappingPairs, narrowPhaseInput); computeMiddlePhase(mOverlappingPairs, narrowPhaseInput);
// Compute the narrow-phase collision detection // Compute the narrow-phase collision detection and report overlapping shapes
computeNarrowPhaseSnapshot(narrowPhaseInput, false); computeNarrowPhaseOverlapSnapshot(narrowPhaseInput, &callback);
// TODO : Report overlaps
} }
// Report all the bodies that overlap with the body in parameter // Report all the bodies that overlap (collide) with the body in parameter
void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* callback) { void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback& callback) {
assert(callback != nullptr);
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
@ -1238,16 +1320,12 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* callb
computeMiddlePhase(overlappingPairs, narrowPhaseInput); computeMiddlePhase(overlappingPairs, narrowPhaseInput);
// Compute the narrow-phase collision detection // Compute the narrow-phase collision detection
computeNarrowPhaseSnapshot(narrowPhaseInput, false); computeNarrowPhaseOverlapSnapshot(narrowPhaseInput, &callback);
// TODO : Report contacts
} }
} }
// Test collision and report contacts between two bodies. // Test collision and report contacts between two bodies.
void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback* callback) { void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback& callback) {
assert(callback != nullptr);
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
@ -1263,17 +1341,13 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body
// Compute the middle-phase collision detection // Compute the middle-phase collision detection
computeMiddlePhase(overlappingPairs, narrowPhaseInput); computeMiddlePhase(overlappingPairs, narrowPhaseInput);
// Compute the narrow-phase collision detection // Compute the narrow-phase collision detection and report contacts
computeNarrowPhaseSnapshot(narrowPhaseInput, true); computeNarrowPhaseCollisionSnapshot(narrowPhaseInput, callback);
// TODO : Report contacts
} }
} }
// Test collision and report all the contacts involving the body in parameter // Test collision and report all the contacts involving the body in parameter
void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* callback) { void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback& callback) {
assert(callback != nullptr);
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
@ -1289,17 +1363,13 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
// Compute the middle-phase collision detection // Compute the middle-phase collision detection
computeMiddlePhase(overlappingPairs, narrowPhaseInput); computeMiddlePhase(overlappingPairs, narrowPhaseInput);
// Compute the narrow-phase collision detection // Compute the narrow-phase collision detection and report contacts
computeNarrowPhaseSnapshot(narrowPhaseInput, true); computeNarrowPhaseCollisionSnapshot(narrowPhaseInput, callback);
// TODO : Report contacts
} }
} }
// Test collision and report contacts between each colliding bodies in the world // Test collision and report contacts between each colliding bodies in the world
void CollisionDetection::testCollision(CollisionCallback* callback) { void CollisionDetection::testCollision(CollisionCallback& callback) {
assert(callback != nullptr);
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
@ -1309,10 +1379,8 @@ void CollisionDetection::testCollision(CollisionCallback* callback) {
// Compute the middle-phase collision detection // Compute the middle-phase collision detection
computeMiddlePhase(mOverlappingPairs, narrowPhaseInput); computeMiddlePhase(mOverlappingPairs, narrowPhaseInput);
// Compute the narrow-phase collision detection // Compute the narrow-phase collision detection and report contacts
computeNarrowPhaseSnapshot(narrowPhaseInput, true); computeNarrowPhaseCollisionSnapshot(narrowPhaseInput, callback);
// TODO : Report contacts
} }
// Filter the overlapping pairs to keep only the pairs where a given body is involved // Filter the overlapping pairs to keep only the pairs where a given body is involved

View File

@ -186,8 +186,17 @@ class CollisionDetection {
/// Compute the narrow-phase collision detection /// Compute the narrow-phase collision detection
void computeNarrowPhase(); void computeNarrowPhase();
/// Compute the narrow-phase collision detection for the testOverlap() methods.
bool computeNarrowPhaseOverlapSnapshot(NarrowPhaseInput& narrowPhaseInput, OverlapCallback* callback);
/// Compute the narrow-phase collision detection for the testCollision() methods /// Compute the narrow-phase collision detection for the testCollision() methods
bool computeNarrowPhaseSnapshot(NarrowPhaseInput& narrowPhaseInput, bool reportContacts); bool computeNarrowPhaseCollisionSnapshot(NarrowPhaseInput& narrowPhaseInput, CollisionCallback& callback);
/// Process the potential contacts after narrow-phase collision detection
void computeSnapshotContactPairs(NarrowPhaseInput& narrowPhaseInput, List<Pair<Entity, Entity>>& overlapPairs) const;
/// Convert the potential contact into actual contacts
void computeSnapshotContactPairs(NarrowPhaseInfoBatch& narrowPhaseInfoBatch, List<Pair<Entity, Entity>>& overlapPairs) 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<int, int>>& overlappingNodes); void updateOverlappingPairs(const List<Pair<int, int>>& overlappingNodes);
@ -225,6 +234,12 @@ class CollisionDetection {
/// 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();
/// Create the actual contact manifolds and contacts points for testCollision() methods
void createSnapshotContacts(List<ContactPair>& contactPairs, List<ContactManifold> &contactManifolds,
List<ContactPoint>& contactPoints,
List<ContactManifoldInfo>& potentialContactManifolds,
List<ContactPointInfo>& potentialContactPoints);
/// 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)
void initContactsWithPreviousOnes(); void initContactsWithPreviousOnes();
@ -232,8 +247,9 @@ class CollisionDetection {
void reduceContactPoints(ContactManifoldInfo& manifold, const Transform& shape1ToWorldTransform, void reduceContactPoints(ContactManifoldInfo& manifold, const Transform& shape1ToWorldTransform,
const List<ContactPointInfo>& potentialContactPoints) const; const List<ContactPointInfo>& potentialContactPoints) const;
/// Report contacts for all the colliding overlapping pairs /// Report contacts
void reportAllContacts(); void reportContacts(CollisionCallback& callback, List<ContactPair>* contactPairs,
List<ContactManifold>* manifolds, List<ContactPoint>* contactPoints);
/// 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,
@ -290,6 +306,9 @@ class CollisionDetection {
/// Ask for a collision shape to be tested again during broad-phase. /// Ask for a collision shape to be tested again during broad-phase.
void askForBroadPhaseCollisionCheck(ProxyShape* shape); void askForBroadPhaseCollisionCheck(ProxyShape* shape);
/// Report contacts
void reportContacts();
/// Compute the collision detection /// Compute the collision detection
void computeCollisionDetection(); void computeCollisionDetection();
@ -301,19 +320,19 @@ class CollisionDetection {
bool testOverlap(CollisionBody* body1, CollisionBody* body2); bool testOverlap(CollisionBody* body1, CollisionBody* body2);
/// Report all the bodies that overlap (collide) with the body in parameter /// Report all the bodies that overlap (collide) with the body in parameter
void testOverlap(CollisionBody* body, OverlapCallback* callback); void testOverlap(CollisionBody* body, OverlapCallback& callback);
/// Report all the bodies that overlap (collide) in the world /// Report all the bodies that overlap (collide) in the world
void testOverlap(OverlapCallback* overlapCallback); void testOverlap(OverlapCallback& overlapCallback);
/// Test collision and report contacts between two bodies. /// Test collision and report contacts between two bodies.
void testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback* callback); void testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback& callback);
/// Test collision and report all the contacts involving the body in parameter /// Test collision and report all the contacts involving the body in parameter
void testCollision(CollisionBody* body, CollisionCallback* callback); void testCollision(CollisionBody* body, CollisionCallback& callback);
/// Test collision and report contacts between each colliding bodies in the world /// Test collision and report contacts between each colliding bodies in the world
void testCollision(CollisionCallback* callback); void testCollision(CollisionCallback& callback);
/// Return a reference to the memory manager /// Return a reference to the memory manager
MemoryManager& getMemoryManager() const; MemoryManager& getMemoryManager() const;

View File

@ -31,7 +31,6 @@
using namespace reactphysics3d; using namespace reactphysics3d;
// Constructor // Constructor
// TODO : REMOVE worldSettings from this constructor
ContactManifold::ContactManifold(Entity bodyEntity1, Entity bodyEntity2, Entity proxyShapeEntity1, Entity proxyShapeEntity2, ContactManifold::ContactManifold(Entity bodyEntity1, Entity bodyEntity2, Entity proxyShapeEntity1, Entity proxyShapeEntity2,
uint contactPointsIndex, int8 nbContactPoints) uint contactPointsIndex, int8 nbContactPoints)
:mContactPointsIndex(0), bodyEntity1(bodyEntity1), bodyEntity2(bodyEntity2), :mContactPointsIndex(0), bodyEntity1(bodyEntity1), bodyEntity2(bodyEntity2),

View File

@ -162,9 +162,6 @@ class ContactManifold {
/// Return the number of contact points in the manifold /// Return the number of contact points in the manifold
int8 getNbContactPoints() const; int8 getNbContactPoints() const;
/// Return a pointer to the first contact point of the manifold
ContactPoint* getContactPoints() const;
// -------------------- Friendship -------------------- // // -------------------- Friendship -------------------- //
friend class DynamicsWorld; friend class DynamicsWorld;

View File

@ -0,0 +1,53 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2018 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "collision/OverlapCallback.h"
#include "engine/CollisionWorld.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
// Contact Pair Constructor
OverlapCallback::OverlapPair::OverlapPair(Pair<Entity, Entity>& overlapPair, CollisionWorld& world)
: mOverlapPair(overlapPair), mWorld(world) {
}
// Return a pointer to the first body in contact
CollisionBody* OverlapCallback::OverlapPair::getBody1() const {
return static_cast<CollisionBody*>(mWorld.mBodyComponents.getBody(mOverlapPair.first));
}
// Return a pointer to the second body in contact
CollisionBody* OverlapCallback::OverlapPair::getBody2() const {
return static_cast<CollisionBody*>(mWorld.mBodyComponents.getBody(mOverlapPair.second));
}
// CollisionCallbackData Constructor
OverlapCallback::CallbackData::CallbackData(List<Pair<Entity, Entity>>& overlapBodies, CollisionWorld& world)
:mOverlapBodies(overlapBodies), mWorld(world) {
}

View File

@ -26,32 +26,141 @@
#ifndef REACTPHYSICS3D_OVERLAP_CALLBACK_H #ifndef REACTPHYSICS3D_OVERLAP_CALLBACK_H
#define REACTPHYSICS3D_OVERLAP_CALLBACK_H #define REACTPHYSICS3D_OVERLAP_CALLBACK_H
// Libraries
#include "containers/List.h"
/// ReactPhysics3D namespace /// ReactPhysics3D namespace
namespace reactphysics3d { namespace reactphysics3d {
// Declarations // Declarations
class CollisionBody; class CollisionBody;
class CollisionWorld;
class ProxyShape;
struct Entity;
// Class OverlapCallback // Class OverlapCallback
/** /**
* This class can be used to register a callback for collision overlap queries. * This class can be used to register a callback for collision overlap queries between bodies.
* You should implement your own class inherited from this one and implement * You should implement your own class inherited from this one and implement the onOverlap() method.
* the notifyOverlap() method. This method will called each time a contact
* point is reported.
*/ */
class OverlapCallback { class OverlapCallback {
public: public:
// Class OverlapPair
/**
* This class represents the contact between two proxy-shapes of the physics world.
*/
class OverlapPair {
private:
// -------------------- Attributes -------------------- //
/// Pair of overlapping body entities
Pair<Entity, Entity>& mOverlapPair;
/// Reference to the physics world
CollisionWorld& mWorld;
// -------------------- Methods -------------------- //
/// Constructor
OverlapPair(Pair<Entity, Entity>& overlapPair, CollisionWorld& world);
public:
// -------------------- Methods -------------------- //
/// Copy constructor
OverlapPair(const OverlapPair& contactPair) = default;
/// Assignment operator
OverlapPair& operator=(const OverlapPair& contactPair) = default;
/// Destructor
~OverlapPair() = default;
/// Return a pointer to the first body in contact
CollisionBody* getBody1() const;
/// Return a pointer to the second body in contact
CollisionBody* getBody2() const;
// -------------------- Friendship -------------------- //
friend class OverlapCallback;
};
// Class CallbackData
/**
* This class contains data about overlap between bodies
*/
class CallbackData {
private:
// -------------------- Attributes -------------------- //
List<Pair<Entity, Entity>>& mOverlapBodies;
/// Reference to the physics world
CollisionWorld& mWorld;
// -------------------- Methods -------------------- //
/// Constructor
CallbackData(List<Pair<Entity, Entity>>& overlapProxyShapes, CollisionWorld& world);
/// Deleted copy constructor
CallbackData(const CallbackData& callbackData) = delete;
/// Deleted assignment operator
CallbackData& operator=(const CallbackData& callbackData) = delete;
/// Destructor
~CallbackData() = default;
public:
// -------------------- Methods -------------------- //
/// Return the number of overlapping pairs of bodies
uint getNbOverlappingPairs() const;
/// Return a given overlapping pair of bodies
OverlapPair getOverlappingPair(uint index) const;
// -------------------- Friendship -------------------- //
friend class CollisionDetection;
};
/// Destructor /// Destructor
virtual ~OverlapCallback() { virtual ~OverlapCallback() {
} }
/// This method will be called for each reported overlapping bodies /// This method will be called to report bodies that overlap
virtual void notifyOverlap(CollisionBody* collisionBody)=0; virtual void onOverlap(CallbackData& callbackData)=0;
}; };
// Return the number of overlapping pairs of bodies
inline uint OverlapCallback::CallbackData::getNbOverlappingPairs() const {
return mOverlapBodies.size();
}
// Return a given overlapping pair of bodies
/// Note that the returned OverlapPair object is only valid during the call of the CollisionCallback::onOverlap()
/// method. Therefore, you need to get contact data from it and make a copy. Do not make a copy of the OverlapPair
/// object itself because it won't be valid after the CollisionCallback::onOverlap() call.
inline OverlapCallback::OverlapPair OverlapCallback::CallbackData::getOverlappingPair(uint index) const {
assert(index < getNbOverlappingPairs());
return OverlapPair(mOverlapBodies[index], mWorld);
}
} }
#endif #endif

View File

@ -78,10 +78,6 @@ void NarrowPhaseInfoBatch::addContactPoint(uint index, const Vector3& contactNor
ContactPointInfo* contactPointInfo = new (allocator.allocate(sizeof(ContactPointInfo))) ContactPointInfo* contactPointInfo = new (allocator.allocate(sizeof(ContactPointInfo)))
ContactPointInfo(contactNormal, penDepth, localPt1, localPt2); ContactPointInfo(contactNormal, penDepth, localPt1, localPt2);
// TODO : DELETE THIS
//std::cout << "Pair: " << overlappingPairs[index]->getId().first << ", " << overlappingPairs[index]->getId().second << std::endl;
//std::cout << ">> Contact Point: " << localPt1.x << ", " << localPt1.y << ", " << localPt1.z << std::endl;
// Add it into the list of contact points // Add it into the list of contact points
contactPoints[index].add(contactPointInfo); contactPoints[index].add(contactPointInfo);
} }

View File

@ -93,18 +93,6 @@ class ContactPoint {
/// Set the mIsRestingContact variable /// Set the mIsRestingContact variable
void setIsRestingContact(bool isRestingContact); void setIsRestingContact(bool isRestingContact);
/// Set to true to make the contact point obsolete
void setIsObsolete(bool isObselete);
/// Set the next contact point in the linked list
void setNext(ContactPoint* next);
/// Set the previous contact point in the linked list
void setPrevious(ContactPoint* previous);
/// Return true if the contact point is obsolete
bool getIsObsolete() const;
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -139,12 +127,6 @@ class ContactPoint {
/// Return true if the contact is a resting contact /// Return true if the contact is a resting contact
bool getIsRestingContact() const; bool getIsRestingContact() const;
/// Return the previous contact point in the linked list
inline ContactPoint* getPrevious() const;
/// Return the next contact point in the linked list
ContactPoint* getNext() const;
/// Return the penetration depth /// Return the penetration depth
decimal getPenetrationDepth() const; decimal getPenetrationDepth() const;
@ -220,54 +202,6 @@ inline void ContactPoint::setIsRestingContact(bool isRestingContact) {
mIsRestingContact = isRestingContact; mIsRestingContact = isRestingContact;
} }
// Return true if the contact point is obsolete
/**
* @return True if the contact is obsolete
*/
inline bool ContactPoint::getIsObsolete() const {
return mIsObsolete;
}
// Set to true to make the contact point obsolete
/**
* @param isObsolete True if the contact is obsolete
*/
inline void ContactPoint::setIsObsolete(bool isObsolete) {
mIsObsolete = isObsolete;
}
// Return the next contact point in the linked list
/**
* @return A pointer to the next contact point in the linked-list of points
*/
inline ContactPoint* ContactPoint::getNext() const {
return mNext;
}
// Set the next contact point in the linked list
/**
* @param next Pointer to the next contact point in the linked-list of points
*/
inline void ContactPoint::setNext(ContactPoint* next) {
mNext = next;
}
// Return the previous contact point in the linked list
/**
* @return A pointer to the previous contact point in the linked-list of points
*/
inline ContactPoint* ContactPoint::getPrevious() const {
return mPrevious;
}
// Set the previous contact point in the linked list
/**
* @param previous Pointer to the previous contact point in the linked-list of points
*/
inline void ContactPoint::setPrevious(ContactPoint* previous) {
mPrevious = previous;
}
// Return the penetration depth of the contact // Return the penetration depth of the contact
/** /**
* @return the penetration depth (in meters) * @return the penetration depth (in meters)

View File

@ -37,6 +37,8 @@
#include "components/TransformComponents.h" #include "components/TransformComponents.h"
#include "components/ProxyShapeComponents.h" #include "components/ProxyShapeComponents.h"
#include "components/DynamicsComponents.h" #include "components/DynamicsComponents.h"
#include "collision/CollisionCallback.h"
#include "collision/OverlapCallback.h"
/// Namespace reactphysics3d /// Namespace reactphysics3d
namespace reactphysics3d { namespace reactphysics3d {
@ -166,19 +168,19 @@ class CollisionWorld {
bool testOverlap(CollisionBody* body1, CollisionBody* body2); bool testOverlap(CollisionBody* body1, CollisionBody* body2);
/// Report all the bodies that overlap (collide) with the body in parameter /// Report all the bodies that overlap (collide) with the body in parameter
void testOverlap(CollisionBody* body, OverlapCallback* overlapCallback); void testOverlap(CollisionBody* body, OverlapCallback& overlapCallback);
/// Report all the bodies that overlap (collide) in the world /// Report all the bodies that overlap (collide) in the world
void testOverlap(OverlapCallback* overlapCallback); void testOverlap(OverlapCallback& overlapCallback);
/// Test collision and report contacts between two bodies. /// Test collision and report contacts between two bodies.
void testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback* callback); void testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback& callback);
/// Test collision and report all the contacts involving the body in parameter /// Test collision and report all the contacts involving the body in parameter
void testCollision(CollisionBody* body, CollisionCallback* callback); void testCollision(CollisionBody* body, CollisionCallback& callback);
/// Test collision and report contacts between each colliding bodies in the world /// Test collision and report contacts between each colliding bodies in the world
void testCollision(CollisionCallback* callback); void testCollision(CollisionCallback& callback);
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
@ -207,6 +209,8 @@ class CollisionWorld {
friend class RigidBody; friend class RigidBody;
friend class ProxyShape; friend class ProxyShape;
friend class ConvexMeshShape; friend class ConvexMeshShape;
friend class CollisionCallback::ContactPair;
friend class OverlapCallback::OverlapPair;
}; };
// Set the collision dispatch configuration // Set the collision dispatch configuration
@ -243,7 +247,7 @@ inline void CollisionWorld::raycast(const Ray& ray,
* @param body2 Pointer to the second body to test * @param body2 Pointer to the second body to test
* @param callback Pointer to the object with the callback method * @param callback Pointer to the object with the callback method
*/ */
inline void CollisionWorld::testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback* callback) { inline void CollisionWorld::testCollision(CollisionBody* body1, CollisionBody* body2, CollisionCallback& callback) {
mCollisionDetection.testCollision(body1, body2, callback); mCollisionDetection.testCollision(body1, body2, callback);
} }
@ -256,7 +260,7 @@ inline void CollisionWorld::testCollision(CollisionBody* body1, CollisionBody* b
* @param body Pointer to the body against which we need to test collision * @param body Pointer to the body against which we need to test collision
* @param callback Pointer to the object with the callback method to report contacts * @param callback Pointer to the object with the callback method to report contacts
*/ */
inline void CollisionWorld::testCollision(CollisionBody* body, CollisionCallback* callback) { inline void CollisionWorld::testCollision(CollisionBody* body, CollisionCallback& callback) {
mCollisionDetection.testCollision(body, callback); mCollisionDetection.testCollision(body, callback);
} }
@ -268,7 +272,7 @@ inline void CollisionWorld::testCollision(CollisionBody* body, CollisionCallback
/** /**
* @param callback Pointer to the object with the callback method to report contacts * @param callback Pointer to the object with the callback method to report contacts
*/ */
inline void CollisionWorld::testCollision(CollisionCallback* callback) { inline void CollisionWorld::testCollision(CollisionCallback& callback) {
mCollisionDetection.testCollision(callback); mCollisionDetection.testCollision(callback);
} }
@ -280,7 +284,7 @@ inline void CollisionWorld::testCollision(CollisionCallback* callback) {
* @param body Pointer to the collision body to test overlap with * @param body Pointer to the collision body to test overlap with
* @param overlapCallback Pointer to the callback class to report overlap * @param overlapCallback Pointer to the callback class to report overlap
*/ */
inline void CollisionWorld::testOverlap(CollisionBody* body, OverlapCallback* overlapCallback) { inline void CollisionWorld::testOverlap(CollisionBody* body, OverlapCallback& overlapCallback) {
mCollisionDetection.testOverlap(body, overlapCallback); mCollisionDetection.testOverlap(body, overlapCallback);
} }
@ -288,7 +292,7 @@ inline void CollisionWorld::testOverlap(CollisionBody* body, OverlapCallback* ov
/// Use this method if you are not interested in contacts but if you simply want to know /// Use this method if you are not interested in contacts but if you simply want to know
/// which bodies overlap. If you want to get the contacts, you need to use the /// which bodies overlap. If you want to get the contacts, you need to use the
/// testCollision() method instead. /// testCollision() method instead.
inline void CollisionWorld::testOverlap(OverlapCallback* overlapCallback) { inline void CollisionWorld::testOverlap(OverlapCallback& overlapCallback) {
mCollisionDetection.testOverlap(overlapCallback); mCollisionDetection.testOverlap(overlapCallback);
} }

View File

@ -126,6 +126,9 @@ void DynamicsWorld::update(decimal timeStep) {
// Create the actual narrow-phase contacts // Create the actual narrow-phase contacts
mCollisionDetection.createContacts(); mCollisionDetection.createContacts();
// Report the contacts to the user
mCollisionDetection.reportContacts();
// Integrate the velocities // Integrate the velocities
integrateRigidBodiesVelocities(); integrateRigidBodiesVelocities();
@ -876,36 +879,3 @@ void DynamicsWorld::enableSleeping(bool isSleepingEnabled) {
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World,
"Dynamics World: isSleepingEnabled=" + (isSleepingEnabled ? std::string("true") : std::string("false")) ); "Dynamics World: isSleepingEnabled=" + (isSleepingEnabled ? std::string("true") : std::string("false")) );
} }
// Return the list of all contacts of the world
/**
* @return A pointer to the first contact manifold in the linked-list of manifolds
*/
List<const ContactManifold*> DynamicsWorld::getContactsList() {
List<const ContactManifold*> contactManifolds(mMemoryManager.getPoolAllocator());
// TODO : Rework how to report contacts
/*
// For each currently overlapping pair of bodies
for (auto it = mCollisionDetection.mOverlappingPairs.begin();
it != mCollisionDetection.mOverlappingPairs.end(); ++it) {
OverlappingPair* pair = it->second;
// For each contact manifold of the pair
const ContactManifoldSet& manifoldSet = pair->getContactManifoldSet();
ContactManifold* manifold = manifoldSet.getContactManifolds();
while (manifold != nullptr) {
// Get the contact manifold
contactManifolds.add(manifold);
manifold = manifold->getNext();
}
}
*/
// Return all the contact manifold
return contactManifolds;
}

View File

@ -240,9 +240,6 @@ class DynamicsWorld : public CollisionWorld {
/// Set an event listener object to receive events callbacks. /// Set an event listener object to receive events callbacks.
void setEventListener(EventListener* eventListener); void setEventListener(EventListener* eventListener);
/// Return the list of all contacts of the world
List<const ContactManifold*> getContactsList();
// -------------------- Friendship -------------------- // // -------------------- Friendship -------------------- //
friend class RigidBody; friend class RigidBody;

View File

@ -39,7 +39,7 @@ namespace reactphysics3d {
* new event listener class to the physics world using the DynamicsWorld::setEventListener() * new event listener class to the physics world using the DynamicsWorld::setEventListener()
* method. * method.
*/ */
class EventListener { class EventListener : public CollisionCallback {
public : public :
@ -47,20 +47,22 @@ class EventListener {
EventListener() = default; EventListener() = default;
/// Destructor /// Destructor
virtual ~EventListener() = default; virtual ~EventListener() override = default;
/// Called when a new contact point is found between two bodies /// Called when some contacts occur
/** /**
* @param contact Information about the contact * @param collisionInfo Information about the contacts
*/ */
virtual void newContact(const CollisionCallback::CollisionCallbackInfo& collisionInfo) {} virtual void onContact(const CollisionCallback::CallbackData& callbackData) override {}
// TODO : Remove this method (no internal steps anymore)
/// Called at the beginning of an internal tick of the simulation step. /// Called at the beginning of an internal tick of the simulation step.
/// Each time the DynamicsWorld::update() method is called, the physics /// Each time the DynamicsWorld::update() method is called, the physics
/// engine will do several internal simulation steps. This method is /// engine will do several internal simulation steps. This method is
/// called at the beginning of each internal simulation step. /// called at the beginning of each internal simulation step.
virtual void beginInternalTick() {} virtual void beginInternalTick() {}
// TODO : Remove this method (no internal steps anymore)
/// Called at the end of an internal tick of the simulation step. /// Called at the end of an internal tick of the simulation step.
/// Each time the DynamicsWorld::update() metho is called, the physics /// Each time the DynamicsWorld::update() metho is called, the physics
/// engine will do several internal simulation steps. This method is /// engine will do several internal simulation steps. This method is

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@ using namespace collisiondetectionscene;
// Constructor // Constructor
CollisionDetectionScene::CollisionDetectionScene(const std::string& name, EngineSettings& settings) CollisionDetectionScene::CollisionDetectionScene(const std::string& name, EngineSettings& settings)
: SceneDemo(name, settings, SCENE_RADIUS, false), mMeshFolderPath("meshes/"), : SceneDemo(name, settings, SCENE_RADIUS, false), mMeshFolderPath("meshes/"),
mContactManager(mPhongShader, mMeshFolderPath), mContactManager(mPhongShader, mMeshFolderPath, mContactPoints),
mAreNormalsDisplayed(false) { mAreNormalsDisplayed(false) {
mSelectedShapeIndex = 0; mSelectedShapeIndex = 0;
@ -160,6 +160,8 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine
// Reset the scene // Reset the scene
void CollisionDetectionScene::reset() { void CollisionDetectionScene::reset() {
SceneDemo::reset();
mSphere1->setTransform(rp3d::Transform(rp3d::Vector3(15, 5, 0), rp3d::Quaternion::identity())); mSphere1->setTransform(rp3d::Transform(rp3d::Vector3(15, 5, 0), rp3d::Quaternion::identity()));
mSphere2->setTransform(rp3d::Transform(rp3d::Vector3(0, 6, 0), rp3d::Quaternion::identity())); mSphere2->setTransform(rp3d::Transform(rp3d::Vector3(0, 6, 0), rp3d::Quaternion::identity()));
mCapsule1->setTransform(rp3d::Transform(rp3d::Vector3(-8, 7, 0), rp3d::Quaternion::identity())); mCapsule1->setTransform(rp3d::Transform(rp3d::Vector3(-8, 7, 0), rp3d::Quaternion::identity()));
@ -206,8 +208,6 @@ CollisionDetectionScene::~CollisionDetectionScene() {
mPhysicsWorld->destroyCollisionBody(mHeightField->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mHeightField->getCollisionBody());
delete mHeightField; delete mHeightField;
mContactManager.resetPoints();
// Destroy the static data for the visual contact points // Destroy the static data for the visual contact points
VisualContactPoint::destroyStaticData(); VisualContactPoint::destroyStaticData();
@ -218,9 +218,9 @@ CollisionDetectionScene::~CollisionDetectionScene() {
// Take a step for the simulation // Take a step for the simulation
void CollisionDetectionScene::update() { void CollisionDetectionScene::update() {
mContactManager.resetPoints(); mContactPoints.clear();
mPhysicsWorld->testCollision(&mContactManager); mPhysicsWorld->testCollision(mContactManager);
SceneDemo::update(); SceneDemo::update();
} }
@ -313,41 +313,33 @@ bool CollisionDetectionScene::keyboardEvent(int key, int scancode, int action, i
return false; return false;
} }
// This method will be called for each reported contact point // This method is called when some contacts occur
void ContactManager::notifyContact(const CollisionCallbackInfo& collisionCallbackInfo) { void ContactManager::onContact(const CallbackData& callbackData) {
// TODO : Rework how to report contacts // For each contact pair
/* for (uint p=0; p < callbackData.getNbContactPairs(); p++) {
// For each contact manifold
rp3d::ContactManifoldListElement* manifoldElement = collisionCallbackInfo.contactManifoldElements;
while (manifoldElement != nullptr) {
// Get the contact manifold ContactPair contactPair = callbackData.getContactPair(p);
rp3d::ContactManifold* contactManifold = manifoldElement->getContactManifold();
// For each contact point // For each contact point of the contact pair
rp3d::ContactPoint* contactPoint = contactManifold->getContactPoints(); for (uint c=0; c < contactPair.getNbContactPoints(); c++) {
while (contactPoint != nullptr) {
// Contact normal ContactPoint contactPoint = contactPair.getContactPoint(c);
rp3d::Vector3 normal = contactPoint->getNormal();
openglframework::Vector3 contactNormal(normal.x, normal.y, normal.z);
rp3d::Vector3 point1 = contactPoint->getLocalPointOnShape1(); // Contact normal
point1 = collisionCallbackInfo.proxyShape1->getLocalToWorldTransform() * point1; rp3d::Vector3 normal = contactPoint.getWorldNormal();
openglframework::Vector3 contactNormal(normal.x, normal.y, normal.z);
openglframework::Vector3 position1(point1.x, point1.y, point1.z); rp3d::Vector3 point1 = contactPoint.getLocalPointOnShape1();
mContactPoints.push_back(ContactPoint(position1, contactNormal, openglframework::Color::red())); point1 = contactPair.getProxyShape1()->getLocalToWorldTransform() * point1;
rp3d::Vector3 point2 = contactPoint->getLocalPointOnShape2(); openglframework::Vector3 position1(point1.x, point1.y, point1.z);
point2 = collisionCallbackInfo.proxyShape2->getLocalToWorldTransform() * point2; mContactPoints.push_back(SceneContactPoint(position1, contactNormal, openglframework::Color::red()));
openglframework::Vector3 position2(point2.x, point2.y, point2.z);
mContactPoints.push_back(ContactPoint(position2, contactNormal, openglframework::Color::blue()));
contactPoint = contactPoint->getNext(); rp3d::Vector3 point2 = contactPoint.getLocalPointOnShape2();
point2 = contactPair.getProxyShape2()->getLocalToWorldTransform() * point2;
openglframework::Vector3 position2(point2.x, point2.y, point2.z);
mContactPoints.push_back(SceneContactPoint(position2, contactNormal, openglframework::Color::blue()));
}
} }
manifoldElement = manifoldElement->getNext();
}
*/
} }

View File

@ -63,30 +63,22 @@ class ContactManager : public rp3d::CollisionCallback {
private: private:
/// All the visual contact points
std::vector<ContactPoint> mContactPoints;
/// Contact point mesh folder path /// Contact point mesh folder path
std::string mMeshFolderPath; std::string mMeshFolderPath;
/// Reference to the list of all the visual contact points
std::vector<SceneContactPoint>& mContactPoints;
public: public:
ContactManager(openglframework::Shader& shader, const std::string& meshFolderPath) ContactManager(openglframework::Shader& shader, const std::string& meshFolderPath,
: mMeshFolderPath(meshFolderPath) { std::vector<SceneContactPoint>& contactPoints)
: mMeshFolderPath(meshFolderPath), mContactPoints(contactPoints) {
} }
/// This method will be called for each reported contact point /// This method is called when some contacts occur
virtual void notifyContact(const CollisionCallbackInfo& collisionCallbackInfo) override; virtual void onContact(const CallbackData& callbackData) override;
void resetPoints() {
mContactPoints.clear();
}
std::vector<ContactPoint> getContactPoints() const {
return mContactPoints;
}
}; };
// Class CollisionDetectionScene // Class CollisionDetectionScene
@ -151,9 +143,6 @@ class CollisionDetectionScene : public SceneDemo {
/// Display/Hide the contact points /// Display/Hide the contact points
virtual void setIsContactPointsDisplayed(bool display) override; virtual void setIsContactPointsDisplayed(bool display) override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override;
}; };
// Display or not the surface normals at hit points // Display or not the surface normals at hit points
@ -171,11 +160,6 @@ inline void CollisionDetectionScene::setIsContactPointsDisplayed(bool display) {
SceneDemo::setIsContactPointsDisplayed(true); SceneDemo::setIsContactPointsDisplayed(true);
} }
// Return all the contact points of the scene
inline std::vector<ContactPoint> CollisionDetectionScene::getContactPoints() {
return mContactManager.getContactPoints();
}
} }
#endif #endif

View File

@ -49,7 +49,9 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); rp3d::DynamicsWorld* dynamicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
dynamicsWorld->setEventListener(this);
mPhysicsWorld = dynamicsWorld;
for (int i=0; i<NB_COMPOUND_SHAPES; i++) { for (int i=0; i<NB_COMPOUND_SHAPES; i++) {
@ -199,6 +201,8 @@ CollisionShapesScene::~CollisionShapesScene() {
/// Reset the scene /// Reset the scene
void CollisionShapesScene::reset() { void CollisionShapesScene::reset() {
SceneDemo::reset();
const float radius = 3.0f; const float radius = 3.0f;
for (uint i = 0; i<NB_COMPOUND_SHAPES; i++) { for (uint i = 0; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -99,16 +99,8 @@ class CollisionShapesScene : public SceneDemo {
/// Reset the scene /// Reset the scene
virtual void reset() override; virtual void reset() override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override;
}; };
// Return all the contact points of the scene
inline std::vector<ContactPoint> CollisionShapesScene::getContactPoints() {
return computeContactPointsOfWorld(getDynamicsWorld());
}
} }
#endif #endif

View File

@ -49,7 +49,9 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); rp3d::DynamicsWorld* dynamicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
dynamicsWorld->setEventListener(this);
mPhysicsWorld = dynamicsWorld;
// ---------- Create the boxes ----------- // // ---------- Create the boxes ----------- //
for (int i = 0; i<NB_COMPOUND_SHAPES; i++) { for (int i = 0; i<NB_COMPOUND_SHAPES; i++) {
@ -206,6 +208,8 @@ ConcaveMeshScene::~ConcaveMeshScene() {
// Reset the scene // Reset the scene
void ConcaveMeshScene::reset() { void ConcaveMeshScene::reset() {
SceneDemo::reset();
const float radius = 15.0f; const float radius = 15.0f;
for (uint i = 0; i<NB_COMPOUND_SHAPES; i++) { for (uint i = 0; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -96,16 +96,8 @@ class ConcaveMeshScene : public SceneDemo {
/// Reset the scene /// Reset the scene
virtual void reset() override; virtual void reset() override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override;
}; };
// Return all the contact points of the scene
inline std::vector<ContactPoint> ConcaveMeshScene::getContactPoints() {
return computeContactPointsOfWorld(getDynamicsWorld());
}
} }
#endif #endif

View File

@ -47,7 +47,9 @@ CubesScene::CubesScene(const std::string& name, EngineSettings& settings)
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); rp3d::DynamicsWorld* dynamicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
dynamicsWorld->setEventListener(this);
mPhysicsWorld = dynamicsWorld;
// Create all the cubes of the scene // Create all the cubes of the scene
for (int i=0; i<NB_CUBES; i++) { for (int i=0; i<NB_CUBES; i++) {
@ -117,6 +119,8 @@ CubesScene::~CubesScene() {
// Reset the scene // Reset the scene
void CubesScene::reset() { void CubesScene::reset() {
SceneDemo::reset();
float radius = 2.0f; float radius = 2.0f;
// Create all the cubes of the scene // Create all the cubes of the scene

View File

@ -67,16 +67,8 @@ class CubesScene : public SceneDemo {
/// Reset the scene /// Reset the scene
virtual void reset() override; virtual void reset() override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override;
}; };
// Return all the contact points of the scene
inline std::vector<ContactPoint> CubesScene::getContactPoints() {
return computeContactPointsOfWorld(getDynamicsWorld());
}
} }
#endif #endif

View File

@ -47,7 +47,9 @@ CubeStackScene::CubeStackScene(const std::string& name, EngineSettings& settings
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); rp3d::DynamicsWorld* dynamicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
dynamicsWorld->setEventListener(this);
mPhysicsWorld = dynamicsWorld;
// Create all the cubes of the scene // Create all the cubes of the scene
for (int i=1; i<=NB_FLOORS; i++) { for (int i=1; i<=NB_FLOORS; i++) {
@ -120,6 +122,8 @@ CubeStackScene::~CubeStackScene() {
// Reset the scene // Reset the scene
void CubeStackScene::reset() { void CubeStackScene::reset() {
SceneDemo::reset();
int index = 0; int index = 0;
for (int i=NB_FLOORS; i > 0; i--) { for (int i=NB_FLOORS; i > 0; i--) {

View File

@ -67,16 +67,8 @@ class CubeStackScene : public SceneDemo {
/// Reset the scene /// Reset the scene
virtual void reset() override; virtual void reset() override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override;
}; };
// Return all the contact points of the scene
inline std::vector<ContactPoint> CubeStackScene::getContactPoints() {
return computeContactPointsOfWorld(getDynamicsWorld());
}
} }
#endif #endif

View File

@ -49,7 +49,9 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); rp3d::DynamicsWorld* dynamicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
dynamicsWorld->setEventListener(this);
mPhysicsWorld = dynamicsWorld;
for (int i = 0; i<NB_COMPOUND_SHAPES; i++) { for (int i = 0; i<NB_COMPOUND_SHAPES; i++) {
@ -205,6 +207,8 @@ HeightFieldScene::~HeightFieldScene() {
// Reset the scene // Reset the scene
void HeightFieldScene::reset() { void HeightFieldScene::reset() {
SceneDemo::reset();
const float radius = 3.0f; const float radius = 3.0f;
for (uint i = 0; i<NB_COMPOUND_SHAPES; i++) { for (uint i = 0; i<NB_COMPOUND_SHAPES; i++) {

View File

@ -98,16 +98,8 @@ class HeightFieldScene : public SceneDemo {
/// Reset the scene /// Reset the scene
virtual void reset() override ; virtual void reset() override ;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override ;
}; };
// Return all the contact points of the scene
inline std::vector<ContactPoint> HeightFieldScene::getContactPoints() {
return computeContactPointsOfWorld(getDynamicsWorld());
}
} }
#endif #endif

View File

@ -48,7 +48,9 @@ JointsScene::JointsScene(const std::string& name, EngineSettings& settings)
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); rp3d::DynamicsWorld* dynamicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
dynamicsWorld->setEventListener(this);
mPhysicsWorld = dynamicsWorld;
// Create the Ball-and-Socket joint // Create the Ball-and-Socket joint
createBallAndSocketJoints(); createBallAndSocketJoints();
@ -129,6 +131,8 @@ void JointsScene::updatePhysics() {
// Reset the scene // Reset the scene
void JointsScene::reset() { void JointsScene::reset() {
SceneDemo::reset();
openglframework::Vector3 positionBox(0, 15, 5); openglframework::Vector3 positionBox(0, 15, 5);
openglframework::Vector3 boxDimension(1, 1, 1); openglframework::Vector3 boxDimension(1, 1, 1);

View File

@ -125,16 +125,8 @@ class JointsScene : public SceneDemo {
/// Reset the scene /// Reset the scene
virtual void reset() override; virtual void reset() override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override;
}; };
// Return all the contact points of the scene
inline std::vector<ContactPoint> JointsScene::getContactPoints() {
return computeContactPointsOfWorld(getDynamicsWorld());
}
} }
#endif #endif

View File

@ -196,6 +196,8 @@ void RaycastScene::changeBody() {
// Reset the scene // Reset the scene
void RaycastScene::reset() { void RaycastScene::reset() {
SceneDemo::reset();
std::vector<PhysicsObject*>::iterator it; std::vector<PhysicsObject*>::iterator it;
for (it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) { for (it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
(*it)->setTransform(rp3d::Transform(rp3d::Vector3::zero(), rp3d::Quaternion::identity())); (*it)->setTransform(rp3d::Transform(rp3d::Vector3::zero(), rp3d::Quaternion::identity()));

View File

@ -65,7 +65,7 @@ class RaycastManager : public rp3d::RaycastCallback {
private: private:
/// All the visual contact points /// All the visual contact points
std::vector<ContactPoint> mHitPoints; std::vector<SceneContactPoint> mHitPoints;
/// Contact point mesh folder path /// Contact point mesh folder path
std::string mMeshFolderPath; std::string mMeshFolderPath;
@ -85,7 +85,7 @@ class RaycastManager : public rp3d::RaycastCallback {
rp3d::Vector3 hitPos = raycastInfo.worldPoint; rp3d::Vector3 hitPos = raycastInfo.worldPoint;
openglframework::Vector3 position(hitPos.x, hitPos.y, hitPos.z); openglframework::Vector3 position(hitPos.x, hitPos.y, hitPos.z);
mHitPoints.push_back(ContactPoint(position, normal, openglframework::Color::red())); mHitPoints.push_back(SceneContactPoint(position, normal, openglframework::Color::red()));
return raycastInfo.hitFraction; return raycastInfo.hitFraction;
} }
@ -95,7 +95,7 @@ class RaycastManager : public rp3d::RaycastCallback {
mHitPoints.clear(); mHitPoints.clear();
} }
std::vector<ContactPoint> getHitPoints() const { std::vector<SceneContactPoint> getHitPoints() const {
return mHitPoints; return mHitPoints;
} }
}; };
@ -181,9 +181,6 @@ class RaycastScene : public SceneDemo {
/// Display/Hide the contact points /// Display/Hide the contact points
virtual void setIsContactPointsDisplayed(bool display) override; virtual void setIsContactPointsDisplayed(bool display) override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() override;
}; };
// Display or not the surface normals at hit points // Display or not the surface normals at hit points
@ -201,11 +198,6 @@ inline void RaycastScene::setIsContactPointsDisplayed(bool display) {
SceneDemo::setIsContactPointsDisplayed(true); SceneDemo::setIsContactPointsDisplayed(true);
} }
// Return all the contact points of the scene
inline std::vector<ContactPoint> RaycastScene::getContactPoints() {
return mRaycastManager.getHitPoints();
}
} }
#endif #endif

View File

@ -185,3 +185,28 @@ void Scene::rotate(int xMouse, int yMouse) {
} }
} }
} }
// Called when some contacts occur
void Scene::onContact(const rp3d::CollisionCallback::CallbackData& callbackData) {
// Clear contacts points
mContactPoints.clear();
// For each contact pair
for (uint p=0; p < callbackData.getNbContactPairs(); p++) {
rp3d::CollisionCallback::ContactPair contactPair = callbackData.getContactPair(p);
// For each contact point of the contact pair
for (uint c=0; c < contactPair.getNbContactPoints(); c++) {
rp3d::CollisionCallback::ContactPoint contactPoint = contactPair.getContactPoint(c);
rp3d::Vector3 point = contactPair.getProxyShape1()->getLocalToWorldTransform() * contactPoint.getLocalPointOnShape1();
rp3d::Vector3 normalWorld = contactPoint.getWorldNormal();
openglframework::Vector3 normal = openglframework::Vector3(normalWorld.x, normalWorld.y, normalWorld.z);
SceneContactPoint contact(openglframework::Vector3(point.x, point.y, point.z), normal, openglframework::Color::red());
mContactPoints.push_back(contact);
}
}
}

View File

@ -31,7 +31,7 @@
#include "reactphysics3d.h" #include "reactphysics3d.h"
// Structure ContactPoint // Structure ContactPoint
struct ContactPoint { struct SceneContactPoint {
public: public:
openglframework::Vector3 point; openglframework::Vector3 point;
@ -39,7 +39,7 @@ struct ContactPoint {
openglframework::Color color; openglframework::Color color;
/// Constructor /// Constructor
ContactPoint(const openglframework::Vector3& pointWorld, const openglframework::Vector3& normalWorld, const openglframework::Color colorPoint) SceneContactPoint(const openglframework::Vector3& pointWorld, const openglframework::Vector3& normalWorld, const openglframework::Color colorPoint)
: point(pointWorld), normal(normalWorld), color(colorPoint) { : point(pointWorld), normal(normalWorld), color(colorPoint) {
} }
@ -88,7 +88,7 @@ struct EngineSettings {
// Class Scene // Class Scene
// Abstract class that represents a 3D scene. // Abstract class that represents a 3D scene.
class Scene { class Scene : public rp3d::EventListener {
protected: protected:
@ -130,12 +130,15 @@ class Scene {
/// True if contact points are displayed /// True if contact points are displayed
bool mIsContactPointsDisplayed; bool mIsContactPointsDisplayed;
/// True if the AABBs of the phycis objects are displayed /// True if the AABBs of the physics objects are displayed
bool mIsAABBsDisplayed; bool mIsAABBsDisplayed;
/// True if we render shapes in wireframe mode /// True if we render shapes in wireframe mode
bool mIsWireframeEnabled; bool mIsWireframeEnabled;
/// Contact points
std::vector<SceneContactPoint> mContactPoints;
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Set the scene position (where the camera needs to look at) /// Set the scene position (where the camera needs to look at)
@ -165,7 +168,7 @@ class Scene {
Scene(const std::string& name, EngineSettings& engineSettings, bool isShadowMappingEnabled = false); Scene(const std::string& name, EngineSettings& engineSettings, bool isShadowMappingEnabled = false);
/// Destructor /// Destructor
virtual ~Scene(); virtual ~Scene() override;
/// Reshape the view /// Reshape the view
virtual void reshape(int width, int height); virtual void reshape(int width, int height);
@ -181,7 +184,7 @@ class Scene {
virtual void render()=0; virtual void render()=0;
/// Reset the scene /// Reset the scene
virtual void reset()=0; virtual void reset();
/// Called when a keyboard event occurs /// Called when a keyboard event occurs
virtual bool keyboardEvent(int key, int scancode, int action, int mods); virtual bool keyboardEvent(int key, int scancode, int action, int mods);
@ -230,11 +233,11 @@ class Scene {
/// Enable/disbale wireframe rendering /// Enable/disbale wireframe rendering
void setIsWireframeEnabled(bool isEnabled); void setIsWireframeEnabled(bool isEnabled);
/// Return all the contact points of the scene
std::vector<ContactPoint> virtual getContactPoints();
/// Update the engine settings /// Update the engine settings
virtual void updateEngineSettings() = 0; virtual void updateEngineSettings() = 0;
/// Called when some contacts occur
virtual void onContact(const rp3d::CollisionCallback::CallbackData& callbackData) override;
}; };
// Called when a keyboard event occurs // Called when a keyboard event occurs
@ -247,6 +250,11 @@ inline void Scene::reshape(int width, int height) {
mCamera.setDimensions(width, height); mCamera.setDimensions(width, height);
} }
// Reset the scene
inline void Scene::reset() {
mContactPoints.clear();
}
// Return a reference to the camera // Return a reference to the camera
inline const openglframework::Camera& Scene::getCamera() const { inline const openglframework::Camera& Scene::getCamera() const {
return mCamera; return mCamera;
@ -306,11 +314,4 @@ inline void Scene::setIsWireframeEnabled(bool isEnabled) {
mIsWireframeEnabled = isEnabled; mIsWireframeEnabled = isEnabled;
} }
// Return all the contact points of the scene
inline std::vector<ContactPoint> Scene::getContactPoints() {
// Return an empty list of contact points
return std::vector<ContactPoint>();
}
#endif #endif

View File

@ -98,7 +98,7 @@ SceneDemo::~SceneDemo() {
mColorShader.destroy(); mColorShader.destroy();
// Destroy the contact points // Destroy the contact points
removeAllContactPoints(); removeAllVisualContactPoints();
// Destroy rendering data for the AABB // Destroy rendering data for the AABB
AABB::destroy(); AABB::destroy();
@ -345,20 +345,17 @@ void SceneDemo::drawTextureQuad() {
void SceneDemo::updateContactPoints() { void SceneDemo::updateContactPoints() {
// Remove the previous contact points // Remove the previous contact points
removeAllContactPoints(); removeAllVisualContactPoints();
if (mIsContactPointsDisplayed) { if (mIsContactPointsDisplayed) {
// Get the current contact points of the scene
std::vector<ContactPoint> contactPoints = getContactPoints();
// For each contact point // For each contact point
std::vector<ContactPoint>::const_iterator it; std::vector<SceneContactPoint>::const_iterator it;
for (it = contactPoints.begin(); it != contactPoints.end(); ++it) { for (it = mContactPoints.begin(); it != mContactPoints.end(); ++it) {
// Create a visual contact point for rendering // Create a visual contact point for rendering
VisualContactPoint* point = new VisualContactPoint(it->point, mMeshFolderPath, it->point + it->normal, it->color); VisualContactPoint* point = new VisualContactPoint(it->point, mMeshFolderPath, it->point + it->normal, it->color);
mContactPoints.push_back(point); mVisualContactPoints.push_back(point);
} }
} }
} }
@ -367,8 +364,8 @@ void SceneDemo::updateContactPoints() {
void SceneDemo::renderContactPoints(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { void SceneDemo::renderContactPoints(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) {
// Render all the contact points // Render all the contact points
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin(); for (std::vector<VisualContactPoint*>::iterator it = mVisualContactPoints.begin();
it != mContactPoints.end(); ++it) { it != mVisualContactPoints.end(); ++it) {
(*it)->render(mColorShader, worldToCameraMatrix); (*it)->render(mColorShader, worldToCameraMatrix);
} }
} }
@ -397,48 +394,14 @@ void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix)
} }
} }
void SceneDemo::removeAllContactPoints() { void SceneDemo::removeAllVisualContactPoints() {
// Destroy all the visual contact points // Destroy all the visual contact points
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin(); for (std::vector<VisualContactPoint*>::iterator it = mVisualContactPoints.begin();
it != mContactPoints.end(); ++it) { it != mVisualContactPoints.end(); ++it) {
delete (*it); delete (*it);
} }
mContactPoints.clear(); mVisualContactPoints.clear();
}
// Return all the contact points of the scene
std::vector<ContactPoint> SceneDemo::computeContactPointsOfWorld(rp3d::DynamicsWorld* world) {
std::vector<ContactPoint> contactPoints;
// Get the list of contact manifolds from the world
rp3d::List<const rp3d::ContactManifold*> manifolds = world->getContactsList();
// TODO : Uncomment and fix this
/*
// For each contact manifold
rp3d::List<const rp3d::ContactManifold*>::Iterator it;
for (it = manifolds.begin(); it != manifolds.end(); ++it) {
const rp3d::ContactManifold* manifold = *it;
// For each contact point of the manifold
rp3d::ContactPoint* contactPoint = manifold->getContactPoints();
while (contactPoint != nullptr) {
rp3d::Vector3 point = manifold->getShape1()->getLocalToWorldTransform() * contactPoint->getLocalPointOnShape1();
rp3d::Vector3 normalWorld = contactPoint->getNormal();
openglframework::Vector3 normal = openglframework::Vector3(normalWorld.x, normalWorld.y, normalWorld.z);
ContactPoint contact(openglframework::Vector3(point.x, point.y, point.z), normal, openglframework::Color::red());
contactPoints.push_back(contact);
contactPoint = contactPoint->getNext();
}
}
*/
return contactPoints;
} }
// Update the engine settings // Update the engine settings

View File

@ -60,7 +60,7 @@ class SceneDemo : public Scene {
static int shadowMapTextureLevel; static int shadowMapTextureLevel;
/// All the visual contact points /// All the visual contact points
std::vector<VisualContactPoint*> mContactPoints; std::vector<VisualContactPoint*> mVisualContactPoints;
/// Shadow map bias matrix /// Shadow map bias matrix
openglframework::Matrix4 mShadowMapBiasMatrix; openglframework::Matrix4 mShadowMapBiasMatrix;
@ -123,7 +123,7 @@ class SceneDemo : public Scene {
void renderAABBs(const openglframework::Matrix4& worldToCameraMatrix); void renderAABBs(const openglframework::Matrix4& worldToCameraMatrix);
/// Remove all contact points /// Remove all contact points
void removeAllContactPoints(); void removeAllVisualContactPoints();
/// Return a reference to the dynamics world /// Return a reference to the dynamics world
rp3d::DynamicsWorld* getDynamicsWorld(); rp3d::DynamicsWorld* getDynamicsWorld();
@ -144,6 +144,9 @@ class SceneDemo : public Scene {
/// Update the scene /// Update the scene
virtual void update() override; virtual void update() override;
/// Reset the scene
virtual void reset() override;
/// Update the physics world (take a simulation step) /// Update the physics world (take a simulation step)
/// Can be called several times per frame /// Can be called several times per frame
virtual void updatePhysics() override; virtual void updatePhysics() override;
@ -159,9 +162,6 @@ class SceneDemo : public Scene {
/// Enabled/Disable the shadow mapping /// Enabled/Disable the shadow mapping
virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override; virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override;
/// Return all the contact points of the scene
std::vector<ContactPoint> computeContactPointsOfWorld(reactphysics3d::DynamicsWorld *world);
}; };
// Enabled/Disable the shadow mapping // Enabled/Disable the shadow mapping
@ -184,6 +184,14 @@ inline const rp3d::DynamicsWorld* SceneDemo::getDynamicsWorld() const {
return dynamic_cast<rp3d::DynamicsWorld*>(mPhysicsWorld); return dynamic_cast<rp3d::DynamicsWorld*>(mPhysicsWorld);
} }
// Reset the scene
inline void SceneDemo::reset() {
Scene::reset();
removeAllVisualContactPoints();
}
#endif #endif