Merge branch 'memory' into develop
This commit is contained in:
commit
d7cf8bcf17
|
@ -6,6 +6,10 @@
|
|||
|
||||
### Changed
|
||||
|
||||
- The library must now be compiled with C++ 17 compiler
|
||||
- If the user sets its own custom allocator, the return allocated memory must now be 16 bytes aligned
|
||||
- The internal allocators now allocates memory that is 16-bytes aligned
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Minimum cmake version required
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# Project configuration
|
||||
project(ReactPhysics3D VERSION 0.9.0 LANGUAGES CXX)
|
||||
|
@ -229,6 +229,7 @@ set (REACTPHYSICS3D_SOURCES
|
|||
"src/memory/SingleFrameAllocator.cpp"
|
||||
"src/memory/HeapAllocator.cpp"
|
||||
"src/memory/MemoryManager.cpp"
|
||||
"src/memory/MemoryAllocator.cpp"
|
||||
"src/utils/Profiler.cpp"
|
||||
"src/utils/DefaultLogger.cpp"
|
||||
"src/utils/DebugRenderer.cpp"
|
||||
|
@ -242,7 +243,7 @@ add_library(reactphysics3d ${REACTPHYSICS3D_HEADERS} ${REACTPHYSICS3D_SOURCES})
|
|||
add_library(ReactPhysics3D::reactphysics3d ALIAS reactphysics3d)
|
||||
|
||||
# C++11 compiler features
|
||||
target_compile_features(reactphysics3d PUBLIC cxx_std_11)
|
||||
target_compile_features(reactphysics3d PUBLIC cxx_std_17)
|
||||
set_target_properties(reactphysics3d PROPERTIES CXX_EXTENSIONS OFF)
|
||||
|
||||
# Library headers
|
||||
|
|
|
@ -63,6 +63,9 @@ class Components {
|
|||
/// Size (in bytes) of a single component
|
||||
size_t mComponentDataSize;
|
||||
|
||||
/// Size (in bytes) to allocate to make sure we can offset the components array to keep alignment
|
||||
size_t mAlignmentMarginSize;
|
||||
|
||||
/// Number of allocated components
|
||||
uint32 mNbAllocatedComponents;
|
||||
|
||||
|
@ -96,11 +99,14 @@ class Components {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Components(MemoryAllocator& allocator, size_t componentDataSize);
|
||||
Components(MemoryAllocator& allocator, size_t componentDataSize, size_t alignmentMarginSize);
|
||||
|
||||
/// Destructor
|
||||
virtual ~Components();
|
||||
|
||||
/// Initialize the components:
|
||||
void init();
|
||||
|
||||
/// Remove a component
|
||||
void removeComponent(Entity entity);
|
||||
|
||||
|
|
|
@ -129,6 +129,9 @@ constexpr uint16 NB_MAX_CONTACT_POINTS_IN_POTENTIAL_MANIFOLD = 256;
|
|||
/// Distance threshold to consider that two contact points in a manifold are the same
|
||||
constexpr decimal SAME_CONTACT_POINT_DISTANCE_THRESHOLD = decimal(0.01);
|
||||
|
||||
/// Global alignment (in bytes) that all allocators must enforce
|
||||
constexpr uint8 GLOBAL_ALIGNMENT = 16;
|
||||
|
||||
/// Current version of ReactPhysics3D
|
||||
const std::string RP3D_VERSION = std::string("0.9.0");
|
||||
|
||||
|
|
|
@ -28,15 +28,19 @@
|
|||
|
||||
// Libraries
|
||||
#include <reactphysics3d/memory/MemoryAllocator.h>
|
||||
#include <reactphysics3d/configuration.h>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class DefaultAllocator
|
||||
/**
|
||||
* This class represents a default memory allocator that uses default malloc/free methods
|
||||
* This class represents a default memory allocator that uses standard C++ functions
|
||||
* to allocated 16-bytes aligned memory.
|
||||
*
|
||||
*/
|
||||
class DefaultAllocator : public MemoryAllocator {
|
||||
|
||||
|
@ -49,15 +53,33 @@ class DefaultAllocator : public MemoryAllocator {
|
|||
DefaultAllocator& operator=(DefaultAllocator& allocator) = default;
|
||||
|
||||
/// Allocate memory of a given size (in bytes) and return a pointer to the
|
||||
/// allocated memory.
|
||||
/// allocated memory. The returned allocated memory must be 16 bytes aligned.
|
||||
virtual void* allocate(size_t size) override {
|
||||
|
||||
return std::malloc(size);
|
||||
// If compiler is Visual Studio
|
||||
#ifdef RP3D_COMPILER_VISUAL_STUDIO
|
||||
|
||||
// Visual Studio doesn't not support standard std:aligned_alloc() method from C++ 17
|
||||
return _aligned_malloc(size, GLOBAL_ALIGNMENT);
|
||||
#else
|
||||
|
||||
// Return 16-bytes aligned memory
|
||||
return std::aligned_alloc(GLOBAL_ALIGNMENT, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Release previously allocated memory.
|
||||
virtual void release(void* pointer, size_t /*size*/) override {
|
||||
std::free(pointer);
|
||||
|
||||
// If compiler is Visual Studio
|
||||
#ifdef RP3D_COMPILER_VISUAL_STUDIO
|
||||
|
||||
// Visual Studio doesn't not support standard std:aligned_alloc() method from c++ 17
|
||||
return _aligned_free(pointer);
|
||||
#else
|
||||
|
||||
return std::free(pointer);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -57,26 +57,33 @@ class HeapAllocator : public MemoryAllocator {
|
|||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Size in bytes of the allocated memory unit
|
||||
size_t size;
|
||||
|
||||
/// True if the memory unit is currently allocated
|
||||
bool isAllocated;
|
||||
|
||||
/// Pointer to the previous memory unit
|
||||
MemoryUnitHeader* previousUnit;
|
||||
|
||||
/// Pointer to the next memory unit
|
||||
MemoryUnitHeader* nextUnit;
|
||||
|
||||
/// Pointer to the previous free (not allocated) memory unit
|
||||
MemoryUnitHeader* previousFreeUnit;
|
||||
|
||||
/// Pointer to the next free (not allocated) memory unit
|
||||
MemoryUnitHeader* nextFreeUnit;
|
||||
|
||||
/// Size in bytes of the allocated memory unit
|
||||
size_t size;
|
||||
|
||||
/// True if the next memory unit has been allocated with the same call to malloc()
|
||||
bool isNextContiguousMemory;
|
||||
|
||||
/// True if the memory unit is currently allocated
|
||||
bool isAllocated = false;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
MemoryUnitHeader(size_t size, MemoryUnitHeader* previousUnit, MemoryUnitHeader* nextUnit, bool isNextContiguousMemory)
|
||||
: size(size), isAllocated(false), previousUnit(previousUnit),
|
||||
nextUnit(nextUnit), isNextContiguousMemory(isNextContiguousMemory) {
|
||||
MemoryUnitHeader(size_t size, MemoryUnitHeader* previousUnit, MemoryUnitHeader* nextUnit,
|
||||
MemoryUnitHeader* previousFreeUnit, MemoryUnitHeader* nextFreeUnit, bool isNextContiguousMemory)
|
||||
: previousUnit(previousUnit), nextUnit(nextUnit), previousFreeUnit(previousFreeUnit), nextFreeUnit(nextFreeUnit), size(size),
|
||||
isNextContiguousMemory(isNextContiguousMemory) {
|
||||
|
||||
assert(size > 0);
|
||||
}
|
||||
|
@ -101,8 +108,8 @@ class HeapAllocator : public MemoryAllocator {
|
|||
/// Pointer to the first memory unit of the linked-list
|
||||
MemoryUnitHeader* mMemoryUnits;
|
||||
|
||||
/// Pointer to a cached free memory unit
|
||||
MemoryUnitHeader* mCachedFreeUnit;
|
||||
/// Pointer to the first item of the linked-list of free units
|
||||
MemoryUnitHeader* mFreeUnits;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/// This variable is incremented by one when the allocate() method has been
|
||||
|
@ -118,12 +125,21 @@ class HeapAllocator : public MemoryAllocator {
|
|||
/// left over space. The second unit is put into the free memory units
|
||||
void splitMemoryUnit(MemoryUnitHeader* unit, size_t size);
|
||||
|
||||
// Merge two contiguous memory units that are not allocated.
|
||||
/// Add the unit from the linked-list of free units
|
||||
void addToFreeUnits(MemoryUnitHeader* unit);
|
||||
|
||||
/// Remove the unit from the linked-list of free units
|
||||
void removeFromFreeUnits(MemoryUnitHeader* unit);
|
||||
|
||||
/// Merge two contiguous memory units that are not allocated.
|
||||
void mergeUnits(MemoryUnitHeader* unit1, MemoryUnitHeader* unit2);
|
||||
|
||||
/// Reserve more memory for the allocator
|
||||
void reserve(size_t sizeToAllocate);
|
||||
|
||||
/// Return the next aligned memory address
|
||||
void* computeAlignedAddress(void* unalignedAddress);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
// Libraries
|
||||
#include <cstring>
|
||||
#include <reactphysics3d/configuration.h>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
@ -50,11 +51,19 @@ class MemoryAllocator {
|
|||
MemoryAllocator& operator=(MemoryAllocator& allocator) = default;
|
||||
|
||||
/// Allocate memory of a given size (in bytes) and return a pointer to the
|
||||
/// allocated memory.
|
||||
/// allocated memory. The return allocated memory must be 16 bytes aligned.
|
||||
virtual void* allocate(size_t size)=0;
|
||||
|
||||
/// Release previously allocated memory.
|
||||
virtual void release(void* pointer, size_t size)=0;
|
||||
|
||||
/// Given a pointer to memory, this method returns the next aligned address
|
||||
// TODO : We need to use uint8 type instead of uint8_t here
|
||||
static void* alignAddress(void* pointer, std::uint8_t alignment);
|
||||
|
||||
/// Given a pointer to memory, this method returns the next aligned address and also output the alignment offset
|
||||
// TODO : We need to use uint8 type instead of uint8_t here
|
||||
static void* alignAddress(void* pointer, std::uint8_t alignment, ptrdiff_t& alignmentOffset);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -104,14 +104,18 @@ class MemoryManager {
|
|||
// Allocate memory of a given type
|
||||
RP3D_FORCE_INLINE void* MemoryManager::allocate(AllocationType allocationType, size_t size) {
|
||||
|
||||
void* allocatedMemory = nullptr;
|
||||
|
||||
switch (allocationType) {
|
||||
case AllocationType::Base: return mBaseAllocator->allocate(size);
|
||||
case AllocationType::Pool: return mPoolAllocator.allocate(size);
|
||||
case AllocationType::Heap: return mHeapAllocator.allocate(size);
|
||||
case AllocationType::Frame: return mSingleFrameAllocator.allocate(size);
|
||||
case AllocationType::Base: allocatedMemory = mBaseAllocator->allocate(size); break;
|
||||
case AllocationType::Pool: allocatedMemory = mPoolAllocator.allocate(size); break;
|
||||
case AllocationType::Heap: allocatedMemory = mHeapAllocator.allocate(size); break;
|
||||
case AllocationType::Frame: allocatedMemory = mSingleFrameAllocator.allocate(size); break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
assert(allocatedMemory == nullptr || reinterpret_cast<uintptr_t>(allocatedMemory) % 16 == 0);
|
||||
|
||||
return allocatedMemory;
|
||||
}
|
||||
|
||||
// Release previously allocated memory.
|
||||
|
|
|
@ -81,13 +81,16 @@ class PoolAllocator : public MemoryAllocator {
|
|||
/// Number of heaps
|
||||
static const int NB_HEAPS = 128;
|
||||
|
||||
/// Minimum unit size
|
||||
static const size_t MIN_UNIT_SIZE = 16;
|
||||
|
||||
/// Maximum memory unit size. An allocation request of a size smaller or equal to
|
||||
/// this size will be handled using the small block allocator. However, for an
|
||||
/// allocation request larger than the maximum block size, the standard malloc()
|
||||
/// will be used.
|
||||
static const size_t MAX_UNIT_SIZE = 1024;
|
||||
static const size_t MAX_UNIT_SIZE = NB_HEAPS * MIN_UNIT_SIZE;
|
||||
|
||||
/// Size a memory chunk
|
||||
/// Size of a memory chunk
|
||||
static const size_t BLOCK_SIZE = 16 * MAX_UNIT_SIZE;
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
|
|
@ -45,10 +45,6 @@ class SingleFrameAllocator : public MemoryAllocator {
|
|||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
/// Number of frames to wait before shrinking the allocated
|
||||
/// memory if too much is allocated
|
||||
static const int NB_FRAMES_UNTIL_SHRINK = 120;
|
||||
|
||||
/// Initial size (in bytes) of the single frame allocator
|
||||
size_t INIT_SINGLE_FRAME_ALLOCATOR_NB_BYTES = 1048576; // 1Mb
|
||||
|
||||
|
@ -69,10 +65,6 @@ class SingleFrameAllocator : public MemoryAllocator {
|
|||
/// Pointer to the next available memory location in the buffer
|
||||
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;
|
||||
|
||||
|
|
|
@ -38,10 +38,9 @@ BallAndSocketJointComponents::BallAndSocketJointComponents(MemoryAllocator& allo
|
|||
sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) +
|
||||
sizeof(Matrix3x3) + sizeof(Matrix3x3) + sizeof(Vector3) +
|
||||
sizeof(Matrix3x3) + sizeof(Vector3) + sizeof(bool) + sizeof(decimal) +
|
||||
sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(bool) + sizeof(Vector3)) {
|
||||
sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(bool) + sizeof(Vector3),
|
||||
18 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -50,31 +49,51 @@ void BallAndSocketJointComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newJointEntities = static_cast<Entity*>(newBuffer);
|
||||
BallAndSocketJoint** newJoints = reinterpret_cast<BallAndSocketJoint**>(newJointEntities + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(newJoints + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(newLocalAnchorPointBody1 + nbComponentsToAllocate);
|
||||
Vector3* newR1World = reinterpret_cast<Vector3*>(newLocalAnchorPointBody2 + nbComponentsToAllocate);
|
||||
Vector3* newR2World = reinterpret_cast<Vector3*>(newR1World + nbComponentsToAllocate);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(newR2World + nbComponentsToAllocate);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(newI1 + nbComponentsToAllocate);
|
||||
Vector3* newBiasVector = reinterpret_cast<Vector3*>(newI2 + nbComponentsToAllocate);
|
||||
Matrix3x3* newInverseMassMatrix = reinterpret_cast<Matrix3x3*>(newBiasVector + nbComponentsToAllocate);
|
||||
Vector3* newImpulse = reinterpret_cast<Vector3*>(newInverseMassMatrix + nbComponentsToAllocate);
|
||||
bool* newIsConeLimitEnabled = reinterpret_cast<bool*>(newImpulse + nbComponentsToAllocate);
|
||||
decimal* newConeLimitImpulse = reinterpret_cast<decimal*>(newIsConeLimitEnabled + nbComponentsToAllocate);
|
||||
decimal* newConeLimitHalfAngle = reinterpret_cast<decimal*>(newConeLimitImpulse + nbComponentsToAllocate);
|
||||
decimal* newInverseMassMatrixConeLimit = reinterpret_cast<decimal*>(newConeLimitHalfAngle + nbComponentsToAllocate);
|
||||
decimal* newBConeLimit = reinterpret_cast<decimal*>(newInverseMassMatrixConeLimit + nbComponentsToAllocate);
|
||||
bool* newIsConeLimitViolated = reinterpret_cast<bool*>(newBConeLimit + nbComponentsToAllocate);
|
||||
Vector3* newConeLimitACrossB = reinterpret_cast<Vector3*>(newIsConeLimitViolated + nbComponentsToAllocate);
|
||||
assert(reinterpret_cast<uintptr_t>(newJointEntities) % GLOBAL_ALIGNMENT == 0);
|
||||
BallAndSocketJoint** newJoints = reinterpret_cast<BallAndSocketJoint**>(MemoryAllocator::alignAddress(newJointEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newJoints) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newJoints + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR1World = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR1World) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR2World = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR1World + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR2World) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newR2World + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI1) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newI1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newBiasVector = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newI2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBiasVector) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newInverseMassMatrix = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newBiasVector + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrix) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newImpulse = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInverseMassMatrix + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulse) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsConeLimitEnabled = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newImpulse + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsConeLimitEnabled) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newConeLimitImpulse = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newIsConeLimitEnabled + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newConeLimitImpulse) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newConeLimitHalfAngle = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newConeLimitImpulse + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newConeLimitHalfAngle) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newInverseMassMatrixConeLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newConeLimitHalfAngle + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixConeLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newBConeLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newInverseMassMatrixConeLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBConeLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsConeLimitViolated = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newBConeLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsConeLimitViolated) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newConeLimitACrossB = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newIsConeLimitViolated + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newConeLimitACrossB) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newConeLimitACrossB + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -38,10 +38,8 @@ ColliderComponents::ColliderComponents(MemoryAllocator& allocator)
|
|||
:Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(Collider*) + sizeof(int32) +
|
||||
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(unsigned short) +
|
||||
sizeof(unsigned short) + sizeof(Transform) + sizeof(Array<uint64>) + sizeof(bool) +
|
||||
sizeof(bool) + sizeof(Material)) {
|
||||
sizeof(bool) + sizeof(Material), 13 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -50,26 +48,40 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newCollidersEntities = static_cast<Entity*>(newBuffer);
|
||||
Entity* newBodiesEntities = reinterpret_cast<Entity*>(newCollidersEntities + nbComponentsToAllocate);
|
||||
Collider** newColliders = reinterpret_cast<Collider**>(newBodiesEntities + nbComponentsToAllocate);
|
||||
int32* newBroadPhaseIds = reinterpret_cast<int32*>(newColliders + nbComponentsToAllocate);
|
||||
Transform* newLocalToBodyTransforms = reinterpret_cast<Transform*>(newBroadPhaseIds + nbComponentsToAllocate);
|
||||
CollisionShape** newCollisionShapes = reinterpret_cast<CollisionShape**>(newLocalToBodyTransforms + nbComponentsToAllocate);
|
||||
unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(newCollisionShapes + nbComponentsToAllocate);
|
||||
unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate);
|
||||
Transform* newLocalToWorldTransforms = reinterpret_cast<Transform*>(newCollideWithMaskBits + nbComponentsToAllocate);
|
||||
Array<uint64>* newOverlappingPairs = reinterpret_cast<Array<uint64>*>(newLocalToWorldTransforms + nbComponentsToAllocate);
|
||||
bool* hasCollisionShapeChangedSize = reinterpret_cast<bool*>(newOverlappingPairs + nbComponentsToAllocate);
|
||||
bool* isTrigger = reinterpret_cast<bool*>(hasCollisionShapeChangedSize + nbComponentsToAllocate);
|
||||
Material* materials = reinterpret_cast<Material*>(isTrigger + nbComponentsToAllocate);
|
||||
Entity* newBodiesEntities = reinterpret_cast<Entity*>(MemoryAllocator::alignAddress(newCollidersEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBodiesEntities) % GLOBAL_ALIGNMENT == 0);
|
||||
Collider** newColliders = reinterpret_cast<Collider**>(MemoryAllocator::alignAddress(newBodiesEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newColliders) % GLOBAL_ALIGNMENT == 0);
|
||||
int32* newBroadPhaseIds = reinterpret_cast<int32*>(MemoryAllocator::alignAddress(newColliders + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBroadPhaseIds) % GLOBAL_ALIGNMENT == 0);
|
||||
Transform* newLocalToBodyTransforms = reinterpret_cast<Transform*>(MemoryAllocator::alignAddress(newBroadPhaseIds + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalToBodyTransforms) % GLOBAL_ALIGNMENT == 0);
|
||||
CollisionShape** newCollisionShapes = reinterpret_cast<CollisionShape**>(MemoryAllocator::alignAddress(newLocalToBodyTransforms + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newCollisionShapes) % GLOBAL_ALIGNMENT == 0);
|
||||
unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(MemoryAllocator::alignAddress(newCollisionShapes + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newCollisionCategoryBits) % GLOBAL_ALIGNMENT == 0);
|
||||
unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(MemoryAllocator::alignAddress(newCollisionCategoryBits + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newCollideWithMaskBits) % GLOBAL_ALIGNMENT == 0);
|
||||
Transform* newLocalToWorldTransforms = reinterpret_cast<Transform*>(MemoryAllocator::alignAddress(newCollideWithMaskBits + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalToWorldTransforms) % GLOBAL_ALIGNMENT == 0);
|
||||
Array<uint64>* newOverlappingPairs = reinterpret_cast<Array<uint64>*>(MemoryAllocator::alignAddress(newLocalToWorldTransforms + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newOverlappingPairs) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* hasCollisionShapeChangedSize = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newOverlappingPairs + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(hasCollisionShapeChangedSize) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* isTrigger = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(hasCollisionShapeChangedSize + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(isTrigger) % GLOBAL_ALIGNMENT == 0);
|
||||
Material* materials = reinterpret_cast<Material*>(MemoryAllocator::alignAddress(isTrigger + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(materials) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(materials + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -35,10 +35,8 @@ using namespace reactphysics3d;
|
|||
// Constructor
|
||||
CollisionBodyComponents::CollisionBodyComponents(MemoryAllocator& allocator)
|
||||
:Components(allocator, sizeof(Entity) + sizeof(CollisionBody*) + sizeof(Array<Entity>) +
|
||||
sizeof(bool) + sizeof(void*)) {
|
||||
sizeof(bool) + sizeof(void*), 5 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -47,18 +45,25 @@ void CollisionBodyComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newBodiesEntities = static_cast<Entity*>(newBuffer);
|
||||
CollisionBody** newBodies = reinterpret_cast<CollisionBody**>(newBodiesEntities + nbComponentsToAllocate);
|
||||
Array<Entity>* newColliders = reinterpret_cast<Array<Entity>*>(newBodies + nbComponentsToAllocate);
|
||||
bool* newIsActive = reinterpret_cast<bool*>(newColliders + nbComponentsToAllocate);
|
||||
void** newUserData = reinterpret_cast<void**>(newIsActive + nbComponentsToAllocate);
|
||||
assert(reinterpret_cast<uintptr_t>(newBodiesEntities) % GLOBAL_ALIGNMENT == 0);
|
||||
CollisionBody** newBodies = reinterpret_cast<CollisionBody**>(MemoryAllocator::alignAddress(newBodiesEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBodies) % GLOBAL_ALIGNMENT == 0);
|
||||
Array<Entity>* newColliders = reinterpret_cast<Array<Entity>*>(MemoryAllocator::alignAddress(newBodies + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newColliders) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsActive = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newColliders + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsActive) % GLOBAL_ALIGNMENT == 0);
|
||||
void** newUserData = reinterpret_cast<void**>(MemoryAllocator::alignAddress(newIsActive + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newUserData) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newUserData + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
Components::Components(MemoryAllocator& allocator, size_t componentDataSize)
|
||||
Components::Components(MemoryAllocator& allocator, size_t componentDataSize, size_t alignmentMarginSize)
|
||||
: mMemoryAllocator(allocator), mNbComponents(0), mComponentDataSize(componentDataSize),
|
||||
mNbAllocatedComponents(0), mBuffer(nullptr), mMapEntityToComponentIndex(allocator),
|
||||
mAlignmentMarginSize(alignmentMarginSize), mNbAllocatedComponents(0), mBuffer(nullptr), mMapEntityToComponentIndex(allocator),
|
||||
mDisabledStartIndex(0) {
|
||||
|
||||
}
|
||||
|
@ -57,6 +57,13 @@ Components::~Components() {
|
|||
}
|
||||
}
|
||||
|
||||
// Initialize the components:
|
||||
void Components::init() {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Compute the index where we need to insert the new component
|
||||
uint32 Components::prepareAddComponent(bool isSleeping) {
|
||||
|
||||
|
|
|
@ -38,10 +38,8 @@ FixedJointComponents::FixedJointComponents(MemoryAllocator& allocator)
|
|||
sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) +
|
||||
sizeof(Matrix3x3) + sizeof(Matrix3x3) + sizeof(Vector3) +
|
||||
sizeof(Vector3) + sizeof(Matrix3x3) + sizeof(Matrix3x3) +
|
||||
sizeof(Vector3) + sizeof(Vector3) + sizeof(Quaternion)) {
|
||||
sizeof(Vector3) + sizeof(Vector3) + sizeof(Quaternion), 15 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -50,28 +48,44 @@ void FixedJointComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newJointEntities = static_cast<Entity*>(newBuffer);
|
||||
FixedJoint** newJoints = reinterpret_cast<FixedJoint**>(newJointEntities + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(newJoints + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(newLocalAnchorPointBody1 + nbComponentsToAllocate);
|
||||
Vector3* newR1World = reinterpret_cast<Vector3*>(newLocalAnchorPointBody2 + nbComponentsToAllocate);
|
||||
Vector3* newR2World = reinterpret_cast<Vector3*>(newR1World + nbComponentsToAllocate);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(newR2World + nbComponentsToAllocate);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(newI1 + nbComponentsToAllocate);
|
||||
Vector3* newImpulseTranslation = reinterpret_cast<Vector3*>(newI2 + nbComponentsToAllocate);
|
||||
Vector3* newImpulseRotation = reinterpret_cast<Vector3*>(newImpulseTranslation + nbComponentsToAllocate);
|
||||
Matrix3x3* newInverseMassMatrixTranslation = reinterpret_cast<Matrix3x3*>(newImpulseRotation + nbComponentsToAllocate);
|
||||
Matrix3x3* newInverseMassMatrixRotation = reinterpret_cast<Matrix3x3*>(newInverseMassMatrixTranslation + nbComponentsToAllocate);
|
||||
Vector3* newBiasTranslation = reinterpret_cast<Vector3*>(newInverseMassMatrixRotation + nbComponentsToAllocate);
|
||||
Vector3* newBiasRotation = reinterpret_cast<Vector3*>(newBiasTranslation + nbComponentsToAllocate);
|
||||
Quaternion* newInitOrientationDifferenceInv = reinterpret_cast<Quaternion*>(newBiasRotation + nbComponentsToAllocate);
|
||||
FixedJoint** newJoints = reinterpret_cast<FixedJoint**>(MemoryAllocator::alignAddress(newJointEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newJoints) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newJoints + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR1World = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR1World) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR2World = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR1World + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR2World) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newR2World + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI1) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newI1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newImpulseTranslation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newI2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newImpulseRotation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newImpulseTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newInverseMassMatrixTranslation = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newImpulseRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newInverseMassMatrixRotation = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newInverseMassMatrixTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newBiasTranslation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInverseMassMatrixRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBiasTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newBiasRotation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newBiasTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBiasRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Quaternion* newInitOrientationDifferenceInv = reinterpret_cast<Quaternion*>(MemoryAllocator::alignAddress(newBiasRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInitOrientationDifferenceInv) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newInitOrientationDifferenceInv + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -43,10 +43,8 @@ HingeJointComponents::HingeJointComponents(MemoryAllocator& allocator)
|
|||
sizeof(Vector3) + sizeof(decimal) + sizeof(decimal) + sizeof(decimal) +
|
||||
sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(decimal) +
|
||||
sizeof(bool) + sizeof(bool) + sizeof(decimal) + sizeof(decimal) +
|
||||
sizeof(bool) + sizeof(bool) + sizeof(decimal) + sizeof(decimal)) {
|
||||
sizeof(bool) + sizeof(bool) + sizeof(decimal) + sizeof(decimal), 35 * GLOBAL_ALIGNMENT ) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -55,48 +53,84 @@ void HingeJointComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newJointEntities = static_cast<Entity*>(newBuffer);
|
||||
HingeJoint** newJoints = reinterpret_cast<HingeJoint**>(newJointEntities + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(newJoints + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(newLocalAnchorPointBody1 + nbComponentsToAllocate);
|
||||
Vector3* newR1World = reinterpret_cast<Vector3*>(newLocalAnchorPointBody2 + nbComponentsToAllocate);
|
||||
Vector3* newR2World = reinterpret_cast<Vector3*>(newR1World + nbComponentsToAllocate);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(newR2World + nbComponentsToAllocate);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(newI1 + nbComponentsToAllocate);
|
||||
Vector3* newImpulseTranslation = reinterpret_cast<Vector3*>(newI2 + nbComponentsToAllocate);
|
||||
Vector2* newImpulseRotation = reinterpret_cast<Vector2*>(newImpulseTranslation + nbComponentsToAllocate);
|
||||
Matrix3x3* newInverseMassMatrixTranslation = reinterpret_cast<Matrix3x3*>(newImpulseRotation + nbComponentsToAllocate);
|
||||
Matrix2x2* newInverseMassMatrixRotation = reinterpret_cast<Matrix2x2*>(newInverseMassMatrixTranslation + nbComponentsToAllocate);
|
||||
Vector3* newBiasTranslation = reinterpret_cast<Vector3*>(newInverseMassMatrixRotation + nbComponentsToAllocate);
|
||||
Vector2* newBiasRotation = reinterpret_cast<Vector2*>(newBiasTranslation + nbComponentsToAllocate);
|
||||
Quaternion* newInitOrientationDifferenceInv = reinterpret_cast<Quaternion*>(newBiasRotation + nbComponentsToAllocate);
|
||||
Vector3* newHingeLocalAxisBody1 = reinterpret_cast<Vector3*>(newInitOrientationDifferenceInv + nbComponentsToAllocate);
|
||||
Vector3* newHingeLocalAxisBody2 = reinterpret_cast<Vector3*>(newHingeLocalAxisBody1 + nbComponentsToAllocate);
|
||||
Vector3* newA1 = reinterpret_cast<Vector3*>(newHingeLocalAxisBody2 + nbComponentsToAllocate);
|
||||
Vector3* newB2CrossA1 = reinterpret_cast<Vector3*>(newA1 + nbComponentsToAllocate);
|
||||
Vector3* newC2CrossA1 = reinterpret_cast<Vector3*>(newB2CrossA1 + nbComponentsToAllocate);
|
||||
decimal* newImpulseLowerLimit = reinterpret_cast<decimal*>(newC2CrossA1 + nbComponentsToAllocate);
|
||||
decimal* newImpulseUpperLimit = reinterpret_cast<decimal*>(newImpulseLowerLimit + nbComponentsToAllocate);
|
||||
decimal* newImpulseMotor = reinterpret_cast<decimal*>(newImpulseUpperLimit + nbComponentsToAllocate);
|
||||
decimal* newInverseMassMatrixLimitMotor = reinterpret_cast<decimal*>(newImpulseMotor + nbComponentsToAllocate);
|
||||
decimal* newInverseMassMatrixMotor = reinterpret_cast<decimal*>(newInverseMassMatrixLimitMotor + nbComponentsToAllocate);
|
||||
decimal* newBLowerLimit = reinterpret_cast<decimal*>(newInverseMassMatrixMotor + nbComponentsToAllocate);
|
||||
decimal* newBUpperLimit = reinterpret_cast<decimal*>(newBLowerLimit + nbComponentsToAllocate);
|
||||
bool* newIsLimitEnabled = reinterpret_cast<bool*>(newBUpperLimit + nbComponentsToAllocate);
|
||||
bool* newIsMotorEnabled = reinterpret_cast<bool*>(newIsLimitEnabled + nbComponentsToAllocate);
|
||||
decimal* newLowerLimit = reinterpret_cast<decimal*>(newIsMotorEnabled + nbComponentsToAllocate);
|
||||
decimal* newUpperLimit = reinterpret_cast<decimal*>(newLowerLimit + nbComponentsToAllocate);
|
||||
bool* newIsLowerLimitViolated = reinterpret_cast<bool*>(newUpperLimit + nbComponentsToAllocate);
|
||||
bool* newIsUpperLimitViolated = reinterpret_cast<bool*>(newIsLowerLimitViolated + nbComponentsToAllocate);
|
||||
decimal* newMotorSpeed = reinterpret_cast<decimal*>(newIsUpperLimitViolated + nbComponentsToAllocate);
|
||||
decimal* newMaxMotorTorque = reinterpret_cast<decimal*>(newMotorSpeed + nbComponentsToAllocate);
|
||||
HingeJoint** newJoints = reinterpret_cast<HingeJoint**>(MemoryAllocator::alignAddress(newJointEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newJoints) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newJoints + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR1World = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR1World) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR2World = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR1World + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR2World) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newR2World + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI1) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newI1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newImpulseTranslation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newI2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector2* newImpulseRotation = reinterpret_cast<Vector2*>(MemoryAllocator::alignAddress(newImpulseTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newInverseMassMatrixTranslation = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newImpulseRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix2x2* newInverseMassMatrixRotation = reinterpret_cast<Matrix2x2*>(MemoryAllocator::alignAddress(newInverseMassMatrixTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newBiasTranslation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInverseMassMatrixRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBiasTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector2* newBiasRotation = reinterpret_cast<Vector2*>(MemoryAllocator::alignAddress(newBiasTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBiasRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Quaternion* newInitOrientationDifferenceInv = reinterpret_cast<Quaternion*>(MemoryAllocator::alignAddress(newBiasRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInitOrientationDifferenceInv) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newHingeLocalAxisBody1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInitOrientationDifferenceInv + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newHingeLocalAxisBody1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newHingeLocalAxisBody2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newHingeLocalAxisBody1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newHingeLocalAxisBody2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newA1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newHingeLocalAxisBody2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newA1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newB2CrossA1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newA1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newB2CrossA1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newC2CrossA1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newB2CrossA1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newC2CrossA1) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newImpulseLowerLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newC2CrossA1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseLowerLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newImpulseUpperLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newImpulseLowerLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseUpperLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newImpulseMotor = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newImpulseUpperLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseMotor) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newInverseMassMatrixLimitMotor = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newImpulseMotor + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixLimitMotor) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newInverseMassMatrixMotor = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newInverseMassMatrixLimitMotor + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixMotor) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newBLowerLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newInverseMassMatrixMotor + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBLowerLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newBUpperLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newBLowerLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBUpperLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsLimitEnabled = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newBUpperLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsLimitEnabled) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsMotorEnabled = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newIsLimitEnabled + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsMotorEnabled) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newLowerLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newIsMotorEnabled + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLowerLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newUpperLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newLowerLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newUpperLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsLowerLimitViolated = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newUpperLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsLowerLimitViolated) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsUpperLimitViolated = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newIsLowerLimitViolated + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsUpperLimitViolated) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newMotorSpeed = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newIsUpperLimitViolated + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newMotorSpeed) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newMaxMotorTorque = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newMotorSpeed + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newMaxMotorTorque) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newMaxMotorTorque + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -35,10 +35,8 @@ using namespace reactphysics3d;
|
|||
JointComponents::JointComponents(MemoryAllocator& allocator)
|
||||
:Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(Entity) + sizeof(Joint*) +
|
||||
sizeof(JointType) + sizeof(JointsPositionCorrectionTechnique) + sizeof(bool) +
|
||||
sizeof(bool)) {
|
||||
sizeof(bool), 8 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -47,21 +45,30 @@ void JointComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newJointsEntities = static_cast<Entity*>(newBuffer);
|
||||
Entity* newBody1Entities = reinterpret_cast<Entity*>(newJointsEntities + nbComponentsToAllocate);
|
||||
Entity* newBody2Entities = reinterpret_cast<Entity*>(newBody1Entities + nbComponentsToAllocate);
|
||||
Joint** newJoints = reinterpret_cast<Joint**>(newBody2Entities + nbComponentsToAllocate);
|
||||
JointType* newTypes = reinterpret_cast<JointType*>(newJoints + nbComponentsToAllocate);
|
||||
JointsPositionCorrectionTechnique* newPositionCorrectionTechniques = reinterpret_cast<JointsPositionCorrectionTechnique*>(newTypes + nbComponentsToAllocate);
|
||||
bool* newIsCollisionEnabled = reinterpret_cast<bool*>(newPositionCorrectionTechniques + nbComponentsToAllocate);
|
||||
bool* newIsAlreadyInIsland = reinterpret_cast<bool*>(newIsCollisionEnabled + nbComponentsToAllocate);
|
||||
Entity* newBody1Entities = reinterpret_cast<Entity*>(MemoryAllocator::alignAddress(newJointsEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBody1Entities) % GLOBAL_ALIGNMENT == 0);
|
||||
Entity* newBody2Entities = reinterpret_cast<Entity*>(MemoryAllocator::alignAddress(newBody1Entities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBody2Entities) % GLOBAL_ALIGNMENT == 0);
|
||||
Joint** newJoints = reinterpret_cast<Joint**>(MemoryAllocator::alignAddress(newBody2Entities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newJoints) % GLOBAL_ALIGNMENT == 0);
|
||||
JointType* newTypes = reinterpret_cast<JointType*>(MemoryAllocator::alignAddress(newJoints + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newTypes) % GLOBAL_ALIGNMENT == 0);
|
||||
JointsPositionCorrectionTechnique* newPositionCorrectionTechniques = reinterpret_cast<JointsPositionCorrectionTechnique*>(MemoryAllocator::alignAddress(newTypes + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newPositionCorrectionTechniques) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsCollisionEnabled = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newPositionCorrectionTechniques + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsCollisionEnabled) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsAlreadyInIsland = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newIsCollisionEnabled + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsAlreadyInIsland) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newIsAlreadyInIsland + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -44,10 +44,8 @@ RigidBodyComponents::RigidBodyComponents(MemoryAllocator& allocator)
|
|||
sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) +
|
||||
sizeof(Quaternion) + sizeof(Vector3) + sizeof(Vector3) +
|
||||
sizeof(bool) + sizeof(bool) + sizeof(Array<Entity>) + sizeof(Array<uint>) +
|
||||
sizeof(Vector3) + sizeof(Vector3)) {
|
||||
sizeof(Vector3) + sizeof(Vector3), 31 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -56,44 +54,76 @@ void RigidBodyComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newBodiesEntities = static_cast<Entity*>(newBuffer);
|
||||
RigidBody** newBodies = reinterpret_cast<RigidBody**>(newBodiesEntities + nbComponentsToAllocate);
|
||||
bool* newIsAllowedToSleep = reinterpret_cast<bool*>(newBodies + nbComponentsToAllocate);
|
||||
bool* newIsSleeping = reinterpret_cast<bool*>(newIsAllowedToSleep + nbComponentsToAllocate);
|
||||
decimal* newSleepTimes = reinterpret_cast<decimal*>(newIsSleeping + nbComponentsToAllocate);
|
||||
BodyType* newBodyTypes = reinterpret_cast<BodyType*>(newSleepTimes + nbComponentsToAllocate);
|
||||
Vector3* newLinearVelocities = reinterpret_cast<Vector3*>(newBodyTypes + nbComponentsToAllocate);
|
||||
Vector3* newAngularVelocities = reinterpret_cast<Vector3*>(newLinearVelocities + nbComponentsToAllocate);
|
||||
Vector3* newExternalForces = reinterpret_cast<Vector3*>(newAngularVelocities + nbComponentsToAllocate);
|
||||
Vector3* newExternalTorques = reinterpret_cast<Vector3*>(newExternalForces + nbComponentsToAllocate);
|
||||
decimal* newLinearDampings = reinterpret_cast<decimal*>(newExternalTorques + nbComponentsToAllocate);
|
||||
decimal* newAngularDampings = reinterpret_cast<decimal*>(newLinearDampings + nbComponentsToAllocate);
|
||||
decimal* newMasses = reinterpret_cast<decimal*>(newAngularDampings + nbComponentsToAllocate);
|
||||
decimal* newInverseMasses = reinterpret_cast<decimal*>(newMasses + nbComponentsToAllocate);
|
||||
Vector3* newInertiaTensorLocal = reinterpret_cast<Vector3*>(newInverseMasses + nbComponentsToAllocate);
|
||||
Vector3* newInertiaTensorLocalInverses = reinterpret_cast<Vector3*>(newInertiaTensorLocal + nbComponentsToAllocate);
|
||||
Matrix3x3* newInertiaTensorWorldInverses = reinterpret_cast<Matrix3x3*>(newInertiaTensorLocalInverses + nbComponentsToAllocate);
|
||||
Vector3* newConstrainedLinearVelocities = reinterpret_cast<Vector3*>(newInertiaTensorWorldInverses + nbComponentsToAllocate);
|
||||
Vector3* newConstrainedAngularVelocities = reinterpret_cast<Vector3*>(newConstrainedLinearVelocities + nbComponentsToAllocate);
|
||||
Vector3* newSplitLinearVelocities = reinterpret_cast<Vector3*>(newConstrainedAngularVelocities + nbComponentsToAllocate);
|
||||
Vector3* newSplitAngularVelocities = reinterpret_cast<Vector3*>(newSplitLinearVelocities + nbComponentsToAllocate);
|
||||
Vector3* newConstrainedPositions = reinterpret_cast<Vector3*>(newSplitAngularVelocities + nbComponentsToAllocate);
|
||||
Quaternion* newConstrainedOrientations = reinterpret_cast<Quaternion*>(newConstrainedPositions + nbComponentsToAllocate);
|
||||
Vector3* newCentersOfMassLocal = reinterpret_cast<Vector3*>(newConstrainedOrientations + nbComponentsToAllocate);
|
||||
Vector3* newCentersOfMassWorld = reinterpret_cast<Vector3*>(newCentersOfMassLocal + nbComponentsToAllocate);
|
||||
bool* newIsGravityEnabled = reinterpret_cast<bool*>(newCentersOfMassWorld + nbComponentsToAllocate);
|
||||
bool* newIsAlreadyInIsland = reinterpret_cast<bool*>(newIsGravityEnabled + nbComponentsToAllocate);
|
||||
Array<Entity>* newJoints = reinterpret_cast<Array<Entity>*>(newIsAlreadyInIsland + nbComponentsToAllocate);
|
||||
Array<uint>* newContactPairs = reinterpret_cast<Array<uint>*>(newJoints + nbComponentsToAllocate);
|
||||
Vector3* newLinearLockAxisFactors = reinterpret_cast<Vector3*>(newContactPairs + nbComponentsToAllocate);
|
||||
Vector3* newAngularLockAxisFactors = reinterpret_cast<Vector3*>(newLinearLockAxisFactors + nbComponentsToAllocate);
|
||||
RigidBody** newBodies = reinterpret_cast<RigidBody**>(MemoryAllocator::alignAddress(newBodiesEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBodies) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsAllowedToSleep = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newBodies + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsAllowedToSleep) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsSleeping = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newIsAllowedToSleep + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsSleeping) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newSleepTimes = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newIsSleeping + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newSleepTimes) % GLOBAL_ALIGNMENT == 0);
|
||||
BodyType* newBodyTypes = reinterpret_cast<BodyType*>(MemoryAllocator::alignAddress(newSleepTimes + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBodyTypes) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLinearVelocities = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newBodyTypes + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLinearVelocities) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newAngularVelocities = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLinearVelocities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newAngularVelocities) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newExternalForces = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newAngularVelocities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newExternalForces) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newExternalTorques = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newExternalForces + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newExternalTorques) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newLinearDampings = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newExternalTorques + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLinearDampings) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newAngularDampings = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newLinearDampings + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newAngularDampings) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newMasses = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newAngularDampings + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newMasses) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newInverseMasses = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newMasses + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMasses) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newInertiaTensorLocal = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInverseMasses + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInertiaTensorLocal) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newInertiaTensorLocalInverses = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInertiaTensorLocal + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInertiaTensorLocal) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newInertiaTensorWorldInverses = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newInertiaTensorLocalInverses + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInertiaTensorWorldInverses) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newConstrainedLinearVelocities = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInertiaTensorWorldInverses + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newConstrainedLinearVelocities) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newConstrainedAngularVelocities = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newConstrainedLinearVelocities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newConstrainedAngularVelocities) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newSplitLinearVelocities = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newConstrainedAngularVelocities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newSplitLinearVelocities) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newSplitAngularVelocities = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newSplitLinearVelocities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newSplitAngularVelocities) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newConstrainedPositions = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newSplitAngularVelocities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newConstrainedPositions) % GLOBAL_ALIGNMENT == 0);
|
||||
Quaternion* newConstrainedOrientations = reinterpret_cast<Quaternion*>(MemoryAllocator::alignAddress(newConstrainedPositions + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newConstrainedOrientations) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newCentersOfMassLocal = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newConstrainedOrientations + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newCentersOfMassLocal) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newCentersOfMassWorld = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newCentersOfMassLocal + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newCentersOfMassWorld) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsGravityEnabled = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newCentersOfMassWorld + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsGravityEnabled) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsAlreadyInIsland = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newIsGravityEnabled + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsAlreadyInIsland) % GLOBAL_ALIGNMENT == 0);
|
||||
Array<Entity>* newJoints = reinterpret_cast<Array<Entity>*>(MemoryAllocator::alignAddress(newIsAlreadyInIsland + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newJoints) % GLOBAL_ALIGNMENT == 0);
|
||||
Array<uint>* newContactPairs = reinterpret_cast<Array<uint>*>(MemoryAllocator::alignAddress(newJoints + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newContactPairs) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLinearLockAxisFactors = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newContactPairs + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLinearLockAxisFactors) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newAngularLockAxisFactors = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLinearLockAxisFactors + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newAngularLockAxisFactors) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newAngularLockAxisFactors + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -45,10 +45,8 @@ SliderJointComponents::SliderJointComponents(MemoryAllocator& allocator)
|
|||
sizeof(bool) + sizeof(bool) + sizeof(decimal) + sizeof(decimal) +
|
||||
sizeof(bool) + sizeof(bool) + sizeof(decimal) + sizeof(decimal) +
|
||||
sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) +
|
||||
sizeof(Vector3) + sizeof(Vector3)) {
|
||||
sizeof(Vector3) + sizeof(Vector3), 40 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -57,53 +55,94 @@ void SliderJointComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newJointEntities = static_cast<Entity*>(newBuffer);
|
||||
SliderJoint** newJoints = reinterpret_cast<SliderJoint**>(newJointEntities + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(newJoints + nbComponentsToAllocate);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(newLocalAnchorPointBody1 + nbComponentsToAllocate);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(newLocalAnchorPointBody2 + nbComponentsToAllocate);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(newI1 + nbComponentsToAllocate);
|
||||
Vector2* newImpulseTranslation = reinterpret_cast<Vector2*>(newI2 + nbComponentsToAllocate);
|
||||
Vector3* newImpulseRotation = reinterpret_cast<Vector3*>(newImpulseTranslation + nbComponentsToAllocate);
|
||||
Matrix2x2* newInverseMassMatrixTranslation = reinterpret_cast<Matrix2x2*>(newImpulseRotation + nbComponentsToAllocate);
|
||||
Matrix3x3* newInverseMassMatrixRotation = reinterpret_cast<Matrix3x3*>(newInverseMassMatrixTranslation + nbComponentsToAllocate);
|
||||
Vector2* newBiasTranslation = reinterpret_cast<Vector2*>(newInverseMassMatrixRotation + nbComponentsToAllocate);
|
||||
Vector3* newBiasRotation = reinterpret_cast<Vector3*>(newBiasTranslation + nbComponentsToAllocate);
|
||||
Quaternion* newInitOrientationDifferenceInv = reinterpret_cast<Quaternion*>(newBiasRotation + nbComponentsToAllocate);
|
||||
Vector3* newSliderAxisBody1 = reinterpret_cast<Vector3*>(newInitOrientationDifferenceInv + nbComponentsToAllocate);
|
||||
Vector3* newSliderAxisWorld = reinterpret_cast<Vector3*>(newSliderAxisBody1 + nbComponentsToAllocate);
|
||||
Vector3* newR1 = reinterpret_cast<Vector3*>(newSliderAxisWorld + nbComponentsToAllocate);
|
||||
Vector3* newR2 = reinterpret_cast<Vector3*>(newR1 + nbComponentsToAllocate);
|
||||
Vector3* newN1 = reinterpret_cast<Vector3*>(newR2 + nbComponentsToAllocate);
|
||||
Vector3* newN2 = reinterpret_cast<Vector3*>(newN1 + nbComponentsToAllocate);
|
||||
decimal* newImpulseLowerLimit = reinterpret_cast<decimal*>(newN2 + nbComponentsToAllocate);
|
||||
decimal* newImpulseUpperLimit = reinterpret_cast<decimal*>(newImpulseLowerLimit + nbComponentsToAllocate);
|
||||
decimal* newImpulseMotor = reinterpret_cast<decimal*>(newImpulseUpperLimit + nbComponentsToAllocate);
|
||||
decimal* newInverseMassMatrixLimit = reinterpret_cast<decimal*>(newImpulseMotor + nbComponentsToAllocate);
|
||||
decimal* newInverseMassMatrixMotor = reinterpret_cast<decimal*>(newInverseMassMatrixLimit + nbComponentsToAllocate);
|
||||
decimal* newBLowerLimit = reinterpret_cast<decimal*>(newInverseMassMatrixMotor + nbComponentsToAllocate);
|
||||
decimal* newBUpperLimit = reinterpret_cast<decimal*>(newBLowerLimit + nbComponentsToAllocate);
|
||||
bool* newIsLimitEnabled = reinterpret_cast<bool*>(newBUpperLimit + nbComponentsToAllocate);
|
||||
bool* newIsMotorEnabled = reinterpret_cast<bool*>(newIsLimitEnabled + nbComponentsToAllocate);
|
||||
decimal* newLowerLimit = reinterpret_cast<decimal*>(newIsMotorEnabled + nbComponentsToAllocate);
|
||||
decimal* newUpperLimit = reinterpret_cast<decimal*>(newLowerLimit + nbComponentsToAllocate);
|
||||
bool* newIsLowerLimitViolated = reinterpret_cast<bool*>(newUpperLimit + nbComponentsToAllocate);
|
||||
bool* newIsUpperLimitViolated = reinterpret_cast<bool*>(newIsLowerLimitViolated + nbComponentsToAllocate);
|
||||
decimal* newMotorSpeed = reinterpret_cast<decimal*>(newIsUpperLimitViolated + nbComponentsToAllocate);
|
||||
decimal* newMaxMotorForce = reinterpret_cast<decimal*>(newMotorSpeed + nbComponentsToAllocate);
|
||||
Vector3* newR2CrossN1 = reinterpret_cast<Vector3*>(newMaxMotorForce + nbComponentsToAllocate);
|
||||
Vector3* newR2CrossN2 = reinterpret_cast<Vector3*>(newR2CrossN1 + nbComponentsToAllocate);
|
||||
Vector3* newR2CrossSliderAxis = reinterpret_cast<Vector3*>(newR2CrossN2 + nbComponentsToAllocate);
|
||||
Vector3* newR1PlusUCrossN1 = reinterpret_cast<Vector3*>(newR2CrossSliderAxis + nbComponentsToAllocate);
|
||||
Vector3* newR1PlusUCrossN2 = reinterpret_cast<Vector3*>(newR1PlusUCrossN1 + nbComponentsToAllocate);
|
||||
Vector3* newR1PlusUCrossSliderAxis = reinterpret_cast<Vector3*>(newR1PlusUCrossN2 + nbComponentsToAllocate);
|
||||
SliderJoint** newJoints = reinterpret_cast<SliderJoint**>(MemoryAllocator::alignAddress(newJointEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newJoints) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newJoints + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newLocalAnchorPointBody2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLocalAnchorPointBody2) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI1 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newLocalAnchorPointBody2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI1) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newI2 = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newI1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newI2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector2* newImpulseTranslation = reinterpret_cast<Vector2*>(MemoryAllocator::alignAddress(newI2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newImpulseRotation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newImpulseTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix2x2* newInverseMassMatrixTranslation = reinterpret_cast<Matrix2x2*>(MemoryAllocator::alignAddress(newImpulseRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Matrix3x3* newInverseMassMatrixRotation = reinterpret_cast<Matrix3x3*>(MemoryAllocator::alignAddress(newInverseMassMatrixTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector2* newBiasTranslation = reinterpret_cast<Vector2*>(MemoryAllocator::alignAddress(newInverseMassMatrixRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBiasTranslation) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newBiasRotation = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newBiasTranslation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBiasRotation) % GLOBAL_ALIGNMENT == 0);
|
||||
Quaternion* newInitOrientationDifferenceInv = reinterpret_cast<Quaternion*>(MemoryAllocator::alignAddress(newBiasRotation + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInitOrientationDifferenceInv) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newSliderAxisBody1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newInitOrientationDifferenceInv + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newSliderAxisBody1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newSliderAxisWorld = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newSliderAxisBody1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newSliderAxisWorld) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newSliderAxisWorld + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newN1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newN1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newN2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newN1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newN2) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newImpulseLowerLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newN2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseLowerLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newImpulseUpperLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newImpulseLowerLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseUpperLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newImpulseMotor = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newImpulseUpperLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newImpulseMotor) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newInverseMassMatrixLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newImpulseMotor + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newInverseMassMatrixMotor = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newInverseMassMatrixLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newInverseMassMatrixMotor) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newBLowerLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newInverseMassMatrixMotor + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBLowerLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newBUpperLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newBLowerLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newBUpperLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsLimitEnabled = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newBUpperLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsLimitEnabled) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsMotorEnabled = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newIsLimitEnabled + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsMotorEnabled) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newLowerLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newIsMotorEnabled + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newLowerLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newUpperLimit = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newLowerLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newUpperLimit) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsLowerLimitViolated = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newUpperLimit + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsLowerLimitViolated) % GLOBAL_ALIGNMENT == 0);
|
||||
bool* newIsUpperLimitViolated = reinterpret_cast<bool*>(MemoryAllocator::alignAddress(newIsLowerLimitViolated + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newIsUpperLimitViolated) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newMotorSpeed = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newIsUpperLimitViolated + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newMotorSpeed) % GLOBAL_ALIGNMENT == 0);
|
||||
decimal* newMaxMotorForce = reinterpret_cast<decimal*>(MemoryAllocator::alignAddress(newMotorSpeed + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newMaxMotorForce) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR2CrossN1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newMaxMotorForce + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR2CrossN1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR2CrossN2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR2CrossN1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR2CrossN2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR2CrossSliderAxis = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR2CrossN2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR2CrossSliderAxis) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR1PlusUCrossN1 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR2CrossSliderAxis + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR1PlusUCrossN1) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR1PlusUCrossN2 = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR1PlusUCrossN1 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR1PlusUCrossN2) % GLOBAL_ALIGNMENT == 0);
|
||||
Vector3* newR1PlusUCrossSliderAxis = reinterpret_cast<Vector3*>(MemoryAllocator::alignAddress(newR1PlusUCrossN2 + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newR1PlusUCrossSliderAxis) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newR1PlusUCrossSliderAxis + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
// Libraries
|
||||
#include <reactphysics3d/components/TransformComponents.h>
|
||||
#include <reactphysics3d/engine/EntityManager.h>
|
||||
#include <reactphysics3d/memory/MemoryAllocator.h>
|
||||
#include <cassert>
|
||||
#include <random>
|
||||
|
||||
|
@ -35,10 +36,9 @@ using namespace reactphysics3d;
|
|||
|
||||
// Constructor
|
||||
TransformComponents::TransformComponents(MemoryAllocator& allocator)
|
||||
:Components(allocator, sizeof(Entity) + sizeof(Transform)) {
|
||||
:Components(allocator, sizeof(Entity) + sizeof(Transform), 2 * GLOBAL_ALIGNMENT) {
|
||||
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -47,15 +47,19 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize + mAlignmentMarginSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
assert(newBuffer != nullptr);
|
||||
assert(reinterpret_cast<uintptr_t>(newBuffer) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// New pointers to components data
|
||||
Entity* newEntities = static_cast<Entity*>(newBuffer);
|
||||
Transform* newTransforms = reinterpret_cast<Transform*>(newEntities + nbComponentsToAllocate);
|
||||
assert(reinterpret_cast<uintptr_t>(newEntities) % GLOBAL_ALIGNMENT == 0);
|
||||
Transform* newTransforms = reinterpret_cast<Transform*>(MemoryAllocator::alignAddress(newEntities + nbComponentsToAllocate, GLOBAL_ALIGNMENT));
|
||||
assert(reinterpret_cast<uintptr_t>(newTransforms) % GLOBAL_ALIGNMENT == 0);
|
||||
assert(reinterpret_cast<uintptr_t>(newTransforms + nbComponentsToAllocate) <= reinterpret_cast<uintptr_t>(newBuffer) + totalSizeBytes);
|
||||
|
||||
// If there was already components before
|
||||
if (mNbComponents > 0) {
|
||||
|
|
|
@ -106,6 +106,16 @@ PhysicsWorld::PhysicsWorld(MemoryManager& memoryManager, PhysicsCommon& physicsC
|
|||
|
||||
mNbWorlds++;
|
||||
|
||||
mTransformComponents.init();
|
||||
mCollidersComponents.init();
|
||||
mCollisionBodyComponents.init();
|
||||
mRigidBodyComponents.init();
|
||||
mJointsComponents.init();
|
||||
mBallAndSocketJointsComponents.init();
|
||||
mFixedJointsComponents.init();
|
||||
mSliderJointsComponents.init();
|
||||
mHingeJointsComponents.init();
|
||||
|
||||
RP3D_LOG(mConfig.worldName, Logger::Level::Information, Logger::Category::World,
|
||||
"Physics World: Physics world " + mName + " has been created", __FILE__, __LINE__);
|
||||
RP3D_LOG(mConfig.worldName, Logger::Level::Information, Logger::Category::World,
|
||||
|
|
|
@ -36,7 +36,7 @@ size_t HeapAllocator::INIT_ALLOCATED_SIZE = 5 * 1048576; // 5 Mb
|
|||
|
||||
// Constructor
|
||||
HeapAllocator::HeapAllocator(MemoryAllocator& baseAllocator, size_t initAllocatedMemory)
|
||||
: mBaseAllocator(baseAllocator), mAllocatedMemory(0), mMemoryUnits(nullptr), mCachedFreeUnit(nullptr) {
|
||||
: mBaseAllocator(baseAllocator), mAllocatedMemory(0), mMemoryUnits(nullptr), mFreeUnits(nullptr) {
|
||||
|
||||
#ifndef NDEBUG
|
||||
mNbTimesAllocateMethodCalled = 0;
|
||||
|
@ -55,12 +55,12 @@ HeapAllocator::~HeapAllocator() {
|
|||
#endif
|
||||
|
||||
// Release the memory allocated for memory unit
|
||||
MemoryUnitHeader* unit = mMemoryUnits;
|
||||
MemoryUnitHeader* unit = mFreeUnits;
|
||||
while (unit != nullptr) {
|
||||
|
||||
assert(!unit->isAllocated);
|
||||
|
||||
MemoryUnitHeader* nextUnit = unit->nextUnit;
|
||||
MemoryUnitHeader* nextUnit = unit->nextFreeUnit;
|
||||
|
||||
const size_t unitSize = unit->size;
|
||||
|
||||
|
@ -76,23 +76,24 @@ HeapAllocator::~HeapAllocator() {
|
|||
/// left over space. The second unit is put into the free memory units
|
||||
void HeapAllocator::splitMemoryUnit(MemoryUnitHeader* unit, size_t size) {
|
||||
|
||||
assert(size <= unit->size);
|
||||
assert(!unit->isAllocated);
|
||||
|
||||
// Split the free memory unit in two memory units, one with the requested memory size
|
||||
// and a second one with the left over space
|
||||
// If the size of the unit is large enough to be slit
|
||||
if (size + sizeof(MemoryUnitHeader) < unit->size) {
|
||||
|
||||
assert(unit->size - size > 0);
|
||||
|
||||
// Create a new memory unit with left over space
|
||||
unsigned char* newUnitLocation = (reinterpret_cast<unsigned char*>(unit)) + sizeof(MemoryUnitHeader) + size;
|
||||
MemoryUnitHeader* newUnit = new (static_cast<void*>(newUnitLocation)) MemoryUnitHeader(unit->size - sizeof(MemoryUnitHeader) - size, unit, unit->nextUnit, unit->isNextContiguousMemory);
|
||||
MemoryUnitHeader* newUnit = new (static_cast<void*>(newUnitLocation)) MemoryUnitHeader(unit->size - sizeof(MemoryUnitHeader) - size, unit, unit->nextUnit, unit, unit->nextFreeUnit, unit->isNextContiguousMemory);
|
||||
assert(newUnit->nextUnit != newUnit);
|
||||
unit->nextUnit = newUnit;
|
||||
unit->nextFreeUnit = newUnit;
|
||||
if (newUnit->nextUnit != nullptr) {
|
||||
newUnit->nextUnit->previousUnit = newUnit;
|
||||
}
|
||||
if (newUnit->nextFreeUnit != nullptr) {
|
||||
newUnit->nextFreeUnit->previousFreeUnit = newUnit;
|
||||
}
|
||||
|
||||
assert(unit->nextUnit != unit);
|
||||
unit->isNextContiguousMemory = true;
|
||||
unit->size = size;
|
||||
|
@ -100,9 +101,19 @@ void HeapAllocator::splitMemoryUnit(MemoryUnitHeader* unit, size_t size) {
|
|||
assert(unit->previousUnit == nullptr || unit->previousUnit->nextUnit == unit);
|
||||
assert(unit->nextUnit == nullptr || unit->nextUnit->previousUnit == unit);
|
||||
|
||||
assert(unit->previousFreeUnit == nullptr || unit->previousFreeUnit->nextFreeUnit == unit);
|
||||
assert(unit->nextFreeUnit == nullptr || unit->nextFreeUnit->previousFreeUnit == unit);
|
||||
|
||||
assert(newUnit->previousUnit == nullptr || newUnit->previousUnit->nextUnit == newUnit);
|
||||
assert(newUnit->nextUnit == nullptr || newUnit->nextUnit->previousUnit == newUnit);
|
||||
}
|
||||
|
||||
assert(newUnit->previousFreeUnit->nextFreeUnit == newUnit);
|
||||
assert(newUnit->nextFreeUnit == nullptr || newUnit->nextFreeUnit->previousFreeUnit == newUnit);
|
||||
|
||||
assert(unit->nextFreeUnit == newUnit);
|
||||
assert(newUnit->previousFreeUnit == unit);
|
||||
assert(!newUnit->isAllocated);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate memory of a given size (in bytes) and return a pointer to the
|
||||
|
@ -117,65 +128,86 @@ void* HeapAllocator::allocate(size_t size) {
|
|||
// We cannot allocate zero bytes
|
||||
if (size == 0) return nullptr;
|
||||
|
||||
// Allocate a little bit more memory to make sure we can return an aligned address
|
||||
const size_t totalSize = size + GLOBAL_ALIGNMENT;
|
||||
|
||||
#ifndef NDEBUG
|
||||
mNbTimesAllocateMethodCalled++;
|
||||
#endif
|
||||
|
||||
MemoryUnitHeader* currentUnit = mMemoryUnits;
|
||||
assert(mMemoryUnits->previousUnit == nullptr);
|
||||
MemoryUnitHeader* currentUnit = mFreeUnits;
|
||||
|
||||
// If there is a cached free memory unit
|
||||
if (mCachedFreeUnit != nullptr) {
|
||||
assert(!mCachedFreeUnit->isAllocated);
|
||||
|
||||
// If the cached free memory unit matches the request
|
||||
if (size <= mCachedFreeUnit->size) {
|
||||
currentUnit = mCachedFreeUnit;
|
||||
mCachedFreeUnit = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// For each memory unit
|
||||
// For each free memory unit
|
||||
while (currentUnit != nullptr) {
|
||||
|
||||
// If we have found a free memory unit with size large enough for the allocation request
|
||||
if (!currentUnit->isAllocated && size <= currentUnit->size) {
|
||||
assert(!currentUnit->isAllocated);
|
||||
|
||||
// Split the free memory unit in two memory units, one with the requested memory size
|
||||
// and a second one with the left over space
|
||||
splitMemoryUnit(currentUnit, size);
|
||||
// If we have found a free memory unit with size large enough for the allocation request
|
||||
if (totalSize <= currentUnit->size) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
currentUnit = currentUnit->nextUnit;
|
||||
assert(currentUnit->nextFreeUnit == nullptr || currentUnit->nextFreeUnit->previousFreeUnit == currentUnit);
|
||||
|
||||
currentUnit = currentUnit->nextFreeUnit;
|
||||
}
|
||||
|
||||
// If we have not found a large enough memory unit we need to allocate more memory
|
||||
// If we have not found a large enough free memory unit
|
||||
if (currentUnit == nullptr) {
|
||||
|
||||
reserve((mAllocatedMemory + size) * 2);
|
||||
// We need to allocate more memory
|
||||
reserve((mAllocatedMemory + totalSize) * 2);
|
||||
|
||||
assert(mCachedFreeUnit != nullptr);
|
||||
assert(!mCachedFreeUnit->isAllocated);
|
||||
assert(mFreeUnits != nullptr);
|
||||
|
||||
// The cached free memory unit is large enough at this point
|
||||
currentUnit = mCachedFreeUnit;
|
||||
|
||||
assert(currentUnit->size >= size);
|
||||
|
||||
splitMemoryUnit(currentUnit, size);
|
||||
currentUnit = mFreeUnits;
|
||||
}
|
||||
|
||||
// Split the free memory unit in two memory units, one with the requested memory size
|
||||
// and a second one with the left over space
|
||||
splitMemoryUnit(currentUnit, totalSize);
|
||||
|
||||
assert(currentUnit->size >= totalSize);
|
||||
assert(!currentUnit->isAllocated);
|
||||
|
||||
currentUnit->isAllocated = true;
|
||||
|
||||
// Cache the next memory unit if it is not allocated
|
||||
if (currentUnit->nextUnit != nullptr && !currentUnit->nextUnit->isAllocated) {
|
||||
mCachedFreeUnit = currentUnit->nextUnit;
|
||||
}
|
||||
removeFromFreeUnits(currentUnit);
|
||||
|
||||
// Return a pointer to the memory area inside the unit
|
||||
return static_cast<void*>(reinterpret_cast<unsigned char*>(currentUnit) + sizeof(MemoryUnitHeader));
|
||||
void* allocatedMemory = static_cast<void*>(reinterpret_cast<unsigned char*>(currentUnit) + sizeof(MemoryUnitHeader));
|
||||
|
||||
// Offset the allocated address such that it is properly aligned
|
||||
allocatedMemory = computeAlignedAddress(allocatedMemory);
|
||||
|
||||
// Check that allocated memory is 16-bytes aligned
|
||||
assert(reinterpret_cast<uintptr_t>(allocatedMemory) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
return allocatedMemory;
|
||||
}
|
||||
|
||||
// Return the next aligned memory address
|
||||
void* HeapAllocator::computeAlignedAddress(void* unalignedAddress) {
|
||||
|
||||
// Take care of alignment to make sure that we always return an address to the
|
||||
// enforce the global alignment of the library
|
||||
|
||||
// Compute the aligned address
|
||||
ptrdiff_t alignmentOffset;
|
||||
void* alignedPointer = alignAddress(unalignedAddress, GLOBAL_ALIGNMENT, alignmentOffset);
|
||||
|
||||
uintptr_t alignedAddress = reinterpret_cast<uintptr_t>(alignedPointer);
|
||||
|
||||
// Store the adjustment in the byte immediately preceding the adjusted address.
|
||||
// This way we can find again the original allocated memory address returned by malloc
|
||||
// when this memory unit is released.
|
||||
assert(alignmentOffset <= GLOBAL_ALIGNMENT);
|
||||
uint8* pAlignedMemory = reinterpret_cast<uint8*>(alignedAddress);
|
||||
pAlignedMemory[-1] = static_cast<uint8>(alignmentOffset);
|
||||
|
||||
return alignedPointer;
|
||||
}
|
||||
|
||||
// Release previously allocated memory.
|
||||
|
@ -193,9 +225,19 @@ void HeapAllocator::release(void* pointer, size_t size) {
|
|||
mNbTimesAllocateMethodCalled--;
|
||||
#endif
|
||||
|
||||
unsigned char* unitLocation = static_cast<unsigned char*>(pointer) - sizeof(MemoryUnitHeader);
|
||||
// Read the alignment offset in order to compute the initial allocated
|
||||
// raw address (instead of the aligned address)
|
||||
const uint8* pAlignedMemory = reinterpret_cast<const uint8*>(pointer);
|
||||
const uintptr_t alignedAddress = reinterpret_cast<uintptr_t>(pAlignedMemory);
|
||||
const ptrdiff_t alignmentOffset = static_cast<ptrdiff_t>(pAlignedMemory[-1]);
|
||||
const uintptr_t initialAddress = alignedAddress - alignmentOffset;
|
||||
void* pInitialAddress = reinterpret_cast<void*>(initialAddress);
|
||||
|
||||
unsigned char* unitLocation = static_cast<unsigned char*>(pInitialAddress) - sizeof(MemoryUnitHeader);
|
||||
MemoryUnitHeader* unit = reinterpret_cast<MemoryUnitHeader*>(unitLocation);
|
||||
assert(unit->isAllocated);
|
||||
assert(unit->nextFreeUnit == nullptr);
|
||||
assert(unit->previousFreeUnit == nullptr);
|
||||
unit->isAllocated = false;
|
||||
|
||||
MemoryUnitHeader* currentUnit = unit;
|
||||
|
@ -203,6 +245,8 @@ void HeapAllocator::release(void* pointer, size_t size) {
|
|||
// If the previous unit is not allocated and memory is contiguous to the current unit
|
||||
if (unit->previousUnit != nullptr && !unit->previousUnit->isAllocated && unit->previousUnit->isNextContiguousMemory) {
|
||||
|
||||
removeFromFreeUnits(unit->previousUnit);
|
||||
|
||||
currentUnit = unit->previousUnit;
|
||||
|
||||
// Merge the two contiguous memory units
|
||||
|
@ -212,11 +256,40 @@ void HeapAllocator::release(void* pointer, size_t size) {
|
|||
// If the next unit is not allocated and memory is contiguous to the current unit
|
||||
if (currentUnit->nextUnit != nullptr && !currentUnit->nextUnit->isAllocated && currentUnit->isNextContiguousMemory) {
|
||||
|
||||
removeFromFreeUnits(unit->nextUnit);
|
||||
|
||||
// Merge the two contiguous memory units
|
||||
mergeUnits(currentUnit, currentUnit->nextUnit);
|
||||
}
|
||||
|
||||
mCachedFreeUnit = currentUnit;
|
||||
addToFreeUnits(currentUnit);
|
||||
}
|
||||
|
||||
// Add the unit from the linked-list of free units
|
||||
void HeapAllocator::addToFreeUnits(MemoryUnitHeader* unit) {
|
||||
|
||||
if (mFreeUnits != nullptr) {
|
||||
assert(mFreeUnits->previousFreeUnit == nullptr);
|
||||
mFreeUnits->previousFreeUnit = unit;
|
||||
}
|
||||
unit->nextFreeUnit = mFreeUnits;
|
||||
mFreeUnits = unit;
|
||||
}
|
||||
|
||||
// Remove the unit from the linked-list of free units
|
||||
void HeapAllocator::removeFromFreeUnits(MemoryUnitHeader* unit) {
|
||||
|
||||
if (unit->previousFreeUnit != nullptr) {
|
||||
unit->previousFreeUnit->nextFreeUnit = unit->nextFreeUnit;
|
||||
}
|
||||
if (unit->nextFreeUnit != nullptr) {
|
||||
unit->nextFreeUnit->previousFreeUnit = unit->previousFreeUnit;
|
||||
}
|
||||
if (unit == mFreeUnits) {
|
||||
mFreeUnits = unit->nextFreeUnit;
|
||||
}
|
||||
unit->nextFreeUnit = nullptr;
|
||||
unit->previousFreeUnit = nullptr;
|
||||
}
|
||||
|
||||
// Merge two contiguous memory units that are not allocated.
|
||||
|
@ -251,8 +324,17 @@ void HeapAllocator::reserve(size_t sizeToAllocate) {
|
|||
void* memory = mBaseAllocator.allocate(sizeToAllocate + sizeof(MemoryUnitHeader));
|
||||
assert(memory != nullptr);
|
||||
|
||||
// Check that allocated memory is 16-bytes aligned
|
||||
assert(reinterpret_cast<uintptr_t>(memory) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// Create a new memory unit for the allocated memory
|
||||
MemoryUnitHeader* memoryUnit = new (memory) MemoryUnitHeader(sizeToAllocate, nullptr, mMemoryUnits, false);
|
||||
MemoryUnitHeader* memoryUnit = new (memory) MemoryUnitHeader(sizeToAllocate, nullptr, mMemoryUnits, nullptr, mFreeUnits, false);
|
||||
|
||||
if (mFreeUnits != nullptr) {
|
||||
|
||||
assert(mFreeUnits->previousFreeUnit == nullptr);
|
||||
mFreeUnits->previousFreeUnit = memoryUnit;
|
||||
}
|
||||
|
||||
if (mMemoryUnits != nullptr) {
|
||||
mMemoryUnits->previousUnit = memoryUnit;
|
||||
|
@ -260,8 +342,7 @@ void HeapAllocator::reserve(size_t sizeToAllocate) {
|
|||
|
||||
// Add the memory unit at the beginning of the linked-list of memory units
|
||||
mMemoryUnits = memoryUnit;
|
||||
|
||||
mCachedFreeUnit = mMemoryUnits;
|
||||
mFreeUnits = mMemoryUnits;
|
||||
|
||||
mAllocatedMemory += sizeToAllocate;
|
||||
}
|
||||
|
|
71
src/memory/MemoryAllocator.cpp
Normal file
71
src/memory/MemoryAllocator.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
/********************************************************************************
|
||||
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
||||
* Copyright (c) 2010-2022 Daniel Chappuis *
|
||||
*********************************************************************************
|
||||
* *
|
||||
* This software is provided 'as-is', without any express or implied warranty. *
|
||||
* In no event will the authors be held liable for any damages arising from the *
|
||||
* use of this software. *
|
||||
* *
|
||||
* Permission is granted to anyone to use this software for any purpose, *
|
||||
* including commercial applications, and to alter it and redistribute it *
|
||||
* freely, subject to the following restrictions: *
|
||||
* *
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim *
|
||||
* that you wrote the original software. If you use this software in a *
|
||||
* product, an acknowledgment in the product documentation would be *
|
||||
* appreciated but is not required. *
|
||||
* *
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be *
|
||||
* misrepresented as being the original software. *
|
||||
* *
|
||||
* 3. This notice may not be removed or altered from any source distribution. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
// Libraries
|
||||
#include <reactphysics3d/memory/MemoryAllocator.h>
|
||||
#include <cassert>
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
/// Given a pointer to memory, this method returns the next aligned address
|
||||
/**
|
||||
* @param pointer Pointer to a memory location
|
||||
* @param alignment Desired alignment
|
||||
* @return Pointer to the next aligned memory location
|
||||
*/
|
||||
void* MemoryAllocator::alignAddress(void* pointer, std::uint8_t alignment) {
|
||||
|
||||
ptrdiff_t alignmentOffset;
|
||||
return alignAddress(pointer, alignment, alignmentOffset);
|
||||
}
|
||||
|
||||
/// Given a pointer to memory, this method returns the next aligned address and also output the alignment offset
|
||||
/**
|
||||
* @param pointer Pointer to a memory location
|
||||
* @param alignment Desired alignment
|
||||
* @param outAlignmentOffset Output alignment offset needed to align the initial pointer
|
||||
* @return Pointer to the next aligned memory location
|
||||
*/
|
||||
void* MemoryAllocator::alignAddress(void* pointer, std::uint8_t alignment, ptrdiff_t& outAlignmentOffset) {
|
||||
|
||||
// Take care of alignment to make sure that we always return an address to the
|
||||
// enforce the global alignment of the library
|
||||
const uintptr_t currentAdress = reinterpret_cast<uintptr_t>(pointer);
|
||||
|
||||
// Calculate the adjustment by masking off the lower bits of the address, to determine how "misaligned" it is.
|
||||
const size_t mask = alignment - 1;
|
||||
const uintptr_t misalignment = currentAdress & mask;
|
||||
outAlignmentOffset = alignment - misalignment;
|
||||
assert(outAlignmentOffset <= alignment);
|
||||
|
||||
// Compute the aligned address
|
||||
const uintptr_t alignedAdress = currentAdress + outAlignmentOffset;
|
||||
void* alignedPointer = reinterpret_cast<void*>(alignedAdress);
|
||||
|
||||
// Check that allocated memory is correctly aligned
|
||||
assert(reinterpret_cast<uintptr_t>(alignedPointer) % alignment == 0);
|
||||
|
||||
return alignedPointer;
|
||||
}
|
|
@ -57,7 +57,7 @@ PoolAllocator::PoolAllocator(MemoryAllocator& baseAllocator) : mBaseAllocator(ba
|
|||
// Initialize the array that contains the sizes of the memory units that will
|
||||
// be allocated in each different heap
|
||||
for (uint i=0; i < NB_HEAPS; i++) {
|
||||
mUnitSizes[i] = (i+1) * 8;
|
||||
mUnitSizes[i] = (i+1) * MIN_UNIT_SIZE;
|
||||
}
|
||||
|
||||
// Initialize the lookup table that maps the size to allocated to the
|
||||
|
@ -116,7 +116,12 @@ void* PoolAllocator::allocate(size_t size) {
|
|||
if (size > MAX_UNIT_SIZE) {
|
||||
|
||||
// Allocate memory using default allocation
|
||||
return mBaseAllocator.allocate(size);
|
||||
void* allocatedMemory = mBaseAllocator.allocate(size);
|
||||
|
||||
// Check that allocated memory is 16-bytes aligned
|
||||
assert(reinterpret_cast<uintptr_t>(allocatedMemory) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
return allocatedMemory;
|
||||
}
|
||||
|
||||
// Get the index of the heap that will take care of the allocation request
|
||||
|
@ -129,7 +134,13 @@ void* PoolAllocator::allocate(size_t size) {
|
|||
// Return a pointer to the memory unit
|
||||
MemoryUnit* unit = mFreeMemoryUnits[indexHeap];
|
||||
mFreeMemoryUnits[indexHeap] = unit->nextUnit;
|
||||
return unit;
|
||||
|
||||
void* allocatedMemory = static_cast<void*>(unit);
|
||||
|
||||
// Check that allocated memory is 16-bytes aligned
|
||||
assert(reinterpret_cast<uintptr_t>(allocatedMemory) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
return allocatedMemory;
|
||||
}
|
||||
else { // If there is no more free memory units in the corresponding heap
|
||||
|
||||
|
@ -170,8 +181,13 @@ void* PoolAllocator::allocate(size_t size) {
|
|||
mFreeMemoryUnits[indexHeap] = newBlock->memoryUnits->nextUnit;
|
||||
mNbCurrentMemoryBlocks++;
|
||||
|
||||
void* allocatedMemory = newBlock->memoryUnits;
|
||||
|
||||
// Check that allocated memory is 16-bytes aligned
|
||||
assert(reinterpret_cast<uintptr_t>(allocatedMemory) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// Return the pointer to the first memory unit of the new allocated block
|
||||
return newBlock->memoryUnits;
|
||||
return allocatedMemory;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,11 +34,17 @@ using namespace reactphysics3d;
|
|||
// Constructor
|
||||
SingleFrameAllocator::SingleFrameAllocator(MemoryAllocator& baseAllocator) : mBaseAllocator(baseAllocator),
|
||||
mTotalSizeBytes(INIT_SINGLE_FRAME_ALLOCATOR_NB_BYTES),
|
||||
mCurrentOffset(0), mNbFramesTooMuchAllocated(0), mNeedToAllocatedMore(false) {
|
||||
mCurrentOffset(0), mNeedToAllocatedMore(false) {
|
||||
|
||||
// Allocate a whole block of memory at the beginning
|
||||
mMemoryBufferStart = static_cast<char*>(mBaseAllocator.allocate(mTotalSizeBytes));
|
||||
assert(mMemoryBufferStart != nullptr);
|
||||
void* allocatedMemory = mBaseAllocator.allocate(mTotalSizeBytes);
|
||||
|
||||
assert(allocatedMemory != nullptr);
|
||||
|
||||
// Check that allocated memory is 16-bytes aligned
|
||||
assert(reinterpret_cast<uintptr_t>(allocatedMemory) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
mMemoryBufferStart = static_cast<char*>(allocatedMemory);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
@ -48,29 +54,37 @@ SingleFrameAllocator::~SingleFrameAllocator() {
|
|||
mBaseAllocator.release(mMemoryBufferStart, mTotalSizeBytes);
|
||||
}
|
||||
|
||||
|
||||
// Allocate memory of a given size (in bytes) and return a pointer to the
|
||||
// allocated memory.
|
||||
// allocated memory. Allocated memory must be 16-bytes aligned.
|
||||
void* SingleFrameAllocator::allocate(size_t size) {
|
||||
|
||||
// Lock the method with a mutex
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
// Allocate a little bit more memory to make sure we can return an aligned address
|
||||
const size_t totalSize = size + GLOBAL_ALIGNMENT;
|
||||
|
||||
// Check that there is enough remaining memory in the buffer
|
||||
if (mCurrentOffset + size > mTotalSizeBytes) {
|
||||
if (mCurrentOffset + totalSize > mTotalSizeBytes) {
|
||||
|
||||
// We need to allocate more memory next time reset() is called
|
||||
mNeedToAllocatedMore = true;
|
||||
mNeedToAllocatedMore = true;
|
||||
|
||||
// Return default memory allocation
|
||||
return mBaseAllocator.allocate(size);
|
||||
// Return default memory allocation
|
||||
return mBaseAllocator.allocate(size);
|
||||
}
|
||||
|
||||
// Next available memory location
|
||||
void* nextAvailableMemory = mMemoryBufferStart + mCurrentOffset;
|
||||
|
||||
// Compute the next aligned memory address
|
||||
nextAvailableMemory = alignAddress(nextAvailableMemory, GLOBAL_ALIGNMENT);
|
||||
|
||||
// Increment the offset
|
||||
mCurrentOffset += size;
|
||||
mCurrentOffset += totalSize;
|
||||
|
||||
// Check that allocated memory is 16-bytes aligned
|
||||
assert(reinterpret_cast<uintptr_t>(nextAvailableMemory) % GLOBAL_ALIGNMENT == 0);
|
||||
|
||||
// Return the next available memory location
|
||||
return nextAvailableMemory;
|
||||
|
@ -97,31 +111,6 @@ void SingleFrameAllocator::reset() {
|
|||
// Lock the method with a mutex
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
// If too much memory is allocated
|
||||
if (mCurrentOffset < mTotalSizeBytes / 2) {
|
||||
|
||||
mNbFramesTooMuchAllocated++;
|
||||
|
||||
if (mNbFramesTooMuchAllocated > NB_FRAMES_UNTIL_SHRINK) {
|
||||
|
||||
// Release the memory allocated at the beginning
|
||||
mBaseAllocator.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*>(mBaseAllocator.allocate(mTotalSizeBytes));
|
||||
assert(mMemoryBufferStart != nullptr);
|
||||
|
||||
mNbFramesTooMuchAllocated = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mNbFramesTooMuchAllocated = 0;
|
||||
}
|
||||
|
||||
// If we need to allocate more memory
|
||||
if (mNeedToAllocatedMore) {
|
||||
|
||||
|
@ -136,7 +125,6 @@ void SingleFrameAllocator::reset() {
|
|||
assert(mMemoryBufferStart != nullptr);
|
||||
|
||||
mNeedToAllocatedMore = false;
|
||||
mNbFramesTooMuchAllocated = 0;
|
||||
}
|
||||
|
||||
// Reset the current offset at the beginning of the block
|
||||
|
|
Loading…
Reference in New Issue
Block a user