Refactor memory allocation

This commit is contained in:
Daniel Chappuis 2018-01-01 18:35:57 +01:00
parent 3be2970d30
commit 261ffef616
75 changed files with 449 additions and 296 deletions

View File

@ -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"

View File

@ -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;
}

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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();

View File

@ -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<bodyindex> reportedBodies;
// Ask the broad-phase to get all the overlapping shapes
LinkedList<int> overlappingNodes(mPoolAllocator);
LinkedList<int> 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<int> overlappingNodes(mPoolAllocator);
LinkedList<int> 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<int> overlappingNodes(mPoolAllocator);
LinkedList<int> 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);

View File

@ -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 <vector>
#include <set>
@ -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

View File

@ -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),

View File

@ -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();

View File

@ -29,7 +29,7 @@
using namespace reactphysics3d;
// Constructor
ContactManifoldInfo::ContactManifoldInfo(Allocator& allocator)
ContactManifoldInfo::ContactManifoldInfo(MemoryAllocator& allocator)
: mContactPointsList(nullptr), mNbContactPoints(0), mNext(nullptr), mAllocator(allocator) {
}

View File

@ -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();

View File

@ -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) {

View File

@ -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();

View File

@ -54,7 +54,7 @@ class HalfEdgeStructure {
List<uint> faceVertices; // Index of the vertices of the face
/// Constructor
Face(Allocator& allocator) : faceVertices(allocator) {}
Face(MemoryAllocator& allocator) : faceVertices(allocator) {}
/// Constructor
Face(List<uint> vertices) : faceVertices(vertices) {}
@ -71,7 +71,7 @@ class HalfEdgeStructure {
private:
/// Reference to a memory allocator
Allocator& mAllocator;
MemoryAllocator& mAllocator;
/// All the faces
List<Face> 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) {}

View File

@ -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) {

View File

@ -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;

View File

@ -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();

View File

@ -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<uint> faceVertices(MemoryManager::getDefaultAllocator(), face->nbVertices);
List<uint> faceVertices(MemoryManager::getBaseAllocator(), face->nbVertices);
// For each vertex of the face
for (uint v=0; v < face->nbVertices; v++) {

View File

@ -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;

View File

@ -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();

View File

@ -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<int> overlappingNodes(allocator);
LinkedList<int> overlappingNodes(memoryManager.getPoolAllocator());
// For all collision shapes that have moved (or have been created) during the
// last simulation step

View File

@ -210,7 +210,7 @@ class BroadPhaseAlgorithm {
void reportAllShapesOverlappingWithAABB(const AABB& aabb, LinkedList<int>& 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;

View File

@ -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);

View File

@ -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;
};
}

View File

@ -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;

View File

@ -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;
};
}

View File

@ -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);

View File

@ -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;
};
}

View File

@ -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

View File

@ -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) {
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
};
}

View File

@ -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);

View File

@ -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;
};
}

View File

@ -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);

View File

@ -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;
};
}

View File

@ -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<uint> 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;

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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
}

View File

@ -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) {
}

View File

@ -28,7 +28,7 @@
// Libraries
#include "configuration.h"
#include "memory/Allocator.h"
#include "memory/MemoryAllocator.h"
#include <cstring>
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) {

View File

@ -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<reactphysics3d::bodyindex>::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

View File

@ -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;

View File

@ -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<ContactPointSolver*>(mSingleFrameAllocator.allocate(sizeof(ContactPointSolver) * nbContactPoints));
mContactPoints = static_cast<ContactPointSolver*>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
sizeof(ContactPointSolver) * nbContactPoints));
assert(mContactPoints != nullptr);
mContactConstraints = static_cast<ContactManifoldSolver*>(mSingleFrameAllocator.allocate(sizeof(ContactManifoldSolver) * nbContactManifolds));
mContactConstraints = static_cast<ContactManifoldSolver*>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
sizeof(ContactManifoldSolver) * nbContactManifolds));
assert(mContactConstraints != nullptr);
// For each island of the world

View File

@ -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;

View File

@ -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<Vector3*>(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3)));
mSplitAngularVelocities = static_cast<Vector3*>(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3)));
mConstrainedLinearVelocities = static_cast<Vector3*>(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3)));
mConstrainedAngularVelocities = static_cast<Vector3*>(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3)));
mConstrainedPositions = static_cast<Vector3*>(mSingleFrameAllocator.allocate(nbBodies * sizeof(Vector3)));
mConstrainedOrientations = static_cast<Quaternion*>(mSingleFrameAllocator.allocate(nbBodies * sizeof(Quaternion)));
mSplitLinearVelocities = static_cast<Vector3*>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
nbBodies * sizeof(Vector3)));
mSplitAngularVelocities = static_cast<Vector3*>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
nbBodies * sizeof(Vector3)));
mConstrainedLinearVelocities = static_cast<Vector3*>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
nbBodies * sizeof(Vector3)));
mConstrainedAngularVelocities = static_cast<Vector3*>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
nbBodies * sizeof(Vector3)));
mConstrainedPositions = static_cast<Vector3*>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
nbBodies * sizeof(Vector3)));
mConstrainedOrientations = static_cast<Quaternion*>(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<reactphysics3d::bodyindex>::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<const BallAndSocketJointInfo&>(
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<const SliderJointInfo&>(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<const HingeJointInfo&>(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<const FixedJointInfo&>(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<Island**>(mSingleFrameAllocator.allocate(sizeof(Island*) * nbBodies));
mIslands = static_cast<Island**>(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<RigidBody**>(mSingleFrameAllocator.allocate(nbBytesStack));
RigidBody** stackBodiesToVisit = static_cast<RigidBody**>(mMemoryManager.allocate(MemoryManager::AllocationType::Frame,
nbBytesStack));
// For each rigid body of the world
for (std::set<RigidBody*>::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) {

View File

@ -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<RigidBody**>(allocator.allocate(sizeof(RigidBody*) * nbMaxBodies));
mContactManifolds = static_cast<ContactManifold**>(allocator.allocate(sizeof(ContactManifold*) * nbMaxContactManifolds));
mJoints = static_cast<Joint**>(allocator.allocate(sizeof(Joint*) * nbMaxJoints));
mBodies = static_cast<RigidBody**>(memoryManager.allocate(MemoryManager::AllocationType::Frame,
sizeof(RigidBody*) * nbMaxBodies));
mContactManifolds = static_cast<ContactManifold**>(memoryManager.allocate(MemoryManager::AllocationType::Frame,
sizeof(ContactManifold*) * nbMaxContactManifolds));
mJoints = static_cast<Joint**>(memoryManager.allocate(MemoryManager::AllocationType::Frame,
sizeof(Joint*) * nbMaxJoints));
}
// Destructor

View File

@ -69,7 +69,7 @@ class Island {
/// Constructor
Island(uint nbMaxBodies, uint nbMaxContactManifolds, uint nbMaxJoints,
SingleFrameAllocator& allocator);
MemoryManager& memoryManager);
/// Destructor
~Island();

View File

@ -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) {

View File

@ -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;
}

View File

@ -225,7 +225,7 @@ decimal reactphysics3d::computePointToLineDistance(const Vector3& linePointA, co
List<Vector3> reactphysics3d::clipSegmentWithPlanes(const Vector3& segA, const Vector3& segB,
const List<Vector3>& planesPoints,
const List<Vector3>& planesNormals,
Allocator& allocator) {
MemoryAllocator& allocator) {
assert(planesPoints.size() == planesNormals.size());
@ -303,7 +303,7 @@ List<Vector3> reactphysics3d::clipSegmentWithPlanes(const Vector3& segA, const V
// Clip a polygon against multiple planes and return the clipped polygon vertices
// This method implements the SutherlandHodgman clipping algorithm
List<Vector3> reactphysics3d::clipPolygonWithPlanes(const List<Vector3>& polygonVertices, const List<Vector3>& planesPoints,
const List<Vector3>& planesNormals, Allocator& allocator) {
const List<Vector3>& planesNormals, MemoryAllocator& allocator) {
assert(planesPoints.size() == planesNormals.size());

View File

@ -115,11 +115,11 @@ decimal computePointToLineDistance(const Vector3& linePointA, const Vector3& lin
List<Vector3> clipSegmentWithPlanes(const Vector3& segA, const Vector3& segB,
const List<Vector3>& planesPoints,
const List<Vector3>& planesNormals,
Allocator& allocator);
MemoryAllocator& allocator);
/// Clip a polygon against multiple planes and return the clipped polygon vertices
List<Vector3> clipPolygonWithPlanes(const List<Vector3>& polygonVertices, const List<Vector3>& planesPoints,
const List<Vector3>& planesNormals, Allocator& allocator);
const List<Vector3>& 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);

View File

@ -27,7 +27,7 @@
#define REACTPHYSICS3D_DEFAULT_ALLOCATOR_H
// Libraries
#include "memory/Allocator.h"
#include "memory/MemoryAllocator.h"
#include <cstdlib>
/// 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;
}
};
}

View File

@ -23,8 +23,8 @@
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_ALLOCATOR_H
#define REACTPHYSICS3D_ALLOCATOR_H
#ifndef REACTPHYSICS3D_MEMORY_ALLOCATOR_H
#define REACTPHYSICS3D_MEMORY_ALLOCATOR_H
// Libraries
#include <cstring>
@ -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;
};
}

View File

@ -30,3 +30,5 @@ using namespace reactphysics3d;
// Static variables
DefaultAllocator MemoryManager::mDefaultAllocator;
MemoryAllocator* MemoryManager::mBaseAllocator = &mDefaultAllocator;

View File

@ -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();
}
}

View File

@ -25,6 +25,7 @@
// Libraries
#include "PoolAllocator.h"
#include "MemoryManager.h"
#include <cstdlib>
#include <cassert>
@ -42,7 +43,7 @@ PoolAllocator::PoolAllocator() {
mNbAllocatedMemoryBlocks = 64;
mNbCurrentMemoryBlocks = 0;
const size_t sizeToAllocate = mNbAllocatedMemoryBlocks * sizeof(MemoryBlock);
mMemoryBlocks = (MemoryBlock*) malloc(sizeToAllocate);
mMemoryBlocks = static_cast<MemoryBlock*>(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<mNbCurrentMemoryBlocks; i++) {
free(mMemoryBlocks[i].memoryUnits);
MemoryManager::getBaseAllocator().release(mMemoryBlocks[i].memoryUnits, BLOCK_SIZE);
}
free(mMemoryBlocks);
MemoryManager::getBaseAllocator().release(mMemoryBlocks, mNbAllocatedMemoryBlocks * sizeof(MemoryBlock));
#ifndef NDEBUG
// Check that the allocate() and release() methods have been called the same
// number of times to avoid memory leaks.
assert(mNbTimesAllocateMethodCalled == 0);
#endif
}
// Allocate memory of a given size (in bytes) and return a pointer to the
@ -108,8 +110,8 @@ void* PoolAllocator::allocate(size_t size) {
// If we need to allocate more than the maximum memory unit size
if (size > 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<MemoryBlock*>(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<MemoryUnit*>(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<void*>(newBlock->memoryUnits);
char* memoryUnitsStartChar = static_cast<char*>(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<void*>(memoryUnitsStartChar + unitSize * i);
void* nextUnitPointer = static_cast<void*>(memoryUnitsStartChar + unitSize * (i+1));
MemoryUnit* unit = static_cast<MemoryUnit*>(unitPointer);
MemoryUnit* nextUnit = static_cast<MemoryUnit*>(nextUnitPointer);
unit->nextUnit = nextUnit;
}
MemoryUnit* lastUnit = (MemoryUnit*) ((size_t)newBlock->memoryUnits + unitSize*(nbUnits-1));
void* lastUnitPointer = static_cast<void*>(memoryUnitsStartChar + unitSize*(nbUnits-1));
MemoryUnit* lastUnit = static_cast<MemoryUnit*>(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<MemoryUnit*>(pointer);
releasedUnit->nextUnit = mFreeMemoryUnits[indexHeap];
mFreeMemoryUnits[indexHeap] = releasedUnit;
}

View File

@ -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

View File

@ -25,17 +25,19 @@
// Libraries
#include "SingleFrameAllocator.h"
#include "MemoryManager.h"
#include <cstdlib>
#include <cassert>
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<char*>(malloc(mTotalSizeBytes));
mMemoryBufferStart = static_cast<char*>(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<size_t>(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<char*>(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<char*>(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<char*>(MemoryManager::getBaseAllocator().allocate(mTotalSizeBytes));
assert(mMemoryBufferStart != nullptr);
mNeedToAllocatedMore = false;
mNbFramesTooMuchAllocated = 0;
}
// Reset the current offset at the beginning of the block
mCurrentOffset = 0;
}

View File

@ -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