The proxy-shapes are now entities

This commit is contained in:
Daniel Chappuis 2019-03-15 17:27:11 +01:00
parent 4b919fb4fc
commit d02b25d32a
20 changed files with 836 additions and 563 deletions

View File

@ -22,6 +22,9 @@
- The CollisionWorld::setCollisionDispatch() method has been removed. In order to use a custom collision - The CollisionWorld::setCollisionDispatch() method has been removed. In order to use a custom collision
algorithm, you must not get the collision dispatch object with the algorithm, you must not get the collision dispatch object with the
CollisionWorld::getCollisionDispatch() method and set a collision algorithm to this object. CollisionWorld::getCollisionDispatch() method and set a collision algorithm to this object.
- The methods CollisionBody::getProxyShapesList() has been remove. You can now use the
CollisionBody::getNbProxyShapes() method to know the number of proxy-shapes of a body and the
CollisionBody::getProxyShape(uint proxyShapeIndex) method to get a given proxy-shape of the body.
## Version 0.7.0 (May 1, 2018) ## Version 0.7.0 (May 1, 2018)

View File

@ -140,6 +140,7 @@ SET (REACTPHYSICS3D_HEADERS
"src/engine/Timer.h" "src/engine/Timer.h"
"src/systems/BroadPhaseSystem.h" "src/systems/BroadPhaseSystem.h"
"src/components/Components.h" "src/components/Components.h"
"src/components/BodyComponents.h"
"src/components/TransformComponents.h" "src/components/TransformComponents.h"
"src/components/ProxyShapesComponents.h" "src/components/ProxyShapesComponents.h"
"src/collision/CollisionCallback.h" "src/collision/CollisionCallback.h"
@ -230,6 +231,7 @@ SET (REACTPHYSICS3D_SOURCES
"src/engine/Entity.cpp" "src/engine/Entity.cpp"
"src/engine/EntityManager.cpp" "src/engine/EntityManager.cpp"
"src/systems/BroadPhaseSystem.cpp" "src/systems/BroadPhaseSystem.cpp"
"src/components/BodyComponents.cpp"
"src/components/TransformComponents.cpp" "src/components/TransformComponents.cpp"
"src/components/ProxyShapesComponents.cpp" "src/components/ProxyShapesComponents.cpp"
"src/collision/CollisionCallback.cpp" "src/collision/CollisionCallback.cpp"

View File

@ -72,19 +72,24 @@ CollisionBody::~CollisionBody() {
ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
const Transform& transform) { const Transform& transform) {
// Create a new entity for the proxy-shape
Entity proxyShapeEntity = mWorld.mEntityManager.createEntity();
// Create a new proxy collision shape to attach the collision shape to the body // Create a new proxy collision shape to attach the collision shape to the body
ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool, ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(ProxyShape))) ProxyShape(this, mWorld.mMemoryManager); sizeof(ProxyShape))) ProxyShape(proxyShapeEntity, this, mWorld.mMemoryManager);
// Add the proxy-shape component to the entity of the body // Add the proxy-shape component to the entity of the body
Vector3 localBoundsMin; Vector3 localBoundsMin;
Vector3 localBoundsMax; Vector3 localBoundsMax;
// TODO : Maybe this method can directly returns an AABB // TODO : Maybe this method can directly returns an AABB
collisionShape->getLocalBounds(localBoundsMin, localBoundsMax); collisionShape->getLocalBounds(localBoundsMin, localBoundsMax);
ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(proxyShape, -1, ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1,
AABB(localBoundsMin, localBoundsMax), AABB(localBoundsMin, localBoundsMax),
transform, collisionShape, decimal(1), 0x0001, 0xFFFF); transform, collisionShape, decimal(1), 0x0001, 0xFFFF);
mWorld.mProxyShapesComponents.addComponent(mEntity, mIsSleeping, proxyShapeComponent); mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, mIsSleeping, proxyShapeComponent);
mWorld.mBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity);
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
@ -118,22 +123,38 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
return proxyShape; return proxyShape;
} }
// Return the linked list of proxy shapes of that body // Return the number of proxy-shapes associated with this body
/** /**
* @return The pointer of the first proxy shape of the linked-list of all the * @return The number of proxy-shapes associated with this body
* proxy shapes of the body
*/ */
ProxyShape* CollisionBody::getProxyShapesList() { uint CollisionBody::getNbProxyShapes() const {
return mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); return static_cast<uint>(mWorld.mBodyComponents.getProxyShapes(mEntity).size());
} }
// Return the linked list of proxy shapes of that body // Return a const pointer to a given proxy-shape of the body
/** /**
* @return The pointer of the first proxy shape of the linked-list of all the * @return The const pointer of a given proxy-shape of the body
* proxy shapes of the body
*/ */
const ProxyShape* CollisionBody::getProxyShapesList() const { const ProxyShape* CollisionBody::getProxyShape(uint proxyShapeIndex) const {
return mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity);
assert(proxyShapeIndex < getNbProxyShapes());
Entity proxyShapeEntity = mWorld.mBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex];
return mWorld.mProxyShapesComponents.getProxyShape(proxyShapeEntity);
}
// Return a pointer to a given proxy-shape of the body
/**
* @return The pointer of a given proxy-shape of the body
*/
ProxyShape* CollisionBody::getProxyShape(uint proxyShapeIndex) {
assert(proxyShapeIndex < getNbProxyShapes());
Entity proxyShapeEntity = mWorld.mBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex];
return mWorld.mProxyShapesComponents.getProxyShape(proxyShapeEntity);
} }
// Remove a collision shape from the body // Remove a collision shape from the body
@ -148,14 +169,16 @@ void CollisionBody::removeCollisionShape(ProxyShape* proxyShape) {
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " removed from body"); "Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " removed from body");
// Remove the proxy-shape component
mWorld.mProxyShapesComponents.removeComponent(proxyShape);
// Remove the proxy-shape from the broad-phase // Remove the proxy-shape from the broad-phase
if (mIsActive && proxyShape->getBroadPhaseId() != -1) { if (proxyShape->getBroadPhaseId() != -1) {
mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape); mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape);
} }
mWorld.mBodyComponents.removeProxyShapeFromBody(mEntity, proxyShape->getEntity());
// Remove the proxy-shape component
mWorld.mProxyShapesComponents.removeComponent(proxyShape->getEntity());
// Call the constructor of the proxy-shape // Call the constructor of the proxy-shape
proxyShape->~ProxyShape(); proxyShape->~ProxyShape();
@ -166,27 +189,13 @@ void CollisionBody::removeCollisionShape(ProxyShape* proxyShape) {
// Remove all the collision shapes // Remove all the collision shapes
void CollisionBody::removeAllCollisionShapes() { void CollisionBody::removeAllCollisionShapes() {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); // Look for the proxy shape that contains the collision shape in parameter.
// Note that we need to copy the list of proxy shapes entities because we are deleting them in a loop.
const List<Entity> proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
// Look for the proxy shape that contains the collision shape in parameter removeCollisionShape(mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]));
while(proxyShape != nullptr) {
if (mIsActive && proxyShape->getBroadPhaseId() != -1) {
mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape);
}
// Destroy the proxy-shape
proxyShape->~ProxyShape();
mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, proxyShape, sizeof(ProxyShape));
// Get the next element in the list
proxyShape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(proxyShape);
} }
// Remove all the proxy-shapes components
mWorld.mProxyShapesComponents.removeComponents(mEntity);
} }
// Reset the contact manifold lists // Reset the contact manifold lists
@ -222,10 +231,13 @@ const Transform& CollisionBody::getTransform() const {
void CollisionBody::updateBroadPhaseState() const { void CollisionBody::updateBroadPhaseState() const {
// For all the proxy collision shapes of the body // For all the proxy collision shapes of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
// Update the proxy // Update the proxy
updateProxyShapeInBroadPhase(shape); updateProxyShapeInBroadPhase(proxyShape);
} }
} }
@ -262,25 +274,31 @@ void CollisionBody::setIsActive(bool isActive) {
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
// For each proxy shape of the body // For each proxy shape of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
// Compute the world-space AABB of the new collision shape // Compute the world-space AABB of the new collision shape
AABB aabb; AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, transform * mWorld.mProxyShapesComponents.getLocalToBodyTransform(shape)); proxyShape->getCollisionShape()->computeAABB(aabb, transform * mWorld.mProxyShapesComponents.getLocalToBodyTransform(proxyShape->getEntity()));
// Add the proxy shape to the collision detection // Add the proxy shape to the collision detection
mWorld.mCollisionDetection.addProxyCollisionShape(shape, aabb); mWorld.mCollisionDetection.addProxyCollisionShape(proxyShape, aabb);
} }
} }
else { // If we have to deactivate the body else { // If we have to deactivate the body
// For each proxy shape of the body // For each proxy shape of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
if (shape->getBroadPhaseId() != -1) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
if (proxyShape->getBroadPhaseId() != -1) {
// Remove the proxy shape from the collision detection // Remove the proxy shape from the collision detection
mWorld.mCollisionDetection.removeProxyCollisionShape(shape); mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape);
} }
} }
@ -298,9 +316,12 @@ void CollisionBody::setIsActive(bool isActive) {
void CollisionBody::askForBroadPhaseCollisionCheck() const { void CollisionBody::askForBroadPhaseCollisionCheck() const {
// For all the proxy collision shapes of the body // For all the proxy collision shapes of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
mWorld.mCollisionDetection.askForBroadPhaseCollisionCheck(shape); ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
mWorld.mCollisionDetection.askForBroadPhaseCollisionCheck(proxyShape);
} }
} }
@ -333,10 +354,13 @@ int CollisionBody::resetIsAlreadyInIslandAndCountManifolds() {
bool CollisionBody::testPointInside(const Vector3& worldPoint) const { bool CollisionBody::testPointInside(const Vector3& worldPoint) const {
// For each collision shape of the body // For each collision shape of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
// Test if the point is inside the collision shape // Test if the point is inside the collision shape
if (shape->testPointInside(worldPoint)) return true; if (proxyShape->testPointInside(worldPoint)) return true;
} }
return false; return false;
@ -359,10 +383,13 @@ bool CollisionBody::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
Ray rayTemp(ray); Ray rayTemp(ray);
// For each collision shape of the body // For each collision shape of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
// Test if the ray hits the collision shape // Test if the ray hits the collision shape
if (shape->raycast(rayTemp, raycastInfo)) { if (proxyShape->raycast(rayTemp, raycastInfo)) {
rayTemp.maxFraction = raycastInfo.hitFraction; rayTemp.maxFraction = raycastInfo.hitFraction;
isHit = true; isHit = true;
} }
@ -379,21 +406,24 @@ AABB CollisionBody::getAABB() const {
AABB bodyAABB; AABB bodyAABB;
if (mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity) == nullptr) return bodyAABB; const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
if (proxyShapesEntities.size() == 0) return bodyAABB;
// TODO : Make sure we compute this in a system // TODO : Make sure we compute this in a system
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[0]);
proxyShape->getCollisionShape()->computeAABB(bodyAABB, transform * proxyShape->getLocalToBodyTransform()); proxyShape->getCollisionShape()->computeAABB(bodyAABB, transform * proxyShape->getLocalToBodyTransform());
// For each proxy shape of the body // For each proxy shape of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { for (uint i=1; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
// Compute the world-space AABB of the collision shape // Compute the world-space AABB of the collision shape
AABB aabb; AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, transform * shape->getLocalToBodyTransform()); proxyShape->getCollisionShape()->computeAABB(aabb, transform * proxyShape->getLocalToBodyTransform());
// Merge the proxy shape AABB with the current body AABB // Merge the proxy shape AABB with the current body AABB
bodyAABB.mergeWithAABB(aabb); bodyAABB.mergeWithAABB(aabb);

View File

@ -166,12 +166,18 @@ class CollisionBody : public Body {
/// Compute and return the AABB of the body by merging all proxy shapes AABBs /// Compute and return the AABB of the body by merging all proxy shapes AABBs
AABB getAABB() const; AABB getAABB() const;
/// Return the linked list of proxy shapes of that body /// Return a const pointer to a given proxy-shape of the body
ProxyShape* getProxyShapesList(); const ProxyShape* getProxyShape(uint proxyShapeIndex) const;
/// Return a pointer to a given proxy-shape of the body
ProxyShape* getProxyShape(uint proxyShapeIndex);
/// Return the linked list of proxy shapes of that body /// Return the linked list of proxy shapes of that body
const ProxyShape* getProxyShapesList() const; const ProxyShape* getProxyShapesList() const;
/// Return the number of proxy-shapes associated with this body
uint getNbProxyShapes() const;
/// Return the world-space coordinates of a point given the local-space coordinates of the body /// Return the world-space coordinates of a point given the local-space coordinates of the body
Vector3 getWorldPoint(const Vector3& localPoint) const; Vector3 getWorldPoint(const Vector3& localPoint) const;

View File

@ -281,9 +281,12 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
const Transform& transform, const Transform& transform,
decimal mass) { decimal mass) {
// Create a new entity for the proxy-shape
Entity proxyShapeEntity = mWorld.mEntityManager.createEntity();
// Create a new proxy collision shape to attach the collision shape to the body // Create a new proxy collision shape to attach the collision shape to the body
ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool, ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(ProxyShape))) ProxyShape(this, mWorld.mMemoryManager); sizeof(ProxyShape))) ProxyShape(proxyShapeEntity, this, mWorld.mMemoryManager);
// Add the proxy-shape component to the entity of the body // Add the proxy-shape component to the entity of the body
Vector3 localBoundsMin; Vector3 localBoundsMin;
@ -291,10 +294,12 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
// TODO : Maybe this method can directly returns an AABB // TODO : Maybe this method can directly returns an AABB
collisionShape->getLocalBounds(localBoundsMin, localBoundsMax); collisionShape->getLocalBounds(localBoundsMin, localBoundsMax);
ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(proxyShape, -1, ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1,
AABB(localBoundsMin, localBoundsMax), AABB(localBoundsMin, localBoundsMax),
transform, collisionShape, mass, 0x0001, 0xFFFF); transform, collisionShape, mass, 0x0001, 0xFFFF);
mWorld.mProxyShapesComponents.addComponent(mEntity, mIsSleeping, proxyShapeComponent); mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, mIsSleeping, proxyShapeComponent);
mWorld.mBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity);
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
@ -500,11 +505,13 @@ void RigidBody::recomputeMassInformation() {
assert(mType == BodyType::DYNAMIC); assert(mType == BodyType::DYNAMIC);
// Compute the total mass of the body // Compute the total mass of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
mInitMass += shape->getMass(); for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
mInitMass += proxyShape->getMass();
if (!mIsCenterOfMassSetByUser) { if (!mIsCenterOfMassSetByUser) {
mCenterOfMassLocal += shape->getLocalToBodyTransform().getPosition() * shape->getMass(); mCenterOfMassLocal += proxyShape->getLocalToBodyTransform().getPosition() * proxyShape->getMass();
} }
} }
@ -528,14 +535,17 @@ void RigidBody::recomputeMassInformation() {
if (!mIsInertiaTensorSetByUser) { if (!mIsInertiaTensorSetByUser) {
// Compute the inertia tensor using all the collision shapes // Compute the inertia tensor using all the collision shapes
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
// Get the inertia tensor of the collision shape in its local-space // Get the inertia tensor of the collision shape in its local-space
Matrix3x3 inertiaTensor; Matrix3x3 inertiaTensor;
shape->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, shape->getMass()); proxyShape->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, proxyShape->getMass());
// Convert the collision shape inertia tensor into the local-space of the body // Convert the collision shape inertia tensor into the local-space of the body
const Transform& shapeTransform = shape->getLocalToBodyTransform(); const Transform& shapeTransform = proxyShape->getLocalToBodyTransform();
Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix(); Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix();
inertiaTensor = rotationMatrix * inertiaTensor * rotationMatrix.getTranspose(); inertiaTensor = rotationMatrix * inertiaTensor * rotationMatrix.getTranspose();
@ -550,7 +560,7 @@ void RigidBody::recomputeMassInformation() {
offsetMatrix[0] += offset * (-offset.x); offsetMatrix[0] += offset * (-offset.x);
offsetMatrix[1] += offset * (-offset.y); offsetMatrix[1] += offset * (-offset.y);
offsetMatrix[2] += offset * (-offset.z); offsetMatrix[2] += offset * (-offset.z);
offsetMatrix *= shape->getMass(); offsetMatrix *= proxyShape->getMass();
inertiaTensorLocal += inertiaTensor + offsetMatrix; inertiaTensorLocal += inertiaTensor + offsetMatrix;
} }
@ -579,14 +589,20 @@ void RigidBody::updateBroadPhaseState() const {
const Vector3 displacement = world.mTimeStep * mLinearVelocity; const Vector3 displacement = world.mTimeStep * mLinearVelocity;
// For all the proxy collision shapes of the body // For all the proxy collision shapes of the body
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
// Recompute the world-space AABB of the collision shape ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, transform * shape->getLocalToBodyTransform());
// Update the broad-phase state for the proxy collision shape if (proxyShape->getBroadPhaseId() != -1) {
mWorld.mCollisionDetection.updateProxyCollisionShape(shape, aabb, displacement);
// Recompute the world-space AABB of the collision shape
AABB aabb;
proxyShape->getCollisionShape()->computeAABB(aabb, transform * proxyShape->getLocalToBodyTransform());
// Update the broad-phase state for the proxy collision shape
mWorld.mCollisionDetection.updateProxyCollisionShape(proxyShape, aabb, displacement);
}
} }
} }
@ -598,12 +614,12 @@ void RigidBody::setProfiler(Profiler* profiler) {
CollisionBody::setProfiler(profiler); CollisionBody::setProfiler(profiler);
// Set the profiler for each proxy shape // Set the profiler for each proxy shape
ProxyShape* proxyShape = getProxyShapesList(); const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
while (proxyShape != nullptr) { for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
proxyShape->setProfiler(profiler); proxyShape->setProfiler(profiler);
proxyShape = proxyShape->getNext();
} }
} }

View File

@ -608,14 +608,18 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2)
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
// For each proxy shape proxy shape of the first body // For each proxy shape proxy shape of the first body
ProxyShape* body1ProxyShape = body1->getProxyShapesList(); const List<Entity>& body1ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body1->getEntity());
while (body1ProxyShape != nullptr) { const List<Entity>& body2ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body2->getEntity());
for (uint i=0; i < body1ProxyShapesEntities.size(); i++) {
ProxyShape* body1ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body1ProxyShapesEntities[i]);
AABB aabb1 = body1ProxyShape->getWorldAABB(); AABB aabb1 = body1ProxyShape->getWorldAABB();
// For each proxy shape of the second body // For each proxy shape of the second body
ProxyShape* body2ProxyShape = body2->getProxyShapesList(); for (uint j=0; j < body2ProxyShapesEntities.size(); j++) {
while (body2ProxyShape != nullptr) {
ProxyShape* body2ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body2ProxyShapesEntities[j]);
AABB aabb2 = body2ProxyShape->getWorldAABB(); AABB aabb2 = body2ProxyShape->getWorldAABB();
@ -630,13 +634,7 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2)
computeMiddlePhaseForProxyShapes(&pair, narrowPhaseInput); computeMiddlePhaseForProxyShapes(&pair, narrowPhaseInput);
} }
// Go to the next proxy shape
body2ProxyShape = body2ProxyShape->getNext();
} }
// Go to the next proxy shape
body1ProxyShape = body1ProxyShape->getNext();
} }
// Test narrow-phase collision // Test narrow-phase collision
@ -656,8 +654,10 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator()); NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
// For each proxy shape proxy shape of the body // For each proxy shape proxy shape of the body
ProxyShape* bodyProxyShape = body->getProxyShapesList(); const List<Entity>& proxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body->getEntity());
while (bodyProxyShape != nullptr) { for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* bodyProxyShape = mWorld->mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
if (bodyProxyShape->getBroadPhaseId() != -1) { if (bodyProxyShape->getBroadPhaseId() != -1) {
@ -713,9 +713,6 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl
element = element->next; element = element->next;
} }
} }
// Go to the next proxy shape
bodyProxyShape = bodyProxyShape->getNext();
} }
} }
@ -728,14 +725,18 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body
OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator()); OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator());
// For each proxy shape proxy shape of the first body // For each proxy shape proxy shape of the first body
ProxyShape* body1ProxyShape = body1->getProxyShapesList(); const List<Entity>& body1ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body1->getEntity());
while (body1ProxyShape != nullptr) { const List<Entity>& body2ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body2->getEntity());
for (uint i=0; i < body1ProxyShapesEntities.size(); i++) {
ProxyShape* body1ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body1ProxyShapesEntities[i]);
AABB aabb1 = body1ProxyShape->getWorldAABB(); AABB aabb1 = body1ProxyShape->getWorldAABB();
// For each proxy shape of the second body // For each proxy shape of the second body
ProxyShape* body2ProxyShape = body2->getProxyShapesList(); for (uint j=0; j < body2ProxyShapesEntities.size(); j++) {
while (body2ProxyShape != nullptr) {
ProxyShape* body2ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body2ProxyShapesEntities[i]);
AABB aabb2 = body2ProxyShape->getWorldAABB(); AABB aabb2 = body2ProxyShape->getWorldAABB();
@ -767,13 +768,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body
// Compute the middle-phase collision detection between the two shapes // Compute the middle-phase collision detection between the two shapes
computeMiddlePhaseForProxyShapes(pair, narrowPhaseInput); computeMiddlePhaseForProxyShapes(pair, narrowPhaseInput);
} }
// Go to the next proxy shape
body2ProxyShape = body2ProxyShape->getNext();
} }
// Go to the next proxy shape
body1ProxyShape = body1ProxyShape->getNext();
} }
// Test narrow-phase collision // Test narrow-phase collision
@ -812,8 +807,10 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator()); OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator());
// For each proxy shape proxy shape of the body // For each proxy shape proxy shape of the body
ProxyShape* bodyProxyShape = body->getProxyShapesList(); const List<Entity>& proxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body->getEntity());
while (bodyProxyShape != nullptr) { for (uint i=0; i < proxyShapesEntities.size(); i++) {
ProxyShape* bodyProxyShape = mWorld->mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
if (bodyProxyShape->getBroadPhaseId() != -1) { if (bodyProxyShape->getBroadPhaseId() != -1) {
@ -870,9 +867,6 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
// Go to the next overlapping proxy shape // Go to the next overlapping proxy shape
element = element->next; element = element->next;
} }
// Go to the next proxy shape
bodyProxyShape = bodyProxyShape->getNext();
} }
} }

View File

@ -39,8 +39,8 @@ using namespace reactphysics3d;
* @param transform Transformation from collision shape local-space to body local-space * @param transform Transformation from collision shape local-space to body local-space
* @param mass Mass of the collision shape (in kilograms) * @param mass Mass of the collision shape (in kilograms)
*/ */
ProxyShape::ProxyShape(CollisionBody* body, MemoryManager& memoryManager) ProxyShape::ProxyShape(Entity entity, CollisionBody* body, MemoryManager& memoryManager)
:mMemoryManager(memoryManager), mBody(body), :mMemoryManager(memoryManager), mEntity(entity), mBody(body),
mUserData(nullptr) { mUserData(nullptr) {
} }
@ -55,7 +55,7 @@ ProxyShape::~ProxyShape() {
* @return Mass of the collision shape (in kilograms) * @return Mass of the collision shape (in kilograms)
*/ */
decimal ProxyShape::getMass() const { decimal ProxyShape::getMass() const {
return mBody->mWorld.mProxyShapesComponents.getMass(this); return mBody->mWorld.mProxyShapesComponents.getMass(mEntity);
} }
@ -66,9 +66,9 @@ decimal ProxyShape::getMass() const {
*/ */
bool ProxyShape::testPointInside(const Vector3& worldPoint) { bool ProxyShape::testPointInside(const Vector3& worldPoint) {
const Transform localToWorld = mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) * const Transform localToWorld = mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) *
mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(this); mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(mEntity);
const Vector3 localPoint = localToWorld.getInverse() * worldPoint; const Vector3 localPoint = localToWorld.getInverse() * worldPoint;
const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this); const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
return collisionShape->testPointInside(localPoint, this); return collisionShape->testPointInside(localPoint, this);
} }
@ -78,9 +78,9 @@ bool ProxyShape::testPointInside(const Vector3& worldPoint) {
*/ */
void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits) { void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits) {
mBody->mWorld.mProxyShapesComponents.setCollisionCategoryBits(this, collisionCategoryBits); mBody->mWorld.mProxyShapesComponents.setCollisionCategoryBits(mEntity, collisionCategoryBits);
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this); int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape, RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(broadPhaseId) + ": Set collisionCategoryBits=" + "ProxyShape " + std::to_string(broadPhaseId) + ": Set collisionCategoryBits=" +
@ -93,9 +93,9 @@ void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits)
*/ */
void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) { void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
mBody->mWorld.mProxyShapesComponents.setCollideWithMaskBits(this, collideWithMaskBits); mBody->mWorld.mProxyShapesComponents.setCollideWithMaskBits(mEntity, collideWithMaskBits);
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this); int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape, RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(broadPhaseId) + ": Set collideWithMaskBits=" + "ProxyShape " + std::to_string(broadPhaseId) + ": Set collideWithMaskBits=" +
@ -106,14 +106,14 @@ void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
void ProxyShape::setLocalToBodyTransform(const Transform& transform) { void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
//mLocalToBodyTransform = transform; //mLocalToBodyTransform = transform;
mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(this, transform); mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(mEntity, transform);
mBody->setIsSleeping(false); mBody->setIsSleeping(false);
// Notify the body that the proxy shape has to be updated in the broad-phase // Notify the body that the proxy shape has to be updated in the broad-phase
mBody->updateProxyShapeInBroadPhase(this, true); mBody->updateProxyShapeInBroadPhase(this, true);
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this); int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape, RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
"ProxyShape " + std::to_string(broadPhaseId) + ": Set localToBodyTransform=" + "ProxyShape " + std::to_string(broadPhaseId) + ": Set localToBodyTransform=" +
@ -126,7 +126,7 @@ void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
*/ */
const AABB ProxyShape::getWorldAABB() const { const AABB ProxyShape::getWorldAABB() const {
AABB aabb; AABB aabb;
CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this); CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
collisionShape->computeAABB(aabb, getLocalToWorldTransform()); collisionShape->computeAABB(aabb, getLocalToWorldTransform());
return aabb; return aabb;
} }
@ -136,7 +136,7 @@ const AABB ProxyShape::getWorldAABB() const {
* @return Pointer to the internal collision shape * @return Pointer to the internal collision shape
*/ */
const CollisionShape* ProxyShape::getCollisionShape() const { const CollisionShape* ProxyShape::getCollisionShape() const {
return mBody->mWorld.mProxyShapesComponents.getCollisionShape(this); return mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
} }
// Return the collision shape // Return the collision shape
@ -144,12 +144,12 @@ const CollisionShape* ProxyShape::getCollisionShape() const {
* @return Pointer to the internal collision shape * @return Pointer to the internal collision shape
*/ */
CollisionShape* ProxyShape::getCollisionShape() { CollisionShape* ProxyShape::getCollisionShape() {
return mBody->mWorld.mProxyShapesComponents.getCollisionShape(this); return mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
} }
// Return the broad-phase id // Return the broad-phase id
int ProxyShape::getBroadPhaseId() const { int ProxyShape::getBroadPhaseId() const {
return mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this); return mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
} }
// Return the local to parent body transform // Return the local to parent body transform
@ -158,25 +158,7 @@ int ProxyShape::getBroadPhaseId() const {
* to the local-space of the parent body * to the local-space of the parent body
*/ */
const Transform& ProxyShape::getLocalToBodyTransform() const { const Transform& ProxyShape::getLocalToBodyTransform() const {
return mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(this); return mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(mEntity);
}
// Return the next proxy shape in the linked list of proxy shapes
/**
* @return Pointer to the next proxy shape in the linked list of proxy shapes
*/
ProxyShape* ProxyShape::getNext() {
// TODO : Delete this method
return mBody->mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(this);
}
// Return the next proxy shape in the linked list of proxy shapes
/**
* @return Pointer to the next proxy shape in the linked list of proxy shapes
*/
const ProxyShape* ProxyShape::getNext() const {
// TODO : Delete this method
return mBody->mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(this);
} }
// Raycast method with feedback information // Raycast method with feedback information
@ -198,7 +180,7 @@ bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
worldToLocalTransform * ray.point2, worldToLocalTransform * ray.point2,
ray.maxFraction); ray.maxFraction);
const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this); const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
bool isHit = collisionShape->raycast(rayLocal, raycastInfo, this, mMemoryManager.getPoolAllocator()); bool isHit = collisionShape->raycast(rayLocal, raycastInfo, this, mMemoryManager.getPoolAllocator());
// Convert the raycast info into world-space // Convert the raycast info into world-space
@ -214,7 +196,7 @@ bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
* @return The collision category bits mask of the proxy shape * @return The collision category bits mask of the proxy shape
*/ */
unsigned short ProxyShape::getCollisionCategoryBits() const { unsigned short ProxyShape::getCollisionCategoryBits() const {
return mBody->mWorld.mProxyShapesComponents.getCollisionCategoryBits(this); return mBody->mWorld.mProxyShapesComponents.getCollisionCategoryBits(mEntity);
} }
// Return the collision bits mask // Return the collision bits mask
@ -222,7 +204,7 @@ unsigned short ProxyShape::getCollisionCategoryBits() const {
* @return The bits mask that specifies with which collision category this shape will collide * @return The bits mask that specifies with which collision category this shape will collide
*/ */
unsigned short ProxyShape::getCollideWithMaskBits() const { unsigned short ProxyShape::getCollideWithMaskBits() const {
return mBody->mWorld.mProxyShapesComponents.getCollideWithMaskBits(this); return mBody->mWorld.mProxyShapesComponents.getCollideWithMaskBits(mEntity);
} }
// Return the local to world transform // Return the local to world transform
@ -232,7 +214,7 @@ unsigned short ProxyShape::getCollideWithMaskBits() const {
*/ */
const Transform ProxyShape::getLocalToWorldTransform() const { const Transform ProxyShape::getLocalToWorldTransform() const {
return mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) * return mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) *
mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(this); mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(mEntity);
} }
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
@ -242,7 +224,7 @@ void ProxyShape::setProfiler(Profiler* profiler) {
mProfiler = profiler; mProfiler = profiler;
CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this); CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
collisionShape->setProfiler(profiler); collisionShape->setProfiler(profiler);
} }

View File

@ -54,6 +54,9 @@ class ProxyShape {
/// Reference to the memory manager /// Reference to the memory manager
MemoryManager& mMemoryManager; MemoryManager& mMemoryManager;
/// Identifier of the entity in the ECS
Entity mEntity;
/// Pointer to the parent body /// Pointer to the parent body
CollisionBody* mBody; CollisionBody* mBody;
@ -111,7 +114,7 @@ class ProxyShape {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Constructor /// Constructor
ProxyShape(CollisionBody* body, MemoryManager& memoryManager); ProxyShape(Entity entity, CollisionBody* body, MemoryManager& memoryManager);
/// Destructor /// Destructor
virtual ~ProxyShape(); virtual ~ProxyShape();
@ -122,6 +125,9 @@ class ProxyShape {
/// Deleted assignment operator /// Deleted assignment operator
ProxyShape& operator=(const ProxyShape& proxyShape) = delete; ProxyShape& operator=(const ProxyShape& proxyShape) = delete;
/// Return the corresponding entity of the proxy-shape
Entity getEntity() const;
/// Return the collision shape /// Return the collision shape
const CollisionShape* getCollisionShape() const; const CollisionShape* getCollisionShape() const;
@ -170,12 +176,6 @@ class ProxyShape {
/// Set the collision category bits /// Set the collision category bits
void setCollisionCategoryBits(unsigned short collisionCategoryBits); void setCollisionCategoryBits(unsigned short collisionCategoryBits);
/// Return the next proxy shape in the linked list of proxy shapes
ProxyShape* getNext();
/// Return the next proxy shape in the linked list of proxy shapes
const ProxyShape* getNext() const;
/// Return the broad-phase id /// Return the broad-phase id
int getBroadPhaseId() const; int getBroadPhaseId() const;
@ -209,6 +209,14 @@ class ProxyShape {
}; };
// Return the corresponding entity of the proxy-shape
/**
* @return The entity of the proxy-shape
*/
inline Entity ProxyShape::getEntity() const {
return mEntity;
}
// Return the parent body // Return the parent body
/** /**
* @return Pointer to the parent body * @return Pointer to the parent body

View File

@ -0,0 +1,294 @@
/********************************************************************************
* 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 "BodyComponents.h"
#include "engine/EntityManager.h"
#include <cassert>
#include <random>
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
// Constructor
BodyComponents::BodyComponents(MemoryAllocator& allocator)
:Components(allocator), mSleepingStartIndex(0){
// 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 memory for a given number of components
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;
// Allocate memory
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
assert(newBuffer != nullptr);
// New pointers to components data
Entity* newBodiesEntities = static_cast<Entity*>(newBuffer);
Body** newBodies = reinterpret_cast<Body**>(newBodiesEntities + nbComponentsToAllocate);
List<Entity>* newProxyShapes = reinterpret_cast<List<Entity>*>(newBodies + nbComponentsToAllocate);
// If there was already components before
if (mNbComponents > 0) {
// Copy component data from the previous buffer to the new one
memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity));
memcpy(newBodies, mBodies, mNbComponents * sizeof(Body*));
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(List<Entity>));
// Deallocate previous memory
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
}
mBuffer = newBuffer;
mBodiesEntities = newBodiesEntities;
mBodies = newBodies;
mProxyShapes = newProxyShapes;
mNbAllocatedComponents = 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++;
}
// Insert the new component data
new (mBodiesEntities + index) Entity(bodyEntity);
mBodies[index] = component.body;
new (mProxyShapes + index) List<Entity>(mMemoryAllocator);
// Map the entity with the new component lookup index
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(bodyEntity, index));
mNbComponents++;
assert(mSleepingStartIndex <= mNbComponents);
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) {
const Entity entity = mBodiesEntities[srcIndex];
// Copy the data of the source component to the destination location
new (mBodiesEntities + destIndex) Entity(mBodiesEntities[srcIndex]);
mBodies[destIndex] = mBodies[srcIndex];
new (mProxyShapes + destIndex) List<Entity>(mProxyShapes[srcIndex]);
// Destroy the source component
destroyComponent(srcIndex);
assert(!mMapEntityToComponentIndex.containsKey(entity));
// Update the entity to component index mapping
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, destIndex));
assert(mMapEntityToComponentIndex[mBodiesEntities[destIndex]] == destIndex);
}
// Swap two components in the array
void BodyComponents::swapComponents(uint32 index1, uint32 index2) {
// Copy component 1 data
Entity entity1(mBodiesEntities[index1]);
Body* body1 = mBodies[index1];
List<Entity> proxyShapes1(mProxyShapes[index1]);
// Destroy component 1
destroyComponent(index1);
moveComponentToIndex(index2, index1);
// Reconstruct component 1 at component 2 location
new (mBodiesEntities + index2) Entity(entity1);
new (mProxyShapes + index2) List<Entity>(proxyShapes1);
mBodies[index2] = body1;
// Update the entity to component index mapping
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2));
assert(mMapEntityToComponentIndex[mBodiesEntities[index1]] == index1);
assert(mMapEntityToComponentIndex[mBodiesEntities[index2]] == index2);
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
}
// Destroy a component at a given index
void BodyComponents::destroyComponent(uint32 index) {
assert(index < mNbComponents);
assert(mMapEntityToComponentIndex[mBodiesEntities[index]] == index);
mMapEntityToComponentIndex.remove(mBodiesEntities[index]);
mBodiesEntities[index].~Entity();
mBodies[index] = nullptr;
mProxyShapes[index].~List<Entity>();
}

View File

@ -0,0 +1,161 @@
/********************************************************************************
* 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_BODY_COMPONENTS_H
#define REACTPHYSICS3D_BODY_COMPONENTS_H
// Libraries
#include "mathematics/Transform.h"
#include "engine/Entity.h"
#include "components/Components.h"
#include "containers/Map.h"
// ReactPhysics3D namespace
namespace reactphysics3d {
// Class declarations
class MemoryAllocator;
class EntityManager;
class Body;
// Class BodyComponents
/**
* This class represent the component of the ECS that contains data about a physics body.
* The components of the sleeping entities (bodies) are always stored at the end of the array.
*/
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;
/// Array of pointers to the corresponding bodies
Body** mBodies;
/// Array with the list of proxy-shapes of each body
List<Entity>* mProxyShapes;
// -------------------- Methods -------------------- //
/// Destroy a component at a given index
void destroyComponent(uint32 index);
/// Move a component from a source to a destination index in the components array
void moveComponentToIndex(uint32 srcIndex, uint32 destIndex);
/// Swap two components in the array
void swapComponents(uint32 index1, uint32 index2);
public:
/// Structure for the data of a body component
struct BodyComponent {
Body* body;
/// Constructor
BodyComponent(Body* body) : body(body) {
}
};
// -------------------- Methods -------------------- //
/// Constructor
BodyComponents(MemoryAllocator& allocator);
/// Destructor
virtual ~BodyComponents();
/// Allocate memory for a given number of components
void allocate(uint32 nbComponentsToAllocate);
/// 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);
/// Set the transform of an entity
void removeProxyShapeFromBody(Entity bodyEntity, Entity proxyShapeEntity);
/// Return a pointer to a body
Body* getBody(Entity bodyEntity);
/// Return the list of proxy-shapes of a body
const List<Entity>& getProxyShapes(Entity bodyEntity) const;
/// Notify if a given entity is sleeping or not
void setIsEntitySleeping(Entity bodyEntity, bool isSleeping);
};
// Add a proxy-shape to a body component
inline void BodyComponents::addProxyShapeToBody(Entity bodyEntity, Entity proxyShapeEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mProxyShapes[mMapEntityToComponentIndex[bodyEntity]].add(proxyShapeEntity);
}
// Set the transform of an entity
inline void BodyComponents::removeProxyShapeFromBody(Entity bodyEntity, Entity proxyShapeEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mProxyShapes[mMapEntityToComponentIndex[bodyEntity]].remove(proxyShapeEntity);
}
// Return a pointer to a body
inline Body* BodyComponents::getBody(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mBodies[mMapEntityToComponentIndex[bodyEntity]];
}
// Return the list of proxy-shapes of a body
inline const List<Entity>& BodyComponents::getProxyShapes(Entity bodyEntity) const {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
return mProxyShapes[mMapEntityToComponentIndex[bodyEntity]];
}
}
#endif

View File

@ -86,6 +86,11 @@ class Components {
virtual ~Components() { virtual ~Components() {
} }
/// Return the number of components
uint32 getNbComponents() const {
return mNbComponents;
}
}; };
} }

View File

@ -36,8 +36,7 @@ using namespace reactphysics3d;
// Constructor // Constructor
ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator) ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator)
:Components(allocator), :Components(allocator),
mSleepingStartIndex(0), mSleepingStartIndex(0) {
mMapProxyShapeToComponentIndex(allocator) {
// Allocate memory for the components data // Allocate memory for the components data
allocate(INIT_ALLOCATED_COMPONENTS); allocate(INIT_ALLOCATED_COMPONENTS);
@ -76,31 +75,29 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
assert(newBuffer != nullptr); assert(newBuffer != nullptr);
// New pointers to components data // New pointers to components data
Entity* newEntities = static_cast<Entity*>(newBuffer); Entity* newProxyShapesEntities = static_cast<Entity*>(newBuffer);
ProxyShape** newProxyShapes = reinterpret_cast<ProxyShape**>(newEntities + nbComponentsToAllocate); Entity* newBodiesEntities = reinterpret_cast<Entity*>(newProxyShapesEntities + nbComponentsToAllocate);
ProxyShape** newProxyShapes = reinterpret_cast<ProxyShape**>(newBodiesEntities + nbComponentsToAllocate);
int* newBroadPhaseIds = reinterpret_cast<int*>(newProxyShapes + nbComponentsToAllocate); int* newBroadPhaseIds = reinterpret_cast<int*>(newProxyShapes + nbComponentsToAllocate);
AABB* newLocalBounds = reinterpret_cast<AABB*>(newBroadPhaseIds + nbComponentsToAllocate); AABB* newLocalBounds = reinterpret_cast<AABB*>(newBroadPhaseIds + nbComponentsToAllocate);
Transform* newLocalToBodyTransforms = reinterpret_cast<Transform*>(newLocalBounds + nbComponentsToAllocate); Transform* newLocalToBodyTransforms = reinterpret_cast<Transform*>(newLocalBounds + nbComponentsToAllocate);
CollisionShape** newCollisionShapes = reinterpret_cast<CollisionShape**>(newLocalToBodyTransforms + nbComponentsToAllocate); CollisionShape** newCollisionShapes = reinterpret_cast<CollisionShape**>(newLocalToBodyTransforms + nbComponentsToAllocate);
decimal* newMasses = reinterpret_cast<decimal*>(newCollisionShapes + nbComponentsToAllocate); decimal* newMasses = reinterpret_cast<decimal*>(newCollisionShapes + nbComponentsToAllocate);
uint32* newPreviousBodyProxyShapes = reinterpret_cast<uint32*>(newMasses + nbComponentsToAllocate); unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(newMasses + nbComponentsToAllocate);
uint32* newNextBodyProxyShapes = reinterpret_cast<uint32*>(newPreviousBodyProxyShapes + nbComponentsToAllocate);
unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(newNextBodyProxyShapes + nbComponentsToAllocate);
unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate); unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate);
// If there was already components before // If there was already components before
if (mNbComponents > 0) { if (mNbComponents > 0) {
// Copy component data from the previous buffer to the new one // Copy component data from the previous buffer to the new one
memcpy(newEntities, mEntities, mNbComponents * sizeof(Entity)); memcpy(newProxyShapesEntities, mProxyShapesEntities, mNbComponents * sizeof(Entity));
memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity));
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(ProxyShape*)); memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(ProxyShape*));
memcpy(newBroadPhaseIds, mBroadPhaseIds, mNbComponents * sizeof(int)); memcpy(newBroadPhaseIds, mBroadPhaseIds, mNbComponents * sizeof(int));
memcpy(newLocalBounds, mLocalBounds, mNbComponents * sizeof(AABB)); memcpy(newLocalBounds, mLocalBounds, mNbComponents * sizeof(AABB));
memcpy(newLocalToBodyTransforms, mLocalToBodyTransforms, mNbComponents * sizeof(Transform)); memcpy(newLocalToBodyTransforms, mLocalToBodyTransforms, mNbComponents * sizeof(Transform));
memcpy(newCollisionShapes, mCollisionShapes, mNbComponents * sizeof(CollisionShape*)); memcpy(newCollisionShapes, mCollisionShapes, mNbComponents * sizeof(CollisionShape*));
memcpy(newMasses, mMasses, mNbComponents * sizeof(decimal)); memcpy(newMasses, mMasses, mNbComponents * sizeof(decimal));
memcpy(newPreviousBodyProxyShapes, mPreviousBodyProxyShapes, mNbComponents * sizeof(uint32));
memcpy(newNextBodyProxyShapes, mNextBodyProxyShapes, mNbComponents * sizeof(uint32));
memcpy(newCollisionCategoryBits, mCollisionCategoryBits, mNbComponents * sizeof(unsigned short)); memcpy(newCollisionCategoryBits, mCollisionCategoryBits, mNbComponents * sizeof(unsigned short));
memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short)); memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short));
@ -109,63 +106,23 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
} }
mBuffer = newBuffer; mBuffer = newBuffer;
mEntities = newEntities; mProxyShapesEntities = newProxyShapesEntities;
mBodiesEntities = newBodiesEntities;
mProxyShapesEntities = newProxyShapesEntities;
mProxyShapes = newProxyShapes; mProxyShapes = newProxyShapes;
mBroadPhaseIds = newBroadPhaseIds; mBroadPhaseIds = newBroadPhaseIds;
mLocalBounds = newLocalBounds; mLocalBounds = newLocalBounds;
mLocalToBodyTransforms = newLocalToBodyTransforms; mLocalToBodyTransforms = newLocalToBodyTransforms;
mCollisionShapes = newCollisionShapes; mCollisionShapes = newCollisionShapes;
mMasses = newMasses; mMasses = newMasses;
mPreviousBodyProxyShapes = newPreviousBodyProxyShapes;
mNextBodyProxyShapes = newNextBodyProxyShapes;
mCollisionCategoryBits = newCollisionCategoryBits; mCollisionCategoryBits = newCollisionCategoryBits;
mCollideWithMaskBits = newCollideWithMaskBits; mCollideWithMaskBits = newCollideWithMaskBits;
mNbAllocatedComponents = nbComponentsToAllocate; mNbAllocatedComponents = nbComponentsToAllocate;
} }
// Add a new proxy-shape at the beginning of the linked-list of proxy-shapes of a given entity
// If it is the first proxy-shape for the entity, it will create the first item of the linked-list
void ProxyShapesComponents::linkProxyShapeWithEntity(Entity entity, uint32 proxyShapeComponentIndex) {
auto it = mMapEntityToComponentIndex.find(entity);
if (it != mMapEntityToComponentIndex.end()) {
// Get the first proxy-shape of the linked-list
uint32 firstProxyShapeIndex = (*it).second;
assert(!hasPreviousProxyShape(firstProxyShapeIndex));
// Update the previous index of the first item of the list
mPreviousBodyProxyShapes[firstProxyShapeIndex] = proxyShapeComponentIndex;
// Map the entity to the new head of the linked-list
mMapEntityToComponentIndex[entity] = proxyShapeComponentIndex;
// Add the new proxy-shape at the beginning of the linked-list
const uint32 nextIndex = firstProxyShapeIndex;
const uint32 previousIndex = proxyShapeComponentIndex;
new (mNextBodyProxyShapes + proxyShapeComponentIndex) uint32(nextIndex);
new (mPreviousBodyProxyShapes + proxyShapeComponentIndex) uint32(previousIndex);
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[proxyShapeComponentIndex]] == proxyShapeComponentIndex);
}
else { // If the entity does not have a proxy-shape yet
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, proxyShapeComponentIndex));
// The new proxy-shape has no previous/next components in the linked-list
new (mNextBodyProxyShapes + proxyShapeComponentIndex) uint32(proxyShapeComponentIndex);
new (mPreviousBodyProxyShapes + proxyShapeComponentIndex) uint32(proxyShapeComponentIndex);
assert(!hasNextProxyShape(proxyShapeComponentIndex));
}
assert(!hasPreviousProxyShape(proxyShapeComponentIndex));
}
// Add a component // Add a component
void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const ProxyShapeComponent& component) { void ProxyShapesComponents::addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component) {
// If we need to allocate more components // If we need to allocate more components
if (mNbComponents == mNbAllocatedComponents) { if (mNbComponents == mNbAllocatedComponents) {
@ -198,8 +155,9 @@ void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const P
} }
// Insert the new component data // Insert the new component data
new (mEntities + index) Entity(entity); new (mProxyShapesEntities + index) Entity(proxyShapeEntity);
mProxyShapes[index] = (component.proxyShape); new (mBodiesEntities + index) Entity(component.bodyEntity);
mProxyShapes[index] = component.proxyShape;
new (mBroadPhaseIds + index) int(component.broadPhaseId); new (mBroadPhaseIds + index) int(component.broadPhaseId);
new (mLocalBounds + index) AABB(component.localBounds); new (mLocalBounds + index) AABB(component.localBounds);
new (mLocalToBodyTransforms + index) Transform(component.localToBodyTransform); new (mLocalToBodyTransforms + index) Transform(component.localToBodyTransform);
@ -208,133 +166,89 @@ void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const P
new (mCollisionCategoryBits + index) unsigned short(component.collisionCategoryBits); new (mCollisionCategoryBits + index) unsigned short(component.collisionCategoryBits);
new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits); new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits);
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(component.proxyShape, index)); // Map the entity with the new component lookup index
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity, index));
mNbComponents++; mNbComponents++;
// Map the entity with the new component lookup index
linkProxyShapeWithEntity(entity, index);
assert(mSleepingStartIndex <= mNbComponents); assert(mSleepingStartIndex <= mNbComponents);
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index || !hasNextProxyShape(index));
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
} }
// Move a component from a source to a destination index in the components array // Move a component from a source to a destination index in the components array
// The destination location must contain a constructed object // The destination location must contain a constructed object
void ProxyShapesComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) { void ProxyShapesComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
const Entity entity = mEntities[srcIndex]; const Entity proxyShapeEntity = mProxyShapesEntities[srcIndex];
const bool isFirstProxyShapeOfBody = mMapEntityToComponentIndex[entity] == srcIndex;
assert(isFirstProxyShapeOfBody || hasPreviousProxyShape(srcIndex));
// Copy the data of the source component to the destination location // Copy the data of the source component to the destination location
new (mEntities + destIndex) Entity(mEntities[srcIndex]); new (mProxyShapesEntities + destIndex) Entity(mProxyShapesEntities[srcIndex]);
new (mBodiesEntities + destIndex) Entity(mBodiesEntities[srcIndex]);
mProxyShapes[destIndex] = mProxyShapes[srcIndex]; mProxyShapes[destIndex] = mProxyShapes[srcIndex];
new (mBroadPhaseIds + destIndex) int(mBroadPhaseIds[srcIndex]); new (mBroadPhaseIds + destIndex) int(mBroadPhaseIds[srcIndex]);
new (mLocalBounds + destIndex) AABB(mLocalBounds[srcIndex]); new (mLocalBounds + destIndex) AABB(mLocalBounds[srcIndex]);
new (mLocalToBodyTransforms + destIndex) Transform(mLocalToBodyTransforms[srcIndex]); new (mLocalToBodyTransforms + destIndex) Transform(mLocalToBodyTransforms[srcIndex]);
mCollisionShapes[destIndex] = mCollisionShapes[srcIndex]; mCollisionShapes[destIndex] = mCollisionShapes[srcIndex];
new (mMasses + destIndex) decimal(mMasses[srcIndex]); new (mMasses + destIndex) decimal(mMasses[srcIndex]);
new (mPreviousBodyProxyShapes + destIndex) uint32(hasPreviousProxyShape(srcIndex) ? mPreviousBodyProxyShapes[srcIndex] : destIndex);
new (mNextBodyProxyShapes + destIndex) uint32(hasNextProxyShape(srcIndex) ? mNextBodyProxyShapes[srcIndex] : destIndex);
new (mCollisionCategoryBits + destIndex) unsigned short(mCollisionCategoryBits[srcIndex]); new (mCollisionCategoryBits + destIndex) unsigned short(mCollisionCategoryBits[srcIndex]);
new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]); new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]);
// Update the the next proxy-shape index of the previous proxy-shape
if (hasPreviousProxyShape(destIndex)) {
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] == srcIndex);
mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] = destIndex;
}
// Update the the previous proxy-shape index of the next proxy-shape
if (hasNextProxyShape(destIndex)) {
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] == srcIndex);
mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] = destIndex;
}
// Destroy the source component // Destroy the source component
destroyComponent(srcIndex); destroyComponent(srcIndex);
// Update the entity to component index mapping if it is the first proxy-shape of the body assert(!mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
if (isFirstProxyShapeOfBody) {
mMapEntityToComponentIndex[entity] = destIndex; // Update the entity to component index mapping
assert(mMapEntityToComponentIndex[mEntities[destIndex]] == destIndex); mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity, destIndex));
}
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(mProxyShapes[destIndex], destIndex)); assert(mMapEntityToComponentIndex[mProxyShapesEntities[destIndex]] == destIndex);
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] == destIndex || !hasNextProxyShape(destIndex));
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] == destIndex || !hasPreviousProxyShape(destIndex));
} }
// Swap two components in the array // Swap two components in the array
void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) { void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) {
// Copy component 1 data // Copy component 1 data
Entity entity1(mEntities[index1]); Entity proxyShapeEntity1(mProxyShapesEntities[index1]);
Entity bodyEntity1(mBodiesEntities[index1]);
ProxyShape* proxyShape1 = mProxyShapes[index1]; ProxyShape* proxyShape1 = mProxyShapes[index1];
int broadPhaseId1 = mBroadPhaseIds[index1]; int broadPhaseId1 = mBroadPhaseIds[index1];
AABB localBounds1 = mLocalBounds[index1]; AABB localBounds1 = mLocalBounds[index1];
Transform localToBodyTransform1 = mLocalToBodyTransforms[index1]; Transform localToBodyTransform1 = mLocalToBodyTransforms[index1];
CollisionShape* collisionShape1 = mCollisionShapes[index1]; CollisionShape* collisionShape1 = mCollisionShapes[index1];
decimal mass1 = mMasses[index1]; decimal mass1 = mMasses[index1];
uint32 previousProxyShape1 = hasPreviousProxyShape(index1) ? mPreviousBodyProxyShapes[index1] : index2;
uint32 nextProxyShape1 = hasNextProxyShape(index1) ? mNextBodyProxyShapes[index1] : index2;
unsigned short collisionCategoryBits1 = mCollisionCategoryBits[index1]; unsigned short collisionCategoryBits1 = mCollisionCategoryBits[index1];
unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1]; unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1];
const bool isFirstBodyProxyShape1 = mMapEntityToComponentIndex[mEntities[index1]] == index1;
// Destroy component 1 // Destroy component 1
destroyComponent(index1); destroyComponent(index1);
moveComponentToIndex(index2, index1); moveComponentToIndex(index2, index1);
// Reconstruct component 1 at component 2 location // Reconstruct component 1 at component 2 location
new (mEntities + index2) Entity(entity1); new (mProxyShapesEntities + index2) Entity(proxyShapeEntity1);
new (mBodiesEntities + index2) Entity(bodyEntity1);
mProxyShapes[index2] = proxyShape1; mProxyShapes[index2] = proxyShape1;
new (mBroadPhaseIds + index2) int(broadPhaseId1); new (mBroadPhaseIds + index2) int(broadPhaseId1);
new (mLocalBounds + index2) AABB(localBounds1); new (mLocalBounds + index2) AABB(localBounds1);
new (mLocalToBodyTransforms + index2) Transform(localToBodyTransform1); new (mLocalToBodyTransforms + index2) Transform(localToBodyTransform1);
mCollisionShapes[index2] = collisionShape1; mCollisionShapes[index2] = collisionShape1;
new (mMasses + index2) decimal(mass1); new (mMasses + index2) decimal(mass1);
new (mPreviousBodyProxyShapes + index2) uint32(previousProxyShape1);
new (mNextBodyProxyShapes + index2) uint32(nextProxyShape1);
new (mCollisionCategoryBits + index2) unsigned short(collisionCategoryBits1); new (mCollisionCategoryBits + index2) unsigned short(collisionCategoryBits1);
new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1); new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1);
// Update the the next proxy-shape index of the previous proxy-shape // Update the entity to component index mapping
if (hasPreviousProxyShape(index2)) { mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity1, index2));
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] == index1);
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] = index2;
}
// Update the the previous proxy-shape index of the next proxy-shape assert(mMapEntityToComponentIndex[mProxyShapesEntities[index1]] == index1);
if (hasNextProxyShape(index2)) { assert(mMapEntityToComponentIndex[mProxyShapesEntities[index2]] == index2);
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] == index1); assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] = index2;
}
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(mProxyShapes[index2], index2));
// Update the entity to component index mapping if it is the first body proxy-shape
if (isFirstBodyProxyShape1) {
assert(!hasPreviousProxyShape(index2));
mMapEntityToComponentIndex[entity1] = index2;
}
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index1]] == index1 || !hasNextProxyShape(index1));
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] == index2 || !hasNextProxyShape(index2));
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index1]] == index1 || !hasPreviousProxyShape(index1));
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] == index2 || !hasPreviousProxyShape(index2));
} }
// Remove a component at a given index // Remove a component at a given index
void ProxyShapesComponents::removeComponent(uint32 index) { void ProxyShapesComponents::removeComponent(Entity proxyShapeEntity) {
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
uint index = mMapEntityToComponentIndex[proxyShapeEntity];
assert(index < mNbComponents); assert(index < mNbComponents);
@ -342,59 +256,6 @@ void ProxyShapesComponents::removeComponent(uint32 index) {
// we replace it with the last element of the array. But we need to make sure that sleeping // 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. // and non-sleeping components stay grouped together.
// If the proxy-shape to destroy does not have a previous proxy-shape in the linked-list of proxy-shapes of its body
if (!hasPreviousProxyShape(index)) {
// Remove the mapping from entity to component index
mMapEntityToComponentIndex.remove(mEntities[index]);
// If the proxy-shape has a next proxy-shape in the linked-list
if (hasNextProxyShape(index)) {
assert(mEntities[index] == mEntities[mNextBodyProxyShapes[index]]);
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(mEntities[mNextBodyProxyShapes[index]], mNextBodyProxyShapes[index]));
}
}
// Update the linked-list of proxy-shapes of a body when a proxy-shape is removed
if (hasPreviousProxyShape(index)) {
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index);
assert(mEntities[index] == mEntities[mPreviousBodyProxyShapes[index]]);
// If the current proxy-shape to remove has a next proxy-shape in the linked-list
if (hasNextProxyShape(index)) {
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index);
// Make sure the next proxy-shape will follow the previous proxy-shape in the linked-list
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] = mNextBodyProxyShapes[index];
}
else {
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] = mPreviousBodyProxyShapes[index];
}
}
// Update the linked-list of proxy-shapes of a body when a proxy-shape is removed
if (hasNextProxyShape(index)) {
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index);
assert(mEntities[index] == mEntities[mNextBodyProxyShapes[index]]);
// If the current proxy-shape to remove has a previous proxy-shape in the linked-list
if (hasPreviousProxyShape(index)) {
// Make sure the previous proxy-shape will precede the next proxy-shape in the linked-list
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] = mPreviousBodyProxyShapes[index];
}
else {
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] = mNextBodyProxyShapes[index];
}
}
// Destroy the component // Destroy the component
destroyComponent(index); destroyComponent(index);
@ -427,30 +288,22 @@ void ProxyShapesComponents::removeComponent(uint32 index) {
mSleepingStartIndex--; mSleepingStartIndex--;
} }
assert(mSleepingStartIndex <= mNbComponents);
mNbComponents--; mNbComponents--;
}
// Return true if a given proxy-shape component has a previous proxy-shape in the linked-list of proxy-shapes of a body assert(mSleepingStartIndex <= mNbComponents);
bool ProxyShapesComponents::hasPreviousProxyShape(uint32 index) const { assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
assert(index < mNbComponents);
return mPreviousBodyProxyShapes[index] != index;
}
// Return true if a given proxy-shape component has a next proxy-shape in the linked-list of proxy-shapes of a body
bool ProxyShapesComponents::hasNextProxyShape(uint32 index) const {
assert(index < mNbComponents);
return mNextBodyProxyShapes[index] != index;
} }
// Destroy a component at a given index // Destroy a component at a given index
void ProxyShapesComponents::destroyComponent(uint32 index) { void ProxyShapesComponents::destroyComponent(uint32 index) {
assert(index < mNbComponents); assert(index < mNbComponents);
assert(mMapEntityToComponentIndex[mProxyShapesEntities[index]] == index);
mMapProxyShapeToComponentIndex.remove(mProxyShapes[index]); mMapEntityToComponentIndex.remove(mProxyShapesEntities[index]);
mEntities[index].~Entity(); mProxyShapesEntities[index].~Entity();
mBodiesEntities[index].~Entity();
mProxyShapes[index] = nullptr; mProxyShapes[index] = nullptr;
mLocalBounds[index].~AABB(); mLocalBounds[index].~AABB();
mLocalToBodyTransforms[index].~Transform(); mLocalToBodyTransforms[index].~Transform();
@ -492,31 +345,4 @@ void ProxyShapesComponents::setIsEntitySleeping(Entity entity, bool isSleeping)
} }
assert(mSleepingStartIndex <= mNbComponents); assert(mSleepingStartIndex <= mNbComponents);
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index || !hasNextProxyShape(index));
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
}
// Remove all the components of a given entity
void ProxyShapesComponents::removeComponents(Entity entity) {
auto it = mMapEntityToComponentIndex.find(entity);
// While there are components for this entity
while (it != mMapEntityToComponentIndex.end()) {
// Remove the component
removeComponent(it->second);
it = mMapEntityToComponentIndex.find(entity);
}
assert(!mMapEntityToComponentIndex.containsKey(entity));
}
// Remove a given proxy-shape
void ProxyShapesComponents::removeComponent(const ProxyShape* proxyShape) {
uint32 index = mMapProxyShapeToComponentIndex[proxyShape];
removeComponent(index);
} }

View File

@ -45,11 +45,9 @@ class ProxyShape;
// Class ProxyShapesComponents // Class ProxyShapesComponents
/** /**
* This class represent the component of the ECS that contains the proxy-shapes of the * This class represent the component of the ECS that contains data about the the proxy-shapes of the
* different entities. There can be several proxy shapes for each entity (body). We store * different bodies. We also make sure that proxy shapes of sleeping entities (bodies) are
* the proxy shapes in a flat array but we keep two arrays with previous/next proxy shapes * always stored at the end of the array.
* link information to quickly know all the proxy shapes of a given entity (body). We also make
* sure that proxy shapes of sleeping entities (bodies) are always stored at the end of the array.
*/ */
class ProxyShapesComponents : public Components { class ProxyShapesComponents : public Components {
@ -57,22 +55,22 @@ class ProxyShapesComponents : public Components {
// -------------------- Constants -------------------- // // -------------------- Constants -------------------- //
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) + sizeof(AABB) + const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) + sizeof(AABB) +
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(uint32) + sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) +
sizeof(uint32) + sizeof(unsigned short) + sizeof(unsigned short); sizeof(unsigned short);
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
/// Index of the first component of a sleeping entity (sleeping components are stored at the end) /// Index of the first component of a sleeping entity (sleeping components are stored at the end)
uint32 mSleepingStartIndex; uint32 mSleepingStartIndex;
/// Map a proxy shape to the index of the corresponding component in the array /// Array of entities of each component
Map<const ProxyShape*, uint32> mMapProxyShapeToComponentIndex; Entity* mBodiesEntities;
/// Array of entities of each component /// Array of entities of each component
Entity* mEntities; Entity* mProxyShapesEntities;
/// Array of pointers to the proxy-shapes /// Array of pointer to the proxy-shapes
ProxyShape** mProxyShapes; ProxyShape** mProxyShapes;
/// Ids of the proxy-shapes for the broad-phase algorithm /// Ids of the proxy-shapes for the broad-phase algorithm
@ -91,14 +89,6 @@ class ProxyShapesComponents : public Components {
/// Masses (in kilogramms) of the proxy-shapes /// Masses (in kilogramms) of the proxy-shapes
decimal* mMasses; decimal* mMasses;
/// Index of the previous proxy-shape in the same body
/// mPreviousBodyProxyShapes[i] == i means that the proxy-shape component has no previous proxy-shape
uint32* mPreviousBodyProxyShapes;
/// Index of the next proxy-shape in the same body
/// mNextBodyProxyShapes[i] == i means that the proxy-shape component has no next proxy-shape
uint32* mNextBodyProxyShapes;
/// Array of bits used to define the collision category of this shape. /// Array of bits used to define the collision category of this shape.
/// You can set a single bit to one to define a category value for this /// You can set a single bit to one to define a category value for this
/// shape. This value is one (0x0001) by default. This variable can be used /// shape. This value is one (0x0001) by default. This variable can be used
@ -114,9 +104,6 @@ class ProxyShapesComponents : public Components {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Remove a component at a given index
void removeComponent(uint32 index);
/// Destroy a component at a given index /// Destroy a component at a given index
void destroyComponent(uint32 index); void destroyComponent(uint32 index);
@ -126,20 +113,12 @@ class ProxyShapesComponents : public Components {
/// Swap two components in the array /// Swap two components in the array
void swapComponents(uint32 index1, uint32 index2); void swapComponents(uint32 index1, uint32 index2);
/// Add a new proxy-shape at the end of the linked-list of proxy-shapes of a given entity
void linkProxyShapeWithEntity(Entity entity, uint32 proxyShapeComponentIndex);
/// Return true if a given proxy-shape component has a previous proxy-shape in the linked-list of proxy-shapes of a body
bool hasPreviousProxyShape(uint32 index) const;
/// Return true if a given proxy-shape component has a next proxy-shape in the linked-list of proxy-shapes of a body
bool hasNextProxyShape(uint32 index) const;
public: public:
/// Structure for the data of a proxy shape component /// Structure for the data of a proxy shape component
struct ProxyShapeComponent { struct ProxyShapeComponent {
Entity bodyEntity;
ProxyShape* proxyShape; ProxyShape* proxyShape;
int broadPhaseId; int broadPhaseId;
AABB localBounds; AABB localBounds;
@ -150,10 +129,10 @@ class ProxyShapesComponents : public Components {
unsigned short collideWithMaskBits; unsigned short collideWithMaskBits;
/// Constructor /// Constructor
ProxyShapeComponent(ProxyShape* proxyShape, int broadPhaseId, AABB localBounds, Transform localToBodyTransform, ProxyShapeComponent(Entity bodyEntity, ProxyShape* proxyShape, int broadPhaseId, AABB localBounds, Transform localToBodyTransform,
CollisionShape* collisionShape, decimal mass, unsigned short collisionCategoryBits, CollisionShape* collisionShape, decimal mass, unsigned short collisionCategoryBits,
unsigned short collideWithMaskBits) unsigned short collideWithMaskBits)
:proxyShape(proxyShape), broadPhaseId(broadPhaseId), localBounds(localBounds), localToBodyTransform(localToBodyTransform), :bodyEntity(bodyEntity), proxyShape(proxyShape), broadPhaseId(broadPhaseId), localBounds(localBounds), localToBodyTransform(localToBodyTransform),
collisionShape(collisionShape), mass(mass), collisionCategoryBits(collisionCategoryBits), collideWithMaskBits(collideWithMaskBits) { collisionShape(collisionShape), mass(mass), collisionCategoryBits(collisionCategoryBits), collideWithMaskBits(collideWithMaskBits) {
} }
@ -165,166 +144,140 @@ class ProxyShapesComponents : public Components {
ProxyShapesComponents(MemoryAllocator& allocator); ProxyShapesComponents(MemoryAllocator& allocator);
/// Destructor /// Destructor
~ProxyShapesComponents(); virtual ~ProxyShapesComponents();
/// Allocate memory for a given number of components /// Allocate memory for a given number of components
void allocate(uint32 nbComponentsToAllocate); void allocate(uint32 nbComponentsToAllocate);
/// Add a component /// Add a component
void addComponent(Entity entity, bool isSleeping, const ProxyShapeComponent& component); void addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component);
/// Remove all the components of a given entity /// Remove a component at a given index
void removeComponents(Entity entity); void removeComponent(Entity proxyShapeEntity);
/// Remove a given proxy-shape
void removeComponent(const ProxyShape* proxyShape);
/// Notify if a given entity is sleeping or not /// Notify if a given entity is sleeping or not
void setIsEntitySleeping(Entity entity, bool isSleeping); void setIsEntitySleeping(Entity entity, bool isSleeping);
/// Return the mass of a proxy-shape /// Return the mass of a proxy-shape
decimal getMass(const ProxyShape* proxyShape) const; decimal getMass(Entity proxyShapeEntity) const;
/// Return a pointer to a given proxy-shape
ProxyShape* getProxyShape(Entity proxyShapeEntity) const;
/// Return the local-to-body transform of a proxy-shape /// Return the local-to-body transform of a proxy-shape
const Transform& getLocalToBodyTransform(const ProxyShape* proxyShape) const; const Transform& getLocalToBodyTransform(Entity proxyShapeEntity) const;
/// Set the local-to-body transform of a proxy-shape /// Set the local-to-body transform of a proxy-shape
void setLocalToBodyTransform(const ProxyShape* proxyShape, const Transform& transform); void setLocalToBodyTransform(Entity proxyShapeEntity, const Transform& transform);
/// Return a pointer to the collision shape of a proxy-shape /// Return a pointer to the collision shape of a proxy-shape
CollisionShape* getCollisionShape(const ProxyShape* proxyShape) const; CollisionShape* getCollisionShape(Entity proxyShapeEntity) const;
/// Return the broad-phase id of a given proxy shape /// Return the broad-phase id of a given proxy shape
int getBroadPhaseId(const ProxyShape* proxyShape) const; int getBroadPhaseId(Entity proxyShapeEntity) const;
/// Set the broad-phase id of a given proxy shape /// Set the broad-phase id of a given proxy shape
void setBroadPhaseId(const ProxyShape* proxyShape, int broadPhaseId); void setBroadPhaseId(Entity proxyShapeEntity, int broadPhaseId);
/// Return the next proxy-shape in the linked-list of all proxy-shapes of a body
ProxyShape* getNextProxyShapeOfBody(const ProxyShape* proxyShape) const;
/// Return the first proxy-shape in the linked-list of all proxy-shapes of a body
ProxyShape* getFirstProxyShapeOfBody(Entity entity) const;
/// Return the collision category bits of a given proxy-shape /// Return the collision category bits of a given proxy-shape
unsigned short getCollisionCategoryBits(const ProxyShape* proxyShape) const; unsigned short getCollisionCategoryBits(Entity proxyShapeEntity) const;
/// Set the collision category bits of a given proxy-shape /// Set the collision category bits of a given proxy-shape
void setCollisionCategoryBits(const ProxyShape* proxyShape, unsigned short collisionCategoryBits); void setCollisionCategoryBits(Entity proxyShapeEntity, unsigned short collisionCategoryBits);
/// Return the "collide with" mask bits of a given proxy-shape /// Return the "collide with" mask bits of a given proxy-shape
unsigned short getCollideWithMaskBits(const ProxyShape* proxyShape) const; unsigned short getCollideWithMaskBits(Entity proxyShapeEntity) const;
/// Set the "collide with" mask bits of a given proxy-shape /// Set the "collide with" mask bits of a given proxy-shape
void setCollideWithMaskBits(const ProxyShape* proxyShape, unsigned short collideWithMaskBits); void setCollideWithMaskBits(Entity proxyShapeEntity, unsigned short collideWithMaskBits);
}; };
// Return the mass of a proxy-shape // Return the mass of a proxy-shape
inline decimal ProxyShapesComponents::getMass(const ProxyShape* proxyShape) const { inline decimal ProxyShapesComponents::getMass(Entity proxyShapeEntity) const {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mMasses[mMapProxyShapeToComponentIndex[proxyShape]]; return mMasses[mMapEntityToComponentIndex[proxyShapeEntity]];
}
// Return a pointer to a given proxy-shape
inline ProxyShape* ProxyShapesComponents::getProxyShape(Entity proxyShapeEntity) const {
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mProxyShapes[mMapEntityToComponentIndex[proxyShapeEntity]];
} }
// Return the local-to-body transform of a proxy-shape // Return the local-to-body transform of a proxy-shape
inline const Transform& ProxyShapesComponents::getLocalToBodyTransform(const ProxyShape* proxyShape) const { inline const Transform& ProxyShapesComponents::getLocalToBodyTransform(Entity proxyShapeEntity) const {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mLocalToBodyTransforms[mMapProxyShapeToComponentIndex[proxyShape]]; return mLocalToBodyTransforms[mMapEntityToComponentIndex[proxyShapeEntity]];
} }
// Set the local-to-body transform of a proxy-shape // Set the local-to-body transform of a proxy-shape
inline void ProxyShapesComponents::setLocalToBodyTransform(const ProxyShape* proxyShape, const Transform& transform) { inline void ProxyShapesComponents::setLocalToBodyTransform(Entity proxyShapeEntity, const Transform& transform) {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
mLocalToBodyTransforms[mMapProxyShapeToComponentIndex[proxyShape]] = transform; mLocalToBodyTransforms[mMapEntityToComponentIndex[proxyShapeEntity]] = transform;
} }
// Return a pointer to the collision shape of a proxy-shape // Return a pointer to the collision shape of a proxy-shape
inline CollisionShape* ProxyShapesComponents::getCollisionShape(const ProxyShape* proxyShape) const { inline CollisionShape* ProxyShapesComponents::getCollisionShape(Entity proxyShapeEntity) const {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mCollisionShapes[mMapProxyShapeToComponentIndex[proxyShape]]; return mCollisionShapes[mMapEntityToComponentIndex[proxyShapeEntity]];
} }
// Return the broad-phase id of a given proxy shape // Return the broad-phase id of a given proxy shape
inline int ProxyShapesComponents::getBroadPhaseId(const ProxyShape* proxyShape) const { inline int ProxyShapesComponents::getBroadPhaseId(Entity proxyShapeEntity) const {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mBroadPhaseIds[mMapProxyShapeToComponentIndex[proxyShape]]; return mBroadPhaseIds[mMapEntityToComponentIndex[proxyShapeEntity]];
} }
// Set the broad-phase id of a given proxy shape // Set the broad-phase id of a given proxy shape
inline void ProxyShapesComponents::setBroadPhaseId(const ProxyShape* proxyShape, int broadPhaseId) { inline void ProxyShapesComponents::setBroadPhaseId(Entity proxyShapeEntity, int broadPhaseId) {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
mBroadPhaseIds[mMapProxyShapeToComponentIndex[proxyShape]] = broadPhaseId; mBroadPhaseIds[mMapEntityToComponentIndex[proxyShapeEntity]] = broadPhaseId;
}
// Return the next proxy-shape in the linked-list of all proxy-shapes of a body
inline ProxyShape* ProxyShapesComponents::getNextProxyShapeOfBody(const ProxyShape* proxyShape) const {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
uint32 proxyShapeIndex = mMapProxyShapeToComponentIndex[proxyShape];
uint32 nextProxyShapeIndex = mNextBodyProxyShapes[proxyShapeIndex];
// If the current proxy-shape has a next one
if (proxyShapeIndex != nextProxyShapeIndex) {
return mProxyShapes[nextProxyShapeIndex];
}
return nullptr;
}
// Return the first proxy-shape in the linked-list of all proxy-shapes of a body
inline ProxyShape* ProxyShapesComponents::getFirstProxyShapeOfBody(Entity entity) const {
auto it = mMapEntityToComponentIndex.find(entity);
if (it != mMapEntityToComponentIndex.end()) {
return mProxyShapes[it->second];
}
return nullptr;
} }
// Return the collision category bits of a given proxy-shape // Return the collision category bits of a given proxy-shape
inline unsigned short ProxyShapesComponents::getCollisionCategoryBits(const ProxyShape* proxyShape) const { inline unsigned short ProxyShapesComponents::getCollisionCategoryBits(Entity proxyShapeEntity) const {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mCollisionCategoryBits[mMapProxyShapeToComponentIndex[proxyShape]]; return mCollisionCategoryBits[mMapEntityToComponentIndex[proxyShapeEntity]];
} }
// Return the "collide with" mask bits of a given proxy-shape // Return the "collide with" mask bits of a given proxy-shape
inline unsigned short ProxyShapesComponents::getCollideWithMaskBits(const ProxyShape* proxyShape) const { inline unsigned short ProxyShapesComponents::getCollideWithMaskBits(Entity proxyShapeEntity) const {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
return mCollideWithMaskBits[mMapProxyShapeToComponentIndex[proxyShape]]; return mCollideWithMaskBits[mMapEntityToComponentIndex[proxyShapeEntity]];
} }
// Set the collision category bits of a given proxy-shape // Set the collision category bits of a given proxy-shape
inline void ProxyShapesComponents::setCollisionCategoryBits(const ProxyShape* proxyShape, unsigned short collisionCategoryBits) { inline void ProxyShapesComponents::setCollisionCategoryBits(Entity proxyShapeEntity, unsigned short collisionCategoryBits) {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
mCollisionCategoryBits[mMapProxyShapeToComponentIndex[proxyShape]] = collisionCategoryBits; mCollisionCategoryBits[mMapEntityToComponentIndex[proxyShapeEntity]] = collisionCategoryBits;
} }
// Set the "collide with" mask bits of a given proxy-shape // Set the "collide with" mask bits of a given proxy-shape
inline void ProxyShapesComponents::setCollideWithMaskBits(const ProxyShape* proxyShape, unsigned short collideWithMaskBits) { inline void ProxyShapesComponents::setCollideWithMaskBits(Entity proxyShapeEntity, unsigned short collideWithMaskBits) {
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
mCollideWithMaskBits[mMapProxyShapeToComponentIndex[proxyShape]] = collideWithMaskBits; mCollideWithMaskBits[mMapEntityToComponentIndex[proxyShapeEntity]] = collideWithMaskBits;
} }
} }

View File

@ -82,20 +82,20 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) {
// Copy component data from the previous buffer to the new one // Copy component data from the previous buffer to the new one
memcpy(newTransforms, mTransforms, mNbComponents * sizeof(Transform)); memcpy(newTransforms, mTransforms, mNbComponents * sizeof(Transform));
memcpy(newEntities, mEntities, mNbComponents * sizeof(Entity)); memcpy(newEntities, mBodies, mNbComponents * sizeof(Entity));
// Deallocate previous memory // Deallocate previous memory
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE); mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
} }
mBuffer = newBuffer; mBuffer = newBuffer;
mEntities = newEntities; mBodies = newEntities;
mTransforms = newTransforms; mTransforms = newTransforms;
mNbAllocatedComponents = nbComponentsToAllocate; mNbAllocatedComponents = nbComponentsToAllocate;
} }
// Add a component // Add a component
void TransformComponents::addComponent(Entity entity, bool isSleeping, const TransformComponent& component) { void TransformComponents::addComponent(Entity bodyEntity, bool isSleeping, const TransformComponent& component) {
// If we need to allocate more components // If we need to allocate more components
if (mNbComponents == mNbAllocatedComponents) { if (mNbComponents == mNbAllocatedComponents) {
@ -128,11 +128,11 @@ void TransformComponents::addComponent(Entity entity, bool isSleeping, const Tra
} }
// Insert the new component data // Insert the new component data
new (mEntities + index) Entity(entity); new (mBodies + index) Entity(bodyEntity);
new (mTransforms + index) Transform(component.transform); new (mTransforms + index) Transform(component.transform);
// Map the entity with the new component lookup index // Map the entity with the new component lookup index
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, index)); mMapEntityToComponentIndex.add(Pair<Entity, uint32>(bodyEntity, index));
mNbComponents++; mNbComponents++;
@ -141,7 +141,11 @@ void TransformComponents::addComponent(Entity entity, bool isSleeping, const Tra
} }
// Remove a component at a given index // Remove a component at a given index
void TransformComponents::removeComponent(uint32 index) { void TransformComponents::removeComponent(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
uint index = mMapEntityToComponentIndex[bodyEntity];
assert(index < mNbComponents); assert(index < mNbComponents);
@ -229,26 +233,28 @@ void TransformComponents::setIsEntitySleeping(Entity entity, bool isSleeping) {
// The destination location must contain a constructed object // The destination location must contain a constructed object
void TransformComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) { void TransformComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
// Copy the data of the source component to the destination location const Entity entity = mBodies[srcIndex];
new (mEntities + destIndex) Entity(mEntities[srcIndex]);
new (mTransforms + destIndex) Transform(mTransforms[srcIndex]);
const Entity entity = mEntities[srcIndex]; // Copy the data of the source component to the destination location
new (mBodies + destIndex) Entity(mBodies[srcIndex]);
new (mTransforms + destIndex) Transform(mTransforms[srcIndex]);
// Destroy the source component // Destroy the source component
destroyComponent(srcIndex); destroyComponent(srcIndex);
assert(!mMapEntityToComponentIndex.containsKey(entity));
// Update the entity to component index mapping // Update the entity to component index mapping
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, destIndex)); mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, destIndex));
assert(mMapEntityToComponentIndex[mEntities[destIndex]] == destIndex); assert(mMapEntityToComponentIndex[mBodies[destIndex]] == destIndex);
} }
// Swap two components in the array // Swap two components in the array
void TransformComponents::swapComponents(uint32 index1, uint32 index2) { void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
// Copy component 1 data // Copy component 1 data
Entity entity1(mEntities[index1]); Entity entity1(mBodies[index1]);
Transform transform1(mTransforms[index1]); Transform transform1(mTransforms[index1]);
// Destroy component 1 // Destroy component 1
@ -257,14 +263,14 @@ void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
moveComponentToIndex(index2, index1); moveComponentToIndex(index2, index1);
// Reconstruct component 1 at component 2 location // Reconstruct component 1 at component 2 location
new (mEntities + index2) Entity(entity1); new (mBodies + index2) Entity(entity1);
new (mTransforms + index2) Transform(transform1); new (mTransforms + index2) Transform(transform1);
// Update the entity to component index mapping // Update the entity to component index mapping
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2)); mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2));
assert(mMapEntityToComponentIndex[mEntities[index1]] == index1); assert(mMapEntityToComponentIndex[mBodies[index1]] == index1);
assert(mMapEntityToComponentIndex[mEntities[index2]] == index2); assert(mMapEntityToComponentIndex[mBodies[index2]] == index2);
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size())); assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
} }
@ -272,25 +278,10 @@ void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
void TransformComponents::destroyComponent(uint32 index) { void TransformComponents::destroyComponent(uint32 index) {
assert(index < mNbComponents); assert(index < mNbComponents);
assert(mMapEntityToComponentIndex[mEntities[index]] == index); assert(mMapEntityToComponentIndex[mBodies[index]] == index);
mMapEntityToComponentIndex.remove(mEntities[index]); mMapEntityToComponentIndex.remove(mBodies[index]);
mEntities[index].~Entity(); mBodies[index].~Entity();
mTransforms[index].~Transform(); mTransforms[index].~Transform();
} }
// Remove all the components of a given entity
void TransformComponents::removeComponents(Entity entity) {
auto it = mMapEntityToComponentIndex.find(entity);
// If there is a component for this entity
if (it != mMapEntityToComponentIndex.end()) {
// Remove the component
removeComponent(it->second);
}
assert(!mMapEntityToComponentIndex.containsKey(entity));
}

View File

@ -58,17 +58,14 @@ class TransformComponents : public Components {
/// Index of the first component of a sleeping entity (sleeping components are stored at the end) /// Index of the first component of a sleeping entity (sleeping components are stored at the end)
uint32 mSleepingStartIndex; uint32 mSleepingStartIndex;
/// Array of entities of each component /// Array of body entities of each component
Entity* mEntities; Entity* mBodies;
/// Array of transform of each component /// Array of transform of each component
Transform* mTransforms; Transform* mTransforms;
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Remove a component at a given index
void removeComponent(uint32 index);
/// Destroy a component at a given index /// Destroy a component at a given index
void destroyComponent(uint32 index); void destroyComponent(uint32 index);
@ -103,29 +100,29 @@ class TransformComponents : public Components {
void allocate(uint32 nbComponentsToAllocate); void allocate(uint32 nbComponentsToAllocate);
/// Add a component /// Add a component
void addComponent(Entity entity, bool isSleeping, const TransformComponent& component); void addComponent(Entity bodyEntity, bool isSleeping, const TransformComponent& component);
/// Remove all the components of a given entity /// Remove a component at a given index
void removeComponents(Entity entity); void removeComponent(Entity bodyEntity);
/// Return the transform of an entity /// Return the transform of an entity
Transform& getTransform(Entity entity) const; Transform& getTransform(Entity bodyEntity) const;
/// Set the transform of an entity /// Set the transform of an entity
void setTransform(Entity entity, const Transform& transform); void setTransform(Entity bodyEntity, const Transform& transform);
/// Notify if a given entity is sleeping or not /// Notify if a given entity is sleeping or not
void setIsEntitySleeping(Entity entity, bool isSleeping); void setIsEntitySleeping(Entity bodyEntity, bool isSleeping);
}; };
// Return the transform of an entity // Return the transform of an entity
inline Transform& TransformComponents::getTransform(Entity entity) const { inline Transform& TransformComponents::getTransform(Entity bodyEntity) const {
return mTransforms[mMapEntityToComponentIndex[entity]]; return mTransforms[mMapEntityToComponentIndex[bodyEntity]];
} }
// Set the transform of an entity // Set the transform of an entity
inline void TransformComponents::setTransform(Entity entity, const Transform& transform) { inline void TransformComponents::setTransform(Entity bodyEntity, const Transform& transform) {
mTransforms[mMapEntityToComponentIndex[entity]] = transform; mTransforms[mMapEntityToComponentIndex[bodyEntity]] = transform;
} }
} }

View File

@ -38,9 +38,10 @@ 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), mEntityManager(mMemoryManager.getPoolAllocator()), : mConfig(worldSettings), mEntityManager(mMemoryManager.getPoolAllocator()),
mTransformComponents(mMemoryManager.getBaseAllocator()), mProxyShapesComponents(mMemoryManager.getBaseAllocator()), mBodyComponents(mMemoryManager.getBaseAllocator()), mTransformComponents(mMemoryManager.getBaseAllocator()),
mCollisionDetection(this, mProxyShapesComponents, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0), mProxyShapesComponents(mMemoryManager.getBaseAllocator()), mCollisionDetection(this, mProxyShapesComponents, mMemoryManager),
mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0), mFreeBodiesIds(mMemoryManager.getPoolAllocator()),
mEventListener(nullptr), mName(worldSettings.worldName),
mIsProfilerCreatedByUser(profiler != nullptr), mIsProfilerCreatedByUser(profiler != nullptr),
mIsLoggerCreatedByUser(logger != nullptr) { mIsLoggerCreatedByUser(logger != nullptr) {
@ -131,6 +132,9 @@ CollisionWorld::~CollisionWorld() {
#endif #endif
assert(mBodies.size() == 0); assert(mBodies.size() == 0);
assert(mBodyComponents.getNbComponents() == 0);
assert(mTransformComponents.getNbComponents() == 0);
assert(mProxyShapesComponents.getNbComponents() == 0);
} }
// Create a collision body and add it to the world // Create a collision body and add it to the world
@ -149,7 +153,6 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
// 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, false, TransformComponents::TransformComponent(transform)); mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform));
// Create the collision body // Create the collision body
@ -159,6 +162,10 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
assert(collisionBody != nullptr); assert(collisionBody != nullptr);
// Add the components
BodyComponents::BodyComponent bodyComponent(collisionBody);
mBodyComponents.addComponent(entity, false, bodyComponent);
// Add the collision body to the world // Add the collision body to the world
mBodies.add(collisionBody); mBodies.add(collisionBody);
@ -197,8 +204,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 entity and its components mBodyComponents.removeComponent(collisionBody->getEntity());
destroyEntity(collisionBody->getEntity()); mTransformComponents.removeComponent(collisionBody->getEntity());
mEntityManager.destroyEntity(collisionBody->getEntity());
// Call the destructor of the collision body // Call the destructor of the collision body
collisionBody->~CollisionBody(); collisionBody->~CollisionBody();
@ -239,26 +247,19 @@ void CollisionWorld::resetContactManifoldListsOfBodies() {
} }
// Notify the world if a body is sleeping or not // Notify the world if a body is sleeping or not
void CollisionWorld::notifyBodySleeping(Entity entity, bool isSleeping) { void CollisionWorld::notifyBodySleeping(Entity bodyEntity, bool isSleeping) {
// TODO : Make sure we notify all the components here ... // TODO : Make sure we notify all the components here ...
// Notify all the components // Notify all the components
mTransformComponents.setIsEntitySleeping(entity, isSleeping); mTransformComponents.setIsEntitySleeping(bodyEntity, isSleeping);
mProxyShapesComponents.setIsEntitySleeping(entity, isSleeping);
}
// Destroy an entity and all the associated components // For each proxy-shape of the body
void CollisionWorld::destroyEntity(Entity entity) { const List<Entity>& proxyShapesEntities = mBodyComponents.getProxyShapes(bodyEntity);
for (uint i=0; i < proxyShapesEntities.size(); i++) {
// Destroy the corresponding entity mProxyShapesComponents.setIsEntitySleeping(proxyShapesEntities[i], isSleeping);
mEntityManager.destroyEntity(entity); }
// TODO : Make sure we notify all the components here ...
// Notify all the components
mTransformComponents.removeComponents(entity);
mProxyShapesComponents.removeComponents(entity);
} }
// Test if the AABBs of two bodies overlap // Test if the AABBs of two bodies overlap

View File

@ -33,6 +33,7 @@
#include "constraint/Joint.h" #include "constraint/Joint.h"
#include "memory/MemoryManager.h" #include "memory/MemoryManager.h"
#include "engine/EntityManager.h" #include "engine/EntityManager.h"
#include "components/BodyComponents.h"
#include "components/TransformComponents.h" #include "components/TransformComponents.h"
#include "components/ProxyShapesComponents.h" #include "components/ProxyShapesComponents.h"
@ -72,6 +73,9 @@ class CollisionWorld {
/// Entity Manager for the ECS /// Entity Manager for the ECS
EntityManager mEntityManager; EntityManager mEntityManager;
/// Body Components
BodyComponents mBodyComponents;
/// Transform Components /// Transform Components
TransformComponents mTransformComponents; TransformComponents mTransformComponents;
@ -128,9 +132,6 @@ class CollisionWorld {
/// Notify the world if a body is sleeping or not /// Notify the world if a body is sleeping or not
void notifyBodySleeping(Entity entity, bool isSleeping); void notifyBodySleeping(Entity entity, bool isSleeping);
/// Destroy an entity and all the associated components
void destroyEntity(Entity entity);
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //

View File

@ -428,7 +428,6 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
// 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, false, TransformComponents::TransformComponent(transform)); mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform));
// Create the rigid body // Create the rigid body
@ -436,6 +435,9 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
sizeof(RigidBody))) RigidBody(transform, *this, entity, bodyID); sizeof(RigidBody))) RigidBody(transform, *this, entity, bodyID);
assert(rigidBody != nullptr); assert(rigidBody != nullptr);
BodyComponents::BodyComponent bodyComponent(rigidBody);
mBodyComponents.addComponent(entity, false, bodyComponent);
// Add the rigid body to the physics world // Add the rigid body to the physics world
mBodies.add(rigidBody); mBodies.add(rigidBody);
mRigidBodies.add(rigidBody); mRigidBodies.add(rigidBody);
@ -480,7 +482,9 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
rigidBody->resetContactManifoldsList(); rigidBody->resetContactManifoldsList();
// Destroy the corresponding entity and its components // Destroy the corresponding entity and its components
destroyEntity(rigidBody->getEntity()); mBodyComponents.removeComponent(rigidBody->getEntity());
mTransformComponents.removeComponent(rigidBody->getEntity());
mEntityManager.destroyEntity(rigidBody->getEntity());
// Call the destructor of the rigid body // Call the destructor of the rigid body
rigidBody->~RigidBody(); rigidBody->~RigidBody();

View File

@ -84,7 +84,7 @@ void BroadPhaseSystem::addProxyCollisionShape(ProxyShape* proxyShape, const AABB
int nodeId = mDynamicAABBTree.addObject(aabb, proxyShape); int nodeId = mDynamicAABBTree.addObject(aabb, proxyShape);
// Set the broad-phase ID of the proxy shape // Set the broad-phase ID of the proxy shape
mProxyShapesComponents.setBroadPhaseId(proxyShape, nodeId); mProxyShapesComponents.setBroadPhaseId(proxyShape->getEntity(), nodeId);
// Add the collision shape into the array of bodies that have moved (or have been created) // Add the collision shape into the array of bodies that have moved (or have been created)
// during the last simulation step // during the last simulation step
@ -98,7 +98,7 @@ void BroadPhaseSystem::removeProxyCollisionShape(ProxyShape* proxyShape) {
int broadPhaseID = proxyShape->getBroadPhaseId(); int broadPhaseID = proxyShape->getBroadPhaseId();
mProxyShapesComponents.setBroadPhaseId(proxyShape, -1); mProxyShapesComponents.setBroadPhaseId(proxyShape->getEntity(), -1);
// Remove the collision shape from the dynamic AABB tree // Remove the collision shape from the dynamic AABB tree
mDynamicAABBTree.removeObject(broadPhaseID); mDynamicAABBTree.removeObject(broadPhaseID);

View File

@ -380,8 +380,9 @@ void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix)
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) { for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
// For each proxy shape of the object // For each proxy shape of the object
rp3d::ProxyShape* proxyShape = (*it)->getCollisionBody()->getProxyShapesList(); for (uint i=0; i < (*it)->getCollisionBody()->getNbProxyShapes(); i++) {
while (proxyShape != nullptr) {
rp3d::ProxyShape* proxyShape = (*it)->getCollisionBody()->getProxyShape(i);
// Get the broad-phase AABB corresponding to the proxy shape // Get the broad-phase AABB corresponding to the proxy shape
rp3d::AABB aabb = mPhysicsWorld->getWorldAABB(proxyShape); rp3d::AABB aabb = mPhysicsWorld->getWorldAABB(proxyShape);
@ -392,8 +393,6 @@ void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix)
// Render the AABB // Render the AABB
AABB::render(aabbCenter, aabbMax - aabbMin, Color::green(), mColorShader, worldToCameraMatrix); AABB::render(aabbCenter, aabbMax - aabbMin, Color::green(), mColorShader, worldToCameraMatrix);
proxyShape = proxyShape->getNext();
} }
} }
} }