Merge branch 'memory' into develop

This commit is contained in:
Daniel Chappuis 2022-03-29 21:09:23 +02:00
commit d7cf8bcf17
25 changed files with 717 additions and 320 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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