From 261ffef616b8d6af37eefd0beec52d2c3bb7a5ff Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Mon, 1 Jan 2018 18:35:57 +0100 Subject: [PATCH] Refactor memory allocation --- CMakeLists.txt | 2 +- src/body/CollisionBody.cpp | 12 +-- src/body/RigidBody.cpp | 12 ++- src/body/RigidBody.h | 4 +- src/collision/CollisionCallback.cpp | 12 ++- src/collision/CollisionCallback.h | 6 +- src/collision/CollisionDetection.cpp | 97 ++++++++++--------- src/collision/CollisionDetection.h | 19 ++-- src/collision/ContactManifold.cpp | 2 +- src/collision/ContactManifold.h | 4 +- src/collision/ContactManifoldInfo.cpp | 2 +- src/collision/ContactManifoldInfo.h | 6 +- src/collision/ContactManifoldSet.cpp | 2 +- src/collision/ContactManifoldSet.h | 4 +- src/collision/HalfEdgeStructure.h | 6 +- src/collision/MiddlePhaseTriangleCallback.h | 4 +- src/collision/NarrowPhaseInfo.cpp | 6 +- src/collision/NarrowPhaseInfo.h | 4 +- src/collision/PolyhedronMesh.cpp | 4 +- src/collision/ProxyShape.cpp | 8 +- src/collision/ProxyShape.h | 9 +- .../broadphase/BroadPhaseAlgorithm.cpp | 4 +- .../broadphase/BroadPhaseAlgorithm.h | 2 +- .../narrowphase/CapsuleVsCapsuleAlgorithm.cpp | 2 +- .../narrowphase/CapsuleVsCapsuleAlgorithm.h | 2 +- .../CapsuleVsConvexPolyhedronAlgorithm.cpp | 2 +- .../CapsuleVsConvexPolyhedronAlgorithm.h | 2 +- ...xPolyhedronVsConvexPolyhedronAlgorithm.cpp | 2 +- ...vexPolyhedronVsConvexPolyhedronAlgorithm.h | 2 +- .../narrowphase/NarrowPhaseAlgorithm.h | 2 +- .../narrowphase/SAT/SATAlgorithm.cpp | 2 +- src/collision/narrowphase/SAT/SATAlgorithm.h | 4 +- .../narrowphase/SphereVsCapsuleAlgorithm.cpp | 2 +- .../narrowphase/SphereVsCapsuleAlgorithm.h | 2 +- .../SphereVsConvexPolyhedronAlgorithm.cpp | 2 +- .../SphereVsConvexPolyhedronAlgorithm.h | 2 +- .../narrowphase/SphereVsSphereAlgorithm.cpp | 2 +- .../narrowphase/SphereVsSphereAlgorithm.h | 2 +- src/collision/shapes/BoxShape.cpp | 6 +- src/collision/shapes/BoxShape.h | 2 +- src/collision/shapes/CapsuleShape.cpp | 2 +- src/collision/shapes/CapsuleShape.h | 2 +- src/collision/shapes/CollisionShape.h | 2 +- src/collision/shapes/ConcaveMeshShape.cpp | 2 +- src/collision/shapes/ConcaveMeshShape.h | 6 +- src/collision/shapes/ConvexMeshShape.cpp | 2 +- src/collision/shapes/ConvexMeshShape.h | 2 +- src/collision/shapes/HeightFieldShape.cpp | 2 +- src/collision/shapes/HeightFieldShape.h | 6 +- src/collision/shapes/SphereShape.cpp | 2 +- src/collision/shapes/SphereShape.h | 2 +- src/collision/shapes/TriangleShape.cpp | 4 +- src/collision/shapes/TriangleShape.h | 4 +- src/configuration.h | 2 +- src/containers/LinkedList.h | 6 +- src/containers/List.h | 6 +- src/engine/CollisionWorld.cpp | 8 +- src/engine/CollisionWorld.h | 10 +- src/engine/ContactSolver.cpp | 12 ++- src/engine/ContactSolver.h | 9 +- src/engine/DynamicsWorld.cpp | 63 +++++++----- src/engine/Island.cpp | 11 ++- src/engine/Island.h | 2 +- src/engine/OverlappingPair.cpp | 2 +- src/engine/OverlappingPair.h | 12 +-- src/mathematics/mathematics_functions.cpp | 4 +- src/mathematics/mathematics_functions.h | 4 +- src/memory/DefaultAllocator.h | 12 +-- src/memory/{Allocator.h => MemoryAllocator.h} | 19 ++-- src/memory/MemoryManager.cpp | 2 + src/memory/MemoryManager.h | 92 +++++++++++++++--- src/memory/PoolAllocator.cpp | 35 ++++--- src/memory/PoolAllocator.h | 16 +-- src/memory/SingleFrameAllocator.cpp | 75 ++++++++++++-- src/memory/SingleFrameAllocator.h | 34 ++++--- 75 files changed, 449 insertions(+), 296 deletions(-) rename src/memory/{Allocator.h => MemoryAllocator.h} (87%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e585e0d1..bc11aebd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,7 +187,7 @@ SET (REACTPHYSICS3D_SOURCES "src/mathematics/Vector3.h" "src/mathematics/Ray.h" "src/mathematics/Vector3.cpp" - "src/memory/Allocator.h" + "src/memory/MemoryAllocator.h" "src/memory/PoolAllocator.h" "src/memory/PoolAllocator.cpp" "src/memory/SingleFrameAllocator.h" diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 56493d28..bb8b0408 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -70,9 +70,9 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, const Transform& transform) { // Create a new proxy collision shape to attach the collision shape to the body - ProxyShape* proxyShape = new (mWorld.mPoolAllocator.allocate( + ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(ProxyShape))) ProxyShape(this, collisionShape, - transform, decimal(1), mWorld.mPoolAllocator); + transform, decimal(1), mWorld.mMemoryManager); #ifdef IS_PROFILING_ACTIVE @@ -123,7 +123,7 @@ void CollisionBody::removeCollisionShape(const ProxyShape* proxyShape) { } current->~ProxyShape(); - mWorld.mPoolAllocator.release(current, sizeof(ProxyShape)); + mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, current, sizeof(ProxyShape)); mNbCollisionShapes--; return; } @@ -143,7 +143,7 @@ void CollisionBody::removeCollisionShape(const ProxyShape* proxyShape) { } elementToRemove->~ProxyShape(); - mWorld.mPoolAllocator.release(elementToRemove, sizeof(ProxyShape)); + mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, elementToRemove, sizeof(ProxyShape)); mNbCollisionShapes--; return; } @@ -169,7 +169,7 @@ void CollisionBody::removeAllCollisionShapes() { } current->~ProxyShape(); - mWorld.mPoolAllocator.release(current, sizeof(ProxyShape)); + mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, current, sizeof(ProxyShape)); // Get the next element in the list current = nextElement; @@ -188,7 +188,7 @@ void CollisionBody::resetContactManifoldsList() { // Delete the current element currentElement->~ContactManifoldListElement(); - mWorld.mPoolAllocator.release(currentElement, sizeof(ContactManifoldListElement)); + mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, currentElement, sizeof(ContactManifoldListElement)); currentElement = nextElement; } diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index 7419fc4c..36c362dc 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -176,7 +176,7 @@ void RigidBody::setMass(decimal mass) { } // Remove a joint from the joints list -void RigidBody::removeJointFromJointsList(PoolAllocator& memoryAllocator, const Joint* joint) { +void RigidBody::removeJointFromJointsList(MemoryManager& memoryManager, const Joint* joint) { assert(joint != nullptr); assert(mJointsList != nullptr); @@ -186,7 +186,8 @@ void RigidBody::removeJointFromJointsList(PoolAllocator& memoryAllocator, const JointListElement* elementToRemove = mJointsList; mJointsList = elementToRemove->next; elementToRemove->~JointListElement(); - memoryAllocator.release(elementToRemove, sizeof(JointListElement)); + memoryManager.release(MemoryManager::AllocationType::Pool, + elementToRemove, sizeof(JointListElement)); } else { // If the element to remove is not the first one in the list JointListElement* currentElement = mJointsList; @@ -195,7 +196,8 @@ void RigidBody::removeJointFromJointsList(PoolAllocator& memoryAllocator, const JointListElement* elementToRemove = currentElement->next; currentElement->next = elementToRemove->next; elementToRemove->~JointListElement(); - memoryAllocator.release(elementToRemove, sizeof(JointListElement)); + memoryManager.release(MemoryManager::AllocationType::Pool, + elementToRemove, sizeof(JointListElement)); break; } currentElement = currentElement->next; @@ -224,9 +226,9 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape, decimal mass) { // Create a new proxy collision shape to attach the collision shape to the body - ProxyShape* proxyShape = new (mWorld.mPoolAllocator.allocate( + ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(ProxyShape))) ProxyShape(this, collisionShape, - transform, mass, mWorld.mPoolAllocator); + transform, mass, mWorld.mMemoryManager); #ifdef IS_PROFILING_ACTIVE diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h index e12cab05..23603bda 100644 --- a/src/body/RigidBody.h +++ b/src/body/RigidBody.h @@ -31,7 +31,7 @@ #include "CollisionBody.h" #include "engine/Material.h" #include "mathematics/mathematics.h" -#include "memory/PoolAllocator.h" +#include "memory/MemoryManager.h" /// Namespace reactphysics3d namespace reactphysics3d { @@ -112,7 +112,7 @@ class RigidBody : public CollisionBody { // -------------------- Methods -------------------- // /// Remove a joint from the joints list - void removeJointFromJointsList(PoolAllocator& memoryAllocator, const Joint* joint); + void removeJointFromJointsList(reactphysics3d::MemoryManager& memoryManager, const Joint* joint); /// Update the transform of the body after a change of the center of mass void updateTransformWithCenterOfMass(); diff --git a/src/collision/CollisionCallback.cpp b/src/collision/CollisionCallback.cpp index db820db4..1702e40a 100644 --- a/src/collision/CollisionCallback.cpp +++ b/src/collision/CollisionCallback.cpp @@ -26,18 +26,18 @@ // Libraries #include "collision/CollisionCallback.h" #include "engine/OverlappingPair.h" -#include "memory/Allocator.h" +#include "memory/MemoryAllocator.h" #include "collision/ContactManifold.h" // We want to use the ReactPhysics3D namespace using namespace reactphysics3d; // Constructor -CollisionCallback::CollisionCallbackInfo::CollisionCallbackInfo(OverlappingPair* pair, Allocator& allocator) : +CollisionCallback::CollisionCallbackInfo::CollisionCallbackInfo(OverlappingPair* pair, MemoryManager& memoryManager) : contactManifoldElements(nullptr), body1(pair->getShape1()->getBody()), body2(pair->getShape2()->getBody()), proxyShape1(pair->getShape1()), proxyShape2(pair->getShape2()), - mMemoryAllocator(allocator) { + mMemoryManager(memoryManager) { assert(pair != nullptr); @@ -52,7 +52,8 @@ CollisionCallback::CollisionCallbackInfo::CollisionCallbackInfo(OverlappingPair* // Add the contact manifold at the beginning of the linked // list of contact manifolds of the first body - ContactManifoldListElement* element = new (mMemoryAllocator.allocate(sizeof(ContactManifoldListElement))) + ContactManifoldListElement* element = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(ContactManifoldListElement))) ContactManifoldListElement(contactManifold, contactManifoldElements); contactManifoldElements = element; @@ -72,7 +73,8 @@ CollisionCallback::CollisionCallbackInfo::~CollisionCallbackInfo() { // Delete and release memory element->~ContactManifoldListElement(); - mMemoryAllocator.release(element, sizeof(ContactManifoldListElement)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, element, + sizeof(ContactManifoldListElement)); element = nextElement; } diff --git a/src/collision/CollisionCallback.h b/src/collision/CollisionCallback.h index 54208fe4..57ae0f04 100644 --- a/src/collision/CollisionCallback.h +++ b/src/collision/CollisionCallback.h @@ -69,11 +69,11 @@ class CollisionCallback { /// Pointer to the proxy shape of second body const ProxyShape* proxyShape2; - /// Memory allocator - Allocator& mMemoryAllocator; + /// Memory manager + MemoryManager& mMemoryManager; // Constructor - CollisionCallbackInfo(OverlappingPair* pair, Allocator& allocator); + CollisionCallbackInfo(OverlappingPair* pair, MemoryManager& memoryManager); // Destructor ~CollisionCallbackInfo(); diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index e57c5fd8..66cf1eb5 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -47,9 +47,8 @@ using namespace reactphysics3d; using namespace std; // Constructor -CollisionDetection::CollisionDetection(CollisionWorld* world, PoolAllocator& memoryAllocator, SingleFrameAllocator& singleFrameAllocator) - : mPoolAllocator(memoryAllocator), mSingleFrameAllocator(singleFrameAllocator), - mWorld(world), mNarrowPhaseInfoList(nullptr), mBroadPhaseAlgorithm(*this), +CollisionDetection::CollisionDetection(CollisionWorld* world, MemoryManager& memoryManager) + : mMemoryManager(memoryManager), mWorld(world), mNarrowPhaseInfoList(nullptr), mBroadPhaseAlgorithm(*this), mIsCollisionShapesAdded(false) { // Set the default collision dispatch configuration @@ -95,7 +94,7 @@ void CollisionDetection::computeBroadPhase() { // Ask the broad-phase to recompute the overlapping pairs of collision // shapes. This call can only add new overlapping pairs in the collision // detection. - mBroadPhaseAlgorithm.computeOverlappingPairs(mPoolAllocator); + mBroadPhaseAlgorithm.computeOverlappingPairs(mMemoryManager); } } @@ -133,7 +132,7 @@ void CollisionDetection::computeMiddlePhase() { // Destroy the overlapping pair itToRemove->second->~OverlappingPair(); - mWorld->mPoolAllocator.release(itToRemove->second, sizeof(OverlappingPair)); + mWorld->mMemoryManager.release(MemoryManager::AllocationType::Pool, itToRemove->second, sizeof(OverlappingPair)); mOverlappingPairs.erase(itToRemove); continue; } @@ -166,10 +165,10 @@ void CollisionDetection::computeMiddlePhase() { // No middle-phase is necessary, simply create a narrow phase info // for the narrow-phase collision detection NarrowPhaseInfo* firstNarrowPhaseInfo = mNarrowPhaseInfoList; - mNarrowPhaseInfoList = new (mSingleFrameAllocator.allocate(sizeof(NarrowPhaseInfo))) + mNarrowPhaseInfoList = new (mMemoryManager.allocate(MemoryManager::AllocationType::Frame, sizeof(NarrowPhaseInfo))) NarrowPhaseInfo(pair, shape1->getCollisionShape(), shape2->getCollisionShape(), shape1->getLocalToWorldTransform(), - shape2->getLocalToWorldTransform(), mSingleFrameAllocator); + shape2->getLocalToWorldTransform(), mMemoryManager.getSingleFrameAllocator()); mNarrowPhaseInfoList->next = firstNarrowPhaseInfo; } @@ -177,7 +176,7 @@ void CollisionDetection::computeMiddlePhase() { else if ((!isShape1Convex && isShape2Convex) || (!isShape2Convex && isShape1Convex)) { NarrowPhaseInfo* narrowPhaseInfo = nullptr; - computeConvexVsConcaveMiddlePhase(pair, mSingleFrameAllocator, &narrowPhaseInfo); + computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getSingleFrameAllocator(), &narrowPhaseInfo); // Add all the narrow-phase info object reported by the callback into the // list of all the narrow-phase info object @@ -202,7 +201,7 @@ void CollisionDetection::computeMiddlePhase() { } // Compute the concave vs convex middle-phase algorithm for a given pair of bodies -void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, Allocator& allocator, +void CollisionDetection::computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, MemoryAllocator& allocator, NarrowPhaseInfo** firstNarrowPhaseInfo) { ProxyShape* shape1 = pair->getShape1(); @@ -273,7 +272,7 @@ void CollisionDetection::computeNarrowPhase() { // Use the narrow-phase collision detection algorithm to check // if there really is a collision. If a collision occurs, the // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(currentNarrowPhaseInfo, true, mSingleFrameAllocator)) { + if (narrowPhaseAlgorithm->testCollision(currentNarrowPhaseInfo, true, mMemoryManager.getSingleFrameAllocator())) { // Add the contact points as a potential contact manifold into the pair currentNarrowPhaseInfo->addContactPointsAsPotentialContactManifold(); @@ -295,7 +294,7 @@ void CollisionDetection::computeNarrowPhase() { narrowPhaseInfoToDelete->~NarrowPhaseInfo(); // Release the allocated memory for the narrow phase info - mSingleFrameAllocator.release(narrowPhaseInfoToDelete, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Frame, narrowPhaseInfoToDelete, sizeof(NarrowPhaseInfo)); } // Convert the potential contact into actual contacts @@ -327,8 +326,9 @@ void CollisionDetection::broadPhaseNotifyOverlappingPair(ProxyShape* shape1, Pro if (mOverlappingPairs.find(pairID) != mOverlappingPairs.end()) return; // Create the overlapping pair and add it into the set of overlapping pairs - OverlappingPair* newPair = new (mPoolAllocator.allocate(sizeof(OverlappingPair))) - OverlappingPair(shape1, shape2, mPoolAllocator, mSingleFrameAllocator); + OverlappingPair* newPair = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(OverlappingPair))) + OverlappingPair(shape1, shape2, mMemoryManager.getPoolAllocator(), + mMemoryManager.getSingleFrameAllocator()); assert(newPair != nullptr); #ifndef NDEBUG @@ -359,7 +359,7 @@ void CollisionDetection::removeProxyCollisionShape(ProxyShape* proxyShape) { // Destroy the overlapping pair itToRemove->second->~OverlappingPair(); - mWorld->mPoolAllocator.release(itToRemove->second, sizeof(OverlappingPair)); + mWorld->mMemoryManager.release(MemoryManager::AllocationType::Pool, itToRemove->second, sizeof(OverlappingPair)); mOverlappingPairs.erase(itToRemove); } else { @@ -403,14 +403,16 @@ void CollisionDetection::addContactManifoldToBody(OverlappingPair* pair) { // Add the contact manifold at the beginning of the linked // list of contact manifolds of the first body - ContactManifoldListElement* listElement1 = new (mPoolAllocator.allocate(sizeof(ContactManifoldListElement))) + ContactManifoldListElement* listElement1 = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(ContactManifoldListElement))) ContactManifoldListElement(contactManifold, body1->mContactManifoldsList); body1->mContactManifoldsList = listElement1; // Add the contact manifold at the beginning of the linked // list of the contact manifolds of the second body - ContactManifoldListElement* listElement2 = new (mPoolAllocator.allocate(sizeof(ContactManifoldListElement))) + ContactManifoldListElement* listElement2 = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(ContactManifoldListElement))) ContactManifoldListElement(contactManifold, body2->mContactManifoldsList); body2->mContactManifoldsList = listElement2; @@ -470,7 +472,7 @@ void CollisionDetection::reportAllContacts() { // If there is a user callback if (mWorld->mEventListener != nullptr && it->second->hasContacts()) { - CollisionCallback::CollisionCallbackInfo collisionInfo(it->second, mPoolAllocator); + CollisionCallback::CollisionCallbackInfo collisionInfo(it->second, mMemoryManager); // Trigger a callback event to report the new contact to the user mWorld->mEventListener->newContact(collisionInfo); @@ -498,9 +500,10 @@ NarrowPhaseInfo* CollisionDetection::computeMiddlePhaseForProxyShapes(Overlappin // No middle-phase is necessary, simply create a narrow phase info // for the narrow-phase collision detection - narrowPhaseInfo = new (mPoolAllocator.allocate(sizeof(NarrowPhaseInfo))) NarrowPhaseInfo(pair, shape1->getCollisionShape(), + narrowPhaseInfo = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(NarrowPhaseInfo))) NarrowPhaseInfo(pair, shape1->getCollisionShape(), shape2->getCollisionShape(), shape1->getLocalToWorldTransform(), - shape2->getLocalToWorldTransform(), mPoolAllocator); + shape2->getLocalToWorldTransform(), mMemoryManager.getPoolAllocator()); } // Concave vs Convex algorithm @@ -508,7 +511,7 @@ NarrowPhaseInfo* CollisionDetection::computeMiddlePhaseForProxyShapes(Overlappin // Run the middle-phase collision detection algorithm to find the triangles of the concave // shape we need to use during the narrow-phase collision detection - computeConvexVsConcaveMiddlePhase(pair, mPoolAllocator, &narrowPhaseInfo); + computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getPoolAllocator(), &narrowPhaseInfo); } pair->clearObsoleteLastFrameCollisionInfos(); @@ -524,7 +527,7 @@ void CollisionDetection::testAABBOverlap(const AABB& aabb, OverlapCallback* over std::unordered_set reportedBodies; // Ask the broad-phase to get all the overlapping shapes - LinkedList overlappingNodes(mPoolAllocator); + LinkedList overlappingNodes(mMemoryManager.getPoolAllocator()); mBroadPhaseAlgorithm.reportAllShapesOverlappingWithAABB(aabb, overlappingNodes); // For each overlaping proxy shape @@ -575,7 +578,8 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) if (aabb1.testCollision(aabb2)) { // Create a temporary overlapping pair - OverlappingPair pair(body1ProxyShape, body2ProxyShape, mPoolAllocator, mPoolAllocator); + OverlappingPair pair(body1ProxyShape, body2ProxyShape, mMemoryManager.getPoolAllocator(), + mMemoryManager.getPoolAllocator()); // Compute the middle-phase collision detection between the two shapes NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(&pair); @@ -600,7 +604,7 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) // Use the narrow-phase collision detection algorithm to check // if there really is a collision. If a collision occurs, the // notifyContact() callback method will be called. - isColliding |= narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, false, mPoolAllocator); + isColliding |= narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, false, mMemoryManager.getPoolAllocator()); } } @@ -611,7 +615,7 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2) currentNarrowPhaseInfo->~NarrowPhaseInfo(); // Release the allocated memory - mPoolAllocator.release(currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); } // Return if we have found a narrow-phase collision @@ -648,7 +652,7 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl const AABB& shapeAABB = mBroadPhaseAlgorithm.getFatAABB(bodyProxyShape->mBroadPhaseID); // Ask the broad-phase to get all the overlapping shapes - LinkedList overlappingNodes(mPoolAllocator); + LinkedList overlappingNodes(mMemoryManager.getPoolAllocator()); mBroadPhaseAlgorithm.reportAllShapesOverlappingWithAABB(shapeAABB, overlappingNodes); const bodyindex bodyId = body->getID(); @@ -670,7 +674,8 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl if ((proxyShape->getCollisionCategoryBits() & categoryMaskBits) != 0) { // Create a temporary overlapping pair - OverlappingPair pair(bodyProxyShape, proxyShape, mPoolAllocator, mPoolAllocator); + OverlappingPair pair(bodyProxyShape, proxyShape, mMemoryManager.getPoolAllocator(), + mMemoryManager.getPoolAllocator()); // Compute the middle-phase collision detection between the two shapes NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(&pair); @@ -695,7 +700,7 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl // Use the narrow-phase collision detection algorithm to check // if there really is a collision. If a collision occurs, the // notifyContact() callback method will be called. - isColliding |= narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, false, mPoolAllocator); + isColliding |= narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, false, mMemoryManager.getPoolAllocator()); } } @@ -706,7 +711,7 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl currentNarrowPhaseInfo->~NarrowPhaseInfo(); // Release the allocated memory - mPoolAllocator.release(currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); } // Return if we have found a narrow-phase collision @@ -754,7 +759,8 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body if (aabb1.testCollision(aabb2)) { // Create a temporary overlapping pair - OverlappingPair pair(body1ProxyShape, body2ProxyShape, mPoolAllocator, mPoolAllocator); + OverlappingPair pair(body1ProxyShape, body2ProxyShape, mMemoryManager.getPoolAllocator(), + mMemoryManager.getPoolAllocator()); // Compute the middle-phase collision detection between the two shapes NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(&pair); @@ -774,7 +780,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body // Use the narrow-phase collision detection algorithm to check // if there really is a collision. If a collision occurs, the // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mPoolAllocator)) { + if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { // Add the contact points as a potential contact manifold into the pair narrowPhaseInfo->addContactPointsAsPotentialContactManifold(); @@ -788,7 +794,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body currentNarrowPhaseInfo->~NarrowPhaseInfo(); // Release the allocated memory - mPoolAllocator.release(currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); } // Process the potential contacts @@ -797,7 +803,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body if (pair.hasContacts()) { // Report the contacts to the user - CollisionCallback::CollisionCallbackInfo collisionInfo(&pair, mPoolAllocator); + CollisionCallback::CollisionCallbackInfo collisionInfo(&pair, mMemoryManager); collisionCallback->notifyContact(collisionInfo); } } @@ -826,7 +832,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c const AABB& shapeAABB = mBroadPhaseAlgorithm.getFatAABB(bodyProxyShape->mBroadPhaseID); // Ask the broad-phase to get all the overlapping shapes - LinkedList overlappingNodes(mPoolAllocator); + LinkedList overlappingNodes(mMemoryManager.getPoolAllocator()); mBroadPhaseAlgorithm.reportAllShapesOverlappingWithAABB(shapeAABB, overlappingNodes); const bodyindex bodyId = body->getID(); @@ -846,7 +852,8 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c if ((proxyShape->getCollisionCategoryBits() & categoryMaskBits) != 0) { // Create a temporary overlapping pair - OverlappingPair pair(bodyProxyShape, proxyShape, mPoolAllocator, mPoolAllocator); + OverlappingPair pair(bodyProxyShape, proxyShape, mMemoryManager.getPoolAllocator(), + mMemoryManager.getPoolAllocator()); // Compute the middle-phase collision detection between the two shapes NarrowPhaseInfo* narrowPhaseInfo = computeMiddlePhaseForProxyShapes(&pair); @@ -866,7 +873,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c // Use the narrow-phase collision detection algorithm to check // if there really is a collision. If a collision occurs, the // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mPoolAllocator)) { + if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { // Add the contact points as a potential contact manifold into the pair narrowPhaseInfo->addContactPointsAsPotentialContactManifold(); @@ -880,7 +887,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c currentNarrowPhaseInfo->~NarrowPhaseInfo(); // Release the allocated memory - mPoolAllocator.release(currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); } // Process the potential contacts @@ -889,7 +896,7 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c if (pair.hasContacts()) { // Report the contacts to the user - CollisionCallback::CollisionCallbackInfo collisionInfo(&pair, mPoolAllocator); + CollisionCallback::CollisionCallbackInfo collisionInfo(&pair, mMemoryManager); callback->notifyContact(collisionInfo); } } @@ -920,8 +927,8 @@ void CollisionDetection::testCollision(CollisionCallback* callback) { OverlappingPair* originalPair = it->second; // Create a new overlapping pair so that we do not work on the original one - OverlappingPair pair(originalPair->getShape1(), originalPair->getShape2(), mPoolAllocator, - mPoolAllocator); + OverlappingPair pair(originalPair->getShape1(), originalPair->getShape2(), mMemoryManager.getPoolAllocator(), + mMemoryManager.getPoolAllocator()); ProxyShape* shape1 = pair.getShape1(); ProxyShape* shape2 = pair.getShape2(); @@ -950,7 +957,7 @@ void CollisionDetection::testCollision(CollisionCallback* callback) { // Use the narrow-phase collision detection algorithm to check // if there really is a collision. If a collision occurs, the // notifyContact() callback method will be called. - if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mPoolAllocator)) { + if (narrowPhaseAlgorithm->testCollision(narrowPhaseInfo, true, mMemoryManager.getPoolAllocator())) { // Add the contact points as a potential contact manifold into the pair narrowPhaseInfo->addContactPointsAsPotentialContactManifold(); @@ -964,7 +971,7 @@ void CollisionDetection::testCollision(CollisionCallback* callback) { currentNarrowPhaseInfo->~NarrowPhaseInfo(); // Release the allocated memory - mPoolAllocator.release(currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, currentNarrowPhaseInfo, sizeof(NarrowPhaseInfo)); } // Process the potential contacts @@ -973,7 +980,7 @@ void CollisionDetection::testCollision(CollisionCallback* callback) { if (pair.hasContacts()) { // Report the contacts to the user - CollisionCallback::CollisionCallbackInfo collisionInfo(&pair, mPoolAllocator); + CollisionCallback::CollisionCallbackInfo collisionInfo(&pair, mMemoryManager); callback->notifyContact(collisionInfo); } } @@ -996,12 +1003,6 @@ EventListener* CollisionDetection::getWorldEventListener() { return mWorld->mEventListener; } -// Return a reference to the world memory allocator -PoolAllocator& CollisionDetection::getWorldMemoryAllocator() { - return mWorld->mPoolAllocator; -} - - // Return the world-space AABB of a given proxy shape const AABB CollisionDetection::getWorldAABB(const ProxyShape* proxyShape) const { assert(proxyShape->mBroadPhaseID > -1); diff --git a/src/collision/CollisionDetection.h b/src/collision/CollisionDetection.h index d728a95f..6aeac709 100644 --- a/src/collision/CollisionDetection.h +++ b/src/collision/CollisionDetection.h @@ -32,8 +32,7 @@ #include "engine/OverlappingPair.h" #include "engine/EventListener.h" #include "narrowphase/DefaultCollisionDispatch.h" -#include "memory/PoolAllocator.h" -#include "memory/SingleFrameAllocator.h" +#include "memory/MemoryManager.h" #include "constraint/ContactPoint.h" #include #include @@ -62,6 +61,9 @@ class CollisionDetection { // -------------------- Attributes -------------------- // + /// Memory manager + MemoryManager& mMemoryManager; + /// Collision Detection Dispatch configuration CollisionDispatch* mCollisionDispatch; @@ -71,12 +73,6 @@ class CollisionDetection { /// Collision detection matrix (algorithms to use) NarrowPhaseAlgorithm* mCollisionMatrix[NB_COLLISION_SHAPE_TYPES][NB_COLLISION_SHAPE_TYPES]; - /// Reference to the memory allocator - PoolAllocator& mPoolAllocator; - - /// Reference to the single frame memory allocator - SingleFrameAllocator& mSingleFrameAllocator; - /// Pointer to the physics world CollisionWorld* mWorld; @@ -133,7 +129,7 @@ class CollisionDetection { void addAllContactManifoldsToBodies(); /// Compute the concave vs convex middle-phase algorithm for a given pair of bodies - void computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, Allocator& allocator, + void computeConvexVsConcaveMiddlePhase(OverlappingPair* pair, MemoryAllocator& allocator, NarrowPhaseInfo** firstNarrowPhaseInfo); /// Compute the middle-phase collision detection between two proxy shapes @@ -156,7 +152,7 @@ class CollisionDetection { // -------------------- Methods -------------------- // /// Constructor - CollisionDetection(CollisionWorld* world, PoolAllocator& memoryAllocator, SingleFrameAllocator& singleFrameAllocator); + CollisionDetection(CollisionWorld* world, MemoryManager& memoryManager); /// Destructor ~CollisionDetection() = default; @@ -223,9 +219,6 @@ class CollisionDetection { /// Return the world event listener EventListener* getWorldEventListener(); - /// Return a reference to the world memory allocator - PoolAllocator& getWorldMemoryAllocator(); - #ifdef IS_PROFILING_ACTIVE /// Set the profiler diff --git a/src/collision/ContactManifold.cpp b/src/collision/ContactManifold.cpp index c2d60422..ba1bcb1e 100644 --- a/src/collision/ContactManifold.cpp +++ b/src/collision/ContactManifold.cpp @@ -30,7 +30,7 @@ using namespace reactphysics3d; // Constructor -ContactManifold::ContactManifold(const ContactManifoldInfo* manifoldInfo, ProxyShape* shape1, ProxyShape* shape2, Allocator& memoryAllocator) +ContactManifold::ContactManifold(const ContactManifoldInfo* manifoldInfo, ProxyShape* shape1, ProxyShape* shape2, MemoryAllocator& memoryAllocator) : mShape1(shape1), mShape2(shape2), mContactPoints(nullptr), mNbContactPoints(0), mFrictionImpulse1(0.0), mFrictionImpulse2(0.0), mFrictionTwistImpulse(0.0), mIsAlreadyInIsland(false), diff --git a/src/collision/ContactManifold.h b/src/collision/ContactManifold.h index 8303f35c..f513ad82 100644 --- a/src/collision/ContactManifold.h +++ b/src/collision/ContactManifold.h @@ -129,7 +129,7 @@ class ContactManifold { bool mIsAlreadyInIsland; /// Reference to the memory allocator - Allocator& mMemoryAllocator; + MemoryAllocator& mMemoryAllocator; /// Pointer to the next contact manifold in the linked-list ContactManifold* mNext; @@ -217,7 +217,7 @@ class ContactManifold { /// Constructor ContactManifold(const ContactManifoldInfo* manifoldInfo, ProxyShape* shape1, ProxyShape* shape2, - Allocator& memoryAllocator); + MemoryAllocator& memoryAllocator); /// Destructor ~ContactManifold(); diff --git a/src/collision/ContactManifoldInfo.cpp b/src/collision/ContactManifoldInfo.cpp index 6740fe4f..a28e3817 100644 --- a/src/collision/ContactManifoldInfo.cpp +++ b/src/collision/ContactManifoldInfo.cpp @@ -29,7 +29,7 @@ using namespace reactphysics3d; // Constructor -ContactManifoldInfo::ContactManifoldInfo(Allocator& allocator) +ContactManifoldInfo::ContactManifoldInfo(MemoryAllocator& allocator) : mContactPointsList(nullptr), mNbContactPoints(0), mNext(nullptr), mAllocator(allocator) { } diff --git a/src/collision/ContactManifoldInfo.h b/src/collision/ContactManifoldInfo.h index 4126f4c8..b2687da5 100644 --- a/src/collision/ContactManifoldInfo.h +++ b/src/collision/ContactManifoldInfo.h @@ -28,7 +28,7 @@ // Libraries #include "collision/ContactPointInfo.h" -#include "memory/Allocator.h" +#include "memory/MemoryAllocator.h" /// ReactPhysics3D namespace namespace reactphysics3d { @@ -57,14 +57,14 @@ class ContactManifoldInfo { ContactManifoldInfo* mNext; /// Reference the the memory allocator where the contact point infos have been allocated - Allocator& mAllocator; + MemoryAllocator& mAllocator; public: // -------------------- Methods -------------------- // /// Constructor - ContactManifoldInfo(Allocator& allocator); + ContactManifoldInfo(MemoryAllocator& allocator); /// Destructor ~ContactManifoldInfo(); diff --git a/src/collision/ContactManifoldSet.cpp b/src/collision/ContactManifoldSet.cpp index 5f70bbc0..c63e6a11 100644 --- a/src/collision/ContactManifoldSet.cpp +++ b/src/collision/ContactManifoldSet.cpp @@ -30,7 +30,7 @@ using namespace reactphysics3d; // Constructor ContactManifoldSet::ContactManifoldSet(ProxyShape* shape1, ProxyShape* shape2, - Allocator& memoryAllocator) + MemoryAllocator& memoryAllocator) : mNbManifolds(0), mShape1(shape1), mShape2(shape2), mMemoryAllocator(memoryAllocator), mManifolds(nullptr) { diff --git a/src/collision/ContactManifoldSet.h b/src/collision/ContactManifoldSet.h index 13d27b70..56b09b04 100644 --- a/src/collision/ContactManifoldSet.h +++ b/src/collision/ContactManifoldSet.h @@ -61,7 +61,7 @@ class ContactManifoldSet { ProxyShape* mShape2; /// Reference to the memory allocator for the contact manifolds - Allocator& mMemoryAllocator; + MemoryAllocator& mMemoryAllocator; /// Contact manifolds of the set ContactManifold* mManifolds; @@ -95,7 +95,7 @@ class ContactManifoldSet { /// Constructor ContactManifoldSet(ProxyShape* shape1, ProxyShape* shape2, - Allocator& memoryAllocator); + MemoryAllocator& memoryAllocator); /// Destructor ~ContactManifoldSet(); diff --git a/src/collision/HalfEdgeStructure.h b/src/collision/HalfEdgeStructure.h index e398913f..15658a93 100644 --- a/src/collision/HalfEdgeStructure.h +++ b/src/collision/HalfEdgeStructure.h @@ -54,7 +54,7 @@ class HalfEdgeStructure { List faceVertices; // Index of the vertices of the face /// Constructor - Face(Allocator& allocator) : faceVertices(allocator) {} + Face(MemoryAllocator& allocator) : faceVertices(allocator) {} /// Constructor Face(List vertices) : faceVertices(vertices) {} @@ -71,7 +71,7 @@ class HalfEdgeStructure { private: /// Reference to a memory allocator - Allocator& mAllocator; + MemoryAllocator& mAllocator; /// All the faces List mFaces; @@ -85,7 +85,7 @@ class HalfEdgeStructure { public: /// Constructor - HalfEdgeStructure(Allocator& allocator, uint facesCapacity, uint verticesCapacity, + HalfEdgeStructure(MemoryAllocator& allocator, uint facesCapacity, uint verticesCapacity, uint edgesCapacity) :mAllocator(allocator), mFaces(allocator, facesCapacity), mVertices(allocator, verticesCapacity), mEdges(allocator, edgesCapacity) {} diff --git a/src/collision/MiddlePhaseTriangleCallback.h b/src/collision/MiddlePhaseTriangleCallback.h index e04d7a9c..b4798a2c 100644 --- a/src/collision/MiddlePhaseTriangleCallback.h +++ b/src/collision/MiddlePhaseTriangleCallback.h @@ -56,7 +56,7 @@ class MiddlePhaseTriangleCallback : public TriangleCallback { const ConcaveShape* mConcaveShape; /// Reference to the single-frame memory allocator - Allocator& mAllocator; + MemoryAllocator& mAllocator; #ifdef IS_PROFILING_ACTIVE @@ -74,7 +74,7 @@ class MiddlePhaseTriangleCallback : public TriangleCallback { MiddlePhaseTriangleCallback(OverlappingPair* overlappingPair, ProxyShape* concaveProxyShape, ProxyShape* convexProxyShape, const ConcaveShape* concaveShape, - Allocator& allocator) + MemoryAllocator& allocator) :mOverlappingPair(overlappingPair), mConcaveProxyShape(concaveProxyShape), mConvexProxyShape(convexProxyShape), mConcaveShape(concaveShape), mAllocator(allocator), narrowPhaseInfoList(nullptr) { diff --git a/src/collision/NarrowPhaseInfo.cpp b/src/collision/NarrowPhaseInfo.cpp index 0189db99..2c7a226c 100644 --- a/src/collision/NarrowPhaseInfo.cpp +++ b/src/collision/NarrowPhaseInfo.cpp @@ -35,7 +35,7 @@ using namespace reactphysics3d; // Constructor NarrowPhaseInfo::NarrowPhaseInfo(OverlappingPair* pair, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, - const Transform& shape2Transform, Allocator& shapeAllocator) + const Transform& shape2Transform, MemoryAllocator& shapeAllocator) : overlappingPair(pair), collisionShape1(shape1), collisionShape2(shape2), shape1ToWorldTransform(shape1Transform), shape2ToWorldTransform(shape2Transform), contactPoints(nullptr), next(nullptr), collisionShapeAllocator(shapeAllocator) { @@ -68,7 +68,7 @@ void NarrowPhaseInfo::addContactPoint(const Vector3& contactNormal, decimal penD assert(penDepth > decimal(0.0)); // Get the memory allocator - Allocator& allocator = overlappingPair->getTemporaryAllocator(); + MemoryAllocator& allocator = overlappingPair->getTemporaryAllocator(); // Create the contact point info ContactPointInfo* contactPointInfo = new (allocator.allocate(sizeof(ContactPointInfo))) @@ -89,7 +89,7 @@ void NarrowPhaseInfo::addContactPointsAsPotentialContactManifold() { void NarrowPhaseInfo::resetContactPoints() { // Get the memory allocator - Allocator& allocator = overlappingPair->getTemporaryAllocator(); + MemoryAllocator& allocator = overlappingPair->getTemporaryAllocator(); // For each remaining contact point info ContactPointInfo* element = contactPoints; diff --git a/src/collision/NarrowPhaseInfo.h b/src/collision/NarrowPhaseInfo.h index b732480c..f9ea1ac9 100644 --- a/src/collision/NarrowPhaseInfo.h +++ b/src/collision/NarrowPhaseInfo.h @@ -67,12 +67,12 @@ struct NarrowPhaseInfo { NarrowPhaseInfo* next; /// Memory allocator for the collision shape (Used to release TriangleShape memory in destructor) - Allocator& collisionShapeAllocator; + MemoryAllocator& collisionShapeAllocator; /// Constructor NarrowPhaseInfo(OverlappingPair* pair, CollisionShape* shape1, CollisionShape* shape2, const Transform& shape1Transform, - const Transform& shape2Transform, Allocator& shapeAllocator); + const Transform& shape2Transform, MemoryAllocator& shapeAllocator); /// Destructor ~NarrowPhaseInfo(); diff --git a/src/collision/PolyhedronMesh.cpp b/src/collision/PolyhedronMesh.cpp index 08a84e7d..64db474e 100644 --- a/src/collision/PolyhedronMesh.cpp +++ b/src/collision/PolyhedronMesh.cpp @@ -36,7 +36,7 @@ using namespace reactphysics3d; * @param polygonVertexArray Pointer to the array of polygons and their vertices */ PolyhedronMesh::PolyhedronMesh(PolygonVertexArray* polygonVertexArray) - : mHalfEdgeStructure(MemoryManager::getDefaultAllocator(), + : mHalfEdgeStructure(MemoryManager::getBaseAllocator(), polygonVertexArray->getNbFaces(), polygonVertexArray->getNbVertices(), (polygonVertexArray->getNbFaces() + polygonVertexArray->getNbVertices() - 2) * 2) { @@ -75,7 +75,7 @@ void PolyhedronMesh::createHalfEdgeStructure() { // Get the polygon face PolygonVertexArray::PolygonFace* face = mPolygonVertexArray->getPolygonFace(f); - List faceVertices(MemoryManager::getDefaultAllocator(), face->nbVertices); + List faceVertices(MemoryManager::getBaseAllocator(), face->nbVertices); // For each vertex of the face for (uint v=0; v < face->nbVertices; v++) { diff --git a/src/collision/ProxyShape.cpp b/src/collision/ProxyShape.cpp index f782b2a8..8847d094 100644 --- a/src/collision/ProxyShape.cpp +++ b/src/collision/ProxyShape.cpp @@ -35,9 +35,9 @@ using namespace reactphysics3d; * @param transform Transformation from collision shape local-space to body local-space * @param mass Mass of the collision shape (in kilograms) */ -ProxyShape::ProxyShape(CollisionBody* body, CollisionShape* shape, const Transform& transform, decimal mass, Allocator& allocator) - :mBody(body), mCollisionShape(shape), mLocalToBodyTransform(transform), mMass(mass), - mNext(nullptr), mBroadPhaseID(-1), mCollisionCategoryBits(0x0001), mCollideWithMaskBits(0xFFFF), mAllocator(allocator) { +ProxyShape::ProxyShape(CollisionBody* body, CollisionShape* shape, const Transform& transform, decimal mass, MemoryManager& memoryManager) + :mMemoryManager(memoryManager), mBody(body), mCollisionShape(shape), mLocalToBodyTransform(transform), mMass(mass), + mNext(nullptr), mBroadPhaseID(-1), mCollisionCategoryBits(0x0001), mCollideWithMaskBits(0xFFFF) { } @@ -76,7 +76,7 @@ bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) { worldToLocalTransform * ray.point2, ray.maxFraction); - bool isHit = mCollisionShape->raycast(rayLocal, raycastInfo, this, mAllocator); + bool isHit = mCollisionShape->raycast(rayLocal, raycastInfo, this, mMemoryManager.getPoolAllocator()); // Convert the raycast info into world-space raycastInfo.worldPoint = localToWorldTransform * raycastInfo.worldPoint; diff --git a/src/collision/ProxyShape.h b/src/collision/ProxyShape.h index 0ba34698..0da79e28 100644 --- a/src/collision/ProxyShape.h +++ b/src/collision/ProxyShape.h @@ -29,6 +29,7 @@ // Libraries #include "body/CollisionBody.h" #include "shapes/CollisionShape.h" +#include "memory/MemoryManager.h" namespace reactphysics3d { @@ -48,6 +49,9 @@ class ProxyShape { // -------------------- Attributes -------------------- // + /// Reference to the memory manager + MemoryManager& mMemoryManager; + /// Pointer to the parent body CollisionBody* mBody; @@ -82,9 +86,6 @@ class ProxyShape { /// proxy shape will collide with every collision categories by default. unsigned short mCollideWithMaskBits; - /// Memory allocator - Allocator& mAllocator; - #ifdef IS_PROFILING_ACTIVE /// Pointer to the profiler @@ -103,7 +104,7 @@ class ProxyShape { /// Constructor ProxyShape(CollisionBody* body, CollisionShape* shape, - const Transform& transform, decimal mass, Allocator& allocator); + const Transform& transform, decimal mass, MemoryManager& memoryManager); /// Destructor virtual ~ProxyShape(); diff --git a/src/collision/broadphase/BroadPhaseAlgorithm.cpp b/src/collision/broadphase/BroadPhaseAlgorithm.cpp index c1484434..8998859e 100644 --- a/src/collision/broadphase/BroadPhaseAlgorithm.cpp +++ b/src/collision/broadphase/BroadPhaseAlgorithm.cpp @@ -185,14 +185,14 @@ void BroadPhaseAlgorithm::reportAllShapesOverlappingWithAABB(const AABB& aabb, } // Compute all the overlapping pairs of collision shapes -void BroadPhaseAlgorithm::computeOverlappingPairs(Allocator& allocator) { +void BroadPhaseAlgorithm::computeOverlappingPairs(MemoryManager& memoryManager) { // TODO : Try to see if we can allocate potential pairs in single frame allocator // Reset the potential overlapping pairs mNbPotentialPairs = 0; - LinkedList overlappingNodes(allocator); + LinkedList overlappingNodes(memoryManager.getPoolAllocator()); // For all collision shapes that have moved (or have been created) during the // last simulation step diff --git a/src/collision/broadphase/BroadPhaseAlgorithm.h b/src/collision/broadphase/BroadPhaseAlgorithm.h index 7e1ff262..30a67920 100644 --- a/src/collision/broadphase/BroadPhaseAlgorithm.h +++ b/src/collision/broadphase/BroadPhaseAlgorithm.h @@ -210,7 +210,7 @@ class BroadPhaseAlgorithm { void reportAllShapesOverlappingWithAABB(const AABB& aabb, LinkedList& overlappingNodes) const; /// Compute all the overlapping pairs of collision shapes - void computeOverlappingPairs(Allocator& allocator); + void computeOverlappingPairs(MemoryManager& memoryManager); /// Return the proxy shape corresponding to the broad-phase node id in parameter ProxyShape* getProxyShapeForBroadPhaseId(int broadPhaseId) const; diff --git a/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.cpp b/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.cpp index bf9eefc2..dce9b04b 100755 --- a/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.cpp +++ b/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.cpp @@ -34,7 +34,7 @@ using namespace reactphysics3d; // This technique is based on the "Robust Contact Creation for Physics Simulations" presentation // by Dirk Gregorius. bool CapsuleVsCapsuleAlgorithm::testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, - Allocator& memoryAllocator) { + MemoryAllocator& memoryAllocator) { assert(narrowPhaseInfo->collisionShape1->getType() == CollisionShapeType::CAPSULE); assert(narrowPhaseInfo->collisionShape2->getType() == CollisionShapeType::CAPSULE); diff --git a/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h b/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h index df9a8854..b122ca14 100644 --- a/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h +++ b/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h @@ -61,7 +61,7 @@ class CapsuleVsCapsuleAlgorithm : public NarrowPhaseAlgorithm { CapsuleVsCapsuleAlgorithm& operator=(const CapsuleVsCapsuleAlgorithm& algorithm) = delete; /// Compute the narrow-phase collision detection between two capsules - virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, Allocator& memoryAllocator) override; + virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, MemoryAllocator& memoryAllocator) override; }; } diff --git a/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.cpp b/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.cpp index f943312b..33a381f0 100644 --- a/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.cpp +++ b/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.cpp @@ -38,7 +38,7 @@ using namespace reactphysics3d; // This technique is based on the "Robust Contact Creation for Physics Simulations" presentation // by Dirk Gregorius. bool CapsuleVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, - Allocator& memoryAllocator) { + MemoryAllocator& memoryAllocator) { // First, we run the GJK algorithm GJKAlgorithm gjkAlgorithm; diff --git a/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h b/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h index d7f96d63..58bb14fb 100644 --- a/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h +++ b/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h @@ -61,7 +61,7 @@ class CapsuleVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm { CapsuleVsConvexPolyhedronAlgorithm& operator=(const CapsuleVsConvexPolyhedronAlgorithm& algorithm) = delete; /// Compute the narrow-phase collision detection between a capsule and a polyhedron - virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, Allocator& memoryAllocator) override; + virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, MemoryAllocator& memoryAllocator) override; }; } diff --git a/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.cpp b/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.cpp index 5cf10b17..375814cd 100644 --- a/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.cpp +++ b/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.cpp @@ -35,7 +35,7 @@ using namespace reactphysics3d; // This technique is based on the "Robust Contact Creation for Physics Simulations" presentation // by Dirk Gregorius. bool ConvexPolyhedronVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, - Allocator& memoryAllocator) { + MemoryAllocator& memoryAllocator) { // Run the SAT algorithm to find the separating axis and compute contact point SATAlgorithm satAlgorithm(memoryAllocator); diff --git a/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h b/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h index 204bc269..ddd10585 100644 --- a/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h +++ b/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h @@ -61,7 +61,7 @@ class ConvexPolyhedronVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm ConvexPolyhedronVsConvexPolyhedronAlgorithm& operator=(const ConvexPolyhedronVsConvexPolyhedronAlgorithm& algorithm) = delete; /// Compute the narrow-phase collision detection between two convex polyhedra - virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, Allocator& memoryAllocator) override; + virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, MemoryAllocator& memoryAllocator) override; }; } diff --git a/src/collision/narrowphase/NarrowPhaseAlgorithm.h b/src/collision/narrowphase/NarrowPhaseAlgorithm.h index 40d3fbc6..3088d874 100644 --- a/src/collision/narrowphase/NarrowPhaseAlgorithm.h +++ b/src/collision/narrowphase/NarrowPhaseAlgorithm.h @@ -92,7 +92,7 @@ class NarrowPhaseAlgorithm { /// Compute a contact info if the two bounding volumes collide virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, - Allocator& memoryAllocator)=0; + MemoryAllocator& memoryAllocator)=0; #ifdef IS_PROFILING_ACTIVE diff --git a/src/collision/narrowphase/SAT/SATAlgorithm.cpp b/src/collision/narrowphase/SAT/SATAlgorithm.cpp index 1992cbc7..66be7d06 100644 --- a/src/collision/narrowphase/SAT/SATAlgorithm.cpp +++ b/src/collision/narrowphase/SAT/SATAlgorithm.cpp @@ -45,7 +45,7 @@ using namespace reactphysics3d; const decimal SATAlgorithm::SAME_SEPARATING_AXIS_BIAS = decimal(0.001); // Constructor -SATAlgorithm::SATAlgorithm(Allocator& memoryAllocator) : mMemoryAllocator(memoryAllocator) { +SATAlgorithm::SATAlgorithm(MemoryAllocator& memoryAllocator) : mMemoryAllocator(memoryAllocator) { } diff --git a/src/collision/narrowphase/SAT/SATAlgorithm.h b/src/collision/narrowphase/SAT/SATAlgorithm.h index 52884f8e..0402067f 100644 --- a/src/collision/narrowphase/SAT/SATAlgorithm.h +++ b/src/collision/narrowphase/SAT/SATAlgorithm.h @@ -51,7 +51,7 @@ class SATAlgorithm { static const decimal SAME_SEPARATING_AXIS_BIAS; /// Memory allocator - Allocator& mMemoryAllocator; + MemoryAllocator& mMemoryAllocator; #ifdef IS_PROFILING_ACTIVE @@ -115,7 +115,7 @@ class SATAlgorithm { // -------------------- Methods -------------------- // /// Constructor - SATAlgorithm(Allocator& memoryAllocator); + SATAlgorithm(MemoryAllocator& memoryAllocator); /// Destructor ~SATAlgorithm() = default; diff --git a/src/collision/narrowphase/SphereVsCapsuleAlgorithm.cpp b/src/collision/narrowphase/SphereVsCapsuleAlgorithm.cpp index f5bfc11d..2e86dfe3 100755 --- a/src/collision/narrowphase/SphereVsCapsuleAlgorithm.cpp +++ b/src/collision/narrowphase/SphereVsCapsuleAlgorithm.cpp @@ -35,7 +35,7 @@ using namespace reactphysics3d; // This technique is based on the "Robust Contact Creation for Physics Simulations" presentation // by Dirk Gregorius. bool SphereVsCapsuleAlgorithm::testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, - Allocator& memoryAllocator) { + MemoryAllocator& memoryAllocator) { bool isSphereShape1 = narrowPhaseInfo->collisionShape1->getType() == CollisionShapeType::SPHERE; diff --git a/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h b/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h index b51bba57..c7c4b39e 100644 --- a/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h +++ b/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h @@ -61,7 +61,7 @@ class SphereVsCapsuleAlgorithm : public NarrowPhaseAlgorithm { SphereVsCapsuleAlgorithm& operator=(const SphereVsCapsuleAlgorithm& algorithm) = delete; /// Compute the narrow-phase collision detection between a sphere and a capsule - virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, Allocator& memoryAllocator) override; + virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, MemoryAllocator& memoryAllocator) override; }; } diff --git a/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.cpp b/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.cpp index 6cc3e578..8d4f562c 100644 --- a/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.cpp +++ b/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.cpp @@ -35,7 +35,7 @@ using namespace reactphysics3d; // This technique is based on the "Robust Contact Creation for Physics Simulations" presentation // by Dirk Gregorius. bool SphereVsConvexPolyhedronAlgorithm::testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, - Allocator& memoryAllocator) { + MemoryAllocator& memoryAllocator) { assert(narrowPhaseInfo->collisionShape1->getType() == CollisionShapeType::CONVEX_POLYHEDRON || narrowPhaseInfo->collisionShape2->getType() == CollisionShapeType::CONVEX_POLYHEDRON); diff --git a/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h b/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h index 17055431..1929f43c 100644 --- a/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h +++ b/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h @@ -61,7 +61,7 @@ class SphereVsConvexPolyhedronAlgorithm : public NarrowPhaseAlgorithm { SphereVsConvexPolyhedronAlgorithm& operator=(const SphereVsConvexPolyhedronAlgorithm& algorithm) = delete; /// Compute the narrow-phase collision detection between a sphere and a convex polyhedron - virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, Allocator& memoryAllocator) override; + virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, MemoryAllocator& memoryAllocator) override; }; } diff --git a/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp b/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp index f8820106..8103380e 100755 --- a/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp +++ b/src/collision/narrowphase/SphereVsSphereAlgorithm.cpp @@ -31,7 +31,7 @@ using namespace reactphysics3d; bool SphereVsSphereAlgorithm::testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, - Allocator& memoryAllocator) { + MemoryAllocator& memoryAllocator) { assert(narrowPhaseInfo->collisionShape1->getType() == CollisionShapeType::SPHERE); assert(narrowPhaseInfo->collisionShape2->getType() == CollisionShapeType::SPHERE); diff --git a/src/collision/narrowphase/SphereVsSphereAlgorithm.h b/src/collision/narrowphase/SphereVsSphereAlgorithm.h index e0741ab8..142053c4 100644 --- a/src/collision/narrowphase/SphereVsSphereAlgorithm.h +++ b/src/collision/narrowphase/SphereVsSphereAlgorithm.h @@ -61,7 +61,7 @@ class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm { SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm) = delete; /// Compute a contact info if the two bounding volume collide - virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, Allocator& memoryAllocator) override; + virtual bool testCollision(NarrowPhaseInfo* narrowPhaseInfo, bool reportContacts, MemoryAllocator& memoryAllocator) override; }; } diff --git a/src/collision/shapes/BoxShape.cpp b/src/collision/shapes/BoxShape.cpp index 079b15c5..c13e32f4 100644 --- a/src/collision/shapes/BoxShape.cpp +++ b/src/collision/shapes/BoxShape.cpp @@ -39,7 +39,7 @@ using namespace reactphysics3d; */ BoxShape::BoxShape(const Vector3& extent) : ConvexPolyhedronShape(CollisionShapeName::BOX), mExtent(extent), - mHalfEdgeStructure(MemoryManager::getDefaultAllocator(), 6, 8, 24) { + mHalfEdgeStructure(MemoryManager::getBaseAllocator(), 6, 8, 24) { assert(extent.x > decimal(0.0)); assert(extent.y > decimal(0.0)); @@ -55,7 +55,7 @@ BoxShape::BoxShape(const Vector3& extent) mHalfEdgeStructure.addVertex(6); mHalfEdgeStructure.addVertex(7); - DefaultAllocator& allocator = MemoryManager::getDefaultAllocator(); + MemoryAllocator& allocator = MemoryManager::getBaseAllocator(); // Faces List face0(allocator, 4); @@ -98,7 +98,7 @@ void BoxShape::computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const } // Raycast method with feedback information -bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const { +bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const { Vector3 rayDirection = ray.point2 - ray.point1; decimal tMin = DECIMAL_SMALLEST; diff --git a/src/collision/shapes/BoxShape.h b/src/collision/shapes/BoxShape.h index b3e094bd..2ebcdce1 100644 --- a/src/collision/shapes/BoxShape.h +++ b/src/collision/shapes/BoxShape.h @@ -64,7 +64,7 @@ class BoxShape : public ConvexPolyhedronShape { virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const override; /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const override; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const override; /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const override; diff --git a/src/collision/shapes/CapsuleShape.cpp b/src/collision/shapes/CapsuleShape.cpp index da29fede..3f89d090 100644 --- a/src/collision/shapes/CapsuleShape.cpp +++ b/src/collision/shapes/CapsuleShape.cpp @@ -85,7 +85,7 @@ bool CapsuleShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyS } // Raycast method with feedback information -bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const { +bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const { const Vector3 n = ray.point2 - ray.point1; diff --git a/src/collision/shapes/CapsuleShape.h b/src/collision/shapes/CapsuleShape.h index 0da2d1f4..7843f139 100644 --- a/src/collision/shapes/CapsuleShape.h +++ b/src/collision/shapes/CapsuleShape.h @@ -62,7 +62,7 @@ class CapsuleShape : public ConvexShape { virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const override; /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const override; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const override; /// Raycasting method between a ray one of the two spheres end cap of the capsule bool raycastWithSphereEndCap(const Vector3& point1, const Vector3& point2, diff --git a/src/collision/shapes/CollisionShape.h b/src/collision/shapes/CollisionShape.h index 4381b05c..8d84ab55 100644 --- a/src/collision/shapes/CollisionShape.h +++ b/src/collision/shapes/CollisionShape.h @@ -87,7 +87,7 @@ class CollisionShape { virtual bool testPointInside(const Vector3& worldPoint, ProxyShape* proxyShape) const=0; /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const=0; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const=0; /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const = 0; diff --git a/src/collision/shapes/ConcaveMeshShape.cpp b/src/collision/shapes/ConcaveMeshShape.cpp index 0b49f20c..8f215fc2 100644 --- a/src/collision/shapes/ConcaveMeshShape.cpp +++ b/src/collision/shapes/ConcaveMeshShape.cpp @@ -111,7 +111,7 @@ void ConcaveMeshShape::testAllTriangles(TriangleCallback& callback, const AABB& // Raycast method with feedback information /// Note that only the first triangle hit by the ray in the mesh will be returned, even if /// the ray hits many triangles. -bool ConcaveMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const { +bool ConcaveMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const { PROFILE("ConcaveMeshShape::raycast()", mProfiler); diff --git a/src/collision/shapes/ConcaveMeshShape.h b/src/collision/shapes/ConcaveMeshShape.h index 52d49a02..c8c91972 100644 --- a/src/collision/shapes/ConcaveMeshShape.h +++ b/src/collision/shapes/ConcaveMeshShape.h @@ -77,7 +77,7 @@ class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback { RaycastInfo& mRaycastInfo; const Ray& mRay; bool mIsHit; - Allocator& mAllocator; + MemoryAllocator& mAllocator; #ifdef IS_PROFILING_ACTIVE @@ -90,7 +90,7 @@ class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback { // Constructor ConcaveMeshRaycastCallback(const DynamicAABBTree& dynamicAABBTree, const ConcaveMeshShape& concaveMeshShape, - ProxyShape* proxyShape, RaycastInfo& raycastInfo, const Ray& ray, Allocator& allocator) + ProxyShape* proxyShape, RaycastInfo& raycastInfo, const Ray& ray, MemoryAllocator& allocator) : mDynamicAABBTree(dynamicAABBTree), mConcaveMeshShape(concaveMeshShape), mProxyShape(proxyShape), mRaycastInfo(raycastInfo), mRay(ray), mIsHit(false), mAllocator(allocator) { @@ -142,7 +142,7 @@ class ConcaveMeshShape : public ConcaveShape { // -------------------- Methods -------------------- // /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const override; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const override; /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const override; diff --git a/src/collision/shapes/ConvexMeshShape.cpp b/src/collision/shapes/ConvexMeshShape.cpp index 19ef5016..5b6c70d6 100644 --- a/src/collision/shapes/ConvexMeshShape.cpp +++ b/src/collision/shapes/ConvexMeshShape.cpp @@ -112,7 +112,7 @@ void ConvexMeshShape::recalculateBounds() { } // Raycast method with feedback information -bool ConvexMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const { +bool ConvexMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const { return proxyShape->mBody->mWorld.mCollisionDetection.mNarrowPhaseGJKAlgorithm.raycast( ray, proxyShape, raycastInfo); } diff --git a/src/collision/shapes/ConvexMeshShape.h b/src/collision/shapes/ConvexMeshShape.h index 1c33d919..44d01df4 100644 --- a/src/collision/shapes/ConvexMeshShape.h +++ b/src/collision/shapes/ConvexMeshShape.h @@ -77,7 +77,7 @@ class ConvexMeshShape : public ConvexPolyhedronShape { virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const override; /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const override; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const override; /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const override; diff --git a/src/collision/shapes/HeightFieldShape.cpp b/src/collision/shapes/HeightFieldShape.cpp index f067a827..badfb68d 100644 --- a/src/collision/shapes/HeightFieldShape.cpp +++ b/src/collision/shapes/HeightFieldShape.cpp @@ -212,7 +212,7 @@ void HeightFieldShape::computeMinMaxGridCoordinates(int* minCoords, int* maxCoor // Raycast method with feedback information /// Note that only the first triangle hit by the ray in the mesh will be returned, even if /// the ray hits many triangles. -bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const { +bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const { // TODO : Implement raycasting without using an AABB for the ray // but using a dynamic AABB tree or octree instead diff --git a/src/collision/shapes/HeightFieldShape.h b/src/collision/shapes/HeightFieldShape.h index 4190c3c7..fc587d4c 100644 --- a/src/collision/shapes/HeightFieldShape.h +++ b/src/collision/shapes/HeightFieldShape.h @@ -49,7 +49,7 @@ class TriangleOverlapCallback : public TriangleCallback { bool mIsHit; decimal mSmallestHitFraction; const HeightFieldShape& mHeightFieldShape; - Allocator& mAllocator; + MemoryAllocator& mAllocator; #ifdef IS_PROFILING_ACTIVE @@ -62,7 +62,7 @@ class TriangleOverlapCallback : public TriangleCallback { // Constructor TriangleOverlapCallback(const Ray& ray, ProxyShape* proxyShape, RaycastInfo& raycastInfo, - const HeightFieldShape& heightFieldShape, Allocator& allocator) + const HeightFieldShape& heightFieldShape, MemoryAllocator& allocator) : mRay(ray), mProxyShape(proxyShape), mRaycastInfo(raycastInfo), mHeightFieldShape (heightFieldShape), mAllocator(allocator) { mIsHit = false; @@ -144,7 +144,7 @@ class HeightFieldShape : public ConcaveShape { // -------------------- Methods -------------------- // /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const override; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const override; /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const override; diff --git a/src/collision/shapes/SphereShape.cpp b/src/collision/shapes/SphereShape.cpp index 7d155f97..3ad7afe7 100644 --- a/src/collision/shapes/SphereShape.cpp +++ b/src/collision/shapes/SphereShape.cpp @@ -41,7 +41,7 @@ SphereShape::SphereShape(decimal radius) } // Raycast method with feedback information -bool SphereShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const { +bool SphereShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const { const Vector3 m = ray.point1; decimal c = m.dot(m) - mMargin * mMargin; diff --git a/src/collision/shapes/SphereShape.h b/src/collision/shapes/SphereShape.h index 18883d79..90b20d2d 100644 --- a/src/collision/shapes/SphereShape.h +++ b/src/collision/shapes/SphereShape.h @@ -55,7 +55,7 @@ class SphereShape : public ConvexShape { virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const override; /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const override; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const override; /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const override; diff --git a/src/collision/shapes/TriangleShape.cpp b/src/collision/shapes/TriangleShape.cpp index 4a7eb013..2257c0e6 100644 --- a/src/collision/shapes/TriangleShape.cpp +++ b/src/collision/shapes/TriangleShape.cpp @@ -45,7 +45,7 @@ using namespace reactphysics3d; * @param margin The collision margin (in meters) around the collision shape */ TriangleShape::TriangleShape(const Vector3* vertices, const Vector3* verticesNormals, uint shapeId, - Allocator& allocator) + MemoryAllocator& allocator) : ConvexPolyhedronShape(CollisionShapeName::TRIANGLE), mFaces{HalfEdgeStructure::Face(allocator), HalfEdgeStructure::Face(allocator)} { mPoints[0] = vertices[0]; @@ -211,7 +211,7 @@ Vector3 TriangleShape::computeSmoothLocalContactNormalForTriangle(const Vector3& // Raycast method with feedback information /// This method use the line vs triangle raycasting technique described in /// Real-time Collision Detection by Christer Ericson. -bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, Allocator& allocator) const { +bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, MemoryAllocator& allocator) const { PROFILE("TriangleShape::raycast()", mProfiler); diff --git a/src/collision/shapes/TriangleShape.h b/src/collision/shapes/TriangleShape.h index 9a2c756e..23f26adc 100644 --- a/src/collision/shapes/TriangleShape.h +++ b/src/collision/shapes/TriangleShape.h @@ -92,7 +92,7 @@ class TriangleShape : public ConvexPolyhedronShape { /// Raycast method with feedback information virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - Allocator& allocator) const override; + MemoryAllocator& allocator) const override; /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const override; @@ -113,7 +113,7 @@ class TriangleShape : public ConvexPolyhedronShape { /// Constructor TriangleShape(const Vector3* vertices, const Vector3* verticesNormals, - uint shapeId, Allocator& allocator); + uint shapeId, MemoryAllocator& allocator); /// Destructor virtual ~TriangleShape() override = default; diff --git a/src/configuration.h b/src/configuration.h index a25c1502..96391e76 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -152,7 +152,7 @@ constexpr int NB_MAX_CONTACT_MANIFOLDS_CONCAVE_SHAPE = 3; constexpr decimal COS_ANGLE_SIMILAR_CONTACT_MANIFOLD = decimal(0.95); /// Size (in bytes) of the single frame allocator -constexpr size_t SIZE_SINGLE_FRAME_ALLOCATOR_BYTES = 15728640; // 15 Mb +constexpr size_t INIT_SINGLE_FRAME_ALLOCATOR_BYTES = 1048576; // 1Mb } diff --git a/src/containers/LinkedList.h b/src/containers/LinkedList.h index 281c134c..997035b7 100644 --- a/src/containers/LinkedList.h +++ b/src/containers/LinkedList.h @@ -27,7 +27,7 @@ #define REACTPHYSICS3D_LINKED_LIST_H // Libraries -#include "memory/Allocator.h" +#include "memory/MemoryAllocator.h" namespace reactphysics3d { @@ -64,14 +64,14 @@ class LinkedList { ListElement* mListHead; /// Memory allocator used to allocate the list elements - Allocator& mAllocator; + MemoryAllocator& mAllocator; public: // -------------------- Methods -------------------- // /// Constructor - LinkedList(Allocator& allocator) : mListHead(nullptr), mAllocator(allocator) { + LinkedList(MemoryAllocator& allocator) : mListHead(nullptr), mAllocator(allocator) { } diff --git a/src/containers/List.h b/src/containers/List.h index 71ae7ef7..176766a5 100644 --- a/src/containers/List.h +++ b/src/containers/List.h @@ -28,7 +28,7 @@ // Libraries #include "configuration.h" -#include "memory/Allocator.h" +#include "memory/MemoryAllocator.h" #include namespace reactphysics3d { @@ -54,7 +54,7 @@ class List { size_t mCapacity; /// Memory allocator - Allocator& mAllocator; + MemoryAllocator& mAllocator; // -------------------- Methods -------------------- // @@ -64,7 +64,7 @@ class List { // -------------------- Methods -------------------- // /// Constructor - List(Allocator& allocator, size_t capacity = 0) + List(MemoryAllocator& allocator, size_t capacity = 0) : mBuffer(nullptr), mSize(0), mCapacity(0), mAllocator(allocator) { if (capacity > 0) { diff --git a/src/engine/CollisionWorld.cpp b/src/engine/CollisionWorld.cpp index 8b29e4a1..da5bf609 100644 --- a/src/engine/CollisionWorld.cpp +++ b/src/engine/CollisionWorld.cpp @@ -33,8 +33,7 @@ using namespace std; // Constructor CollisionWorld::CollisionWorld() - : mSingleFrameAllocator(SIZE_SINGLE_FRAME_ALLOCATOR_BYTES), - mCollisionDetection(this, mPoolAllocator, mSingleFrameAllocator), mCurrentBodyID(0), + : mCollisionDetection(this, mMemoryManager), mCurrentBodyID(0), mEventListener(nullptr) { #ifdef IS_PROFILING_ACTIVE @@ -74,7 +73,8 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) { assert(bodyID < std::numeric_limits::max()); // Create the collision body - CollisionBody* collisionBody = new (mPoolAllocator.allocate(sizeof(CollisionBody))) + CollisionBody* collisionBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(CollisionBody))) CollisionBody(transform, *this, bodyID); assert(collisionBody != nullptr); @@ -111,7 +111,7 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) { mBodies.erase(collisionBody); // Free the object from the memory allocator - mPoolAllocator.release(collisionBody, sizeof(CollisionBody)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, collisionBody, sizeof(CollisionBody)); } // Return the next available body ID diff --git a/src/engine/CollisionWorld.h b/src/engine/CollisionWorld.h index ead42710..9f1fea58 100644 --- a/src/engine/CollisionWorld.h +++ b/src/engine/CollisionWorld.h @@ -39,8 +39,7 @@ #include "collision/CollisionDetection.h" #include "constraint/Joint.h" #include "constraint/ContactPoint.h" -#include "memory/DefaultAllocator.h" -#include "memory/PoolAllocator.h" +#include "memory/MemoryManager.h" #include "EventListener.h" /// Namespace reactphysics3d @@ -62,11 +61,8 @@ class CollisionWorld { // -------------------- Attributes -------------------- // - /// Pool Memory allocator - PoolAllocator mPoolAllocator; - - /// Single frame Memory allocator - SingleFrameAllocator mSingleFrameAllocator; + /// Memory manager + MemoryManager mMemoryManager; /// Reference to the collision detection CollisionDetection mCollisionDetection; diff --git a/src/engine/ContactSolver.cpp b/src/engine/ContactSolver.cpp index 6361badd..f4762c49 100644 --- a/src/engine/ContactSolver.cpp +++ b/src/engine/ContactSolver.cpp @@ -39,9 +39,9 @@ const decimal ContactSolver::BETA_SPLIT_IMPULSE = decimal(0.2); const decimal ContactSolver::SLOP = decimal(0.01); // Constructor -ContactSolver::ContactSolver(SingleFrameAllocator& allocator) - :mSplitLinearVelocities(nullptr), mSplitAngularVelocities(nullptr), - mContactConstraints(nullptr), mSingleFrameAllocator(allocator), +ContactSolver::ContactSolver(MemoryManager& memoryManager) + :mMemoryManager(memoryManager), mSplitLinearVelocities(nullptr), + mSplitAngularVelocities(nullptr), mContactConstraints(nullptr), mLinearVelocities(nullptr), mAngularVelocities(nullptr), mIsSplitImpulseActive(true) { @@ -75,10 +75,12 @@ void ContactSolver::init(Island** islands, uint nbIslands, decimal timeStep) { if (nbContactManifolds == 0 || nbContactPoints == 0) return; // TODO : Count exactly the number of constraints to allocate here - mContactPoints = static_cast(mSingleFrameAllocator.allocate(sizeof(ContactPointSolver) * nbContactPoints)); + mContactPoints = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + sizeof(ContactPointSolver) * nbContactPoints)); assert(mContactPoints != nullptr); - mContactConstraints = static_cast(mSingleFrameAllocator.allocate(sizeof(ContactManifoldSolver) * nbContactManifolds)); + mContactConstraints = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + sizeof(ContactManifoldSolver) * nbContactManifolds)); assert(mContactConstraints != nullptr); // For each island of the world diff --git a/src/engine/ContactSolver.h b/src/engine/ContactSolver.h index 05bd569c..8799a1ad 100644 --- a/src/engine/ContactSolver.h +++ b/src/engine/ContactSolver.h @@ -272,6 +272,10 @@ class ContactSolver { // -------------------- Attributes -------------------- // + /// Memory manager + MemoryManager& mMemoryManager; + + /// Split linear velocities for the position contact solver (split impulse) Vector3* mSplitLinearVelocities; @@ -293,9 +297,6 @@ class ContactSolver { /// Number of contact constraints uint mNbContactManifolds; - /// Single frame memory allocator - SingleFrameAllocator& mSingleFrameAllocator; - /// Array of linear velocities Vector3* mLinearVelocities; @@ -339,7 +340,7 @@ class ContactSolver { // -------------------- Methods -------------------- // /// Constructor - ContactSolver(SingleFrameAllocator& allocator); + ContactSolver(MemoryManager& memoryManager); /// Destructor ~ContactSolver() = default; diff --git a/src/engine/DynamicsWorld.cpp b/src/engine/DynamicsWorld.cpp index 054c4dc5..35b1ba04 100644 --- a/src/engine/DynamicsWorld.cpp +++ b/src/engine/DynamicsWorld.cpp @@ -41,7 +41,7 @@ using namespace std; */ DynamicsWorld::DynamicsWorld(const Vector3 &gravity) : CollisionWorld(), - mContactSolver(mSingleFrameAllocator), + mContactSolver(mMemoryManager), mNbVelocitySolverIterations(DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS), mNbPositionSolverIterations(DEFAULT_POSITION_SOLVER_NB_ITERATIONS), mIsSleepingEnabled(SLEEPING_ENABLED), mGravity(gravity), mTimeStep(decimal(1.0f / 60.0f)), @@ -147,7 +147,7 @@ void DynamicsWorld::update(decimal timeStep) { resetBodiesForceAndTorque(); // Reset the single frame memory allocator - mSingleFrameAllocator.reset(); + mMemoryManager.resetFrameAllocator(); } // Integrate position and orientation of the rigid bodies. @@ -236,12 +236,18 @@ void DynamicsWorld::initVelocityArrays() { // Allocate memory for the bodies velocity arrays uint nbBodies = mRigidBodies.size(); - mSplitLinearVelocities = static_cast(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3))); - mSplitAngularVelocities = static_cast(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3))); - mConstrainedLinearVelocities = static_cast(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3))); - mConstrainedAngularVelocities = static_cast(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3))); - mConstrainedPositions = static_cast(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3))); - mConstrainedOrientations = static_cast(mSingleFrameAllocator.allocate(nbBodies * sizeof(Quaternion))); + mSplitLinearVelocities = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + nbBodies * sizeof(Vector3))); + mSplitAngularVelocities = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + nbBodies * sizeof(Vector3))); + mConstrainedLinearVelocities = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + nbBodies * sizeof(Vector3))); + mConstrainedAngularVelocities = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + nbBodies * sizeof(Vector3))); + mConstrainedPositions = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + nbBodies * sizeof(Vector3))); + mConstrainedOrientations = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + nbBodies * sizeof(Quaternion))); assert(mSplitLinearVelocities != nullptr); assert(mSplitAngularVelocities != nullptr); assert(mConstrainedLinearVelocities != nullptr); @@ -412,8 +418,8 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) { assert(bodyID < std::numeric_limits::max()); // Create the rigid body - RigidBody* rigidBody = new (mPoolAllocator.allocate(sizeof(RigidBody))) RigidBody(transform, - *this, bodyID); + RigidBody* rigidBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(RigidBody))) RigidBody(transform, *this, bodyID); assert(rigidBody != nullptr); // Add the rigid body to the physics world @@ -459,7 +465,7 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) { mRigidBodies.erase(rigidBody); // Free the object from the memory allocator - mPoolAllocator.release(rigidBody, sizeof(RigidBody)); + mMemoryManager.release(MemoryManager::AllocationType::Pool, rigidBody, sizeof(RigidBody)); } // Create a joint between two bodies in the world and return a pointer to the new joint @@ -477,7 +483,8 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) { // Ball-and-Socket joint case JointType::BALLSOCKETJOINT: { - void* allocatedMemory = mPoolAllocator.allocate(sizeof(BallAndSocketJoint)); + void* allocatedMemory = mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(BallAndSocketJoint)); const BallAndSocketJointInfo& info = static_cast( jointInfo); newJoint = new (allocatedMemory) BallAndSocketJoint(info); @@ -487,7 +494,8 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) { // Slider joint case JointType::SLIDERJOINT: { - void* allocatedMemory = mPoolAllocator.allocate(sizeof(SliderJoint)); + void* allocatedMemory = mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(SliderJoint)); const SliderJointInfo& info = static_cast(jointInfo); newJoint = new (allocatedMemory) SliderJoint(info); break; @@ -496,7 +504,8 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) { // Hinge joint case JointType::HINGEJOINT: { - void* allocatedMemory = mPoolAllocator.allocate(sizeof(HingeJoint)); + void* allocatedMemory = mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(HingeJoint)); const HingeJointInfo& info = static_cast(jointInfo); newJoint = new (allocatedMemory) HingeJoint(info); break; @@ -505,7 +514,8 @@ Joint* DynamicsWorld::createJoint(const JointInfo& jointInfo) { // Fixed joint case JointType::FIXEDJOINT: { - void* allocatedMemory = mPoolAllocator.allocate(sizeof(FixedJoint)); + void* allocatedMemory = mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(FixedJoint)); const FixedJointInfo& info = static_cast(jointInfo); newJoint = new (allocatedMemory) FixedJoint(info); break; @@ -558,8 +568,8 @@ void DynamicsWorld::destroyJoint(Joint* joint) { mJoints.erase(joint); // Remove the joint from the joint list of the bodies involved in the joint - joint->mBody1->removeJointFromJointsList(mPoolAllocator, joint); - joint->mBody2->removeJointFromJointsList(mPoolAllocator, joint); + joint->mBody1->removeJointFromJointsList(mMemoryManager, joint); + joint->mBody2->removeJointFromJointsList(mMemoryManager, joint); size_t nbBytes = joint->getSizeInBytes(); @@ -567,7 +577,7 @@ void DynamicsWorld::destroyJoint(Joint* joint) { joint->~Joint(); // Release the allocated memory - mPoolAllocator.release(joint, nbBytes); + mMemoryManager.release(MemoryManager::AllocationType::Pool, joint, nbBytes); } // Add the joint to the list of joints of the two bodies involved in the joint @@ -576,13 +586,15 @@ void DynamicsWorld::addJointToBody(Joint* joint) { assert(joint != nullptr); // Add the joint at the beginning of the linked list of joints of the first body - void* allocatedMemory1 = mPoolAllocator.allocate(sizeof(JointListElement)); + void* allocatedMemory1 = mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(JointListElement)); JointListElement* jointListElement1 = new (allocatedMemory1) JointListElement(joint, joint->mBody1->mJointsList); joint->mBody1->mJointsList = jointListElement1; // Add the joint at the beginning of the linked list of joints of the second body - void* allocatedMemory2 = mPoolAllocator.allocate(sizeof(JointListElement)); + void* allocatedMemory2 = mMemoryManager.allocate(MemoryManager::AllocationType::Pool, + sizeof(JointListElement)); JointListElement* jointListElement2 = new (allocatedMemory2) JointListElement(joint, joint->mBody2->mJointsList); joint->mBody2->mJointsList = jointListElement2; @@ -603,7 +615,8 @@ void DynamicsWorld::computeIslands() { // Allocate and create the array of islands pointer. This memory is allocated // in the single frame allocator - mIslands = static_cast(mSingleFrameAllocator.allocate(sizeof(Island*) * nbBodies)); + mIslands = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + sizeof(Island*) * nbBodies)); mNbIslands = 0; int nbContactManifolds = 0; @@ -619,7 +632,8 @@ void DynamicsWorld::computeIslands() { // Create a stack (using an array) for the rigid bodies to visit during the Depth First Search size_t nbBytesStack = sizeof(RigidBody*) * nbBodies; - RigidBody** stackBodiesToVisit = static_cast(mSingleFrameAllocator.allocate(nbBytesStack)); + RigidBody** stackBodiesToVisit = static_cast(mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + nbBytesStack)); // For each rigid body of the world for (std::set::iterator it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) { @@ -642,9 +656,10 @@ void DynamicsWorld::computeIslands() { body->mIsAlreadyInIsland = true; // Create the new island - void* allocatedMemoryIsland = mSingleFrameAllocator.allocate(sizeof(Island)); + void* allocatedMemoryIsland = mMemoryManager.allocate(MemoryManager::AllocationType::Frame, + sizeof(Island)); mIslands[mNbIslands] = new (allocatedMemoryIsland) Island(nbBodies, nbContactManifolds, mJoints.size(), - mSingleFrameAllocator); + mMemoryManager); // While there are still some bodies to visit in the stack while (stackIndex > 0) { diff --git a/src/engine/Island.cpp b/src/engine/Island.cpp index 19eef304..34b65540 100644 --- a/src/engine/Island.cpp +++ b/src/engine/Island.cpp @@ -29,14 +29,17 @@ using namespace reactphysics3d; // Constructor -Island::Island(uint nbMaxBodies, uint nbMaxContactManifolds, uint nbMaxJoints, SingleFrameAllocator& allocator) +Island::Island(uint nbMaxBodies, uint nbMaxContactManifolds, uint nbMaxJoints, MemoryManager& memoryManager) : mBodies(nullptr), mContactManifolds(nullptr), mJoints(nullptr), mNbBodies(0), mNbContactManifolds(0), mNbJoints(0) { // Allocate memory for the arrays on the single frame allocator - mBodies = static_cast(allocator.allocate(sizeof(RigidBody*) * nbMaxBodies)); - mContactManifolds = static_cast(allocator.allocate(sizeof(ContactManifold*) * nbMaxContactManifolds)); - mJoints = static_cast(allocator.allocate(sizeof(Joint*) * nbMaxJoints)); + mBodies = static_cast(memoryManager.allocate(MemoryManager::AllocationType::Frame, + sizeof(RigidBody*) * nbMaxBodies)); + mContactManifolds = static_cast(memoryManager.allocate(MemoryManager::AllocationType::Frame, + sizeof(ContactManifold*) * nbMaxContactManifolds)); + mJoints = static_cast(memoryManager.allocate(MemoryManager::AllocationType::Frame, + sizeof(Joint*) * nbMaxJoints)); } // Destructor diff --git a/src/engine/Island.h b/src/engine/Island.h index 5f370004..ca1e6fdd 100644 --- a/src/engine/Island.h +++ b/src/engine/Island.h @@ -69,7 +69,7 @@ class Island { /// Constructor Island(uint nbMaxBodies, uint nbMaxContactManifolds, uint nbMaxJoints, - SingleFrameAllocator& allocator); + MemoryManager& memoryManager); /// Destructor ~Island(); diff --git a/src/engine/OverlappingPair.cpp b/src/engine/OverlappingPair.cpp index 431476ed..7a95be95 100644 --- a/src/engine/OverlappingPair.cpp +++ b/src/engine/OverlappingPair.cpp @@ -33,7 +33,7 @@ using namespace reactphysics3d; // Constructor OverlappingPair::OverlappingPair(ProxyShape* shape1, ProxyShape* shape2, - Allocator& persistentMemoryAllocator, Allocator& temporaryMemoryAllocator) + MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator) : mContactManifoldSet(shape1, shape2, persistentMemoryAllocator), mPotentialContactManifolds(nullptr), mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator) { diff --git a/src/engine/OverlappingPair.h b/src/engine/OverlappingPair.h index 8c65e633..f3631775 100644 --- a/src/engine/OverlappingPair.h +++ b/src/engine/OverlappingPair.h @@ -113,18 +113,18 @@ class OverlappingPair { ContactManifoldInfo* mPotentialContactManifolds; /// Persistent memory allocator - Allocator& mPersistentAllocator; + MemoryAllocator& mPersistentAllocator; /// Memory allocator used to allocated memory for the ContactManifoldInfo and ContactPointInfo - Allocator& mTempMemoryAllocator; + MemoryAllocator& mTempMemoryAllocator; public: // -------------------- Methods -------------------- // /// Constructor - OverlappingPair(ProxyShape* shape1, ProxyShape* shape2, Allocator& persistentMemoryAllocator, - Allocator& temporaryMemoryAllocator); + OverlappingPair(ProxyShape* shape1, ProxyShape* shape2, MemoryAllocator& persistentMemoryAllocator, + MemoryAllocator& temporaryMemoryAllocator); /// Destructor ~OverlappingPair(); @@ -157,7 +157,7 @@ class OverlappingPair { void addContactManifold(const ContactManifoldInfo* contactManifoldInfo); /// Return a reference to the temporary memory allocator - Allocator& getTemporaryAllocator(); + MemoryAllocator& getTemporaryAllocator(); /// Return true if one of the shapes of the pair is a concave shape bool hasConcaveShape() const; @@ -264,7 +264,7 @@ inline bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body } // Return a reference to the temporary memory allocator -inline Allocator& OverlappingPair::getTemporaryAllocator() { +inline MemoryAllocator& OverlappingPair::getTemporaryAllocator() { return mTempMemoryAllocator; } diff --git a/src/mathematics/mathematics_functions.cpp b/src/mathematics/mathematics_functions.cpp index 0d8994f4..9fa13083 100755 --- a/src/mathematics/mathematics_functions.cpp +++ b/src/mathematics/mathematics_functions.cpp @@ -225,7 +225,7 @@ decimal reactphysics3d::computePointToLineDistance(const Vector3& linePointA, co List reactphysics3d::clipSegmentWithPlanes(const Vector3& segA, const Vector3& segB, const List& planesPoints, const List& planesNormals, - Allocator& allocator) { + MemoryAllocator& allocator) { assert(planesPoints.size() == planesNormals.size()); @@ -303,7 +303,7 @@ List reactphysics3d::clipSegmentWithPlanes(const Vector3& segA, const V // Clip a polygon against multiple planes and return the clipped polygon vertices // This method implements the Sutherland–Hodgman clipping algorithm List reactphysics3d::clipPolygonWithPlanes(const List& polygonVertices, const List& planesPoints, - const List& planesNormals, Allocator& allocator) { + const List& planesNormals, MemoryAllocator& allocator) { assert(planesPoints.size() == planesNormals.size()); diff --git a/src/mathematics/mathematics_functions.h b/src/mathematics/mathematics_functions.h index 5081d741..eda0fdd3 100755 --- a/src/mathematics/mathematics_functions.h +++ b/src/mathematics/mathematics_functions.h @@ -115,11 +115,11 @@ decimal computePointToLineDistance(const Vector3& linePointA, const Vector3& lin List clipSegmentWithPlanes(const Vector3& segA, const Vector3& segB, const List& planesPoints, const List& planesNormals, - Allocator& allocator); + MemoryAllocator& allocator); /// Clip a polygon against multiple planes and return the clipped polygon vertices List clipPolygonWithPlanes(const List& polygonVertices, const List& planesPoints, - const List& planesNormals, Allocator& allocator); + const List& planesNormals, MemoryAllocator& allocator); /// Project a point onto a plane that is given by a point and its unit length normal Vector3 projectPointOntoPlane(const Vector3& point, const Vector3& planeNormal, const Vector3& planePoint); diff --git a/src/memory/DefaultAllocator.h b/src/memory/DefaultAllocator.h index 367171bd..ac4ddd04 100644 --- a/src/memory/DefaultAllocator.h +++ b/src/memory/DefaultAllocator.h @@ -27,7 +27,7 @@ #define REACTPHYSICS3D_DEFAULT_ALLOCATOR_H // Libraries -#include "memory/Allocator.h" +#include "memory/MemoryAllocator.h" #include /// ReactPhysics3D namespace @@ -37,13 +37,16 @@ namespace reactphysics3d { /** * This class represents a default memory allocator that uses default malloc/free methods */ -class DefaultAllocator : public Allocator { +class DefaultAllocator : public MemoryAllocator { public: /// Destructor virtual ~DefaultAllocator() = default; + /// Assignment operator + DefaultAllocator& operator=(DefaultAllocator& allocator) = default; + /// Allocate memory of a given size (in bytes) and return a pointer to the /// allocated memory. virtual void* allocate(size_t size) override { @@ -54,11 +57,6 @@ class DefaultAllocator : public Allocator { virtual void release(void* pointer, size_t size) override { free(pointer); } - - /// Return true if memory needs to be release with this allocator - virtual bool isReleaseNeeded() const override { - return true; - } }; } diff --git a/src/memory/Allocator.h b/src/memory/MemoryAllocator.h similarity index 87% rename from src/memory/Allocator.h rename to src/memory/MemoryAllocator.h index 0440a5c9..c0d86a33 100644 --- a/src/memory/Allocator.h +++ b/src/memory/MemoryAllocator.h @@ -23,8 +23,8 @@ * * ********************************************************************************/ -#ifndef REACTPHYSICS3D_ALLOCATOR_H -#define REACTPHYSICS3D_ALLOCATOR_H +#ifndef REACTPHYSICS3D_MEMORY_ALLOCATOR_H +#define REACTPHYSICS3D_MEMORY_ALLOCATOR_H // Libraries #include @@ -32,16 +32,22 @@ /// ReactPhysics3D namespace namespace reactphysics3d { -// Class Allocator +// Class MemoryAllocator /** * Abstract class with the basic interface of all the derived memory allocators */ -class Allocator { +class MemoryAllocator { public: + /// Constructor + MemoryAllocator() = default; + /// Destructor - virtual ~Allocator() = default; + virtual ~MemoryAllocator() = default; + + /// Assignment operator + MemoryAllocator& operator=(MemoryAllocator& allocator) = default; /// Allocate memory of a given size (in bytes) and return a pointer to the /// allocated memory. @@ -49,9 +55,6 @@ class Allocator { /// Release previously allocated memory. virtual void release(void* pointer, size_t size)=0; - - /// Return true if memory needs to be release with this allocator - virtual bool isReleaseNeeded() const=0; }; } diff --git a/src/memory/MemoryManager.cpp b/src/memory/MemoryManager.cpp index 85832cb1..99a32655 100644 --- a/src/memory/MemoryManager.cpp +++ b/src/memory/MemoryManager.cpp @@ -30,3 +30,5 @@ using namespace reactphysics3d; // Static variables DefaultAllocator MemoryManager::mDefaultAllocator; +MemoryAllocator* MemoryManager::mBaseAllocator = &mDefaultAllocator; + diff --git a/src/memory/MemoryManager.h b/src/memory/MemoryManager.h index 922a5a17..8d986a31 100644 --- a/src/memory/MemoryManager.h +++ b/src/memory/MemoryManager.h @@ -27,7 +27,10 @@ #define REACTPHYSICS3D_MEMORY_MANAGER_H // Libraries +#include "memory/MemoryAllocator.h" #include "memory/DefaultAllocator.h" +#include "memory/PoolAllocator.h" +#include "memory/SingleFrameAllocator.h" /// Namespace ReactPhysics3D namespace reactphysics3d { @@ -41,31 +44,98 @@ class MemoryManager { private: - /// Default memory allocator + /// Default malloc/free memory allocator static DefaultAllocator mDefaultAllocator; + /// Pointer to the base memory allocator to use + static MemoryAllocator* mBaseAllocator; + + /// Memory pool allocator + PoolAllocator mPoolAllocator; + + /// Single frame stack allocator + SingleFrameAllocator mSingleFrameAllocator; + public: /// Memory allocation types enum class AllocationType { - Default, // Default memory allocator + Base, // Base memory allocator Pool, // Memory pool allocator Frame, // Single frame memory allocator }; - /// Constructor - MemoryManager(); + /// Constructor + MemoryManager() = default; - /// Destructor - ~MemoryManager(); + /// Destructor + ~MemoryManager() = default; - /// Return the default memory allocator - static DefaultAllocator& getDefaultAllocator(); + /// Allocate memory of a given type + void* allocate(AllocationType allocationType, size_t size); + + /// Release previously allocated memory. + void release(AllocationType allocationType, void* pointer, size_t size); + + /// Return the pool allocator + PoolAllocator& getPoolAllocator(); + + /// Return the single frame stack allocator + SingleFrameAllocator& getSingleFrameAllocator(); + + /// Return the base memory allocator + static MemoryAllocator& getBaseAllocator(); + + /// Set the base memory allocator + static void setBaseAllocator(MemoryAllocator* memoryAllocator); + + /// Reset the single frame allocator + void resetFrameAllocator(); }; -// Return the default memory allocator -inline DefaultAllocator& MemoryManager::getDefaultAllocator() { - return mDefaultAllocator; +// Allocate memory of a given type +inline void* MemoryManager::allocate(AllocationType allocationType, size_t size) { + + switch (allocationType) { + case AllocationType::Base: return mBaseAllocator->allocate(size); break; + case AllocationType::Pool: return mPoolAllocator.allocate(size); break; + case AllocationType::Frame: return mSingleFrameAllocator.allocate(size); break; + } +} + +// Release previously allocated memory. +inline void MemoryManager::release(AllocationType allocationType, void* pointer, size_t size) { + + switch (allocationType) { + case AllocationType::Base: mBaseAllocator->release(pointer, size); break; + case AllocationType::Pool: mPoolAllocator.release(pointer, size); break; + case AllocationType::Frame: mSingleFrameAllocator.release(pointer, size); break; + } +} + +// Return the pool allocator +inline PoolAllocator& MemoryManager::getPoolAllocator() { + return mPoolAllocator; +} + +// Return the single frame stack allocator +inline SingleFrameAllocator& MemoryManager::getSingleFrameAllocator() { + return mSingleFrameAllocator; +} + +// Return the base memory allocator +inline MemoryAllocator& MemoryManager::getBaseAllocator() { + return *mBaseAllocator; +} + +// Set the base memory allocator +inline void MemoryManager::setBaseAllocator(MemoryAllocator* baseAllocator) { + mBaseAllocator = baseAllocator; +} + +// Reset the single frame allocator +inline void MemoryManager::resetFrameAllocator() { + mSingleFrameAllocator.reset(); } } diff --git a/src/memory/PoolAllocator.cpp b/src/memory/PoolAllocator.cpp index 53cee0a1..2a9507c4 100644 --- a/src/memory/PoolAllocator.cpp +++ b/src/memory/PoolAllocator.cpp @@ -25,6 +25,7 @@ // Libraries #include "PoolAllocator.h" +#include "MemoryManager.h" #include #include @@ -42,7 +43,7 @@ PoolAllocator::PoolAllocator() { mNbAllocatedMemoryBlocks = 64; mNbCurrentMemoryBlocks = 0; const size_t sizeToAllocate = mNbAllocatedMemoryBlocks * sizeof(MemoryBlock); - mMemoryBlocks = (MemoryBlock*) malloc(sizeToAllocate); + mMemoryBlocks = static_cast(MemoryManager::getBaseAllocator().allocate(sizeToAllocate)); memset(mMemoryBlocks, 0, sizeToAllocate); memset(mFreeMemoryUnits, 0, sizeof(mFreeMemoryUnits)); @@ -55,7 +56,7 @@ PoolAllocator::PoolAllocator() { // Initialize the array that contains the sizes the memory units that will // be allocated in each different heap - for (int i=0; i < NB_HEAPS; i++) { + for (uint i=0; i < NB_HEAPS; i++) { mUnitSizes[i] = (i+1) * 8; } @@ -82,16 +83,17 @@ PoolAllocator::~PoolAllocator() { // Release the memory allocated for each block for (uint i=0; i MAX_UNIT_SIZE) { - // Allocate memory using standard malloc() function - return malloc(size); + // Allocate memory using default allocation + return MemoryManager::getBaseAllocator().allocate(size); } // Get the index of the heap that will take care of the allocation request @@ -132,7 +134,7 @@ void* PoolAllocator::allocate(size_t size) { // Allocate more memory to contain the blocks MemoryBlock* currentMemoryBlocks = mMemoryBlocks; mNbAllocatedMemoryBlocks += 64; - mMemoryBlocks = (MemoryBlock*) malloc(mNbAllocatedMemoryBlocks * sizeof(MemoryBlock)); + mMemoryBlocks = static_cast(MemoryManager::getBaseAllocator().allocate(mNbAllocatedMemoryBlocks * sizeof(MemoryBlock))); memcpy(mMemoryBlocks, currentMemoryBlocks,mNbCurrentMemoryBlocks * sizeof(MemoryBlock)); memset(mMemoryBlocks + mNbCurrentMemoryBlocks, 0, 64 * sizeof(MemoryBlock)); free(currentMemoryBlocks); @@ -141,17 +143,22 @@ void* PoolAllocator::allocate(size_t size) { // Allocate a new memory blocks for the corresponding heap and divide it in many // memory units MemoryBlock* newBlock = mMemoryBlocks + mNbCurrentMemoryBlocks; - newBlock->memoryUnits = (MemoryUnit*) malloc(BLOCK_SIZE); + newBlock->memoryUnits = static_cast(MemoryManager::getBaseAllocator().allocate(BLOCK_SIZE)); assert(newBlock->memoryUnits != nullptr); size_t unitSize = mUnitSizes[indexHeap]; uint nbUnits = BLOCK_SIZE / unitSize; assert(nbUnits * unitSize <= BLOCK_SIZE); + void* memoryUnitsStart = static_cast(newBlock->memoryUnits); + char* memoryUnitsStartChar = static_cast(memoryUnitsStart); for (size_t i=0; i < nbUnits - 1; i++) { - MemoryUnit* unit = (MemoryUnit*) ((size_t)newBlock->memoryUnits + unitSize * i); - MemoryUnit* nextUnit = (MemoryUnit*) ((size_t)newBlock->memoryUnits + unitSize * (i+1)); + void* unitPointer = static_cast(memoryUnitsStartChar + unitSize * i); + void* nextUnitPointer = static_cast(memoryUnitsStartChar + unitSize * (i+1)); + MemoryUnit* unit = static_cast(unitPointer); + MemoryUnit* nextUnit = static_cast(nextUnitPointer); unit->nextUnit = nextUnit; } - MemoryUnit* lastUnit = (MemoryUnit*) ((size_t)newBlock->memoryUnits + unitSize*(nbUnits-1)); + void* lastUnitPointer = static_cast(memoryUnitsStartChar + unitSize*(nbUnits-1)); + MemoryUnit* lastUnit = static_cast(lastUnitPointer); lastUnit->nextUnit = nullptr; // Add the new allocated block into the list of free memory units in the heap @@ -176,8 +183,8 @@ void PoolAllocator::release(void* pointer, size_t size) { // If the size is larger than the maximum memory unit size if (size > MAX_UNIT_SIZE) { - // Release the memory using the standard free() function - free(pointer); + // Release the memory using the default deallocation + MemoryManager::getBaseAllocator().release(pointer, size); return; } @@ -187,7 +194,7 @@ void PoolAllocator::release(void* pointer, size_t size) { // Insert the released memory unit into the list of free memory units of the // corresponding heap - MemoryUnit* releasedUnit = (MemoryUnit*) pointer; + MemoryUnit* releasedUnit = static_cast(pointer); releasedUnit->nextUnit = mFreeMemoryUnits[indexHeap]; mFreeMemoryUnits[indexHeap] = releasedUnit; } diff --git a/src/memory/PoolAllocator.h b/src/memory/PoolAllocator.h index b06778d5..25f31198 100644 --- a/src/memory/PoolAllocator.h +++ b/src/memory/PoolAllocator.h @@ -28,7 +28,7 @@ // Libraries #include "configuration.h" -#include "Allocator.h" +#include "MemoryAllocator.h" /// ReactPhysics3D namespace namespace reactphysics3d { @@ -40,7 +40,7 @@ namespace reactphysics3d { * efficiently. This implementation is inspired by the small block allocator * described here : http://www.codeproject.com/useritems/Small_Block_Allocator.asp */ -class PoolAllocator : public Allocator { +class PoolAllocator : public MemoryAllocator { private : @@ -131,23 +131,17 @@ class PoolAllocator : public Allocator { /// Destructor virtual ~PoolAllocator() override; + /// Assignment operator + PoolAllocator& operator=(PoolAllocator& allocator) = default; + /// Allocate memory of a given size (in bytes) and return a pointer to the /// allocated memory. virtual void* allocate(size_t size) override; /// Release previously allocated memory. virtual void release(void* pointer, size_t size) override; - - /// Return true if memory needs to be release with this allocator - virtual bool isReleaseNeeded() const override; - }; -// Return true if memory needs to be release with this allocator -inline bool PoolAllocator::isReleaseNeeded() const { - return true; -} - } #endif diff --git a/src/memory/SingleFrameAllocator.cpp b/src/memory/SingleFrameAllocator.cpp index a2e436cd..c9d6533a 100644 --- a/src/memory/SingleFrameAllocator.cpp +++ b/src/memory/SingleFrameAllocator.cpp @@ -25,17 +25,19 @@ // Libraries #include "SingleFrameAllocator.h" +#include "MemoryManager.h" #include #include using namespace reactphysics3d; // Constructor -SingleFrameAllocator::SingleFrameAllocator(size_t totalSizeBytes) - : mTotalSizeBytes(totalSizeBytes), mCurrentOffset(0) { +SingleFrameAllocator::SingleFrameAllocator() + : mTotalSizeBytes(INIT_SINGLE_FRAME_ALLOCATOR_BYTES), + mCurrentOffset(0), mNbFramesTooMuchAllocated(0), mNeedToAllocatedMore(false) { // Allocate a whole block of memory at the beginning - mMemoryBufferStart = static_cast(malloc(mTotalSizeBytes)); + mMemoryBufferStart = static_cast(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes)); assert(mMemoryBufferStart != nullptr); } @@ -43,7 +45,7 @@ SingleFrameAllocator::SingleFrameAllocator(size_t totalSizeBytes) SingleFrameAllocator::~SingleFrameAllocator() { // Release the memory allocated at the beginning - free(mMemoryBufferStart); + MemoryManager::getBaseAllocator().release(mMemoryBufferStart, mTotalSizeBytes); } @@ -52,14 +54,13 @@ SingleFrameAllocator::~SingleFrameAllocator() { void* SingleFrameAllocator::allocate(size_t size) { // Check that there is enough remaining memory in the buffer - if (static_cast(mCurrentOffset) + size > mTotalSizeBytes) { + if (mCurrentOffset + size > mTotalSizeBytes) { - // This should never occur. If it does, you must increase the initial - // size of memory of this allocator - assert(false); + // We need to allocate more memory next time reset() is called + mNeedToAllocatedMore = true; - // Return null - return nullptr; + // Return default memory allocation + return MemoryManager::getBaseAllocator().allocate(size); } // Next available memory location @@ -72,9 +73,63 @@ void* SingleFrameAllocator::allocate(size_t size) { return nextAvailableMemory; } +// Release previously allocated memory. +void SingleFrameAllocator::release(void* pointer, size_t size) { + + // If allocated memory is not within the single frame allocation range + char* p = static_cast(pointer); + if (p < mMemoryBufferStart || p > mMemoryBufferStart + mTotalSizeBytes) { + + // Use default deallocation + MemoryManager::getBaseAllocator().release(pointer, size); + } +} + // Reset the marker of the current allocated memory void SingleFrameAllocator::reset() { + // If too much memory is allocated + if (mCurrentOffset < mTotalSizeBytes / 2) { + + mNbFramesTooMuchAllocated++; + + if (mNbFramesTooMuchAllocated > NB_FRAMES_UNTIL_SHRINK) { + + // Release the memory allocated at the beginning + MemoryManager::getBaseAllocator().release(mMemoryBufferStart, mTotalSizeBytes); + + // Divide the total memory to allocate by two + mTotalSizeBytes /= 2; + if (mTotalSizeBytes <= 0) mTotalSizeBytes = 1; + + // Allocate a whole block of memory at the beginning + mMemoryBufferStart = static_cast(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes)); + assert(mMemoryBufferStart != nullptr); + + mNbFramesTooMuchAllocated = 0; + } + } + else { + mNbFramesTooMuchAllocated = 0; + } + + // If we need to allocate more memory + if (mNeedToAllocatedMore) { + + // Release the memory allocated at the beginning + MemoryManager::getBaseAllocator().release(mMemoryBufferStart, mTotalSizeBytes); + + // Multiply the total memory to allocate by two + mTotalSizeBytes *= 2; + + // Allocate a whole block of memory at the beginning + mMemoryBufferStart = static_cast(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes)); + assert(mMemoryBufferStart != nullptr); + + mNeedToAllocatedMore = false; + mNbFramesTooMuchAllocated = 0; + } + // Reset the current offset at the beginning of the block mCurrentOffset = 0; } diff --git a/src/memory/SingleFrameAllocator.h b/src/memory/SingleFrameAllocator.h index 426c2a2d..d3142908 100644 --- a/src/memory/SingleFrameAllocator.h +++ b/src/memory/SingleFrameAllocator.h @@ -27,7 +27,7 @@ #define REACTPHYSICS3D_SINGLE_FRAME_ALLOCATOR_H // Libraries -#include "Allocator.h" +#include "MemoryAllocator.h" #include "configuration.h" /// ReactPhysics3D namespace @@ -38,10 +38,16 @@ namespace reactphysics3d { * This class represent a memory allocator used to efficiently allocate * memory on the heap that is used during a single frame. */ -class SingleFrameAllocator : public Allocator { +class SingleFrameAllocator : public MemoryAllocator { private : + // -------------------- Constants -------------------- // + + /// Number of frames to wait before shrinking the allocated + /// memory if too much is allocated + static const int NB_FRAMES_UNTIL_SHRINK = 120; + // -------------------- Attributes -------------------- // /// Total size (in bytes) of memory of the allocator @@ -51,36 +57,38 @@ class SingleFrameAllocator : public Allocator { char* mMemoryBufferStart; /// Pointer to the next available memory location in the buffer - int mCurrentOffset; + size_t mCurrentOffset; + + /// Current number of frames since we detected too much memory + /// is allocated + size_t mNbFramesTooMuchAllocated; + + /// True if we need to allocate more memory in the next reset() call + bool mNeedToAllocatedMore; public : // -------------------- Methods -------------------- // /// Constructor - SingleFrameAllocator(size_t totalSizeBytes); + SingleFrameAllocator(); /// Destructor virtual ~SingleFrameAllocator() override; + /// Assignment operator + SingleFrameAllocator& operator=(SingleFrameAllocator& allocator) = default; + /// Allocate memory of a given size (in bytes) virtual void* allocate(size_t size) override; /// Release previously allocated memory. - virtual void release(void* pointer, size_t size) override { } + virtual void release(void* pointer, size_t size) override; /// Reset the marker of the current allocated memory virtual void reset(); - - /// Return true if memory needs to be release with this allocator - virtual bool isReleaseNeeded() const override; }; -// Return true if memory needs to be release with this allocator -inline bool SingleFrameAllocator::isReleaseNeeded() const { - return false; -} - } #endif