diff --git a/src/body/Body.h b/src/body/Body.h index 335eb36e..71c03b8c 100644 --- a/src/body/Body.h +++ b/src/body/Body.h @@ -56,7 +56,7 @@ class Body { bool operator<(const Body& body2) const; // Smaller than operator bool operator>(const Body& body2) const; // Larger than operator bool operator==(const Body& body2) const; // Equal operator - bool operator!=(const Body& body2) const; // Equal operator + bool operator!=(const Body& body2) const; // Not equal operator }; // Return the id of the body @@ -79,7 +79,7 @@ inline bool Body::operator==(const Body& body2) const { return (id == body2.id); } -// Equal operator +// Not equal operator inline bool Body::operator!=(const Body& body2) const { return (id != body2.id); } diff --git a/src/collision/BroadPhasePair.cpp b/src/collision/BroadPhasePair.cpp new file mode 100644 index 00000000..e09b0187 --- /dev/null +++ b/src/collision/BroadPhasePair.cpp @@ -0,0 +1,40 @@ +/******************************************************************************** +* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ * +* Copyright (c) 2010-2012 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 "BroadPhasePair.h" + +using namespace reactphysics3d; + + // Constructor +BroadPhasePair::BroadPhasePair(CollisionBody* body1, CollisionBody* body2) + : body1(body1), body2(body2), previousSeparatingAxis(Vector3(1,1,1)) { + +} + +// Destructor +BroadPhasePair::~BroadPhasePair() { + +} diff --git a/src/collision/BroadPhasePair.h b/src/collision/BroadPhasePair.h new file mode 100644 index 00000000..6f03ec1e --- /dev/null +++ b/src/collision/BroadPhasePair.h @@ -0,0 +1,89 @@ +/******************************************************************************** +* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ * +* Copyright (c) 2010-2012 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. * +* * +********************************************************************************/ + +#ifndef BROAD_PHASE_PAIR_H +#define BROAD_PHASE_PAIR_H + +// Libraries +#include "../body/CollisionBody.h" + +// ReactPhysics3D namespace +namespace reactphysics3d { + +// struct BroadPhasePair +// This structure represents a pair of bodies +// during the broad-phase collision detection +struct BroadPhasePair { + + public: + CollisionBody* body1; // Pointer to the first body + CollisionBody* body2; // Pointer to the second body + Vector3 previousSeparatingAxis; // Previous cached separating axis + + BroadPhasePair(CollisionBody* body1, CollisionBody* body2); // Constructor + ~BroadPhasePair(); // Destructor + + bodyindexpair getBodiesIndexPair() const; // Return the pair of bodies index + + // Operators + bool operator<(const BroadPhasePair& broadPhasePair2) const; // Smaller than operator + bool operator>(const BroadPhasePair& broadPhasePair2) const; // Larger than operator + bool operator==(const BroadPhasePair& broadPhasePair2) const; // Equal operator + bool operator!=(const BroadPhasePair& broadPhasePair2) const; // Not equal operator +}; + +// Return the pair of bodies index +inline bodyindexpair BroadPhasePair::getBodiesIndexPair() const { + + // Construct the pair of body index + bodyindexpair indexPair = body1->getID() < body2->getID() ? std::make_pair(body1->getID(), body2->getID()) : + std::make_pair(body2->getID(), body1->getID()); + assert(indexPair.first != indexPair.second); + return indexPair; +} + +// Smaller than operator +inline bool BroadPhasePair::operator<(const BroadPhasePair& broadPhasePair2) const { + return (body1 < broadPhasePair2.body1 ? true : (body2 < broadPhasePair2.body2)); +} + +// Larger than operator +inline bool BroadPhasePair::operator>(const BroadPhasePair& broadPhasePair2) const { + return (body1 > broadPhasePair2.body1 ? true : (body2 > broadPhasePair2.body2)); +} + +// Equal operator +inline bool BroadPhasePair::operator==(const BroadPhasePair& broadPhasePair2) const { + return (body1 == broadPhasePair2.body1 && body2 == broadPhasePair2.body2); +} + +// Not equal operator +inline bool BroadPhasePair::operator!=(const BroadPhasePair& broadPhasePair2) const { + return (body1 != broadPhasePair2.body1 || body2 != broadPhasePair2.body2); +} + +} + +#endif diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index dab0b6e7..6abd83db 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -56,12 +56,6 @@ CollisionDetection::CollisionDetection(PhysicsWorld* world) // Destructor CollisionDetection::~CollisionDetection() { - // Delete the remaining overlapping pairs - for (map, OverlappingPair*>::iterator it=overlappingPairs.begin(); it != overlappingPairs.end(); it++) { - // Delete the overlapping pair - (*it).second->OverlappingPair::~OverlappingPair(); - memoryPoolOverlappingPairs.freeObject((*it).second); - } // Delete the broad-phase algorithm delete broadPhaseAlgorithm; @@ -107,32 +101,31 @@ void CollisionDetection::computeBroadPhase() { broadPhaseAlgorithm->updateObject(*it, *((*it)->getAABB())); } } - - // TODO : DELETE THIS - //std::cout << "Nb overlapping pairs : " << overlappingPairs.size() << std::endl; - //std::cout << "Nb active pairs in pair manager : " << broadPhaseAlgorithm->getNbOverlappingPairs() << std::endl; } // Compute the narrow-phase collision detection bool CollisionDetection::computeNarrowPhase() { bool collisionExists = false; - map, OverlappingPair*>::iterator it; + map::iterator it; // For each possible collision pair of bodies for (it = overlappingPairs.begin(); it != overlappingPairs.end(); it++) { - ContactInfo* contactInfo = NULL; + ContactInfo* contactInfo = 0; - CollisionBody* const body1 = (*it).second->getBody1(); - CollisionBody* const body2 = (*it).second->getBody2(); + BroadPhasePair* pair = (*it).second; + assert(pair); + + CollisionBody* const body1 = pair->body1; + CollisionBody* const body2 = pair->body2; // Update the contact cache of the overlapping pair - (*it).second->update(); + world->updateOverlappingPair(pair); // Select the narrow phase algorithm to use according to the two collision shapes NarrowPhaseAlgorithm& narrowPhaseAlgorithm = SelectNarrowPhaseAlgorithm(body1->getCollisionShape(), body2->getCollisionShape()); // Notify the narrow-phase algorithm about the overlapping pair we are going to test - narrowPhaseAlgorithm.setCurrentOverlappingPair((*it).second); + narrowPhaseAlgorithm.setCurrentOverlappingPair(pair); // Use the narrow-phase collision detection algorithm to check if there really is a collision if (narrowPhaseAlgorithm.testCollision(body1->getCollisionShape(), body1->getTransform(), @@ -140,24 +133,12 @@ bool CollisionDetection::computeNarrowPhase() { assert(contactInfo); collisionExists = true; - RigidBody* const rigidBody1 = dynamic_cast(body1); - RigidBody* const rigidBody2 = dynamic_cast(body2); + // Notify the world about the new narrow-phase contact + world->notifyNewContact(pair, contactInfo); - // Create a new contact - Contact* contact = new (memoryPoolContacts.allocateObject()) Contact(rigidBody1, rigidBody2, contactInfo); - // Delete and remove the contact info from the memory pool contactInfo->ContactInfo::~ContactInfo(); memoryPoolContactInfos.freeObject(contactInfo); - - // Add the contact to the contact cache of the corresponding overlapping pair - (*it).second->addContact(contact); - - // Add all the contacts in the contact cache of the two bodies - // to the set of constraints in the physics world - for (uint i=0; i<(*it).second->getNbContacts(); i++) { - world->addConstraint((*it).second->getContact(i)); - } } } @@ -166,34 +147,37 @@ bool CollisionDetection::computeNarrowPhase() { // Allow the broadphase to notify the collision detection about an overlapping pair // This method is called by a broad-phase collision detection algorithm -void CollisionDetection::broadPhaseNotifyAddedOverlappingPair(const BroadPhasePair* addedPair) { +void CollisionDetection::broadPhaseNotifyAddedOverlappingPair(BodyPair* addedPair) { - // Construct the pair of body index - pair indexPair = addedPair->body1->getID() < addedPair->body2->getID() ? make_pair(addedPair->body1->getID(), addedPair->body2->getID()) : - make_pair(addedPair->body2->getID(), addedPair->body1->getID()); - assert(indexPair.first != indexPair.second); + // Get the pair of body index + bodyindexpair indexPair = addedPair->getBodiesIndexPair(); + + // Create the corresponding broad-phase pair object + BroadPhasePair* broadPhasePair = new (memoryPoolOverlappingPairs.allocateObject()) BroadPhasePair(addedPair->body1, addedPair->body2); // Add the pair into the set of overlapping pairs (if not there yet) - OverlappingPair* newPair = new (memoryPoolOverlappingPairs.allocateObject()) OverlappingPair(addedPair->body1, addedPair->body2, memoryPoolContacts); - pair, OverlappingPair*>::iterator, bool> check = overlappingPairs.insert(make_pair(indexPair, newPair)); - - // If the overlapping pair was already in the set of overlapping pair - if (!check.second) { - // Delete the new pair - newPair->OverlappingPair::~OverlappingPair(); - memoryPoolOverlappingPairs.freeObject(newPair); - } + pair::iterator, bool> check = overlappingPairs.insert(make_pair(indexPair, broadPhasePair)); + assert(check.second); + + // Notify the world about the new broad-phase overlapping pair + world->notifyAddedOverlappingPair(broadPhasePair); } // Allow the broadphase to notify the collision detection about a removed overlapping pair -void CollisionDetection::broadPhaseNotifyRemovedOverlappingPair(const BroadPhasePair* removedPair) { +void CollisionDetection::broadPhaseNotifyRemovedOverlappingPair(BodyPair* removedPair) { - // Construct the pair of body index - pair indexPair = removedPair->body1->getID() < removedPair->body2->getID() ? make_pair(removedPair->body1->getID(), removedPair->body2->getID()) : - make_pair(removedPair->body2->getID(), removedPair->body1->getID()); + // Get the pair of body index + bodyindexpair indexPair = removedPair->getBodiesIndexPair(); + + // Get the broad-phase pair + BroadPhasePair* broadPhasePair = overlappingPairs[indexPair]; + assert(broadPhasePair); + + // Notify the world about the removed broad-phase pair + world->notifyRemovedOverlappingPair(broadPhasePair); // Remove the overlapping pair from the memory pool - overlappingPairs[indexPair]->OverlappingPair::~OverlappingPair(); - memoryPoolOverlappingPairs.freeObject(overlappingPairs[indexPair]); + broadPhasePair->BroadPhasePair::~BroadPhasePair(); + memoryPoolOverlappingPairs.freeObject(broadPhasePair); overlappingPairs.erase(indexPair); } diff --git a/src/collision/CollisionDetection.h b/src/collision/CollisionDetection.h index cc8397ec..7b325952 100644 --- a/src/collision/CollisionDetection.h +++ b/src/collision/CollisionDetection.h @@ -28,8 +28,8 @@ // Libraries #include "../body/CollisionBody.h" -#include "OverlappingPair.h" #include "broadphase/BroadPhaseAlgorithm.h" +#include "BroadPhasePair.h" #include "../memory/MemoryPool.h" #include "narrowphase/GJK/GJKAlgorithm.h" #include "narrowphase/SphereVsSphereAlgorithm.h" @@ -60,16 +60,13 @@ class CollisionDetection { private : PhysicsWorld* world; // Pointer to the physics world - std::map, OverlappingPair*> overlappingPairs; // Broad-phase overlapping pairs of bodies - std::set > currentStepOverlappingPairs; // Overlapping pairs of bodies at the current collision detection step - std::set > lastStepOverlappingPairs; // Overlapping pairs of bodies at the last collision detection step + std::map overlappingPairs; // Broad-phase overlapping pairs of bodies BroadPhaseAlgorithm* broadPhaseAlgorithm; // Broad-phase algorithm GJKAlgorithm narrowPhaseGJKAlgorithm; // Narrow-phase GJK algorithm SphereVsSphereAlgorithm narrowPhaseSphereVsSphereAlgorithm; // Narrow-phase Sphere vs Sphere algorithm - MemoryPool memoryPoolContacts; // Memory pool for the contacts - MemoryPool memoryPoolOverlappingPairs; // Memory pool for the overlapping pairs MemoryPool memoryPoolContactInfos; // Memory pool for the contact info - + MemoryPool memoryPoolOverlappingPairs; // Memory pool for the overlapping pairs + void computeBroadPhase(); // Compute the broad-phase collision detection bool computeNarrowPhase(); // Compute the narrow-phase collision detection NarrowPhaseAlgorithm& SelectNarrowPhaseAlgorithm(CollisionShape* collisionShape1, @@ -81,22 +78,11 @@ class CollisionDetection { void addBody(CollisionBody* body); // Add a body to the collision detection void removeBody(CollisionBody* body); // Remove a body from the collision detection - OverlappingPair* getOverlappingPair(bodyindex body1ID, bodyindex body2ID); // Return an overlapping pair or null bool computeCollisionDetection(); // Compute the collision detection - void broadPhaseNotifyAddedOverlappingPair(const BroadPhasePair* pair); // Allow the broadphase to notify the collision detection about a new overlapping pair - void broadPhaseNotifyRemovedOverlappingPair(const BroadPhasePair* pair); // Allow the broadphase to notify the collision detection about a removed overlapping pair + void broadPhaseNotifyAddedOverlappingPair(BodyPair* pair); // Allow the broadphase to notify the collision detection about a new overlapping pair + void broadPhaseNotifyRemovedOverlappingPair(BodyPair* pair); // Allow the broadphase to notify the collision detection about a removed overlapping pair }; -// Return an overlapping pair of bodies according to the given bodies ID -// The method returns null if the pair of bodies is not overlapping -inline OverlappingPair* CollisionDetection::getOverlappingPair(bodyindex body1ID, bodyindex body2ID) { - std::pair pair = (body1ID < body2ID) ? std::make_pair(body1ID, body2ID) : std::make_pair(body2ID, body1ID); - if (overlappingPairs.count(pair) == 1) { - return overlappingPairs[pair]; - } - return 0; -} - // Select the narrow-phase collision algorithm to use given two collision shapes inline NarrowPhaseAlgorithm& CollisionDetection::SelectNarrowPhaseAlgorithm(CollisionShape* collisionShape1, CollisionShape* collisionShape2) { diff --git a/src/collision/broadphase/BroadPhaseAlgorithm.h b/src/collision/broadphase/BroadPhaseAlgorithm.h index 1d3a7343..54946d7c 100644 --- a/src/collision/broadphase/BroadPhaseAlgorithm.h +++ b/src/collision/broadphase/BroadPhaseAlgorithm.h @@ -66,8 +66,8 @@ class BroadPhaseAlgorithm { virtual void removeObject(CollisionBody* body)=0; // Notify the broad-phase about an object that has been removed from the world virtual void updateObject(CollisionBody* body, const AABB& aabb)=0; // Notify the broad-phase that the AABB of an object has changed - BroadPhasePair* beginOverlappingPairsPointer() const; // Return a pointer to the first active pair (used to iterate over the active pairs) - BroadPhasePair* endOverlappingPairsPointer() const; // Return a pointer to the last active pair (used to iterate over the active pairs) + BodyPair* beginOverlappingPairsPointer() const; // Return a pointer to the first active pair (used to iterate over the active pairs) + BodyPair* endOverlappingPairsPointer() const; // Return a pointer to the last active pair (used to iterate over the active pairs) }; // TODO : DELETE THIS METHOD @@ -77,12 +77,12 @@ inline uint BroadPhaseAlgorithm::getNbOverlappingPairs() const { // Return a pointer to the first active pair (used to iterate over the overlapping pairs) -inline BroadPhasePair* BroadPhaseAlgorithm::beginOverlappingPairsPointer() const { +inline BodyPair* BroadPhaseAlgorithm::beginOverlappingPairsPointer() const { return pairManager.beginOverlappingPairsPointer(); } // Return a pointer to the last active pair (used to iterate over the overlapping pairs) -inline BroadPhasePair* BroadPhaseAlgorithm::endOverlappingPairsPointer() const { +inline BodyPair* BroadPhaseAlgorithm::endOverlappingPairsPointer() const { return pairManager.endOverlappingPairsPointer(); } diff --git a/src/collision/broadphase/PairManager.cpp b/src/collision/broadphase/PairManager.cpp index 99b85881..9ad5d8e7 100644 --- a/src/collision/broadphase/PairManager.cpp +++ b/src/collision/broadphase/PairManager.cpp @@ -56,7 +56,7 @@ PairManager::~PairManager() { // that pair. If the pair to add does not already exist in the set of // overlapping pairs, it will be created and if it already exists, we only // return a pointer to that pair. -BroadPhasePair* PairManager::addPair(CollisionBody* body1, CollisionBody* body2) { +BodyPair* PairManager::addPair(CollisionBody* body1, CollisionBody* body2) { // Sort the bodies to have the body with smallest ID first sortBodiesUsingID(body1, body2); @@ -69,7 +69,7 @@ BroadPhasePair* PairManager::addPair(CollisionBody* body1, CollisionBody* body2) uint hashValue = computeHashBodies(id1, id2) & hashMask; // Try to find the pair in the current overlapping pairs. - BroadPhasePair* pair = findPairWithHashValue(id1, id2, hashValue); + BodyPair* pair = findPairWithHashValue(id1, id2, hashValue); // If the pair is already in the set of overlapping pairs if (pair) { @@ -93,7 +93,7 @@ BroadPhasePair* PairManager::addPair(CollisionBody* body1, CollisionBody* body2) } // Create the new overlapping pair - BroadPhasePair* newPair = &overlappingPairs[nbOverlappingPairs]; + BodyPair* newPair = &overlappingPairs[nbOverlappingPairs]; newPair->body1 = body1; newPair->body2 = body2; @@ -119,7 +119,7 @@ bool PairManager::removePair(bodyindex id1, bodyindex id2) { const uint hashValue = computeHashBodies(id1, id2) & hashMask; // Find the pair to remove - const BroadPhasePair* pair = findPairWithHashValue(id1, id2, hashValue); + BodyPair* pair = findPairWithHashValue(id1, id2, hashValue); // If we have not found the pair if (!pair) { @@ -184,7 +184,7 @@ void PairManager::removePairWithHashValue(bodyindex id1, bodyindex id2, luint ha // now free because of the pair we want to remove // Get the last pair - const BroadPhasePair* lastPair = &overlappingPairs[indexLastPair]; + const BodyPair* lastPair = &overlappingPairs[indexLastPair]; const uint lastPairHashValue = computeHashBodies(lastPair->body1->getID(), lastPair->body2->getID()) & hashMask; // Compute the initial offset of the last pair @@ -223,7 +223,7 @@ void PairManager::removePairWithHashValue(bodyindex id1, bodyindex id2, luint ha } // Look for a pair in the set of overlapping pairs -BroadPhasePair* PairManager::lookForAPair(bodyindex id1, bodyindex id2, luint hashValue) const { +BodyPair* PairManager::lookForAPair(bodyindex id1, bodyindex id2, luint hashValue) const { // Look for the pair in the set of overlapping pairs bodyindex offset = hashTable[hashValue]; @@ -256,7 +256,7 @@ void PairManager::reallocatePairs() { } // Reallocate the overlapping pairs - BroadPhasePair* newOverlappingPairs = (BroadPhasePair*) malloc(nbElementsHashTable * sizeof(BroadPhasePair)); + BodyPair* newOverlappingPairs = (BodyPair*) malloc(nbElementsHashTable * sizeof(BodyPair)); bodyindex* newOffsetNextPair = (bodyindex*) malloc(nbElementsHashTable * sizeof(bodyindex)); assert(newOverlappingPairs); @@ -264,8 +264,8 @@ void PairManager::reallocatePairs() { // If there is already some overlapping pairs if (nbOverlappingPairs) { - // Copy the pairs to the new place - memcpy(newOverlappingPairs, overlappingPairs, nbOverlappingPairs * sizeof(BroadPhasePair)); + // Copy the pairs to the new location + memcpy(newOverlappingPairs, overlappingPairs, nbOverlappingPairs * sizeof(BodyPair)); } // Recompute the hash table with the new hash values diff --git a/src/collision/broadphase/PairManager.h b/src/collision/broadphase/PairManager.h index 05991cce..ee39c698 100644 --- a/src/collision/broadphase/PairManager.h +++ b/src/collision/broadphase/PairManager.h @@ -28,6 +28,7 @@ // Libraries #include "../../body/CollisionBody.h" +#include // Namespace ReactPhysics3D @@ -35,15 +36,26 @@ namespace reactphysics3d { // Declaration class CollisionDetection; - -// Structure BroadPhasePair that represents a pair of bodies + +// struct BodyPair +// This structure represents a pair of bodies // during the broad-phase collision detection -struct BroadPhasePair { +struct BodyPair { + public: CollisionBody* body1; // Pointer to the first body CollisionBody* body2; // Pointer to the second body -}; + // Return the pair of bodies index + bodyindexpair getBodiesIndexPair() const { + + // Construct the pair of body index + bodyindexpair indexPair = body1->getID() < body2->getID() ? std::make_pair(body1->getID(), body2->getID()) : + std::make_pair(body2->getID(), body1->getID()); + assert(indexPair.first != indexPair.second); + return indexPair; + } +}; /* -------------------------------------------------------------------- Class PairManager : @@ -63,23 +75,23 @@ class PairManager { bodyindex* offsetNextPair; // Array that contains for each offset, the offset of the next pair with // the same hash value // for a given same hash value - BroadPhasePair* overlappingPairs; // Array that contains the currently active pairs + BodyPair* overlappingPairs; // Array that contains the currently active pairs static bodyindex INVALID_INDEX; // Invalid ID CollisionDetection& collisionDetection; // Reference to the collision detection void sortBodiesUsingID(CollisionBody*& body1, CollisionBody*& body2) const; // Sort the bodies according to their IDs (smallest ID first) void sortIDs(bodyindex& id1, bodyindex& id2) const; // Sort the IDs (smallest ID first) - bool isDifferentPair(const BroadPhasePair& pair1, bodyindex pair2ID1, + bool isDifferentPair(const BodyPair& pair1, bodyindex pair2ID1, bodyindex pair2ID2) const; // Return true if pair1 and pair2 are the same uint computeHashBodies(uint id1, uint id2) const; // Compute the hash value of two bodies using their IDs int computeHash32Bits(int key) const; // This method returns an hash value for a 32 bits key luint computeNextPowerOfTwo(luint number) const; // Return the next power of two void reallocatePairs(); // Reallocate memory for more pairs void shrinkMemory(); // Shrink the allocated memory - bodyindex computePairOffset(const BroadPhasePair* pair) const; // Compute the offset of a given pair - BroadPhasePair* lookForAPair(bodyindex id1, bodyindex id2, + bodyindex computePairOffset(const BodyPair* pair) const; // Compute the offset of a given pair + BodyPair* lookForAPair(bodyindex id1, bodyindex id2, luint hashValue) const; // Look for a pair in the set of overlapping pairs - BroadPhasePair* findPairWithHashValue(bodyindex id1, bodyindex id2, + BodyPair* findPairWithHashValue(bodyindex id1, bodyindex id2, luint hashValue) const; // Find a pair given two body IDs and an hash value void removePairWithHashValue(bodyindex id1, bodyindex id2, luint hashValue, bodyindex indexPair); // Remove a pair from the set of active pair @@ -88,14 +100,14 @@ class PairManager { ~PairManager(); // Destructor bodyindex getNbOverlappingPairs() const; // Return the number of active pairs - BroadPhasePair* addPair(CollisionBody* body1, CollisionBody* body2); // Add a pair of bodies in the pair manager + BodyPair* addPair(CollisionBody* body1, CollisionBody* body2); // Add a pair of bodies in the pair manager bool removePair(bodyindex id1, bodyindex id2); // Remove a pair of bodies from the pair manager - BroadPhasePair* findPair(bodyindex id1, bodyindex id2) const; // Find a pair given two body IDs - BroadPhasePair* beginOverlappingPairsPointer() const; // Return a pointer to the first overlapping pair (used to iterate over the active pairs) - BroadPhasePair* endOverlappingPairsPointer() const; // Return a pointer to the last overlapping pair (used to iterate over the active pairs) - void registerAddedOverlappingPairCallback(void (CollisionDetection::*callbackFunction) (const BroadPhasePair* addedActivePair)); // Register a callback function (using a function pointer) that will be called when a new overlapping pair is added in the pair manager + BodyPair* findPair(bodyindex id1, bodyindex id2) const; // Find a pair given two body IDs + BodyPair* beginOverlappingPairsPointer() const; // Return a pointer to the first overlapping pair (used to iterate over the active pairs) + BodyPair* endOverlappingPairsPointer() const; // Return a pointer to the last overlapping pair (used to iterate over the active pairs) + void registerAddedOverlappingPairCallback(void (CollisionDetection::*callbackFunction) (const BodyPair* addedActivePair)); // Register a callback function (using a function pointer) that will be called when a new overlapping pair is added in the pair manager void unregisterAddedOverlappingPairCallback(); // Unregister the callback function that will be called when a new active pair is added in the pair manager - void registerRemovedOverlappingPairCallback(void (CollisionDetection::*callbackFunction) (const BroadPhasePair* removedActivePair)); // Register a callback function (using a function pointer) that will be called when an overlapping pair is removed from the pair manager + void registerRemovedOverlappingPairCallback(void (CollisionDetection::*callbackFunction) (const BodyPair* removedActivePair)); // Register a callback function (using a function pointer) that will be called when an overlapping pair is removed from the pair manager void unregisterRemovedOverlappingPairCallback(); // Unregister a callback function that will be called when a active pair is removed from the pair manager }; @@ -110,7 +122,7 @@ inline uint PairManager::computeHashBodies(uint id1, uint id2) const { } // Return true if pair1 and pair2 are the same -inline bool PairManager::isDifferentPair(const BroadPhasePair& pair1, bodyindex pair2ID1, bodyindex pair2ID2) const { +inline bool PairManager::isDifferentPair(const BodyPair& pair1, bodyindex pair2ID1, bodyindex pair2ID2) const { return (pair2ID1 != pair1.body1->getID() || pair2ID2 != pair1.body2->getID()); } @@ -161,7 +173,7 @@ inline int PairManager::computeHash32Bits(int key) const { } // Find a pair given two body IDs -inline BroadPhasePair* PairManager::findPair(bodyindex id1, bodyindex id2) const { +inline BodyPair* PairManager::findPair(bodyindex id1, bodyindex id2) const { // Check if the hash table has been allocated yet if (!hashTable) return 0; @@ -179,7 +191,7 @@ inline BroadPhasePair* PairManager::findPair(bodyindex id1, bodyindex id2) const // Find a pair given two body IDs and an hash value // This internal version is used to avoid computing multiple times in the // caller method -inline BroadPhasePair* PairManager::findPairWithHashValue(bodyindex id1, bodyindex id2, luint hashValue) const { +inline BodyPair* PairManager::findPairWithHashValue(bodyindex id1, bodyindex id2, luint hashValue) const { // Check if the hash table has been allocated yet if (!hashTable) return 0; @@ -202,19 +214,19 @@ inline void PairManager::shrinkMemory() { } // Compute the offset of a given pair in the array of overlapping pairs -inline bodyindex PairManager::computePairOffset(const BroadPhasePair* pair) const { - return ((bodyindex)((size_t(pair) - size_t(overlappingPairs))) / sizeof(BroadPhasePair)); +inline bodyindex PairManager::computePairOffset(const BodyPair* pair) const { + return ((bodyindex)((size_t(pair) - size_t(overlappingPairs))) / sizeof(BodyPair)); } // Return a pointer to the first overlapping pair (used to iterate over the overlapping pairs) or // returns 0 if there is no overlapping pairs. -inline BroadPhasePair* PairManager::beginOverlappingPairsPointer() const { +inline BodyPair* PairManager::beginOverlappingPairsPointer() const { return &overlappingPairs[0]; } // Return a pointer to the last overlapping pair (used to iterate over the overlapping pairs) or // returns 0 if there is no overlapping pairs. -inline BroadPhasePair* PairManager::endOverlappingPairsPointer() const { +inline BodyPair* PairManager::endOverlappingPairsPointer() const { if (nbOverlappingPairs > 0) { return &overlappingPairs[nbOverlappingPairs-1]; } diff --git a/src/collision/narrowphase/GJK/GJKAlgorithm.cpp b/src/collision/narrowphase/GJK/GJKAlgorithm.cpp index 18a6befa..e0450503 100644 --- a/src/collision/narrowphase/GJK/GJKAlgorithm.cpp +++ b/src/collision/narrowphase/GJK/GJKAlgorithm.cpp @@ -28,7 +28,6 @@ #include "Simplex.h" #include "../../../constraint/Contact.h" #include "../../../configuration.h" -#include "../../OverlappingPair.h" #include #include #include @@ -87,7 +86,7 @@ bool GJKAlgorithm::testCollision(const CollisionShape* collisionShape1, const Tr Simplex simplex; // Get the previous point V (last cached separating axis) - Vector3 v = currentOverlappingPair->getCachedSeparatingAxis(); + Vector3 v = currentOverlappingPair->previousSeparatingAxis; // Initialize the upper bound for the square distance decimal distSquare = DECIMAL_LARGEST; @@ -107,7 +106,7 @@ bool GJKAlgorithm::testCollision(const CollisionShape* collisionShape1, const Tr if (vDotw > 0.0 && vDotw * vDotw > distSquare * marginSquare) { // Cache the current separating axis for frame coherence - currentOverlappingPair->setCachedSeparatingAxis(v); + currentOverlappingPair->previousSeparatingAxis = v; // No intersection, we return false return false; diff --git a/src/collision/narrowphase/NarrowPhaseAlgorithm.h b/src/collision/narrowphase/NarrowPhaseAlgorithm.h index 04fe036e..2278b090 100644 --- a/src/collision/narrowphase/NarrowPhaseAlgorithm.h +++ b/src/collision/narrowphase/NarrowPhaseAlgorithm.h @@ -29,7 +29,10 @@ // Libraries #include "../../body/Body.h" #include "../ContactInfo.h" -#include "../OverlappingPair.h" +#include "../broadphase/PairManager.h" +#include "../../memory/MemoryPool.h" +#include "../BroadPhasePair.h" + // Namespace ReactPhysics3D namespace reactphysics3d { @@ -46,20 +49,20 @@ namespace reactphysics3d { class NarrowPhaseAlgorithm { protected : MemoryPool& memoryPoolContactInfos; // Reference to the memory pool for contact infos - OverlappingPair* currentOverlappingPair; // Overlapping pair of the bodies currently tested for collision + BroadPhasePair* currentOverlappingPair; // Overlapping pair of the bodies currently tested for collision public : NarrowPhaseAlgorithm(MemoryPool& memoryPool); // Constructor virtual ~NarrowPhaseAlgorithm(); // Destructor - void setCurrentOverlappingPair(OverlappingPair* overlappingPair); // Set the current overlapping pair of bodies + void setCurrentOverlappingPair(BroadPhasePair* overlappingPair); // Set the current overlapping pair of bodies virtual bool testCollision(const CollisionShape* collisionShape1, const Transform& transform1, const CollisionShape* collisionShape2, const Transform& transform2, ContactInfo*& contactInfo)=0; // Return true and compute a contact info if the two bounding volume collide }; // Set the current overlapping pair of bodies -inline void NarrowPhaseAlgorithm::setCurrentOverlappingPair(OverlappingPair* overlappingPair) { +inline void NarrowPhaseAlgorithm::setCurrentOverlappingPair(BroadPhasePair *overlappingPair) { currentOverlappingPair = overlappingPair; } diff --git a/src/configuration.h b/src/configuration.h index ac9eefb8..fb1c00a1 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -29,6 +29,7 @@ // Libraries #include #include +#include #include "decimal.h" // Windows platform @@ -47,6 +48,7 @@ namespace reactphysics3d { typedef unsigned int uint; typedef long unsigned int luint; typedef short unsigned int bodyindex; // TODO : Replace whenever possible using the bodyindex type +typedef std::pair bodyindexpair; // Mathematical constants const reactphysics3d::decimal DECIMAL_SMALLEST = - std::numeric_limits::max(); // Minimun decimal value diff --git a/src/collision/OverlappingPair.cpp b/src/engine/OverlappingPair.cpp similarity index 100% rename from src/collision/OverlappingPair.cpp rename to src/engine/OverlappingPair.cpp diff --git a/src/collision/OverlappingPair.h b/src/engine/OverlappingPair.h similarity index 100% rename from src/collision/OverlappingPair.h rename to src/engine/OverlappingPair.h diff --git a/src/collision/PersistentContactCache.cpp b/src/engine/PersistentContactCache.cpp similarity index 100% rename from src/collision/PersistentContactCache.cpp rename to src/engine/PersistentContactCache.cpp diff --git a/src/collision/PersistentContactCache.h b/src/engine/PersistentContactCache.h similarity index 100% rename from src/collision/PersistentContactCache.h rename to src/engine/PersistentContactCache.h diff --git a/src/engine/PhysicsWorld.cpp b/src/engine/PhysicsWorld.cpp index 88571601..169951e0 100644 --- a/src/engine/PhysicsWorld.cpp +++ b/src/engine/PhysicsWorld.cpp @@ -40,6 +40,12 @@ PhysicsWorld::PhysicsWorld(const Vector3& gravity) // Destructor PhysicsWorld::~PhysicsWorld() { + // Delete the remaining overlapping pairs + for (map, OverlappingPair*>::iterator it=overlappingPairs.begin(); it != overlappingPairs.end(); it++) { + // Delete the overlapping pair + (*it).second->OverlappingPair::~OverlappingPair(); + memoryPoolOverlappingPairs.freeObject((*it).second); + } } // Create a rigid body into the physics world @@ -118,3 +124,56 @@ void PhysicsWorld::removeAllConstraints() { constraints.clear(); } +// Notify the world about a new broad-phase overlapping pair +void PhysicsWorld::notifyAddedOverlappingPair(const BroadPhasePair* addedPair) { + + // Get the pair of body index + std::pair indexPair = addedPair->getBodiesIndexPair(); + + // Add the pair into the set of overlapping pairs (if not there yet) + OverlappingPair* newPair = new (memoryPoolOverlappingPairs.allocateObject()) OverlappingPair(addedPair->body1, addedPair->body2, memoryPoolContacts); + std::pair, OverlappingPair*>::iterator, bool> check = overlappingPairs.insert(make_pair(indexPair, newPair)); + assert(check.second); +} + +// Notify the world about a removed broad-phase overlapping pair +void PhysicsWorld::notifyRemovedOverlappingPair(const BroadPhasePair* removedPair) { + + // Get the pair of body index + std::pair indexPair = removedPair->getBodiesIndexPair(); + + // Remove the overlapping pair from the memory pool + overlappingPairs[indexPair]->OverlappingPair::~OverlappingPair(); + memoryPoolOverlappingPairs.freeObject(overlappingPairs[indexPair]); + overlappingPairs.erase(indexPair); +} + +// Notify the world about a new narrow-phase contact +void PhysicsWorld::notifyNewContact(const BroadPhasePair* broadPhasePair, const ContactInfo* contactInfo) { + + RigidBody* const rigidBody1 = dynamic_cast(broadPhasePair->body1); + RigidBody* const rigidBody2 = dynamic_cast(broadPhasePair->body2); + + assert(rigidBody1); + assert(rigidBody2); + + // Create a new contact + Contact* contact = new (memoryPoolContacts.allocateObject()) Contact(rigidBody1, rigidBody2, contactInfo); + assert(contact); + + // Get the corresponding overlapping pair + pair indexPair = broadPhasePair->getBodiesIndexPair(); + OverlappingPair* overlappingPair = overlappingPairs[indexPair]; + assert(overlappingPair); + + // Add the contact to the contact cache of the corresponding overlapping pair + overlappingPair->addContact(contact); + + // Add all the contacts in the contact cache of the two bodies + // to the set of constraints in the physics world + for (uint i=0; igetNbContacts(); i++) { + addConstraint(overlappingPair->getContact(i)); + } +} + + diff --git a/src/engine/PhysicsWorld.h b/src/engine/PhysicsWorld.h index c3be2158..74c0b6c8 100644 --- a/src/engine/PhysicsWorld.h +++ b/src/engine/PhysicsWorld.h @@ -32,6 +32,7 @@ #include #include "../mathematics/mathematics.h" #include "../body/CollisionBody.h" +#include "OverlappingPair.h" #include "../collision/CollisionDetection.h" #include "../constraint/Constraint.h" #include "../constraint/Contact.h" @@ -54,11 +55,19 @@ class PhysicsWorld { std::set rigidBodies; // All the rigid bodies of the physics world std::vector freeRigidBodyIDs; // List of free ID for rigid bodies std::vector constraints; // List that contains all the current constraints + std::map, OverlappingPair*> overlappingPairs; // Broad-phase overlapping pairs of bodies Vector3 gravity; // Gravity vector of the world bool isGravityOn; // True if the gravity force is on bodyindex currentBodyID; // Current body ID - MemoryPool memoryPoolRigidBodies; // Memory pool for rigid bodies memory allocation - + MemoryPool memoryPoolRigidBodies; // Memory pool for rigid bodies memory allocation + MemoryPool memoryPoolOverlappingPairs; // Memory pool for the overlapping pairs + MemoryPool memoryPoolContacts; // Memory pool for the contacts + + void notifyAddedOverlappingPair(const BroadPhasePair* addedPair); // Notify the world about a new broad-phase overlapping pair + void notifyRemovedOverlappingPair(const BroadPhasePair* removedPair); // Notify the world about a removed broad-phase overlapping pair + void notifyNewContact(const BroadPhasePair* pair, const ContactInfo* contactInfo); // Notify the world about a new narrow-phase contact + void updateOverlappingPair(const BroadPhasePair* pair); // Update the overlapping pair + public : PhysicsWorld(const Vector3& gravity); // Constructor virtual ~PhysicsWorld(); // Destructor @@ -80,8 +89,25 @@ class PhysicsWorld { std::set::iterator getBodiesEndIterator(); // Return an iterator to the end of the bodies of the physics world std::set::iterator getRigidBodiesBeginIterator(); // Return an iterator to the beginning of the rigid bodies of the physics world std::set::iterator getRigidBodiesEndIterator(); // Return an iterator to the end of the rigid bodies of the physics world + + // Friends + friend class CollisionDetection; }; +// Update the overlapping pair +inline void PhysicsWorld::updateOverlappingPair(const BroadPhasePair* pair) { + + // Get the pair of body index + std::pair indexPair = pair->getBodiesIndexPair(); + + // Get the corresponding overlapping pair + OverlappingPair* overlappingPair = overlappingPairs[indexPair]; + + // Update the contact cache of the overlapping pair + overlappingPair->update(); +} + + // Add a constraint into the physics world inline void PhysicsWorld::addConstraint(Constraint* constraint) { assert(constraint != 0);