Refactor components
This commit is contained in:
parent
d02b25d32a
commit
91416ae5ba
|
@ -231,6 +231,7 @@ SET (REACTPHYSICS3D_SOURCES
|
|||
"src/engine/Entity.cpp"
|
||||
"src/engine/EntityManager.cpp"
|
||||
"src/systems/BroadPhaseSystem.cpp"
|
||||
"src/components/Components.cpp"
|
||||
"src/components/BodyComponents.cpp"
|
||||
"src/components/TransformComponents.cpp"
|
||||
"src/components/ProxyShapesComponents.cpp"
|
||||
|
|
|
@ -34,30 +34,10 @@ using namespace reactphysics3d;
|
|||
|
||||
// Constructor
|
||||
BodyComponents::BodyComponents(MemoryAllocator& allocator)
|
||||
:Components(allocator), mSleepingStartIndex(0){
|
||||
:Components(allocator, sizeof(Entity) + sizeof(Body*) + sizeof(List<Entity>)) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
BodyComponents::~BodyComponents() {
|
||||
|
||||
if (mNbAllocatedComponents > 0) {
|
||||
|
||||
// Destroy all the remaining components
|
||||
for (uint32 i = 0; i < mNbComponents; i++) {
|
||||
|
||||
// TODO : MAke sure we do not delete already deleted components
|
||||
destroyComponent(i);
|
||||
}
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = mNbAllocatedComponents * COMPONENT_DATA_SIZE;
|
||||
|
||||
// Release the allocated memory
|
||||
mMemoryAllocator.release(mBuffer, totalSizeBytes);
|
||||
}
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -66,7 +46,7 @@ void BodyComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * COMPONENT_DATA_SIZE;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
|
@ -86,7 +66,7 @@ void BodyComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(List<Entity>));
|
||||
|
||||
// Deallocate previous memory
|
||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize);
|
||||
}
|
||||
|
||||
mBuffer = newBuffer;
|
||||
|
@ -99,35 +79,8 @@ void BodyComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
// Add a component
|
||||
void BodyComponents::addComponent(Entity bodyEntity, bool isSleeping, const BodyComponent& component) {
|
||||
|
||||
// If we need to allocate more components
|
||||
if (mNbComponents == mNbAllocatedComponents) {
|
||||
allocate(mNbAllocatedComponents * 2);
|
||||
}
|
||||
|
||||
uint32 index;
|
||||
|
||||
// If the component to add is part of a sleeping entity or there are no sleeping entity
|
||||
if (isSleeping) {
|
||||
|
||||
// Add the component at the end of the array
|
||||
index = mNbComponents;
|
||||
|
||||
mSleepingStartIndex = index;
|
||||
}
|
||||
// If the component to add is not part of a sleeping entity
|
||||
else {
|
||||
|
||||
// If there already are sleeping components
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// Move the first sleeping component to the end of the array
|
||||
moveComponentToIndex(mSleepingStartIndex, mNbComponents);
|
||||
}
|
||||
|
||||
index = mSleepingStartIndex;
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
// Prepare to add new component (allocate memory if necessary and compute insertion index)
|
||||
uint32 index = prepareAddComponent(isSleeping);
|
||||
|
||||
// Insert the new component data
|
||||
new (mBodiesEntities + index) Entity(bodyEntity);
|
||||
|
@ -143,95 +96,6 @@ void BodyComponents::addComponent(Entity bodyEntity, bool isSleeping, const Body
|
|||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Remove a component at a given index
|
||||
void BodyComponents::removeComponent(Entity bodyEntity) {
|
||||
|
||||
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||
|
||||
uint index = mMapEntityToComponentIndex[bodyEntity];
|
||||
|
||||
assert(index < mNbComponents);
|
||||
|
||||
// We want to keep the arrays tightly packed. Therefore, when a component is removed,
|
||||
// we replace it with the last element of the array. But we need to make sure that sleeping
|
||||
// and non-sleeping components stay grouped together.
|
||||
|
||||
// Destroy the component
|
||||
destroyComponent(index);
|
||||
|
||||
// If the component to remove is sleeping
|
||||
if (index >= mSleepingStartIndex) {
|
||||
|
||||
// If the component is not the last one
|
||||
if (index != mNbComponents - 1) {
|
||||
|
||||
// We replace it by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, index);
|
||||
}
|
||||
}
|
||||
else { // If the component to remove is not sleeping
|
||||
|
||||
// If it not the last awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// We replace it by the last awake component
|
||||
moveComponentToIndex(mSleepingStartIndex - 1, index);
|
||||
}
|
||||
|
||||
// If there are sleeping components at the end
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// We replace the last awake component by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
mNbComponents--;
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Notify if a given entity is sleeping or not
|
||||
void BodyComponents::setIsEntitySleeping(Entity entity, bool isSleeping) {
|
||||
|
||||
const uint32 index = mMapEntityToComponentIndex[entity];
|
||||
|
||||
// If the component was sleeping and is not sleeping anymore
|
||||
if (!isSleeping && index >= mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex < mNbComponents);
|
||||
|
||||
// If the sleeping component is not the first sleeping component
|
||||
if (mSleepingStartIndex != index) {
|
||||
|
||||
// Swap the first sleeping component with the one we need to wake up
|
||||
swapComponents(index, mSleepingStartIndex);
|
||||
}
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
// If the component was awake and must now go to sleep
|
||||
else if (isSleeping && index < mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex > 0);
|
||||
|
||||
// If the awake component is not the only awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// Swap the last awake component with the one we need to put to sleep
|
||||
swapComponents(index, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Move a component from a source to a destination index in the components array
|
||||
// The destination location must contain a constructed object
|
||||
void BodyComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
||||
|
@ -283,7 +147,8 @@ void BodyComponents::swapComponents(uint32 index1, uint32 index2) {
|
|||
// Destroy a component at a given index
|
||||
void BodyComponents::destroyComponent(uint32 index) {
|
||||
|
||||
assert(index < mNbComponents);
|
||||
Components::destroyComponent(index);
|
||||
|
||||
assert(mMapEntityToComponentIndex[mBodiesEntities[index]] == index);
|
||||
|
||||
mMapEntityToComponentIndex.remove(mBodiesEntities[index]);
|
||||
|
|
|
@ -49,15 +49,8 @@ class BodyComponents : public Components {
|
|||
|
||||
private:
|
||||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(Body*) + sizeof(List<Entity>);
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
||||
uint32 mSleepingStartIndex;
|
||||
|
||||
/// Array of body entities of each component
|
||||
Entity* mBodiesEntities;
|
||||
|
||||
|
@ -69,14 +62,17 @@ class BodyComponents : public Components {
|
|||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Allocate memory for a given number of components
|
||||
virtual void allocate(uint32 nbComponentsToAllocate) override;
|
||||
|
||||
/// Destroy a component at a given index
|
||||
void destroyComponent(uint32 index);
|
||||
virtual void destroyComponent(uint32 index) override;
|
||||
|
||||
/// Move a component from a source to a destination index in the components array
|
||||
void moveComponentToIndex(uint32 srcIndex, uint32 destIndex);
|
||||
virtual void moveComponentToIndex(uint32 srcIndex, uint32 destIndex) override;
|
||||
|
||||
/// Swap two components in the array
|
||||
void swapComponents(uint32 index1, uint32 index2);
|
||||
virtual void swapComponents(uint32 index1, uint32 index2) override;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -97,17 +93,11 @@ class BodyComponents : public Components {
|
|||
BodyComponents(MemoryAllocator& allocator);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BodyComponents();
|
||||
|
||||
/// Allocate memory for a given number of components
|
||||
void allocate(uint32 nbComponentsToAllocate);
|
||||
virtual ~BodyComponents() override = default;
|
||||
|
||||
/// Add a component
|
||||
void addComponent(Entity bodyEntity, bool isSleeping, const BodyComponent& component);
|
||||
|
||||
/// Remove a component at a given index
|
||||
void removeComponent(Entity bodyEntity);
|
||||
|
||||
/// Add a proxy-shape to a body component
|
||||
void addProxyShapeToBody(Entity bodyEntity, Entity proxyShapeEntity);
|
||||
|
||||
|
|
189
src/components/Components.cpp
Normal file
189
src/components/Components.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
/********************************************************************************
|
||||
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
||||
* Copyright (c) 2010-2018 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 "Components.h"
|
||||
#include <cassert>
|
||||
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
Components::Components(MemoryAllocator& allocator, size_t componentDataSize)
|
||||
: mMemoryAllocator(allocator), mNbComponents(0), mComponentDataSize(componentDataSize),
|
||||
mNbAllocatedComponents(0), mBuffer(nullptr), mMapEntityToComponentIndex(allocator),
|
||||
mSleepingStartIndex(0) {
|
||||
|
||||
}
|
||||
|
||||
Components::~Components() {
|
||||
|
||||
// If there are allocated components
|
||||
if (mNbAllocatedComponents > 0) {
|
||||
|
||||
// Destroy all the remaining components
|
||||
for (uint32 i = 0; i < mNbComponents; i++) {
|
||||
|
||||
destroyComponent(i);
|
||||
}
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = mNbAllocatedComponents * mComponentDataSize;
|
||||
|
||||
// Release the allocated memory
|
||||
mMemoryAllocator.release(mBuffer, totalSizeBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the index where we need to insert the new component
|
||||
uint32 Components::prepareAddComponent(bool isSleeping) {
|
||||
|
||||
// If we need to allocate more components
|
||||
if (mNbComponents == mNbAllocatedComponents) {
|
||||
allocate(mNbAllocatedComponents * 2);
|
||||
}
|
||||
|
||||
uint32 index;
|
||||
|
||||
// If the component to add is part of a sleeping entity or there are no sleeping entity
|
||||
if (isSleeping) {
|
||||
|
||||
// Add the component at the end of the array
|
||||
index = mNbComponents;
|
||||
|
||||
mSleepingStartIndex = index;
|
||||
}
|
||||
// If the component to add is not part of a sleeping entity
|
||||
else {
|
||||
|
||||
// If there already are sleeping components
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// Move the first sleeping component to the end of the array
|
||||
moveComponentToIndex(mSleepingStartIndex, mNbComponents);
|
||||
}
|
||||
|
||||
index = mSleepingStartIndex;
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
// Destroy a component at a given index
|
||||
void Components::destroyComponent(uint32 index) {
|
||||
|
||||
assert(index < mNbComponents);
|
||||
}
|
||||
|
||||
// Remove a component at a given index
|
||||
void Components::removeComponent(Entity entity) {
|
||||
|
||||
assert(mMapEntityToComponentIndex.containsKey(entity));
|
||||
|
||||
uint index = mMapEntityToComponentIndex[entity];
|
||||
|
||||
assert(index < mNbComponents);
|
||||
|
||||
// We want to keep the arrays tightly packed. Therefore, when a component is removed,
|
||||
// we replace it with the last element of the array. But we need to make sure that sleeping
|
||||
// and non-sleeping components stay grouped together.
|
||||
|
||||
// Destroy the component
|
||||
destroyComponent(index);
|
||||
|
||||
// If the component to remove is sleeping
|
||||
if (index >= mSleepingStartIndex) {
|
||||
|
||||
// If the component is not the last one
|
||||
if (index != mNbComponents - 1) {
|
||||
|
||||
// We replace it by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, index);
|
||||
}
|
||||
}
|
||||
else { // If the component to remove is not sleeping
|
||||
|
||||
// If it not the last awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// We replace it by the last awake component
|
||||
moveComponentToIndex(mSleepingStartIndex - 1, index);
|
||||
}
|
||||
|
||||
// If there are sleeping components at the end
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// We replace the last awake component by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
mNbComponents--;
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Notify if a given entity is sleeping or not
|
||||
void Components::setIsEntitySleeping(Entity entity, bool isSleeping) {
|
||||
|
||||
const uint32 index = mMapEntityToComponentIndex[entity];
|
||||
|
||||
// If the component was sleeping and is not sleeping anymore
|
||||
if (!isSleeping && index >= mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex < mNbComponents);
|
||||
|
||||
// If the sleeping component is not the first sleeping component
|
||||
if (mSleepingStartIndex != index) {
|
||||
|
||||
// Swap the first sleeping component with the one we need to wake up
|
||||
swapComponents(index, mSleepingStartIndex);
|
||||
}
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
// If the component was awake and must now go to sleep
|
||||
else if (isSleeping && index < mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex > 0);
|
||||
|
||||
// If the awake component is not the only awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// Swap the last awake component with the one we need to put to sleep
|
||||
swapComponents(index, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
|
@ -48,8 +48,9 @@ class Components {
|
|||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
|
||||
/// Number of components to allocated at the beginning
|
||||
const uint32 INIT_ALLOCATED_COMPONENTS = 10;
|
||||
const uint32 INIT_NB_ALLOCATED_COMPONENTS = 10;
|
||||
|
||||
/// Number of valid entities to hit before stopping garbage collection
|
||||
const uint32 GARBAGE_COLLECTION_MAX_VALID_ENTITIES = 5;
|
||||
|
@ -62,6 +63,9 @@ class Components {
|
|||
/// Current number of components
|
||||
uint32 mNbComponents;
|
||||
|
||||
// Size (in bytes) of a single component
|
||||
size_t mComponentDataSize;
|
||||
|
||||
/// Number of allocated components
|
||||
uint32 mNbAllocatedComponents;
|
||||
|
||||
|
@ -71,28 +75,49 @@ class Components {
|
|||
/// Map an entity to the index of its component in the array
|
||||
Map<Entity, uint32> mMapEntityToComponentIndex;
|
||||
|
||||
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
||||
uint32 mSleepingStartIndex;
|
||||
|
||||
/// Compute the index where we need to insert the new component
|
||||
uint32 prepareAddComponent(bool isSleeping);
|
||||
|
||||
/// Allocate memory for a given number of components
|
||||
virtual void allocate(uint32 nbComponentsToAllocate)=0;
|
||||
|
||||
/// Destroy a component at a given index
|
||||
virtual void destroyComponent(uint32 index);
|
||||
|
||||
/// Move a component from a source to a destination index in the components array
|
||||
virtual void moveComponentToIndex(uint32 srcIndex, uint32 destIndex)=0;
|
||||
|
||||
/// Swap two components in the array
|
||||
virtual void swapComponents(uint32 index1, uint32 index2)=0;
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Components(MemoryAllocator& allocator)
|
||||
: mMemoryAllocator(allocator), mNbComponents(0), mNbAllocatedComponents(0),
|
||||
mBuffer(nullptr), mMapEntityToComponentIndex(allocator) {
|
||||
|
||||
}
|
||||
Components(MemoryAllocator& allocator, size_t componentDataSize);
|
||||
|
||||
/// Destructor
|
||||
virtual ~Components() {
|
||||
virtual ~Components();
|
||||
|
||||
}
|
||||
/// Remove a component
|
||||
void removeComponent(Entity entity);
|
||||
|
||||
// Notify if a given entity is sleeping or not
|
||||
void setIsEntitySleeping(Entity entity, bool isSleeping);
|
||||
|
||||
/// Return the number of components
|
||||
uint32 getNbComponents() const {
|
||||
return mNbComponents;
|
||||
}
|
||||
uint32 getNbComponents() const;
|
||||
};
|
||||
|
||||
// Return the number of components
|
||||
inline uint32 Components::getNbComponents() const {
|
||||
return mNbComponents;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,31 +35,12 @@ using namespace reactphysics3d;
|
|||
|
||||
// Constructor
|
||||
ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator)
|
||||
:Components(allocator),
|
||||
mSleepingStartIndex(0) {
|
||||
:Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) + sizeof(AABB) +
|
||||
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) +
|
||||
sizeof(unsigned short)) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
ProxyShapesComponents::~ProxyShapesComponents() {
|
||||
|
||||
if (mNbAllocatedComponents > 0) {
|
||||
|
||||
// Destroy all the remaining components
|
||||
for (uint32 i = 0; i < mNbComponents; i++) {
|
||||
|
||||
// TODO : MAke sure we do not delete already deleted components
|
||||
destroyComponent(i);
|
||||
}
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = mNbAllocatedComponents * COMPONENT_DATA_SIZE;
|
||||
|
||||
// Release the allocated memory
|
||||
mMemoryAllocator.release(mBuffer, totalSizeBytes);
|
||||
}
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -68,7 +49,7 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * COMPONENT_DATA_SIZE;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
|
@ -102,7 +83,7 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short));
|
||||
|
||||
// Deallocate previous memory
|
||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize);
|
||||
}
|
||||
|
||||
mBuffer = newBuffer;
|
||||
|
@ -124,35 +105,8 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
// Add a component
|
||||
void ProxyShapesComponents::addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component) {
|
||||
|
||||
// If we need to allocate more components
|
||||
if (mNbComponents == mNbAllocatedComponents) {
|
||||
allocate(mNbAllocatedComponents * 2);
|
||||
}
|
||||
|
||||
uint32 index;
|
||||
|
||||
// If the component to add is part of a sleeping entity
|
||||
if (isSleeping) {
|
||||
|
||||
// Add the component at the end of the array
|
||||
index = mNbComponents;
|
||||
|
||||
mSleepingStartIndex = index;
|
||||
}
|
||||
// If the component to add is not part of a sleeping entity
|
||||
else {
|
||||
|
||||
// If there already are sleeping components
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// Move the first sleeping component to the end of the array
|
||||
moveComponentToIndex(mSleepingStartIndex, mNbComponents);
|
||||
}
|
||||
|
||||
index = mSleepingStartIndex;
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
// Prepare to add new component (allocate memory if necessary and compute insertion index)
|
||||
uint32 index = prepareAddComponent(isSleeping);
|
||||
|
||||
// Insert the new component data
|
||||
new (mProxyShapesEntities + index) Entity(proxyShapeEntity);
|
||||
|
@ -243,61 +197,11 @@ void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) {
|
|||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Remove a component at a given index
|
||||
void ProxyShapesComponents::removeComponent(Entity proxyShapeEntity) {
|
||||
|
||||
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||
|
||||
uint index = mMapEntityToComponentIndex[proxyShapeEntity];
|
||||
|
||||
assert(index < mNbComponents);
|
||||
|
||||
// We want to keep the arrays tightly packed. Therefore, when a component is removed,
|
||||
// we replace it with the last element of the array. But we need to make sure that sleeping
|
||||
// and non-sleeping components stay grouped together.
|
||||
|
||||
// Destroy the component
|
||||
destroyComponent(index);
|
||||
|
||||
// If the component to remove is sleeping
|
||||
if (index >= mSleepingStartIndex) {
|
||||
|
||||
// If the component is not the last one
|
||||
if (index != mNbComponents - 1) {
|
||||
|
||||
// We replace it by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, index);
|
||||
}
|
||||
}
|
||||
else { // If the component to remove is not sleeping
|
||||
|
||||
// If it not the last awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// We replace it by the last awake component
|
||||
moveComponentToIndex(mSleepingStartIndex - 1, index);
|
||||
}
|
||||
|
||||
// If there are sleeping components at the end
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// We replace the last awake component by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
mNbComponents--;
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Destroy a component at a given index
|
||||
void ProxyShapesComponents::destroyComponent(uint32 index) {
|
||||
|
||||
assert(index < mNbComponents);
|
||||
Components::destroyComponent(index);
|
||||
|
||||
assert(mMapEntityToComponentIndex[mProxyShapesEntities[index]] == index);
|
||||
|
||||
mMapEntityToComponentIndex.remove(mProxyShapesEntities[index]);
|
||||
|
@ -309,40 +213,3 @@ void ProxyShapesComponents::destroyComponent(uint32 index) {
|
|||
mLocalToBodyTransforms[index].~Transform();
|
||||
mCollisionShapes[index] = nullptr;
|
||||
}
|
||||
|
||||
// Notify if a given entity is sleeping or not
|
||||
void ProxyShapesComponents::setIsEntitySleeping(Entity entity, bool isSleeping) {
|
||||
|
||||
const uint32 index = mMapEntityToComponentIndex[entity];
|
||||
|
||||
// If the component was sleeping and is not sleeping anymore
|
||||
if (!isSleeping && index >= mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex < mNbComponents);
|
||||
|
||||
// If the sleeping component is not the first sleeping component
|
||||
if (mSleepingStartIndex != index) {
|
||||
|
||||
// Swap the first sleeping component with the one we need to wake up
|
||||
swapComponents(index, mSleepingStartIndex);
|
||||
}
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
// If the component was awake and must now go to sleep
|
||||
else if (isSleeping && index < mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex > 0);
|
||||
|
||||
// If the awake component is not the only awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// Swap the last awake component with the one we need to put to sleep
|
||||
swapComponents(index, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
}
|
||||
|
|
|
@ -53,17 +53,8 @@ class ProxyShapesComponents : public Components {
|
|||
|
||||
private:
|
||||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) + sizeof(AABB) +
|
||||
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) +
|
||||
sizeof(unsigned short);
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
||||
uint32 mSleepingStartIndex;
|
||||
|
||||
/// Array of entities of each component
|
||||
Entity* mBodiesEntities;
|
||||
|
||||
|
@ -104,14 +95,17 @@ class ProxyShapesComponents : public Components {
|
|||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Allocate memory for a given number of components
|
||||
virtual void allocate(uint32 nbComponentsToAllocate) override;
|
||||
|
||||
/// Destroy a component at a given index
|
||||
void destroyComponent(uint32 index);
|
||||
virtual void destroyComponent(uint32 index) override;
|
||||
|
||||
/// Move a component from a source to a destination index in the components array
|
||||
void moveComponentToIndex(uint32 srcIndex, uint32 destIndex);
|
||||
virtual void moveComponentToIndex(uint32 srcIndex, uint32 destIndex) override;
|
||||
|
||||
/// Swap two components in the array
|
||||
void swapComponents(uint32 index1, uint32 index2);
|
||||
virtual void swapComponents(uint32 index1, uint32 index2) override;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -144,20 +138,11 @@ class ProxyShapesComponents : public Components {
|
|||
ProxyShapesComponents(MemoryAllocator& allocator);
|
||||
|
||||
/// Destructor
|
||||
virtual ~ProxyShapesComponents();
|
||||
|
||||
/// Allocate memory for a given number of components
|
||||
void allocate(uint32 nbComponentsToAllocate);
|
||||
virtual ~ProxyShapesComponents() override = default;
|
||||
|
||||
/// Add a component
|
||||
void addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component);
|
||||
|
||||
/// Remove a component at a given index
|
||||
void removeComponent(Entity proxyShapeEntity);
|
||||
|
||||
/// Notify if a given entity is sleeping or not
|
||||
void setIsEntitySleeping(Entity entity, bool isSleeping);
|
||||
|
||||
/// Return the mass of a proxy-shape
|
||||
decimal getMass(Entity proxyShapeEntity) const;
|
||||
|
||||
|
|
|
@ -35,30 +35,10 @@ using namespace reactphysics3d;
|
|||
|
||||
// Constructor
|
||||
TransformComponents::TransformComponents(MemoryAllocator& allocator)
|
||||
:Components(allocator), mSleepingStartIndex(0){
|
||||
:Components(allocator, sizeof(Entity) + sizeof(Transform)) {
|
||||
|
||||
// Allocate memory for the components data
|
||||
allocate(INIT_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
TransformComponents::~TransformComponents() {
|
||||
|
||||
if (mNbAllocatedComponents > 0) {
|
||||
|
||||
// Destroy all the remaining components
|
||||
for (uint32 i = 0; i < mNbComponents; i++) {
|
||||
|
||||
// TODO : MAke sure we do not delete already deleted components
|
||||
destroyComponent(i);
|
||||
}
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = mNbAllocatedComponents * COMPONENT_DATA_SIZE;
|
||||
|
||||
// Release the allocated memory
|
||||
mMemoryAllocator.release(mBuffer, totalSizeBytes);
|
||||
}
|
||||
allocate(INIT_NB_ALLOCATED_COMPONENTS);
|
||||
}
|
||||
|
||||
// Allocate memory for a given number of components
|
||||
|
@ -67,7 +47,7 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||
|
||||
// Size for the data of a single component (in bytes)
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * COMPONENT_DATA_SIZE;
|
||||
const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize;
|
||||
|
||||
// Allocate memory
|
||||
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||
|
@ -85,7 +65,7 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
memcpy(newEntities, mBodies, mNbComponents * sizeof(Entity));
|
||||
|
||||
// Deallocate previous memory
|
||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize);
|
||||
}
|
||||
|
||||
mBuffer = newBuffer;
|
||||
|
@ -97,35 +77,8 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) {
|
|||
// Add a component
|
||||
void TransformComponents::addComponent(Entity bodyEntity, bool isSleeping, const TransformComponent& component) {
|
||||
|
||||
// If we need to allocate more components
|
||||
if (mNbComponents == mNbAllocatedComponents) {
|
||||
allocate(mNbAllocatedComponents * 2);
|
||||
}
|
||||
|
||||
uint32 index;
|
||||
|
||||
// If the component to add is part of a sleeping entity or there are no sleeping entity
|
||||
if (isSleeping) {
|
||||
|
||||
// Add the component at the end of the array
|
||||
index = mNbComponents;
|
||||
|
||||
mSleepingStartIndex = index;
|
||||
}
|
||||
// If the component to add is not part of a sleeping entity
|
||||
else {
|
||||
|
||||
// If there already are sleeping components
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// Move the first sleeping component to the end of the array
|
||||
moveComponentToIndex(mSleepingStartIndex, mNbComponents);
|
||||
}
|
||||
|
||||
index = mSleepingStartIndex;
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
// Prepare to add new component (allocate memory if necessary and compute insertion index)
|
||||
uint32 index = prepareAddComponent(isSleeping);
|
||||
|
||||
// Insert the new component data
|
||||
new (mBodies + index) Entity(bodyEntity);
|
||||
|
@ -140,95 +93,6 @@ void TransformComponents::addComponent(Entity bodyEntity, bool isSleeping, const
|
|||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Remove a component at a given index
|
||||
void TransformComponents::removeComponent(Entity bodyEntity) {
|
||||
|
||||
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||
|
||||
uint index = mMapEntityToComponentIndex[bodyEntity];
|
||||
|
||||
assert(index < mNbComponents);
|
||||
|
||||
// We want to keep the arrays tightly packed. Therefore, when a component is removed,
|
||||
// we replace it with the last element of the array. But we need to make sure that sleeping
|
||||
// and non-sleeping components stay grouped together.
|
||||
|
||||
// Destroy the component
|
||||
destroyComponent(index);
|
||||
|
||||
// If the component to remove is sleeping
|
||||
if (index >= mSleepingStartIndex) {
|
||||
|
||||
// If the component is not the last one
|
||||
if (index != mNbComponents - 1) {
|
||||
|
||||
// We replace it by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, index);
|
||||
}
|
||||
}
|
||||
else { // If the component to remove is not sleeping
|
||||
|
||||
// If it not the last awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// We replace it by the last awake component
|
||||
moveComponentToIndex(mSleepingStartIndex - 1, index);
|
||||
}
|
||||
|
||||
// If there are sleeping components at the end
|
||||
if (mSleepingStartIndex != mNbComponents) {
|
||||
|
||||
// We replace the last awake component by the last sleeping component
|
||||
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
mNbComponents--;
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Notify if a given entity is sleeping or not
|
||||
void TransformComponents::setIsEntitySleeping(Entity entity, bool isSleeping) {
|
||||
|
||||
const uint32 index = mMapEntityToComponentIndex[entity];
|
||||
|
||||
// If the component was sleeping and is not sleeping anymore
|
||||
if (!isSleeping && index >= mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex < mNbComponents);
|
||||
|
||||
// If the sleeping component is not the first sleeping component
|
||||
if (mSleepingStartIndex != index) {
|
||||
|
||||
// Swap the first sleeping component with the one we need to wake up
|
||||
swapComponents(index, mSleepingStartIndex);
|
||||
}
|
||||
|
||||
mSleepingStartIndex++;
|
||||
}
|
||||
// If the component was awake and must now go to sleep
|
||||
else if (isSleeping && index < mSleepingStartIndex) {
|
||||
|
||||
assert(mSleepingStartIndex > 0);
|
||||
|
||||
// If the awake component is not the only awake component
|
||||
if (index != mSleepingStartIndex - 1) {
|
||||
|
||||
// Swap the last awake component with the one we need to put to sleep
|
||||
swapComponents(index, mSleepingStartIndex - 1);
|
||||
}
|
||||
|
||||
mSleepingStartIndex--;
|
||||
}
|
||||
|
||||
assert(mSleepingStartIndex <= mNbComponents);
|
||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||
}
|
||||
|
||||
// Move a component from a source to a destination index in the components array
|
||||
// The destination location must contain a constructed object
|
||||
void TransformComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
||||
|
@ -277,7 +141,8 @@ void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
|
|||
// Destroy a component at a given index
|
||||
void TransformComponents::destroyComponent(uint32 index) {
|
||||
|
||||
assert(index < mNbComponents);
|
||||
Components::destroyComponent(index);
|
||||
|
||||
assert(mMapEntityToComponentIndex[mBodies[index]] == index);
|
||||
|
||||
mMapEntityToComponentIndex.remove(mBodies[index]);
|
||||
|
|
|
@ -49,15 +49,8 @@ class TransformComponents : public Components {
|
|||
|
||||
private:
|
||||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(Transform);
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
||||
uint32 mSleepingStartIndex;
|
||||
|
||||
/// Array of body entities of each component
|
||||
Entity* mBodies;
|
||||
|
||||
|
@ -66,14 +59,17 @@ class TransformComponents : public Components {
|
|||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Allocate memory for a given number of components
|
||||
virtual void allocate(uint32 nbComponentsToAllocate) override;
|
||||
|
||||
/// Destroy a component at a given index
|
||||
void destroyComponent(uint32 index);
|
||||
virtual void destroyComponent(uint32 index) override;
|
||||
|
||||
/// Move a component from a source to a destination index in the components array
|
||||
void moveComponentToIndex(uint32 srcIndex, uint32 destIndex);
|
||||
virtual void moveComponentToIndex(uint32 srcIndex, uint32 destIndex) override;
|
||||
|
||||
/// Swap two components in the array
|
||||
void swapComponents(uint32 index1, uint32 index2);
|
||||
virtual void swapComponents(uint32 index1, uint32 index2) override;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -94,25 +90,16 @@ class TransformComponents : public Components {
|
|||
TransformComponents(MemoryAllocator& allocator);
|
||||
|
||||
/// Destructor
|
||||
virtual ~TransformComponents();
|
||||
|
||||
/// Allocate memory for a given number of components
|
||||
void allocate(uint32 nbComponentsToAllocate);
|
||||
virtual ~TransformComponents() override = default;
|
||||
|
||||
/// Add a component
|
||||
void addComponent(Entity bodyEntity, bool isSleeping, const TransformComponent& component);
|
||||
|
||||
/// Remove a component at a given index
|
||||
void removeComponent(Entity bodyEntity);
|
||||
|
||||
/// Return the transform of an entity
|
||||
Transform& getTransform(Entity bodyEntity) const;
|
||||
|
||||
/// Set the transform of an entity
|
||||
void setTransform(Entity bodyEntity, const Transform& transform);
|
||||
|
||||
/// Notify if a given entity is sleeping or not
|
||||
void setIsEntitySleeping(Entity bodyEntity, bool isSleeping);
|
||||
};
|
||||
|
||||
// Return the transform of an entity
|
||||
|
|
Loading…
Reference in New Issue
Block a user