From 5d2cf593b50a215350de0f9acf49198a02fcb52a Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Fri, 21 Nov 2014 21:38:17 +0100 Subject: [PATCH] Remove the PairManager class --- src/collision/broadphase/PairManager.cpp | 289 --------------- src/collision/broadphase/PairManager.h | 333 ------------------ .../narrowphase/NarrowPhaseAlgorithm.h | 1 - 3 files changed, 623 deletions(-) delete mode 100644 src/collision/broadphase/PairManager.cpp delete mode 100644 src/collision/broadphase/PairManager.h diff --git a/src/collision/broadphase/PairManager.cpp b/src/collision/broadphase/PairManager.cpp deleted file mode 100644 index 882920bb..00000000 --- a/src/collision/broadphase/PairManager.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/******************************************************************************** -* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ * -* Copyright (c) 2010-2013 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 "PairManager.h" -#include "../CollisionDetection.h" -#include -#include - -using namespace reactphysics3d; - -// Initialization of static variables -bodyindex PairManager::INVALID_INDEX = std::numeric_limits::max(); - -// Constructor of PairManager -PairManager::PairManager(CollisionDetection& collisionDetection) - : mCollisionDetection(collisionDetection) { - mHashTable = NULL; - mOverlappingPairs = NULL; - mOffsetNextPair = NULL; - mNbOverlappingPairs = 0; - mHashMask = 0; - mNbElementsHashTable = 0; -} - -// Destructor of PairManager -PairManager::~PairManager() { - - // Release the allocated memory - free(mOffsetNextPair); - free(mOverlappingPairs); - free(mHashTable); -} - -// Add a pair of bodies in the pair manager and returns a pointer to 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. -BodyPair* PairManager::addPair(CollisionBody* body1, CollisionBody* body2) { - - // Sort the bodies to have the body with smallest ID first - sortBodiesUsingID(body1, body2); - - // Get the bodies IDs - bodyindex id1 = body1->getID(); - bodyindex id2 = body2->getID(); - - // Compute the hash value of the two bodies - uint hashValue = computeHashBodies(id1, id2) & mHashMask; - - // Try to find the pair in the current overlapping pairs. - BodyPair* pair = findPairWithHashValue(id1, id2, hashValue); - - // If the pair is already in the set of overlapping pairs - if (pair) { - // We only return a pointer to that pair - return pair; - } - - // If we need to allocate more pairs in the set of overlapping pairs - if (mNbOverlappingPairs >= mNbElementsHashTable) { - // Increase the size of the hash table (always a power of two) - mNbElementsHashTable = computeNextPowerOfTwo(mNbOverlappingPairs + 1); - - // Compute the new hash mask with the new hash size - mHashMask = mNbElementsHashTable - 1; - - // Reallocate more pairs - reallocatePairs(); - - // Compute the new hash value (using the new hash size and hash mask) - hashValue = computeHashBodies(id1, id2) & mHashMask; - } - - // Create the new overlapping pair - BodyPair* newPair = &mOverlappingPairs[mNbOverlappingPairs]; - newPair->body1 = body1; - newPair->body2 = body2; - - // Put the new pair as the initial pair with this hash value - mOffsetNextPair[mNbOverlappingPairs] = mHashTable[hashValue]; - mHashTable[hashValue] = mNbOverlappingPairs++; - - // Notify the collision detection about this new overlapping pair - mCollisionDetection.broadPhaseNotifyOverlappingPair(newPair); - - // Return a pointer to the new created pair - return newPair; -} - -// Remove a pair of bodies from the pair manager. -/// This method returns true if the pair has been found and removed. -bool PairManager::removePair(bodyindex id1, bodyindex id2) { - - // Sort the bodies IDs - sortIDs(id1, id2); - - // Compute the hash value of the pair to remove - const uint hashValue = computeHashBodies(id1, id2) & mHashMask; - - // Find the pair to remove - BodyPair* pair = findPairWithHashValue(id1, id2, hashValue); - - // If we have not found the pair - if (pair == NULL) { - return false; - } - - assert(pair->body1->getID() == id1); - assert(pair->body2->getID() == id2); - - // Notify the collision detection about this removed overlapping pair - mCollisionDetection.broadPhaseNotifyRemovedOverlappingPair(pair); - - // Remove the pair from the set of overlapping pairs - removePairWithHashValue(id1, id2, hashValue, computePairOffset(pair)); - - // Try to shrink the memory used by the pair manager - shrinkMemory(); - - return true; -} - -// Internal method to remove a pair from the set of overlapping pair -void PairManager::removePairWithHashValue(bodyindex id1, bodyindex id2, luint hashValue, - bodyindex indexPair) { - - // Get the initial offset of the pairs with - // the corresponding hash value - bodyindex offset = mHashTable[hashValue]; - assert(offset != INVALID_INDEX); - - // Look for the pair in the set of overlapping pairs - bodyindex previousPair = INVALID_INDEX; - while(offset != indexPair) { - previousPair = offset; - offset = mOffsetNextPair[offset]; - } - - // If the pair was the first one with this hash - // value in the hash table - if (previousPair == INVALID_INDEX) { - // Replace the pair to remove in the - // hash table by the next one - mHashTable[hashValue] = mOffsetNextPair[indexPair]; - } - else { // If the pair was not the first one - // Replace the pair to remove in the - // hash table by the next one - assert(mOffsetNextPair[previousPair] == indexPair); - mOffsetNextPair[previousPair] = mOffsetNextPair[indexPair]; - } - - const bodyindex indexLastPair = mNbOverlappingPairs - 1; - - // If the pair to remove is the last one in the list - if (indexPair == indexLastPair) { - - // We simply decrease the number of overlapping pairs - mNbOverlappingPairs--; - } - else { // If the pair to remove is in the middle of the list - - // Now, we want to move the last pair into the location that is - // now free because of the pair we want to remove - - // Get the last pair - const BodyPair* lastPair = &mOverlappingPairs[indexLastPair]; - const uint lastPairHashValue = computeHashBodies(lastPair->body1->getID(), - lastPair->body2->getID()) & mHashMask; - - // Compute the initial offset of the last pair - bodyindex offset = mHashTable[lastPairHashValue]; - assert(offset != INVALID_INDEX); - - // Go through the pairs with the same hash value - // and find the offset of the last pair - bodyindex previous = INVALID_INDEX; - while(offset != indexLastPair) { - previous = offset; - offset = mOffsetNextPair[offset]; - } - - // If the last pair is not the first one with this hash value - if (previous != INVALID_INDEX) { - - // Remove the offset of the last pair in the "nextOffset" array - assert(mOffsetNextPair[previous] == indexLastPair); - mOffsetNextPair[previous] = mOffsetNextPair[indexLastPair]; - } - else { // If the last pair is the first offset with this hash value - - // Remove the offset of the last pair in the "nextOffset" array - mHashTable[lastPairHashValue] = mOffsetNextPair[indexLastPair]; - } - - // Replace the pair to remove by the last pair in - // the overlapping pairs array - mOverlappingPairs[indexPair] = mOverlappingPairs[indexLastPair]; - mOffsetNextPair[indexPair] = mHashTable[lastPairHashValue]; - mHashTable[lastPairHashValue] = indexPair; - - mNbOverlappingPairs--; - } -} - -// Look for a pair in the set of overlapping pairs -BodyPair* PairManager::lookForAPair(bodyindex id1, bodyindex id2, luint hashValue) const { - - // Look for the pair in the set of overlapping pairs - bodyindex offset = mHashTable[hashValue]; - while (offset != INVALID_INDEX && isDifferentPair(mOverlappingPairs[offset], id1, id2)) { - offset = mOffsetNextPair[offset]; - } - - // If the pair has not been found in the overlapping pairs - if (offset == INVALID_INDEX) { - return NULL; - } - - assert(offset < mNbOverlappingPairs); - - // The pair has been found in the set of overlapping pairs, then - // we return a pointer to it - return &mOverlappingPairs[offset]; -} - -// Reallocate more pairs -void PairManager::reallocatePairs() { - - // Reallocate the hash table and initialize it - free(mHashTable); - mHashTable = (bodyindex*) malloc(mNbElementsHashTable * sizeof(bodyindex)); - assert(mHashTable != NULL); - for (bodyindex i=0; igetID(), - mOverlappingPairs[i].body2->getID()) & mHashMask; - newOffsetNextPair[i] = mHashTable[newHashValue]; - mHashTable[newHashValue] = i; - } - - // Delete the old pairs - free(mOffsetNextPair); - free(mOverlappingPairs); - - // Replace by the new data - mOverlappingPairs = newOverlappingPairs; - mOffsetNextPair = newOffsetNextPair; -} diff --git a/src/collision/broadphase/PairManager.h b/src/collision/broadphase/PairManager.h deleted file mode 100644 index cec8569f..00000000 --- a/src/collision/broadphase/PairManager.h +++ /dev/null @@ -1,333 +0,0 @@ -/******************************************************************************** -* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ * -* Copyright (c) 2010-2013 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 REACTPHYSICS3D_PAIR_MANAGER_H -#define REACTPHYSICS3D_PAIR_MANAGER_H - -// TODO : REMOVE THE PAIR MANAGER CLASS - -// Libraries -#include "../../body/CollisionBody.h" -#include - - -/// Namespace ReactPhysics3D -namespace reactphysics3d { - -// Declaration -class CollisionDetection; - -// Structure BodyPair -/** - * This structure represents a pair of bodies - * during the broad-phase collision detection. - */ -struct BodyPair { - - public: - - /// Pointer to the first body - CollisionBody* body1; - - /// Pointer to the second body - CollisionBody* body2; - - /// 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 -/** - * This class is a data-structure contains the pairs of bodies that - * are overlapping during the broad-phase collision detection. - * This class implements the pair manager described by Pierre Terdiman - * in www.codercorner.com/SAP.pdf. - */ -class PairManager { - - private : - - // -------------------- Attributes -------------------- // - - /// Number of elements in the hash table - bodyindex mNbElementsHashTable; - - /// Hash mask for the hash function - uint mHashMask; - - /// Number of overlapping pairs - bodyindex mNbOverlappingPairs; - - /// Hash table that contains the offset of the first pair of the list of - /// pairs with the same hash value in the "overlappingPairs" array - bodyindex* mHashTable; - - /// Array that contains for each offset, the offset of the next pair with - /// the same hash value for a given same hash value - bodyindex* mOffsetNextPair; - - /// Array that contains the overlapping pairs - BodyPair* mOverlappingPairs; - - /// Invalid ID - static bodyindex INVALID_INDEX; - - /// Reference to the collision detection - CollisionDetection& mCollisionDetection; - - // -------------------- Methods -------------------- // - - /// Private copy-constructor - PairManager(const PairManager& pairManager); - - /// Private assignment operator - PairManager& operator=(const PairManager& pairManager); - - /// Sort the bodies according to their IDs (smallest ID first) - void sortBodiesUsingID(CollisionBody*& body1, CollisionBody*& body2) const; - - /// Sort the IDs (smallest ID first) - void sortIDs(bodyindex& id1, bodyindex& id2) const; - - /// Return true if pair1 and pair2 are the same - bool isDifferentPair(const BodyPair& pair1, bodyindex pair2ID1, bodyindex pair2ID2) const; - - /// Compute the hash value of two bodies using their IDs - uint computeHashBodies(uint id1, uint id2) const; - - /// This method returns an hash value for a 32 bits key. - int computeHash32Bits(int key) const; - - /// Reallocate memory for more pairs - void reallocatePairs(); - - /// Shrink the allocated memory - void shrinkMemory(); - - /// Compute the offset of a given pair - bodyindex computePairOffset(const BodyPair* pair) const; - - /// Look for a pair in the set of overlapping pairs - BodyPair* lookForAPair(bodyindex id1, bodyindex id2, luint hashValue) const; - - /// Find a pair given two body IDs and an hash value. - BodyPair* findPairWithHashValue(bodyindex id1, bodyindex id2, luint hashValue) const; - - /// Remove a pair from the set of active pair - void removePairWithHashValue(bodyindex id1, bodyindex id2, luint hashValue, - bodyindex indexPair); - - public : - - // ----- Methods ----- // - - /// Constructor - PairManager(CollisionDetection& collisionDetection); - - /// Destructor - ~PairManager(); - - /// Return the number of active pairs - bodyindex getNbOverlappingPairs() const; - - /// Add a pair of bodies in the pair manager and returns a pointer to that pair. - BodyPair* addPair(CollisionBody* body1, CollisionBody* body2); - - /// Remove a pair of bodies from the pair manager. - bool removePair(bodyindex id1, bodyindex id2); - - /// Find a pair given two body IDs - BodyPair* findPair(bodyindex id1, bodyindex id2) const; - - /// Return the next power of two - static luint computeNextPowerOfTwo(luint number); - - /// Return a pointer to the first overlapping pair (used to - /// iterate over the active pairs). - BodyPair* beginOverlappingPairsPointer() const; - - /// Return a pointer to the last overlapping pair (used to - /// iterate over the active pairs). - BodyPair* endOverlappingPairsPointer() const; - - /// Register a callback function (using a function pointer) that will be - /// called when a new overlapping pair is added in the pair manager. - void registerAddedOverlappingPairCallback(void (CollisionDetection::*callbackFunction) - (const BodyPair* addedActivePair)); - - /// Unregister the callback function that will be called - /// when a new active pair is added in the pair manager - void unregisterAddedOverlappingPairCallback(); - - /// 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)); - - /// Unregister a callback function that will be called - /// when a active pair is removed from the pair manager - void unregisterRemovedOverlappingPairCallback(); -}; - -// Return the number of overlapping pairs -inline bodyindex PairManager::getNbOverlappingPairs() const { - return mNbOverlappingPairs; -} - -// Compute the hash value of two bodies -inline uint PairManager::computeHashBodies(uint id1, uint id2) const { - return computeHash32Bits(id1 | (id2 << 16)); -} - -// Return true if pair1 and pair2 are the same -inline bool PairManager::isDifferentPair(const BodyPair& pair1, bodyindex pair2ID1, - bodyindex pair2ID2) const { - return (pair2ID1 != pair1.body1->getID() || pair2ID2 != pair1.body2->getID()); -} - -// Return the next power of two of a 32bits integer using a SWAR algorithm -inline luint PairManager::computeNextPowerOfTwo(luint number) { - number |= (number >> 1); - number |= (number >> 2); - number |= (number >> 4); - number |= (number >> 8); - number |= (number >> 16); - return number+1; -} - -// Sort the bodies according to their IDs (smallest ID first) -inline void PairManager::sortBodiesUsingID(CollisionBody*& body1, CollisionBody*& body2) const { - - // If the ID of body1 is larger than the ID of body 2 - if (body1->getID() > body2->getID()) { - - // Swap the two bodies pointers - CollisionBody* temp = body2; - body2 = body1; - body1 = temp; - } -} - -// Sort the IDs (smallest ID first) -inline void PairManager::sortIDs(bodyindex &id1, bodyindex &id2) const { - if (id1 > id2) { - bodyindex temp = id2; - id2 = id1; - id1 = temp; - } -} - -// This method returns an hash value for a 32 bits key. -/// using Thomas Wang's hash technique. -/// This hash function can be found at : -/// http://www.concentric.net/~ttwang/tech/inthash.htm -inline int PairManager::computeHash32Bits(int key) const { - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; -} - -// Find a pair given two body IDs -inline BodyPair* PairManager::findPair(bodyindex id1, bodyindex id2) const { - - // Check if the hash table has been allocated yet - if (mHashTable == NULL) return NULL; - - // Sort the IDs - sortIDs(id1, id2); - - // Compute the hash value of the pair to find - uint hashValue = computeHashBodies(id1, id2) & mHashMask; - - // Look for the pair in the set of overlapping pairs - return lookForAPair(id1, id2, hashValue); -} - -// 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 BodyPair* PairManager::findPairWithHashValue(bodyindex id1, bodyindex id2, - luint hashValue) const { - - // Check if the hash table has been allocated yet - if (mHashTable == NULL) return NULL; - - // Look for the pair in the set of overlapping pairs - return lookForAPair(id1, id2, hashValue); -} - -// Try to reduce the allocated memory by the pair manager -inline void PairManager::shrinkMemory() { - - // Check if the allocated memory can be reduced - const bodyindex correctNbElementsHashTable = computeNextPowerOfTwo(mNbOverlappingPairs); - if (mNbElementsHashTable == correctNbElementsHashTable) return; - - // Reduce the allocated memory - mNbElementsHashTable = correctNbElementsHashTable; - mHashMask = mNbElementsHashTable - 1; - reallocatePairs(); -} - -// Compute the offset of a given pair in the array of overlapping pairs -inline bodyindex PairManager::computePairOffset(const BodyPair* pair) const { - return ((bodyindex)((size_t(pair) - size_t(mOverlappingPairs))) / 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 BodyPair* PairManager::beginOverlappingPairsPointer() const { - return &mOverlappingPairs[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 BodyPair* PairManager::endOverlappingPairsPointer() const { - if (mNbOverlappingPairs > 0) { - return &mOverlappingPairs[mNbOverlappingPairs-1]; - } - else { - return &mOverlappingPairs[0]; - } -} - -} - -#endif - - diff --git a/src/collision/narrowphase/NarrowPhaseAlgorithm.h b/src/collision/narrowphase/NarrowPhaseAlgorithm.h index 4fdb07b0..74d1ca0c 100644 --- a/src/collision/narrowphase/NarrowPhaseAlgorithm.h +++ b/src/collision/narrowphase/NarrowPhaseAlgorithm.h @@ -29,7 +29,6 @@ // Libraries #include "body/Body.h" #include "constraint/ContactPoint.h" -#include "collision/broadphase/PairManager.h" #include "memory/MemoryAllocator.h" #include "engine/OverlappingPair.h"