Start working on ECS
This commit is contained in:
parent
d905ff5c7f
commit
fa9b1817fe
|
@ -128,6 +128,8 @@ SET (REACTPHYSICS3D_HEADERS
|
||||||
"src/constraint/HingeJoint.h"
|
"src/constraint/HingeJoint.h"
|
||||||
"src/constraint/Joint.h"
|
"src/constraint/Joint.h"
|
||||||
"src/constraint/SliderJoint.h"
|
"src/constraint/SliderJoint.h"
|
||||||
|
"src/engine/Entity.h"
|
||||||
|
"src/engine/EntityManager.h"
|
||||||
"src/engine/CollisionWorld.h"
|
"src/engine/CollisionWorld.h"
|
||||||
"src/engine/ConstraintSolver.h"
|
"src/engine/ConstraintSolver.h"
|
||||||
"src/engine/ContactSolver.h"
|
"src/engine/ContactSolver.h"
|
||||||
|
@ -138,6 +140,7 @@ SET (REACTPHYSICS3D_HEADERS
|
||||||
"src/engine/OverlappingPair.h"
|
"src/engine/OverlappingPair.h"
|
||||||
"src/engine/Timer.h"
|
"src/engine/Timer.h"
|
||||||
"src/engine/Timer.cpp"
|
"src/engine/Timer.cpp"
|
||||||
|
"src/components/TransformComponents.h"
|
||||||
"src/collision/CollisionCallback.h"
|
"src/collision/CollisionCallback.h"
|
||||||
"src/collision/OverlapCallback.h"
|
"src/collision/OverlapCallback.h"
|
||||||
"src/mathematics/mathematics.h"
|
"src/mathematics/mathematics.h"
|
||||||
|
@ -224,6 +227,9 @@ SET (REACTPHYSICS3D_SOURCES
|
||||||
"src/engine/Material.cpp"
|
"src/engine/Material.cpp"
|
||||||
"src/engine/OverlappingPair.cpp"
|
"src/engine/OverlappingPair.cpp"
|
||||||
"src/engine/Timer.cpp"
|
"src/engine/Timer.cpp"
|
||||||
|
"src/engine/Entity.cpp"
|
||||||
|
"src/engine/EntityManager.cpp"
|
||||||
|
"src/components/TransformComponents.cpp"
|
||||||
"src/collision/CollisionCallback.cpp"
|
"src/collision/CollisionCallback.cpp"
|
||||||
"src/mathematics/mathematics_functions.cpp"
|
"src/mathematics/mathematics_functions.cpp"
|
||||||
"src/mathematics/Matrix2x2.cpp"
|
"src/mathematics/Matrix2x2.cpp"
|
||||||
|
|
|
@ -35,8 +35,8 @@ using namespace reactphysics3d;
|
||||||
/**
|
/**
|
||||||
* @param id ID of the new body
|
* @param id ID of the new body
|
||||||
*/
|
*/
|
||||||
Body::Body(bodyindex id)
|
Body::Body(Entity entity, bodyindex id)
|
||||||
: mID(id), mIsAlreadyInIsland(false), mIsAllowedToSleep(true), mIsActive(true),
|
: mID(id), mEntity(entity), mIsAlreadyInIsland(false), mIsAllowedToSleep(true), mIsActive(true),
|
||||||
mIsSleeping(false), mSleepTime(0), mUserData(nullptr) {
|
mIsSleeping(false), mSleepTime(0), mUserData(nullptr) {
|
||||||
|
|
||||||
#ifdef IS_LOGGING_ACTIVE
|
#ifdef IS_LOGGING_ACTIVE
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
// Libraries
|
// Libraries
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#include "engine/Entity.h"
|
||||||
|
|
||||||
/// Namespace reactphysics3d
|
/// Namespace reactphysics3d
|
||||||
namespace reactphysics3d {
|
namespace reactphysics3d {
|
||||||
|
@ -50,8 +51,12 @@ class Body {
|
||||||
// -------------------- Attributes -------------------- //
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
/// ID of the body
|
/// ID of the body
|
||||||
|
// TODO : Remove this
|
||||||
bodyindex mID;
|
bodyindex mID;
|
||||||
|
|
||||||
|
/// Identifier of the entity in the ECS
|
||||||
|
Entity mEntity;
|
||||||
|
|
||||||
/// True if the body has already been added in an island (for sleeping technique)
|
/// True if the body has already been added in an island (for sleeping technique)
|
||||||
bool mIsAlreadyInIsland;
|
bool mIsAlreadyInIsland;
|
||||||
|
|
||||||
|
@ -88,7 +93,7 @@ class Body {
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Body(bodyindex id);
|
Body(Entity entity, bodyindex id);
|
||||||
|
|
||||||
/// Deleted copy-constructor
|
/// Deleted copy-constructor
|
||||||
Body(const Body& body) = delete;
|
Body(const Body& body) = delete;
|
||||||
|
@ -102,6 +107,9 @@ class Body {
|
||||||
/// Return the ID of the body
|
/// Return the ID of the body
|
||||||
bodyindex getId() const;
|
bodyindex getId() const;
|
||||||
|
|
||||||
|
/// Return the corresponding entity of the body
|
||||||
|
Entity getEntity() const;
|
||||||
|
|
||||||
/// Return whether or not the body is allowed to sleep
|
/// Return whether or not the body is allowed to sleep
|
||||||
bool isAllowedToSleep() const;
|
bool isAllowedToSleep() const;
|
||||||
|
|
||||||
|
@ -157,6 +165,14 @@ inline bodyindex Body::getId() const {
|
||||||
return mID;
|
return mID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the corresponding entity of the body
|
||||||
|
/**
|
||||||
|
* @return The entity of the body
|
||||||
|
*/
|
||||||
|
inline Entity Body::getEntity() const {
|
||||||
|
return mEntity;
|
||||||
|
}
|
||||||
|
|
||||||
// Return whether or not the body is allowed to sleep
|
// Return whether or not the body is allowed to sleep
|
||||||
/**
|
/**
|
||||||
* @return True if the body is allowed to sleep and false otherwise
|
* @return True if the body is allowed to sleep and false otherwise
|
||||||
|
|
|
@ -39,8 +39,8 @@ using namespace reactphysics3d;
|
||||||
* @param world The physics world where the body is created
|
* @param world The physics world where the body is created
|
||||||
* @param id ID of the body
|
* @param id ID of the body
|
||||||
*/
|
*/
|
||||||
CollisionBody::CollisionBody(const Transform& transform, CollisionWorld& world, bodyindex id)
|
CollisionBody::CollisionBody(const Transform& transform, CollisionWorld& world, Entity entity, bodyindex id)
|
||||||
: Body(id), mType(BodyType::DYNAMIC), mTransform(transform), mProxyCollisionShapes(nullptr),
|
: Body(entity, id), mType(BodyType::DYNAMIC), mTransform(transform), mProxyCollisionShapes(nullptr),
|
||||||
mNbCollisionShapes(0), mContactManifoldsList(nullptr), mWorld(world) {
|
mNbCollisionShapes(0), mContactManifoldsList(nullptr), mWorld(world) {
|
||||||
|
|
||||||
#ifdef IS_PROFILING_ACTIVE
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
|
|
@ -118,7 +118,7 @@ class CollisionBody : public Body {
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
CollisionBody(const Transform& transform, CollisionWorld& world, bodyindex id);
|
CollisionBody(const Transform& transform, CollisionWorld& world, Entity entity, bodyindex id);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
virtual ~CollisionBody() override;
|
virtual ~CollisionBody() override;
|
||||||
|
|
|
@ -39,8 +39,8 @@ using namespace reactphysics3d;
|
||||||
* @param world The world where the body has been added
|
* @param world The world where the body has been added
|
||||||
* @param id The ID of the body
|
* @param id The ID of the body
|
||||||
*/
|
*/
|
||||||
RigidBody::RigidBody(const Transform& transform, CollisionWorld& world, bodyindex id)
|
RigidBody::RigidBody(const Transform& transform, CollisionWorld& world, Entity entity, bodyindex id)
|
||||||
: CollisionBody(transform, world, id), mArrayIndex(0), mInitMass(decimal(1.0)),
|
: CollisionBody(transform, world, entity, id), mArrayIndex(0), mInitMass(decimal(1.0)),
|
||||||
mCenterOfMassLocal(0, 0, 0), mCenterOfMassWorld(transform.getPosition()),
|
mCenterOfMassLocal(0, 0, 0), mCenterOfMassWorld(transform.getPosition()),
|
||||||
mIsGravityEnabled(true), mMaterial(world.mConfig), mLinearDamping(decimal(0.0)), mAngularDamping(decimal(0.0)),
|
mIsGravityEnabled(true), mMaterial(world.mConfig), mLinearDamping(decimal(0.0)), mAngularDamping(decimal(0.0)),
|
||||||
mJointsList(nullptr), mIsCenterOfMassSetByUser(false), mIsInertiaTensorSetByUser(false) {
|
mJointsList(nullptr), mIsCenterOfMassSetByUser(false), mIsInertiaTensorSetByUser(false) {
|
||||||
|
|
|
@ -134,7 +134,7 @@ class RigidBody : public CollisionBody {
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
RigidBody(const Transform& transform, CollisionWorld& world, bodyindex id);
|
RigidBody(const Transform& transform, CollisionWorld& world, Entity entity, bodyindex id);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
virtual ~RigidBody() override;
|
virtual ~RigidBody() override;
|
||||||
|
|
190
src/components/TransformComponents.cpp
Normal file
190
src/components/TransformComponents.cpp
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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 "TransformComponents.h"
|
||||||
|
#include "engine/EntityManager.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
// We want to use the ReactPhysics3D namespace
|
||||||
|
using namespace reactphysics3d;
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
TransformComponents::TransformComponents(MemoryAllocator& allocator)
|
||||||
|
:mMemoryAllocator(allocator), mNbComponents(0), mNbAllocatedComponents(0),
|
||||||
|
mBuffer(nullptr), mMapEntityToComponentIndex(allocator) {
|
||||||
|
|
||||||
|
// 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++) {
|
||||||
|
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 memory for a given number of components
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Allocate memory
|
||||||
|
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||||
|
assert(newBuffer != nullptr);
|
||||||
|
|
||||||
|
// New pointers to components data
|
||||||
|
Entity* newEntities = static_cast<Entity*>(newBuffer);
|
||||||
|
Transform* newTransforms = reinterpret_cast<Transform*>(newEntities + mNbAllocatedComponents);
|
||||||
|
|
||||||
|
// If there was already components before
|
||||||
|
if (mNbAllocatedComponents > 0) {
|
||||||
|
|
||||||
|
// Copy component data from the previous buffer to the new one
|
||||||
|
memcpy(newTransforms, mTransforms, mNbComponents * sizeof(Transform));
|
||||||
|
memcpy(newEntities, mEntities, mNbComponents * sizeof(Entity));
|
||||||
|
|
||||||
|
// Deallocate previous memory
|
||||||
|
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mBuffer = newBuffer;
|
||||||
|
mEntities = newEntities;
|
||||||
|
mTransforms = newTransforms;
|
||||||
|
mNbAllocatedComponents = nbComponentsToAllocate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a component
|
||||||
|
void TransformComponents::addComponent(Entity entity, const TransformComponent& component) {
|
||||||
|
|
||||||
|
// If we need to allocate more components
|
||||||
|
if (mNbComponents == mNbAllocatedComponents) {
|
||||||
|
allocate(mNbAllocatedComponents * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map the entity with the new component lookup index
|
||||||
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, mNbComponents));
|
||||||
|
|
||||||
|
// Insert the new component data
|
||||||
|
new (mEntities + mNbComponents) Entity(entity);
|
||||||
|
new (mTransforms + mNbComponents) Transform(component.transform);
|
||||||
|
|
||||||
|
mNbComponents++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform garbage collection to remove unused components
|
||||||
|
void TransformComponents::garbageCollection(const EntityManager& entityManager) {
|
||||||
|
|
||||||
|
// TODO : Make sure we call this method each frame
|
||||||
|
|
||||||
|
// We use lazy garbage collection. The idea is to pick random components and destroy
|
||||||
|
// them if their corresponding entities have been destroyed. We do this until we hit
|
||||||
|
// GARBAGE_COLLECTION_MAX_VALID_ENTITIES in a row. Therefore, it cost almost nothing
|
||||||
|
// if there are no destroyed entities and it very quickly destroys components where there
|
||||||
|
// are a lot of destroyed entities.
|
||||||
|
|
||||||
|
uint32 nbHitValidEntitiesInARow = 0;
|
||||||
|
|
||||||
|
// For random number generation
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 eng(rd());
|
||||||
|
|
||||||
|
while (mNbComponents > 0 && nbHitValidEntitiesInARow < GARBAGE_COLLECTION_MAX_VALID_ENTITIES) {
|
||||||
|
|
||||||
|
// Select a random index in the components array
|
||||||
|
std::uniform_int_distribution<uint32> distr(0, mNbComponents - 1);
|
||||||
|
uint32 i = distr(eng);
|
||||||
|
|
||||||
|
// If the corresponding entity is valid
|
||||||
|
if (entityManager.isValid(mEntities[i])) {
|
||||||
|
nbHitValidEntitiesInARow++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbHitValidEntitiesInARow = 0;
|
||||||
|
|
||||||
|
// Destroy the component
|
||||||
|
removeComponent(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a component at a given index
|
||||||
|
void TransformComponents::removeComponent(uint32 index) {
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
const uint32 lastIndex = mNbComponents - 1;
|
||||||
|
|
||||||
|
Entity entity = mEntities[index];
|
||||||
|
Entity lastEntity = mEntities[lastIndex];
|
||||||
|
|
||||||
|
if (mNbComponents > 1 && index != lastIndex) {
|
||||||
|
|
||||||
|
// Replace the data of the component to destroy by the data of the last component
|
||||||
|
mEntities[index] = mEntities[lastIndex];
|
||||||
|
mTransforms[index] = mTransforms[lastIndex];
|
||||||
|
|
||||||
|
// Update the entity to component index mapping
|
||||||
|
mMapEntityToComponentIndex[lastEntity] = index;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// Call the destructors on the component values
|
||||||
|
destroyComponent(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the entity to component index mapping
|
||||||
|
mMapEntityToComponentIndex.remove(entity);
|
||||||
|
|
||||||
|
mNbComponents--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy a component at a given index
|
||||||
|
void TransformComponents::destroyComponent(uint32 index) {
|
||||||
|
|
||||||
|
mEntities[index].~Entity();
|
||||||
|
mTransforms[index].~Transform();
|
||||||
|
}
|
140
src/components/TransformComponents.h
Normal file
140
src/components/TransformComponents.h
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef REACTPHYSICS3D_TRANSFORM_COMPONENTS_H
|
||||||
|
#define REACTPHYSICS3D_TRANSFORM_COMPONENTS_H
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "mathematics/Transform.h"
|
||||||
|
#include "engine/Entity.h"
|
||||||
|
#include "containers/Map.h"
|
||||||
|
|
||||||
|
// ReactPhysics3D namespace
|
||||||
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
// Class declarations
|
||||||
|
class MemoryAllocator;
|
||||||
|
class EntityManager;
|
||||||
|
|
||||||
|
// Class TransformComponents
|
||||||
|
/**
|
||||||
|
* This class represent the component of the ECS that contains the transforms of the
|
||||||
|
* different entities. The position and orientation of the bodies are stored there.
|
||||||
|
*/
|
||||||
|
class TransformComponents {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// -------------------- Constants -------------------- //
|
||||||
|
|
||||||
|
/// Number of components to allocated at the beginning
|
||||||
|
const uint32 INIT_ALLOCATED_COMPONENTS = 10;
|
||||||
|
|
||||||
|
/// Number of valid entities to hit before stopping garbage collection
|
||||||
|
const uint32 GARBAGE_COLLECTION_MAX_VALID_ENTITIES = 5;
|
||||||
|
|
||||||
|
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(Transform);
|
||||||
|
|
||||||
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
/// Memory allocator
|
||||||
|
MemoryAllocator& mMemoryAllocator;
|
||||||
|
|
||||||
|
/// Current number of components
|
||||||
|
uint32 mNbComponents;
|
||||||
|
|
||||||
|
/// Number of allocated components
|
||||||
|
uint32 mNbAllocatedComponents;
|
||||||
|
|
||||||
|
/// Allocated memory for all the data of the components
|
||||||
|
void* mBuffer;
|
||||||
|
|
||||||
|
/// Map an entity to the index of its component in the array
|
||||||
|
Map<Entity, uint32> mMapEntityToComponentIndex;
|
||||||
|
|
||||||
|
/// Array of entities of each component
|
||||||
|
Entity* mEntities;
|
||||||
|
|
||||||
|
/// Array of transform of each component
|
||||||
|
Transform* mTransforms;
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Remove a component at a given index
|
||||||
|
void removeComponent(uint32 index);
|
||||||
|
|
||||||
|
/// Destroy a component at a given index
|
||||||
|
void destroyComponent(uint32 index);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Structure for the data of a transform component
|
||||||
|
struct TransformComponent {
|
||||||
|
|
||||||
|
const Transform& transform;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
TransformComponent(const Transform& transform) : transform(transform) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
TransformComponents(MemoryAllocator& allocator);
|
||||||
|
|
||||||
|
/// Destructor
|
||||||
|
~TransformComponents();
|
||||||
|
|
||||||
|
/// Allocate memory for a given number of components
|
||||||
|
void allocate(uint32 nbComponentsToAllocate);
|
||||||
|
|
||||||
|
/// Add a component
|
||||||
|
void addComponent(Entity entity, const TransformComponent& component);
|
||||||
|
|
||||||
|
/// Perform garbage collection to remove unused components
|
||||||
|
void garbageCollection(const EntityManager& entityManager);
|
||||||
|
|
||||||
|
/// Return the transform of an entity
|
||||||
|
Transform& getTransform(Entity entity) const;
|
||||||
|
|
||||||
|
/// Set the transform of an entity
|
||||||
|
void setTransform(Entity entity, const Transform& transform);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the transform of an entity
|
||||||
|
inline Transform& TransformComponents::getTransform(Entity entity) const {
|
||||||
|
return mTransforms[mMapEntityToComponentIndex[entity]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the transform of an entity
|
||||||
|
inline void TransformComponents::setTransform(Entity entity, const Transform& transform) {
|
||||||
|
mTransforms[mMapEntityToComponentIndex[entity]] = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -53,8 +53,6 @@ using uint = unsigned int;
|
||||||
using uchar = unsigned char;
|
using uchar = unsigned char;
|
||||||
using ushort = unsigned short;
|
using ushort = unsigned short;
|
||||||
using luint = long unsigned int;
|
using luint = long unsigned int;
|
||||||
using bodyindex = luint;
|
|
||||||
using bodyindexpair = Pair<bodyindex, bodyindex>;
|
|
||||||
|
|
||||||
using int8 = std::int8_t;
|
using int8 = std::int8_t;
|
||||||
using uint8 = std::uint8_t;
|
using uint8 = std::uint8_t;
|
||||||
|
@ -63,6 +61,10 @@ using uint16 = std::uint16_t;
|
||||||
using int32 = std::int32_t;
|
using int32 = std::int32_t;
|
||||||
using uint32 = std::uint32_t;
|
using uint32 = std::uint32_t;
|
||||||
|
|
||||||
|
// TODO : Delete this
|
||||||
|
using bodyindex = luint;
|
||||||
|
using bodyindexpair = Pair<bodyindex, bodyindex>;
|
||||||
|
|
||||||
// ------------------- Enumerations ------------------- //
|
// ------------------- Enumerations ------------------- //
|
||||||
|
|
||||||
/// Position correction technique used in the constraint solver (for joints).
|
/// Position correction technique used in the constraint solver (for joints).
|
||||||
|
|
|
@ -37,7 +37,9 @@ uint CollisionWorld::mNbWorlds = 0;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler)
|
CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler)
|
||||||
: mConfig(worldSettings), mCollisionDetection(this, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0),
|
: mConfig(worldSettings), mEntityManager(mMemoryManager.getPoolAllocator()),
|
||||||
|
mTransformComponents(mMemoryManager.getBaseAllocator()),
|
||||||
|
mCollisionDetection(this, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0),
|
||||||
mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName),
|
mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName),
|
||||||
mIsProfilerCreatedByUser(profiler != nullptr),
|
mIsProfilerCreatedByUser(profiler != nullptr),
|
||||||
mIsLoggerCreatedByUser(logger != nullptr) {
|
mIsLoggerCreatedByUser(logger != nullptr) {
|
||||||
|
@ -138,16 +140,22 @@ CollisionWorld::~CollisionWorld() {
|
||||||
*/
|
*/
|
||||||
CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
|
CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
|
||||||
|
|
||||||
|
// Create a new entity for the body
|
||||||
|
Entity entity = mEntityManager.createEntity();
|
||||||
|
|
||||||
// Get the next available body ID
|
// Get the next available body ID
|
||||||
bodyindex bodyID = computeNextAvailableBodyId();
|
bodyindex bodyID = computeNextAvailableBodyId();
|
||||||
|
|
||||||
// Largest index cannot be used (it is used for invalid index)
|
// Largest index cannot be used (it is used for invalid index)
|
||||||
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
||||||
|
|
||||||
|
// Add a transform component
|
||||||
|
mTransformComponents.addComponent(entity, TransformComponents::TransformComponent(transform));
|
||||||
|
|
||||||
// Create the collision body
|
// Create the collision body
|
||||||
CollisionBody* collisionBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
CollisionBody* collisionBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
||||||
sizeof(CollisionBody)))
|
sizeof(CollisionBody)))
|
||||||
CollisionBody(transform, *this, bodyID);
|
CollisionBody(transform, *this, entity, bodyID);
|
||||||
|
|
||||||
assert(collisionBody != nullptr);
|
assert(collisionBody != nullptr);
|
||||||
|
|
||||||
|
@ -189,6 +197,9 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) {
|
||||||
// Reset the contact manifold list of the body
|
// Reset the contact manifold list of the body
|
||||||
collisionBody->resetContactManifoldsList();
|
collisionBody->resetContactManifoldsList();
|
||||||
|
|
||||||
|
// Destroy the corresponding entity
|
||||||
|
mEntityManager.destroyEntity(collisionBody->getEntity());
|
||||||
|
|
||||||
// Call the destructor of the collision body
|
// Call the destructor of the collision body
|
||||||
collisionBody->~CollisionBody();
|
collisionBody->~CollisionBody();
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "collision/CollisionDetection.h"
|
#include "collision/CollisionDetection.h"
|
||||||
#include "constraint/Joint.h"
|
#include "constraint/Joint.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
|
#include "engine/EntityManager.h"
|
||||||
|
#include "components/TransformComponents.h"
|
||||||
|
|
||||||
/// Namespace reactphysics3d
|
/// Namespace reactphysics3d
|
||||||
namespace reactphysics3d {
|
namespace reactphysics3d {
|
||||||
|
@ -66,6 +68,12 @@ class CollisionWorld {
|
||||||
/// Configuration of the physics world
|
/// Configuration of the physics world
|
||||||
WorldSettings mConfig;
|
WorldSettings mConfig;
|
||||||
|
|
||||||
|
/// Entity Manager for the ECS
|
||||||
|
EntityManager mEntityManager;
|
||||||
|
|
||||||
|
/// Transform Components
|
||||||
|
TransformComponents mTransformComponents;
|
||||||
|
|
||||||
/// Reference to the collision detection
|
/// Reference to the collision detection
|
||||||
CollisionDetection mCollisionDetection;
|
CollisionDetection mCollisionDetection;
|
||||||
|
|
||||||
|
@ -190,6 +198,7 @@ class CollisionWorld {
|
||||||
friend class CollisionDetection;
|
friend class CollisionDetection;
|
||||||
friend class CollisionBody;
|
friend class CollisionBody;
|
||||||
friend class RigidBody;
|
friend class RigidBody;
|
||||||
|
friend class ProxyShape;
|
||||||
friend class ConvexMeshShape;
|
friend class ConvexMeshShape;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -417,15 +417,21 @@ void DynamicsWorld::solvePositionCorrection() {
|
||||||
*/
|
*/
|
||||||
RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
|
RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
|
||||||
|
|
||||||
|
// Create a new entity for the body
|
||||||
|
Entity entity = mEntityManager.createEntity();
|
||||||
|
|
||||||
// Compute the body ID
|
// Compute the body ID
|
||||||
bodyindex bodyID = computeNextAvailableBodyId();
|
bodyindex bodyID = computeNextAvailableBodyId();
|
||||||
|
|
||||||
// Largest index cannot be used (it is used for invalid index)
|
// Largest index cannot be used (it is used for invalid index)
|
||||||
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
||||||
|
|
||||||
|
// Add a transform component
|
||||||
|
mTransformComponents.addComponent(entity, TransformComponents::TransformComponent(transform));
|
||||||
|
|
||||||
// Create the rigid body
|
// Create the rigid body
|
||||||
RigidBody* rigidBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
RigidBody* rigidBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
||||||
sizeof(RigidBody))) RigidBody(transform, *this, bodyID);
|
sizeof(RigidBody))) RigidBody(transform, *this, entity, bodyID);
|
||||||
assert(rigidBody != nullptr);
|
assert(rigidBody != nullptr);
|
||||||
|
|
||||||
// Add the rigid body to the physics world
|
// Add the rigid body to the physics world
|
||||||
|
@ -471,6 +477,9 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
|
||||||
// Reset the contact manifold list of the body
|
// Reset the contact manifold list of the body
|
||||||
rigidBody->resetContactManifoldsList();
|
rigidBody->resetContactManifoldsList();
|
||||||
|
|
||||||
|
// Destroy the corresponding entity
|
||||||
|
mEntityManager.destroyEntity(rigidBody->getEntity());
|
||||||
|
|
||||||
// Call the destructor of the rigid body
|
// Call the destructor of the rigid body
|
||||||
rigidBody->~RigidBody();
|
rigidBody->~RigidBody();
|
||||||
|
|
||||||
|
|
60
src/engine/Entity.cpp
Normal file
60
src/engine/Entity.cpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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 "Entity.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace reactphysics3d;
|
||||||
|
|
||||||
|
// Static members initialization
|
||||||
|
const uint32 Entity::ENTITY_INDEX_BITS = 24;
|
||||||
|
const uint32 Entity::ENTITY_INDEX_MASK = (1 << Entity::ENTITY_INDEX_BITS) - 1;
|
||||||
|
const uint32 Entity::ENTITY_GENERATION_BITS = 8;
|
||||||
|
const uint32 Entity::ENTITY_GENERATION_MASK = (1 << Entity::ENTITY_GENERATION_BITS) - 1;
|
||||||
|
const uint32 Entity::MINIMUM_FREE_INDICES = 1024;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Entity::Entity(uint32 index, uint32 generation)
|
||||||
|
:id((index & ENTITY_INDEX_MASK) | ((generation & ENTITY_GENERATION_MASK) << ENTITY_INDEX_BITS)) {
|
||||||
|
|
||||||
|
uint32 test1 = index & ENTITY_INDEX_MASK;
|
||||||
|
uint32 test2 = (generation & ENTITY_INDEX_MASK) << ENTITY_INDEX_BITS;
|
||||||
|
uint32 test3 = test1 | test2;
|
||||||
|
uint32 test = getIndex();
|
||||||
|
assert(getIndex() == index);
|
||||||
|
assert(getGeneration() == generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignment operator
|
||||||
|
Entity& Entity::operator=(const Entity& entity) {
|
||||||
|
|
||||||
|
if (&entity != this) {
|
||||||
|
|
||||||
|
id = entity.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
144
src/engine/Entity.h
Normal file
144
src/engine/Entity.h
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef REACTPHYSICS3D_ENTITY_H
|
||||||
|
#define REACTPHYSICS3D_ENTITY_H
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
/// Namespace reactphysics3d
|
||||||
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
// Structure Entity
|
||||||
|
/**
|
||||||
|
* This class is used to identify an entity in the Entity-Component-System.
|
||||||
|
* Entities are used for bodies in the physics engine. The id of an entity is
|
||||||
|
* a 32 bits integer that is separated in two parts. The index and the generation
|
||||||
|
* parts. The idea is that the index part directly gives us the index of the entity
|
||||||
|
* in a lookup array. However, we want to support deletion of the entities. That's why
|
||||||
|
* we have the generation part. This number is used to distinguish the entities created
|
||||||
|
* at the same index in the array. If it is the case, we will increase the generation number
|
||||||
|
* each time.
|
||||||
|
*
|
||||||
|
* We use 24 bits for the index. Therefore, we support 16 millions simultaneous entries.
|
||||||
|
* We use 8 bits for the generation. Therefore, we support 256 entries created at the same index.
|
||||||
|
* To prevent reaching the 256 entries too fast, we make sure that we do not reuse the same index
|
||||||
|
* slot too ofen. To do that, we put recycled indices in a queue and only reuse values from that
|
||||||
|
* queue when it contains at least MINIMUM_FREE_INDICES values. It means, an id will reappear until
|
||||||
|
* its index has run 256 laps through the queue. It means that we must create and destroy at least
|
||||||
|
* 256 * MINIMUM_FREE_INDICES entities until an id can reappear. This seems reasonably safe.
|
||||||
|
*
|
||||||
|
* This implementation is based on the following article:
|
||||||
|
* http://bitsquid.blogspot.com/2014/08/building-data-oriented-entity-system.html
|
||||||
|
*/
|
||||||
|
struct Entity {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/// Number of bits reserved for the index
|
||||||
|
static const uint32 ENTITY_INDEX_BITS;
|
||||||
|
|
||||||
|
/// Mask for the index part of the id
|
||||||
|
static const uint32 ENTITY_INDEX_MASK;
|
||||||
|
|
||||||
|
/// Number of bits reserved for the generation number
|
||||||
|
static const uint32 ENTITY_GENERATION_BITS;
|
||||||
|
|
||||||
|
/// Mask for the generation part of the id
|
||||||
|
static const uint32 ENTITY_GENERATION_MASK;
|
||||||
|
|
||||||
|
/// Minimum of free indices in the queue before we reuse one from the queue
|
||||||
|
static const uint32 MINIMUM_FREE_INDICES;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
/// Id of the entity
|
||||||
|
uint32 id;
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
Entity(uint32 index, uint32 generation);
|
||||||
|
|
||||||
|
/// Return the lookup index of the entity in a array
|
||||||
|
uint32 getIndex() const;
|
||||||
|
|
||||||
|
/// Return the generation number of the entity
|
||||||
|
uint32 getGeneration() const;
|
||||||
|
|
||||||
|
/// Assignment operator
|
||||||
|
Entity& operator=(const Entity& entity);
|
||||||
|
|
||||||
|
/// Equality operator
|
||||||
|
bool operator==(const Entity& entity) const;
|
||||||
|
|
||||||
|
/// Inequality operator (it != end())
|
||||||
|
bool operator!=(const Entity& entity) const;
|
||||||
|
|
||||||
|
// -------------------- Friendship -------------------- //
|
||||||
|
|
||||||
|
friend class EntityManager;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the lookup index of the entity in a array
|
||||||
|
inline uint32 Entity::getIndex() const {
|
||||||
|
return id & ENTITY_INDEX_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the generation number of the entity
|
||||||
|
inline uint32 Entity::getGeneration() const {
|
||||||
|
return (id >> ENTITY_INDEX_BITS) & ENTITY_GENERATION_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equality operator
|
||||||
|
inline bool Entity::operator==(const Entity& entity) const {
|
||||||
|
|
||||||
|
return entity.id == id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inequality operator (it != end())
|
||||||
|
inline bool Entity::operator!=(const Entity& entity) const {
|
||||||
|
return entity.id != id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash function for a reactphysics3d Entity
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
template <> struct hash<reactphysics3d::Entity> {
|
||||||
|
|
||||||
|
size_t operator()(const reactphysics3d::Entity& entity) const {
|
||||||
|
|
||||||
|
return entity.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
75
src/engine/EntityManager.cpp
Normal file
75
src/engine/EntityManager.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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 "EntityManager.h"
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
|
using namespace reactphysics3d;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
EntityManager::EntityManager(MemoryAllocator& allocator)
|
||||||
|
:mGenerations(allocator), mFreeIndices(allocator) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new entity
|
||||||
|
Entity EntityManager::createEntity() {
|
||||||
|
|
||||||
|
uint32 index;
|
||||||
|
|
||||||
|
// If there are already enough free indices to start using them
|
||||||
|
if (mFreeIndices.size() > Entity::MINIMUM_FREE_INDICES) {
|
||||||
|
|
||||||
|
// Recycle an index from the free indices
|
||||||
|
index = mFreeIndices.getFront();
|
||||||
|
mFreeIndices.popFront();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// We start at generation 0
|
||||||
|
mGenerations.add(0);
|
||||||
|
|
||||||
|
// Create a new indice
|
||||||
|
index = static_cast<uint32>(mGenerations.size()) - 1;
|
||||||
|
|
||||||
|
assert(index < (1 << Entity::ENTITY_INDEX_BITS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a new entity
|
||||||
|
return Entity(index, mGenerations[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy an entity
|
||||||
|
void EntityManager::destroyEntity(Entity entity) {
|
||||||
|
|
||||||
|
const uint32 index = entity.getIndex();
|
||||||
|
|
||||||
|
// Increment the generation of this index
|
||||||
|
mGenerations[index]++;
|
||||||
|
|
||||||
|
// Add the index into the deque of free indices
|
||||||
|
mFreeIndices.addBack(index);
|
||||||
|
}
|
80
src/engine/EntityManager.h
Normal file
80
src/engine/EntityManager.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef REACTPHYSICS3D_ENTITY_MANAGER_H
|
||||||
|
#define REACTPHYSICS3D_ENTITY_MANAGER_H
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "containers/List.h"
|
||||||
|
#include "containers/Deque.h"
|
||||||
|
#include "engine/Entity.h"
|
||||||
|
|
||||||
|
/// Namespace reactphysics3d
|
||||||
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
// Class EntityManager
|
||||||
|
/**
|
||||||
|
* This class is responsible to manage the entities of the ECS.
|
||||||
|
*/
|
||||||
|
class EntityManager {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
/// List storing the generations of the created entities
|
||||||
|
List<uint8> mGenerations;
|
||||||
|
|
||||||
|
/// Deque with the indices of destroyed entities that can be reused
|
||||||
|
Deque<uint32> mFreeIndices;
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
EntityManager(MemoryAllocator& allocator);
|
||||||
|
|
||||||
|
/// Create a new entity
|
||||||
|
Entity createEntity();
|
||||||
|
|
||||||
|
/// Destroy an entity
|
||||||
|
void destroyEntity(Entity entity);
|
||||||
|
|
||||||
|
/// Return true if the entity is still valid (not destroyed)
|
||||||
|
bool isValid(Entity entity) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return true if the entity is still valid (not destroyed)
|
||||||
|
inline bool EntityManager::isValid(Entity entity) const {
|
||||||
|
return mGenerations[entity.getIndex()] == entity.getGeneration();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user