From ca80d95d840fdc26408b79bbe94f24995fccc3e3 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Tue, 16 Jul 2019 07:15:13 +0200 Subject: [PATCH] Add RigidBodyComponents class --- CMakeLists.txt | 2 + src/body/CollisionBody.cpp | 46 ++--- src/body/RigidBody.cpp | 34 ++-- src/body/RigidBody.h | 2 + src/collision/CollisionCallback.cpp | 4 +- src/collision/CollisionDetection.cpp | 6 +- src/collision/OverlapCallback.cpp | 4 +- src/collision/ProxyShape.cpp | 2 +- src/components/CollisionBodyComponents.cpp | 29 +--- src/components/CollisionBodyComponents.h | 87 +--------- src/components/RigidBodyComponents.cpp | 173 +++++++++++++++++++ src/components/RigidBodyComponents.h | 187 +++++++++++++++++++++ src/engine/CollisionWorld.cpp | 20 ++- src/engine/CollisionWorld.h | 8 +- src/engine/DynamicsWorld.cpp | 33 ++-- testbed/common/Box.cpp | 10 +- testbed/common/Capsule.cpp | 10 +- testbed/common/ConcaveMesh.cpp | 10 +- testbed/common/ConvexMesh.cpp | 10 +- testbed/common/Dumbbell.cpp | 10 +- testbed/common/HeightField.cpp | 10 +- testbed/common/Sphere.cpp | 10 +- 22 files changed, 485 insertions(+), 222 deletions(-) create mode 100644 src/components/RigidBodyComponents.cpp create mode 100644 src/components/RigidBodyComponents.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 477df7a5..dce9b270 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,7 @@ SET (REACTPHYSICS3D_HEADERS "src/systems/BroadPhaseSystem.h" "src/components/Components.h" "src/components/CollisionBodyComponents.h" + "src/components/RigidBodyComponents.h" "src/components/TransformComponents.h" "src/components/ProxyShapeComponents.h" "src/components/DynamicsComponents.h" @@ -233,6 +234,7 @@ SET (REACTPHYSICS3D_SOURCES "src/systems/BroadPhaseSystem.cpp" "src/components/Components.cpp" "src/components/CollisionBodyComponents.cpp" + "src/components/RigidBodyComponents.cpp" "src/components/TransformComponents.cpp" "src/components/ProxyShapeComponents.cpp" "src/components/DynamicsComponents.cpp" diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 80cd0e7d..39dae6a4 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -87,12 +87,12 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, con // TODO : Maybe this method can directly returns an AABB collisionShape->getLocalBounds(localBoundsMin, localBoundsMax); ProxyShapeComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1, - AABB(localBoundsMin, localBoundsMax), - transform, collisionShape, decimal(1), 0x0001, 0xFFFF); - bool isSleeping = mWorld.mBodyComponents.getIsSleeping(mEntity); - mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, isSleeping, proxyShapeComponent); + AABB(localBoundsMin, localBoundsMax), + transform, collisionShape, decimal(1), 0x0001, 0xFFFF); + bool isActive = mWorld.mCollisionBodyComponents.getIsActive(mEntity); + mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, isActive, proxyShapeComponent); - mWorld.mBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity); + mWorld.mCollisionBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity); #ifdef IS_PROFILING_ACTIVE @@ -131,7 +131,7 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, con * @return The number of proxy-shapes associated with this body */ uint CollisionBody::getNbProxyShapes() const { - return static_cast(mWorld.mBodyComponents.getProxyShapes(mEntity).size()); + return static_cast(mWorld.mCollisionBodyComponents.getProxyShapes(mEntity).size()); } // Return a const pointer to a given proxy-shape of the body @@ -142,7 +142,7 @@ const ProxyShape* CollisionBody::getProxyShape(uint proxyShapeIndex) const { assert(proxyShapeIndex < getNbProxyShapes()); - Entity proxyShapeEntity = mWorld.mBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex]; + Entity proxyShapeEntity = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex]; return mWorld.mProxyShapesComponents.getProxyShape(proxyShapeEntity); } @@ -155,7 +155,7 @@ ProxyShape* CollisionBody::getProxyShape(uint proxyShapeIndex) { assert(proxyShapeIndex < getNbProxyShapes()); - Entity proxyShapeEntity = mWorld.mBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex]; + Entity proxyShapeEntity = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex]; return mWorld.mProxyShapesComponents.getProxyShape(proxyShapeEntity); } @@ -177,7 +177,7 @@ void CollisionBody::removeCollisionShape(ProxyShape* proxyShape) { mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape); } - mWorld.mBodyComponents.removeProxyShapeFromBody(mEntity, proxyShape->getEntity()); + mWorld.mCollisionBodyComponents.removeProxyShapeFromBody(mEntity, proxyShape->getEntity()); // Remove the proxy-shape component mWorld.mProxyShapesComponents.removeComponent(proxyShape->getEntity()); @@ -194,7 +194,7 @@ void CollisionBody::removeAllCollisionShapes() { // 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 proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { removeCollisionShape(mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i])); @@ -217,7 +217,7 @@ const Transform& CollisionBody::getTransform() const { void CollisionBody::updateBroadPhaseState() const { // For all the proxy collision shapes of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { // Update the proxy @@ -232,9 +232,9 @@ void CollisionBody::updateBroadPhaseState() const { void CollisionBody::setIsActive(bool isActive) { // If the state does not change - if (mWorld.mBodyComponents.getIsActive(mEntity) == isActive) return; + if (mWorld.mCollisionBodyComponents.getIsActive(mEntity) == isActive) return; - mWorld.mBodyComponents.setIsActive(mEntity, isActive); + mWorld.mCollisionBodyComponents.setIsActive(mEntity, isActive); // If we have to activate the body if (isActive) { @@ -242,7 +242,7 @@ void CollisionBody::setIsActive(bool isActive) { const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); // For each proxy shape of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); @@ -258,7 +258,7 @@ void CollisionBody::setIsActive(bool isActive) { else { // If we have to deactivate the body // For each proxy shape of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); @@ -281,7 +281,7 @@ void CollisionBody::setIsActive(bool isActive) { void CollisionBody::askForBroadPhaseCollisionCheck() const { // For all the proxy collision shapes of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); @@ -299,7 +299,7 @@ void CollisionBody::askForBroadPhaseCollisionCheck() const { bool CollisionBody::testPointInside(const Vector3& worldPoint) const { // For each collision shape of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); @@ -322,13 +322,13 @@ bool CollisionBody::testPointInside(const Vector3& worldPoint) const { bool CollisionBody::raycast(const Ray& ray, RaycastInfo& raycastInfo) { // If the body is not active, it cannot be hit by rays - if (!mWorld.mBodyComponents.getIsActive(mEntity)) return false; + if (!mWorld.mCollisionBodyComponents.getIsActive(mEntity)) return false; bool isHit = false; Ray rayTemp(ray); // For each collision shape of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); @@ -351,7 +351,7 @@ AABB CollisionBody::getAABB() const { AABB bodyAABB; - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); if (proxyShapesEntities.size() == 0) return bodyAABB; // TODO : Make sure we compute this in a system @@ -401,7 +401,7 @@ void CollisionBody::setTransform(const Transform& transform) { * @return True if the body currently active and false otherwise */ bool CollisionBody::isActive() const { - return mWorld.mBodyComponents.getIsActive(mEntity); + return mWorld.mCollisionBodyComponents.getIsActive(mEntity); } // Return a pointer to the user data attached to this body @@ -409,7 +409,7 @@ bool CollisionBody::isActive() const { * @return A pointer to the user data you have attached to the body */ void* CollisionBody::getUserData() const { - return mWorld.mBodyComponents.getUserData(mEntity); + return mWorld.mCollisionBodyComponents.getUserData(mEntity); } // Attach user data to this body @@ -417,7 +417,7 @@ void* CollisionBody::getUserData() const { * @param userData A pointer to the user data you want to attach to the body */ void CollisionBody::setUserData(void* userData) { - mWorld.mBodyComponents.setUserData(mEntity, userData); + mWorld.mCollisionBodyComponents.setUserData(mEntity, userData); } // Return the world-space coordinates of a point given the local-space coordinates of the body diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index fb6d73f5..247d64cd 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -171,7 +171,7 @@ void RigidBody::applyForce(const Vector3& force, const Vector3& point) { if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Awake the body if it was sleeping - if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { + if (mWorld.mRigidBodyComponents.getIsSleeping(mEntity)) { setIsSleeping(false); } @@ -223,7 +223,7 @@ void RigidBody::applyForceToCenterOfMass(const Vector3& force) { if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Awake the body if it was sleeping - if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { + if (mWorld.mRigidBodyComponents.getIsSleeping(mEntity)) { setIsSleeping(false); } @@ -408,10 +408,10 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape, ProxyShapeComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1, AABB(localBoundsMin, localBoundsMax), transform, collisionShape, mass, 0x0001, 0xFFFF); - bool isSleeping = mWorld.mBodyComponents.getIsSleeping(mEntity); + bool isSleeping = mWorld.mRigidBodyComponents.getIsSleeping(mEntity); mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, isSleeping, proxyShapeComponent); - mWorld.mBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity); + mWorld.mCollisionBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity); #ifdef IS_PROFILING_ACTIVE @@ -626,7 +626,7 @@ void RigidBody::recomputeMassInformation() { assert(mWorld.mDynamicsComponents.getBodyType(mEntity) == BodyType::DYNAMIC); // Compute the total mass of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); mWorld.mDynamicsComponents.setInitMass(mEntity, mWorld.mDynamicsComponents.getInitMass(mEntity) + proxyShape->getMass()); @@ -657,7 +657,7 @@ void RigidBody::recomputeMassInformation() { if (!mIsInertiaTensorSetByUser) { // Compute the inertia tensor using all the collision shapes - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); @@ -739,7 +739,7 @@ void RigidBody::applyTorque(const Vector3& torque) { if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Awake the body if it was sleeping - if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { + if (mWorld.mRigidBodyComponents.getIsSleeping(mEntity)) { setIsSleeping(false); } @@ -751,26 +751,26 @@ void RigidBody::applyTorque(const Vector3& torque) { // Set the variable to know whether or not the body is sleeping void RigidBody::setIsSleeping(bool isSleeping) { - bool isBodySleeping = mWorld.mBodyComponents.getIsSleeping(mEntity); + bool isBodySleeping = mWorld.mRigidBodyComponents.getIsSleeping(mEntity); if (isBodySleeping == isSleeping) return; // If the body is not active, do nothing (it is sleeping) - if (!mWorld.mBodyComponents.getIsActive(mEntity)) { + if (!mWorld.mCollisionBodyComponents.getIsActive(mEntity)) { assert(isBodySleeping); return; } if (isSleeping) { - mWorld.mBodyComponents.setSleepTime(mEntity, decimal(0.0)); + mWorld.mRigidBodyComponents.setSleepTime(mEntity, decimal(0.0)); } else { if (isBodySleeping) { - mWorld.mBodyComponents.setSleepTime(mEntity, decimal(0.0)); + mWorld.mRigidBodyComponents.setSleepTime(mEntity, decimal(0.0)); } } - mWorld.mBodyComponents.setIsSleeping(mEntity, isSleeping); + mWorld.mRigidBodyComponents.setIsSleeping(mEntity, isSleeping); // Notify all the components mWorld.notifyBodyDisabled(mEntity, isSleeping); @@ -795,7 +795,7 @@ void RigidBody::setIsSleeping(bool isSleeping) { */ void RigidBody::setIsAllowedToSleep(bool isAllowedToSleep) { - mWorld.mBodyComponents.setIsAllowedToSleep(mEntity, isAllowedToSleep); + mWorld.mRigidBodyComponents.setIsAllowedToSleep(mEntity, isAllowedToSleep); if (!isAllowedToSleep) setIsSleeping(false); @@ -809,7 +809,7 @@ void RigidBody::setIsAllowedToSleep(bool isAllowedToSleep) { * @return True if the body is allowed to sleep and false otherwise */ bool RigidBody::isAllowedToSleep() const { - return mWorld.mBodyComponents.getIsAllowedToSleep(mEntity); + return mWorld.mRigidBodyComponents.getIsAllowedToSleep(mEntity); } // Return whether or not the body is sleeping @@ -817,7 +817,7 @@ bool RigidBody::isAllowedToSleep() const { * @return True if the body is currently sleeping and false otherwise */ bool RigidBody::isSleeping() const { - return mWorld.mBodyComponents.getIsSleeping(mEntity); + return mWorld.mRigidBodyComponents.getIsSleeping(mEntity); } // Set whether or not the body is active @@ -827,7 +827,7 @@ bool RigidBody::isSleeping() const { void RigidBody::setIsActive(bool isActive) { // If the state does not change - if (mWorld.mBodyComponents.getIsActive(mEntity) == isActive) return; + if (mWorld.mCollisionBodyComponents.getIsActive(mEntity) == isActive) return; setIsSleeping(!isActive); @@ -842,7 +842,7 @@ void RigidBody::setProfiler(Profiler* profiler) { CollisionBody::setProfiler(profiler); // Set the profiler for each proxy shape - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); + const List& proxyShapesEntities = mWorld.mCollisionBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h index 6e2c9d9a..0a9c45c9 100644 --- a/src/body/RigidBody.h +++ b/src/body/RigidBody.h @@ -195,6 +195,8 @@ class RigidBody : public CollisionBody { virtual void setIsActive(bool isActive) override; /// Add a collision shape to the body. + // TODO : Remove the mass from this parameter so that we can correctly use inheritance here + // The user will then need to call ProxyShape->setMass() to set the mass of the shape virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, const Transform& transform, decimal mass); diff --git a/src/collision/CollisionCallback.cpp b/src/collision/CollisionCallback.cpp index 0162edfa..d7ee91b4 100644 --- a/src/collision/CollisionCallback.cpp +++ b/src/collision/CollisionCallback.cpp @@ -47,12 +47,12 @@ CollisionCallback::ContactPair::ContactPair(const reactphysics3d::ContactPair& c // Return a pointer to the first body in contact CollisionBody* CollisionCallback::ContactPair::getBody1() const { - return static_cast(mWorld.mBodyComponents.getBody(mContactPair.body1Entity)); + return static_cast(mWorld.mCollisionBodyComponents.getBody(mContactPair.body1Entity)); } // Return a pointer to the second body in contact CollisionBody* CollisionCallback::ContactPair::getBody2() const { - return static_cast(mWorld.mBodyComponents.getBody(mContactPair.body2Entity)); + return static_cast(mWorld.mCollisionBodyComponents.getBody(mContactPair.body2Entity)); } // Return a pointer to the first proxy-shape in contact (in body 1) diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index 14937350..f4cbf475 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -243,8 +243,8 @@ void CollisionDetection::computeMiddlePhase(OverlappingPairMap& overlappingPairs mWorld->mDynamicsComponents.getBodyType(body2Entity) == BodyType::STATIC; // Check that at least one body is enabled (active and awake) and not static - bool isBody1Active = !mWorld->mBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; - bool isBody2Active = !mWorld->mBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; + bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; + bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; if (!isBody1Active && !isBody2Active) continue; // Check if the bodies are in the set of bodies that cannot collide between each other @@ -932,7 +932,7 @@ void CollisionDetection::processPotentialContacts(NarrowPhaseInfoBatch& narrowPh Entity body1Entity = narrowPhaseInfoBatch.overlappingPairs[i]->getShape1()->getBody()->getEntity(); Entity body2Entity = narrowPhaseInfoBatch.overlappingPairs[i]->getShape2()->getBody()->getEntity(); - assert(!mWorld->mBodyComponents.getIsEntityDisabled(body1Entity) || !mWorld->mBodyComponents.getIsEntityDisabled(body2Entity)); + assert(!mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) || !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity)); // TODO : We should probably use a single frame allocator here const uint newContactPairIndex = contactPairs->size(); diff --git a/src/collision/OverlapCallback.cpp b/src/collision/OverlapCallback.cpp index 096f9421..fe41b7ac 100644 --- a/src/collision/OverlapCallback.cpp +++ b/src/collision/OverlapCallback.cpp @@ -38,12 +38,12 @@ OverlapCallback::OverlapPair::OverlapPair(Pair& overlapPair, Col // Return a pointer to the first body in contact CollisionBody* OverlapCallback::OverlapPair::getBody1() const { - return static_cast(mWorld.mBodyComponents.getBody(mOverlapPair.first)); + return static_cast(mWorld.mCollisionBodyComponents.getBody(mOverlapPair.first)); } // Return a pointer to the second body in contact CollisionBody* OverlapCallback::OverlapPair::getBody2() const { - return static_cast(mWorld.mBodyComponents.getBody(mOverlapPair.second)); + return static_cast(mWorld.mCollisionBodyComponents.getBody(mOverlapPair.second)); } // CollisionCallbackData Constructor diff --git a/src/collision/ProxyShape.cpp b/src/collision/ProxyShape.cpp index 2bbfb6f9..052ee301 100644 --- a/src/collision/ProxyShape.cpp +++ b/src/collision/ProxyShape.cpp @@ -119,7 +119,7 @@ void ProxyShape::setLocalToBodyTransform(const Transform& transform) { RigidBody* rigidBody = static_cast(mBody); if (rigidBody != nullptr) { - mBody->mWorld.mBodyComponents.setIsSleeping(mBody->getEntity(), false); + mBody->mWorld.mRigidBodyComponents.setIsSleeping(mBody->getEntity(), false); } mBody->mWorld.mCollisionDetection.updateProxyShape(mEntity); diff --git a/src/components/CollisionBodyComponents.cpp b/src/components/CollisionBodyComponents.cpp index 7e70a4be..d5288292 100644 --- a/src/components/CollisionBodyComponents.cpp +++ b/src/components/CollisionBodyComponents.cpp @@ -35,8 +35,7 @@ using namespace reactphysics3d; // Constructor CollisionBodyComponents::CollisionBodyComponents(MemoryAllocator& allocator) :Components(allocator, sizeof(Entity) + sizeof(CollisionBody*) + sizeof(List) + - sizeof(bool) + sizeof(bool) + sizeof(bool) + sizeof(decimal) + - sizeof(void*)) { + sizeof(bool) + sizeof(void*)) { // Allocate memory for the components data allocate(INIT_NB_ALLOCATED_COMPONENTS); @@ -58,11 +57,8 @@ void CollisionBodyComponents::allocate(uint32 nbComponentsToAllocate) { Entity* newBodiesEntities = static_cast(newBuffer); CollisionBody** newBodies = reinterpret_cast(newBodiesEntities + nbComponentsToAllocate); List* newProxyShapes = reinterpret_cast*>(newBodies + nbComponentsToAllocate); - bool* newIsAllowedToSleep = reinterpret_cast(newProxyShapes + nbComponentsToAllocate); - bool* newIsActive = reinterpret_cast(newIsAllowedToSleep + nbComponentsToAllocate); - bool* newIsSleeping = reinterpret_cast(newIsActive + nbComponentsToAllocate); - decimal* newSleepTimes = reinterpret_cast(newIsSleeping + nbComponentsToAllocate); - void** newUserData = reinterpret_cast(newIsSleeping + nbComponentsToAllocate); + bool* newIsActive = reinterpret_cast(newProxyShapes + nbComponentsToAllocate); + void** newUserData = reinterpret_cast(newIsActive + nbComponentsToAllocate); // If there was already components before if (mNbComponents > 0) { @@ -71,10 +67,7 @@ void CollisionBodyComponents::allocate(uint32 nbComponentsToAllocate) { memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity)); memcpy(newBodies, mBodies, mNbComponents * sizeof(CollisionBody*)); memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(List)); - memcpy(newIsAllowedToSleep, mIsAllowedToSleep, mNbComponents * sizeof(bool)); memcpy(newIsActive, mIsActive, mNbComponents * sizeof(bool)); - memcpy(newIsSleeping, mIsSleeping, mNbComponents * sizeof(bool)); - memcpy(newSleepTimes, mSleepTimes, mNbComponents * sizeof(bool)); memcpy(newUserData, mUserData, mNbComponents * sizeof(void*)); // Deallocate previous memory @@ -85,16 +78,13 @@ void CollisionBodyComponents::allocate(uint32 nbComponentsToAllocate) { mBodiesEntities = newBodiesEntities; mBodies = newBodies; mProxyShapes = newProxyShapes; - mIsAllowedToSleep = newIsAllowedToSleep; mIsActive = newIsActive; - mIsSleeping = newIsSleeping; - mSleepTimes = newSleepTimes; mUserData = newUserData; mNbAllocatedComponents = nbComponentsToAllocate; } // Add a component -void CollisionBodyComponents::addComponent(Entity bodyEntity, bool isSleeping, const BodyComponent& component) { +void CollisionBodyComponents::addComponent(Entity bodyEntity, bool isSleeping, const CollisionBodyComponent& component) { // Prepare to add new component (allocate memory if necessary and compute insertion index) uint32 index = prepareAddComponent(isSleeping); @@ -103,10 +93,7 @@ void CollisionBodyComponents::addComponent(Entity bodyEntity, bool isSleeping, c new (mBodiesEntities + index) Entity(bodyEntity); mBodies[index] = component.body; new (mProxyShapes + index) List(mMemoryAllocator); - mIsAllowedToSleep[index] = true; mIsActive[index] = true; - mIsSleeping[index] = false; - mSleepTimes[index] = decimal(0); mUserData[index] = nullptr; // Map the entity with the new component lookup index @@ -128,10 +115,7 @@ void CollisionBodyComponents::moveComponentToIndex(uint32 srcIndex, uint32 destI new (mBodiesEntities + destIndex) Entity(mBodiesEntities[srcIndex]); mBodies[destIndex] = mBodies[srcIndex]; new (mProxyShapes + destIndex) List(mProxyShapes[srcIndex]); - mIsAllowedToSleep[destIndex] = mIsAllowedToSleep[srcIndex]; mIsActive[destIndex] = mIsActive[srcIndex]; - mIsSleeping[destIndex] = mIsSleeping[srcIndex]; - mSleepTimes[destIndex] = mSleepTimes[srcIndex]; mUserData[destIndex] = mUserData[srcIndex]; // Destroy the source component @@ -152,10 +136,7 @@ void CollisionBodyComponents::swapComponents(uint32 index1, uint32 index2) { Entity entity1(mBodiesEntities[index1]); CollisionBody* body1 = mBodies[index1]; List proxyShapes1(mProxyShapes[index1]); - bool isAllowedToSleep1 = mIsAllowedToSleep[index1]; bool isActive1 = mIsActive[index1]; - bool isSleeping1 = mIsSleeping[index1]; - decimal sleepTime1 = mSleepTimes[index1]; void* userData1 = mUserData[index1]; // Destroy component 1 @@ -167,9 +148,7 @@ void CollisionBodyComponents::swapComponents(uint32 index1, uint32 index2) { new (mBodiesEntities + index2) Entity(entity1); new (mProxyShapes + index2) List(proxyShapes1); mBodies[index2] = body1; - mIsAllowedToSleep[index2] = isAllowedToSleep1; mIsActive[index2] = isActive1; - mIsSleeping[index2] = isSleeping1; mUserData[index2] = userData1; // Update the entity to component index mapping diff --git a/src/components/CollisionBodyComponents.h b/src/components/CollisionBodyComponents.h index be53ceef..99b0a42d 100644 --- a/src/components/CollisionBodyComponents.h +++ b/src/components/CollisionBodyComponents.h @@ -23,8 +23,8 @@ * * ********************************************************************************/ -#ifndef REACTPHYSICS3D_BODY_COMPONENTS_H -#define REACTPHYSICS3D_BODY_COMPONENTS_H +#ifndef REACTPHYSICS3D_COLLISION_BODY_COMPONENTS_H +#define REACTPHYSICS3D_COLLISION_BODY_COMPONENTS_H // Libraries #include "mathematics/Transform.h" @@ -60,18 +60,9 @@ class CollisionBodyComponents : public Components { /// Array with the list of proxy-shapes of each body List* mProxyShapes; - /// Array of boolean values to know if the body is allowed to go to sleep - bool* mIsAllowedToSleep; - /// Array of boolean values to know if the body is active. bool* mIsActive; - /// Array of boolean values to know if the body is sleeping - bool* mIsSleeping; - - /// Array with values for elapsed time since the body velocity was below the sleep velocity - decimal* mSleepTimes; - /// Array of pointers that can be used to attach user data to the body void** mUserData; @@ -91,13 +82,13 @@ class CollisionBodyComponents : public Components { public: - /// Structure for the data of a body component - struct BodyComponent { + /// Structure for the data of a collision body component + struct CollisionBodyComponent { CollisionBody* body; /// Constructor - BodyComponent(CollisionBody* body) : body(body) { + CollisionBodyComponent(CollisionBody* body) : body(body) { } }; @@ -111,7 +102,7 @@ class CollisionBodyComponents : public Components { virtual ~CollisionBodyComponents() override = default; /// Add a component - void addComponent(Entity bodyEntity, bool isSleeping, const BodyComponent& component); + void addComponent(Entity bodyEntity, bool isSleeping, const CollisionBodyComponent& component); /// Add a proxy-shape to a body component void addProxyShapeToBody(Entity bodyEntity, Entity proxyShapeEntity); @@ -125,30 +116,12 @@ class CollisionBodyComponents : public Components { /// Return the list of proxy-shapes of a body const List& getProxyShapes(Entity bodyEntity) const; - /// Return true if the body is allowed to sleep - bool getIsAllowedToSleep(Entity bodyEntity) const; - - /// Set the value to know if the body is allowed to sleep - void setIsAllowedToSleep(Entity bodyEntity, bool isAllowedToSleep) const; - /// Return true if the body is active bool getIsActive(Entity bodyEntity) const; /// Set the value to know if the body is active void setIsActive(Entity bodyEntity, bool isActive) const; - /// Return true if the body is sleeping - bool getIsSleeping(Entity bodyEntity) const; - - /// Set the value to know if the body is sleeping - void setIsSleeping(Entity bodyEntity, bool isSleeping) const; - - /// Return the sleep time - decimal getSleepTime(Entity bodyEntity) const; - - /// Set the sleep time - void setSleepTime(Entity bodyEntity, decimal sleepTime) const; - /// Return the user data associated with the body void* getUserData(Entity bodyEntity) const; @@ -188,22 +161,6 @@ inline const List& CollisionBodyComponents::getProxyShapes(Entity bodyEn return mProxyShapes[mMapEntityToComponentIndex[bodyEntity]]; } -// Return true if the body is allowed to sleep -inline bool CollisionBodyComponents::getIsAllowedToSleep(Entity bodyEntity) const { - - assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - - return mIsAllowedToSleep[mMapEntityToComponentIndex[bodyEntity]]; -} - -// Set the value to know if the body is allowed to sleep -inline void CollisionBodyComponents::setIsAllowedToSleep(Entity bodyEntity, bool isAllowedToSleep) const { - - assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - - mIsAllowedToSleep[mMapEntityToComponentIndex[bodyEntity]] = isAllowedToSleep; -} - // Return true if the body is active inline bool CollisionBodyComponents::getIsActive(Entity bodyEntity) const { @@ -220,38 +177,6 @@ inline void CollisionBodyComponents::setIsActive(Entity bodyEntity, bool isActiv mIsActive[mMapEntityToComponentIndex[bodyEntity]] = isActive; } -// Return true if the body is sleeping -inline bool CollisionBodyComponents::getIsSleeping(Entity bodyEntity) const { - - assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - - return mIsSleeping[mMapEntityToComponentIndex[bodyEntity]]; -} - -// Set the value to know if the body is sleeping -inline void CollisionBodyComponents::setIsSleeping(Entity bodyEntity, bool isSleeping) const { - - assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - - mIsSleeping[mMapEntityToComponentIndex[bodyEntity]] = isSleeping; -} - -// Return the sleep time -inline decimal CollisionBodyComponents::getSleepTime(Entity bodyEntity) const { - - assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - - return mSleepTimes[mMapEntityToComponentIndex[bodyEntity]]; -} - -// Set the sleep time -inline void CollisionBodyComponents::setSleepTime(Entity bodyEntity, decimal sleepTime) const { - - assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - - mSleepTimes[mMapEntityToComponentIndex[bodyEntity]] = sleepTime; -} - // Return the user data associated with the body inline void* CollisionBodyComponents::getUserData(Entity bodyEntity) const { diff --git a/src/components/RigidBodyComponents.cpp b/src/components/RigidBodyComponents.cpp new file mode 100644 index 00000000..ac4d2346 --- /dev/null +++ b/src/components/RigidBodyComponents.cpp @@ -0,0 +1,173 @@ +/******************************************************************************** +* 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 "RigidBodyComponents.h" +#include "engine/EntityManager.h" +#include +#include + +// We want to use the ReactPhysics3D namespace +using namespace reactphysics3d; + +// Constructor +RigidBodyComponents::RigidBodyComponents(MemoryAllocator& allocator) + :Components(allocator, sizeof(Entity) + sizeof(RigidBody*) + + sizeof(bool) + sizeof(bool) + sizeof(decimal) ) { + + // Allocate memory for the components data + allocate(INIT_NB_ALLOCATED_COMPONENTS); +} + +// Allocate memory for a given number of components +void RigidBodyComponents::allocate(uint32 nbComponentsToAllocate) { + + assert(nbComponentsToAllocate > mNbAllocatedComponents); + + // Size for the data of a single component (in bytes) + const size_t totalSizeBytes = nbComponentsToAllocate * mComponentDataSize; + + // Allocate memory + void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes); + assert(newBuffer != nullptr); + + // New pointers to components data + Entity* newBodiesEntities = static_cast(newBuffer); + RigidBody** newBodies = reinterpret_cast(newBodiesEntities + nbComponentsToAllocate); + bool* newIsAllowedToSleep = reinterpret_cast(newBodies + nbComponentsToAllocate); + bool* newIsSleeping = reinterpret_cast(newIsAllowedToSleep + nbComponentsToAllocate); + decimal* newSleepTimes = reinterpret_cast(newIsSleeping + 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, mRigidBodies, mNbComponents * sizeof(RigidBody*)); + memcpy(newIsAllowedToSleep, mIsAllowedToSleep, mNbComponents * sizeof(bool)); + memcpy(newIsSleeping, mIsSleeping, mNbComponents * sizeof(bool)); + memcpy(newSleepTimes, mSleepTimes, mNbComponents * sizeof(bool)); + + // Deallocate previous memory + mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize); + } + + mBuffer = newBuffer; + mBodiesEntities = newBodiesEntities; + mRigidBodies = newBodies; + mIsAllowedToSleep = newIsAllowedToSleep; + mIsSleeping = newIsSleeping; + mSleepTimes = newSleepTimes; + mNbAllocatedComponents = nbComponentsToAllocate; +} + +// Add a component +void RigidBodyComponents::addComponent(Entity bodyEntity, bool isSleeping, const RigidBodyComponent& component) { + + // Prepare to add new component (allocate memory if necessary and compute insertion index) + uint32 index = prepareAddComponent(isSleeping); + + // Insert the new component data + new (mBodiesEntities + index) Entity(bodyEntity); + mRigidBodies[index] = component.body; + mIsAllowedToSleep[index] = true; + mIsSleeping[index] = false; + mSleepTimes[index] = decimal(0); + + // Map the entity with the new component lookup index + mMapEntityToComponentIndex.add(Pair(bodyEntity, index)); + + mNbComponents++; + + assert(mDisabledStartIndex <= mNbComponents); + assert(mNbComponents == static_cast(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 RigidBodyComponents::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]); + mRigidBodies[destIndex] = mRigidBodies[srcIndex]; + mIsAllowedToSleep[destIndex] = mIsAllowedToSleep[srcIndex]; + mIsSleeping[destIndex] = mIsSleeping[srcIndex]; + mSleepTimes[destIndex] = mSleepTimes[srcIndex]; + + // Destroy the source component + destroyComponent(srcIndex); + + assert(!mMapEntityToComponentIndex.containsKey(entity)); + + // Update the entity to component index mapping + mMapEntityToComponentIndex.add(Pair(entity, destIndex)); + + assert(mMapEntityToComponentIndex[mBodiesEntities[destIndex]] == destIndex); +} + +// Swap two components in the array +void RigidBodyComponents::swapComponents(uint32 index1, uint32 index2) { + + // Copy component 1 data + Entity entity1(mBodiesEntities[index1]); + RigidBody* body1 = mRigidBodies[index1]; + bool isAllowedToSleep1 = mIsAllowedToSleep[index1]; + bool isSleeping1 = mIsSleeping[index1]; + decimal sleepTime1 = mSleepTimes[index1]; + + // Destroy component 1 + destroyComponent(index1); + + moveComponentToIndex(index2, index1); + + // Reconstruct component 1 at component 2 location + new (mBodiesEntities + index2) Entity(entity1); + mRigidBodies[index2] = body1; + mIsAllowedToSleep[index2] = isAllowedToSleep1; + mIsSleeping[index2] = isSleeping1; + mSleepTimes[index2] = sleepTime1; + + // Update the entity to component index mapping + mMapEntityToComponentIndex.add(Pair(entity1, index2)); + + assert(mMapEntityToComponentIndex[mBodiesEntities[index1]] == index1); + assert(mMapEntityToComponentIndex[mBodiesEntities[index2]] == index2); + assert(mNbComponents == static_cast(mMapEntityToComponentIndex.size())); +} + +// Destroy a component at a given index +void RigidBodyComponents::destroyComponent(uint32 index) { + + Components::destroyComponent(index); + + assert(mMapEntityToComponentIndex[mBodiesEntities[index]] == index); + + mMapEntityToComponentIndex.remove(mBodiesEntities[index]); + + mBodiesEntities[index].~Entity(); + mRigidBodies[index] = nullptr; +} diff --git a/src/components/RigidBodyComponents.h b/src/components/RigidBodyComponents.h new file mode 100644 index 00000000..02cdf6e5 --- /dev/null +++ b/src/components/RigidBodyComponents.h @@ -0,0 +1,187 @@ +/******************************************************************************** +* 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_RIGID_BODY_COMPONENTS_H +#define REACTPHYSICS3D_RIGID_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 RigidBody; + +// Class RigidBodyComponents +/** + * This class represent the component of the ECS that contains data about a rigid body. + * The components of the sleeping entities (bodies) are always stored at the end of the array. + */ +class RigidBodyComponents : public Components { + + private: + + // -------------------- Attributes -------------------- // + + /// Array of body entities of each component + Entity* mBodiesEntities; + + /// Array of pointers to the corresponding rigid bodies + RigidBody** mRigidBodies; + + /// Array of boolean values to know if the body is allowed to go to sleep + bool* mIsAllowedToSleep; + + /// Array of boolean values to know if the body is sleeping + bool* mIsSleeping; + + /// Array with values for elapsed time since the body velocity was below the sleep velocity + decimal* mSleepTimes; + + // -------------------- Methods -------------------- // + + /// Allocate memory for a given number of components + virtual void allocate(uint32 nbComponentsToAllocate) override; + + /// Destroy a component at a given index + virtual void destroyComponent(uint32 index) override; + + /// Move a component from a source to a destination index in the components array + virtual void moveComponentToIndex(uint32 srcIndex, uint32 destIndex) override; + + /// Swap two components in the array + virtual void swapComponents(uint32 index1, uint32 index2) override; + + public: + + /// Structure for the data of a rigid body component + struct RigidBodyComponent { + + RigidBody* body; + + /// Constructor + RigidBodyComponent(RigidBody* body) : body(body) { + + } + }; + + // -------------------- Methods -------------------- // + + /// Constructor + RigidBodyComponents(MemoryAllocator& allocator); + + /// Destructor + virtual ~RigidBodyComponents() override = default; + + /// Add a component + void addComponent(Entity bodyEntity, bool isSleeping, const RigidBodyComponent& component); + + /// Return a pointer to a rigid body + RigidBody* getRigidBody(Entity bodyEntity); + + /// Return true if the body is allowed to sleep + bool getIsAllowedToSleep(Entity bodyEntity) const; + + /// Set the value to know if the body is allowed to sleep + void setIsAllowedToSleep(Entity bodyEntity, bool isAllowedToSleep) const; + + /// Return true if the body is sleeping + bool getIsSleeping(Entity bodyEntity) const; + + /// Set the value to know if the body is sleeping + void setIsSleeping(Entity bodyEntity, bool isSleeping) const; + + /// Return the sleep time + decimal getSleepTime(Entity bodyEntity) const; + + /// Set the sleep time + void setSleepTime(Entity bodyEntity, decimal sleepTime) const; +}; + +// Return a pointer to a body rigid +inline RigidBody* RigidBodyComponents::getRigidBody(Entity bodyEntity) { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + return mRigidBodies[mMapEntityToComponentIndex[bodyEntity]]; +} + +// Return true if the body is allowed to sleep +inline bool RigidBodyComponents::getIsAllowedToSleep(Entity bodyEntity) const { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + return mIsAllowedToSleep[mMapEntityToComponentIndex[bodyEntity]]; +} + +// Set the value to know if the body is allowed to sleep +inline void RigidBodyComponents::setIsAllowedToSleep(Entity bodyEntity, bool isAllowedToSleep) const { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + mIsAllowedToSleep[mMapEntityToComponentIndex[bodyEntity]] = isAllowedToSleep; +} + +// Return true if the body is sleeping +inline bool RigidBodyComponents::getIsSleeping(Entity bodyEntity) const { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + return mIsSleeping[mMapEntityToComponentIndex[bodyEntity]]; +} + +// Set the value to know if the body is sleeping +inline void RigidBodyComponents::setIsSleeping(Entity bodyEntity, bool isSleeping) const { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + mIsSleeping[mMapEntityToComponentIndex[bodyEntity]] = isSleeping; +} + +// Return the sleep time +inline decimal RigidBodyComponents::getSleepTime(Entity bodyEntity) const { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + return mSleepTimes[mMapEntityToComponentIndex[bodyEntity]]; +} + +// Set the sleep time +inline void RigidBodyComponents::setSleepTime(Entity bodyEntity, decimal sleepTime) const { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + mSleepTimes[mMapEntityToComponentIndex[bodyEntity]] = sleepTime; +} + +} + +#endif diff --git a/src/engine/CollisionWorld.cpp b/src/engine/CollisionWorld.cpp index 4d906e98..5bc953e5 100644 --- a/src/engine/CollisionWorld.cpp +++ b/src/engine/CollisionWorld.cpp @@ -38,8 +38,9 @@ uint CollisionWorld::mNbWorlds = 0; // Constructor CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler) : mConfig(worldSettings), mEntityManager(mMemoryManager.getPoolAllocator()), - mBodyComponents(mMemoryManager.getBaseAllocator()), mTransformComponents(mMemoryManager.getBaseAllocator()), - mProxyShapesComponents(mMemoryManager.getBaseAllocator()), mDynamicsComponents(mMemoryManager.getBaseAllocator()), + mCollisionBodyComponents(mMemoryManager.getBaseAllocator()), mRigidBodyComponents(mMemoryManager.getBaseAllocator()), + mTransformComponents(mMemoryManager.getBaseAllocator()), mProxyShapesComponents(mMemoryManager.getBaseAllocator()), + mDynamicsComponents(mMemoryManager.getBaseAllocator()), mCollisionDetection(this, mProxyShapesComponents, mTransformComponents, mDynamicsComponents, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName), mIsProfilerCreatedByUser(profiler != nullptr), @@ -132,7 +133,7 @@ CollisionWorld::~CollisionWorld() { #endif assert(mBodies.size() == 0); - assert(mBodyComponents.getNbComponents() == 0); + assert(mCollisionBodyComponents.getNbComponents() == 0); assert(mTransformComponents.getNbComponents() == 0); assert(mProxyShapesComponents.getNbComponents() == 0); } @@ -157,8 +158,8 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) { assert(collisionBody != nullptr); // Add the components - CollisionBodyComponents::BodyComponent bodyComponent(collisionBody); - mBodyComponents.addComponent(entity, false, bodyComponent); + CollisionBodyComponents::CollisionBodyComponent bodyComponent(collisionBody); + mCollisionBodyComponents.addComponent(entity, false, bodyComponent); // Add the collision body to the world mBodies.add(collisionBody); @@ -192,7 +193,7 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) { // Remove all the collision shapes of the body collisionBody->removeAllCollisionShapes(); - mBodyComponents.removeComponent(collisionBody->getEntity()); + mCollisionBodyComponents.removeComponent(collisionBody->getEntity()); mTransformComponents.removeComponent(collisionBody->getEntity()); mEntityManager.destroyEntity(collisionBody->getEntity()); @@ -209,12 +210,13 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) { // Notify the world if a body is disabled (sleeping) or not void CollisionWorld::notifyBodyDisabled(Entity bodyEntity, bool isDisabled) { - if (isDisabled == mBodyComponents.getIsEntityDisabled(bodyEntity)) return; + if (isDisabled == mCollisionBodyComponents.getIsEntityDisabled(bodyEntity)) return; // TODO : Make sure we notify all the components here ... // Notify all the components - mBodyComponents.setIsEntityDisabled(bodyEntity, isDisabled); + mCollisionBodyComponents.setIsEntityDisabled(bodyEntity, isDisabled); + mRigidBodyComponents.setIsEntityDisabled(bodyEntity, isDisabled); mTransformComponents.setIsEntityDisabled(bodyEntity, isDisabled); if (mDynamicsComponents.hasComponent(bodyEntity)) { @@ -222,7 +224,7 @@ void CollisionWorld::notifyBodyDisabled(Entity bodyEntity, bool isDisabled) { } // For each proxy-shape of the body - const List& proxyShapesEntities = mBodyComponents.getProxyShapes(bodyEntity); + const List& proxyShapesEntities = mCollisionBodyComponents.getProxyShapes(bodyEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { mProxyShapesComponents.setIsEntityDisabled(proxyShapesEntities[i], isDisabled); diff --git a/src/engine/CollisionWorld.h b/src/engine/CollisionWorld.h index c627469b..587b5eaa 100644 --- a/src/engine/CollisionWorld.h +++ b/src/engine/CollisionWorld.h @@ -34,6 +34,7 @@ #include "memory/MemoryManager.h" #include "engine/EntityManager.h" #include "components/CollisionBodyComponents.h" +#include "components/RigidBodyComponents.h" #include "components/TransformComponents.h" #include "components/ProxyShapeComponents.h" #include "components/DynamicsComponents.h" @@ -76,8 +77,11 @@ class CollisionWorld { /// Entity Manager for the ECS EntityManager mEntityManager; - /// Body Components - CollisionBodyComponents mBodyComponents; + /// Collision Body Components + CollisionBodyComponents mCollisionBodyComponents; + + /// Rigid Body Components + RigidBodyComponents mRigidBodyComponents; /// Transform Components TransformComponents mTransformComponents; diff --git a/src/engine/DynamicsWorld.cpp b/src/engine/DynamicsWorld.cpp index 620ce9e1..8e32e252 100644 --- a/src/engine/DynamicsWorld.cpp +++ b/src/engine/DynamicsWorld.cpp @@ -50,7 +50,7 @@ using namespace std; DynamicsWorld::DynamicsWorld(const Vector3& gravity, const WorldSettings& worldSettings, Logger* logger, Profiler* profiler) : CollisionWorld(worldSettings, logger, profiler), mIslands(mMemoryManager.getSingleFrameAllocator()), - mContactSolver(mMemoryManager, mIslands, mBodyComponents, mDynamicsComponents, mProxyShapesComponents, mConfig), + mContactSolver(mMemoryManager, mIslands, mCollisionBodyComponents, mDynamicsComponents, mProxyShapesComponents, mConfig), mConstraintSolver(mIslands, mDynamicsComponents), mNbVelocitySolverIterations(mConfig.defaultVelocitySolverNbIterations), mNbPositionSolverIterations(mConfig.defaultPositionSolverNbIterations), @@ -384,8 +384,11 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) { sizeof(RigidBody))) RigidBody(transform, *this, entity); assert(rigidBody != nullptr); - CollisionBodyComponents::BodyComponent bodyComponent(rigidBody); - mBodyComponents.addComponent(entity, false, bodyComponent); + CollisionBodyComponents::CollisionBodyComponent bodyComponent(rigidBody); + mCollisionBodyComponents.addComponent(entity, false, bodyComponent); + + RigidBodyComponents::RigidBodyComponent rigidBodyComponent(rigidBody); + mRigidBodyComponents.addComponent(entity, false, rigidBodyComponent); // Add the rigid body to the physics world mBodies.add(rigidBody); @@ -425,7 +428,8 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) { } // Destroy the corresponding entity and its components - mBodyComponents.removeComponent(rigidBody->getEntity()); + mCollisionBodyComponents.removeComponent(rigidBody->getEntity()); + mRigidBodyComponents.removeComponent(rigidBody->getEntity()); mTransformComponents.removeComponent(rigidBody->getEntity()); mEntityManager.destroyEntity(rigidBody->getEntity()); @@ -678,7 +682,7 @@ void DynamicsWorld::createIslands() { mIslands.bodyEntities[islandIndex].add(bodyToVisitEntity); // TODO : Do not use pointer to rigid body here (maybe move getType() into a component) - RigidBody* rigidBodyToVisit = static_cast(mBodyComponents.getBody(bodyToVisitEntity)); + RigidBody* rigidBodyToVisit = static_cast(mCollisionBodyComponents.getBody(bodyToVisitEntity)); // Awake the body if it is sleeping rigidBodyToVisit->setIsSleeping(false); @@ -703,8 +707,8 @@ void DynamicsWorld::createIslands() { // Get the other body of the contact manifold // TODO : Maybe avoid those casts here - RigidBody* body1 = dynamic_cast(mBodyComponents.getBody(pair.body1Entity)); - RigidBody* body2 = dynamic_cast(mBodyComponents.getBody(pair.body2Entity)); + RigidBody* body1 = dynamic_cast(mCollisionBodyComponents.getBody(pair.body1Entity)); + RigidBody* body2 = dynamic_cast(mCollisionBodyComponents.getBody(pair.body2Entity)); // If the colliding body is a RigidBody (and not a CollisionBody instead) if (body1 != nullptr && body2 != nullptr) { @@ -801,8 +805,7 @@ void DynamicsWorld::updateSleepingBodies() { const Entity bodyEntity = mIslands.bodyEntities[i][b]; - // TODO : We should use a RigidBody* type here - CollisionBody* body = mBodyComponents.getBody(bodyEntity); + RigidBody* body = mRigidBodyComponents.getRigidBody(bodyEntity); // Skip static bodies if (mDynamicsComponents.getBodyType(body->getEntity()) == BodyType::STATIC) continue; @@ -810,18 +813,18 @@ void DynamicsWorld::updateSleepingBodies() { // If the body is velocity is large enough to stay awake if (mDynamicsComponents.getLinearVelocity(bodyEntity).lengthSquare() > sleepLinearVelocitySquare || mDynamicsComponents.getAngularVelocity(bodyEntity).lengthSquare() > sleepAngularVelocitySquare || - !mBodyComponents.getIsAllowedToSleep(body->getEntity())) { + !mRigidBodyComponents.getIsAllowedToSleep(body->getEntity())) { // Reset the sleep time of the body - mBodyComponents.setSleepTime(body->getEntity(), decimal(0.0)); + mRigidBodyComponents.setSleepTime(body->getEntity(), decimal(0.0)); minSleepTime = decimal(0.0); } else { // If the body velocity is below the sleeping velocity threshold // Increase the sleep time - decimal sleepTime = mBodyComponents.getSleepTime(body->getEntity()); - mBodyComponents.setSleepTime(body->getEntity(), sleepTime + mTimeStep); - sleepTime = mBodyComponents.getSleepTime(body->getEntity()); + decimal sleepTime = mRigidBodyComponents.getSleepTime(body->getEntity()); + mRigidBodyComponents.setSleepTime(body->getEntity(), sleepTime + mTimeStep); + sleepTime = mRigidBodyComponents.getSleepTime(body->getEntity()); if (sleepTime < minSleepTime) { minSleepTime = sleepTime; } @@ -838,7 +841,7 @@ void DynamicsWorld::updateSleepingBodies() { // TODO : We should use a RigidBody* type here (remove the cast) const Entity bodyEntity = mIslands.bodyEntities[i][b]; - RigidBody* body = static_cast(mBodyComponents.getBody(bodyEntity)); + RigidBody* body = static_cast(mCollisionBodyComponents.getBody(bodyEntity)); body->setIsSleeping(true); } } diff --git a/testbed/common/Box.cpp b/testbed/common/Box.cpp index 44df49cf..8d55eed9 100644 --- a/testbed/common/Box.cpp +++ b/testbed/common/Box.cpp @@ -160,12 +160,10 @@ void Box::render(openglframework::Shader& shader, const openglframework::Matrix4 shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - rp3d::RigidBody* rigidBody = static_cast(mBody); - if (rigidBody != nullptr) { - openglframework::Color currentColor = rigidBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); - } + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor; + openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); + shader.setVector4Uniform("vertexColor", color, false); // Bind the VAO mVAO.bind(); diff --git a/testbed/common/Capsule.cpp b/testbed/common/Capsule.cpp index f7c18300..f2ee3e52 100644 --- a/testbed/common/Capsule.cpp +++ b/testbed/common/Capsule.cpp @@ -141,12 +141,10 @@ void Capsule::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - rp3d::RigidBody* rigidBody = static_cast(mBody); - if (rigidBody != nullptr) { - openglframework::Color currentColor = rigidBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); - } + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor; + openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); + shader.setVector4Uniform("vertexColor", color, false); // Bind the VAO mVAO.bind(); diff --git a/testbed/common/ConcaveMesh.cpp b/testbed/common/ConcaveMesh.cpp index 45fdd73c..487312b0 100644 --- a/testbed/common/ConcaveMesh.cpp +++ b/testbed/common/ConcaveMesh.cpp @@ -150,12 +150,10 @@ void ConcaveMesh::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - rp3d::RigidBody* rigidBody = static_cast(mBody); - if (rigidBody != nullptr) { - openglframework::Color currentColor = rigidBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); - } + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor; + openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); + shader.setVector4Uniform("vertexColor", color, false); // Bind the VAO mVAO.bind(); diff --git a/testbed/common/ConvexMesh.cpp b/testbed/common/ConvexMesh.cpp index d590104a..c676d165 100644 --- a/testbed/common/ConvexMesh.cpp +++ b/testbed/common/ConvexMesh.cpp @@ -160,12 +160,10 @@ void ConvexMesh::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - rp3d::RigidBody* rigidBody = static_cast(mBody); - if (rigidBody != nullptr) { - openglframework::Color currentColor = rigidBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); - } + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor; + openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); + shader.setVector4Uniform("vertexColor", color, false); // Bind the VAO mVAO.bind(); diff --git a/testbed/common/Dumbbell.cpp b/testbed/common/Dumbbell.cpp index ea285b0b..111f63e2 100644 --- a/testbed/common/Dumbbell.cpp +++ b/testbed/common/Dumbbell.cpp @@ -178,12 +178,10 @@ void Dumbbell::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - rp3d::RigidBody* rigidBody = static_cast(mBody); - if (rigidBody != nullptr) { - openglframework::Color currentColor = rigidBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); - } + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor; + openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); + shader.setVector4Uniform("vertexColor", color, false); // Bind the VAO mVAO.bind(); diff --git a/testbed/common/HeightField.cpp b/testbed/common/HeightField.cpp index 5ea7243b..e9aee55a 100644 --- a/testbed/common/HeightField.cpp +++ b/testbed/common/HeightField.cpp @@ -132,12 +132,10 @@ void HeightField::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - rp3d::RigidBody* rigidBody = static_cast(mBody); - if (rigidBody != nullptr) { - openglframework::Color currentColor = rigidBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); - } + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor; + openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); + shader.setVector4Uniform("vertexColor", color, false); // Bind the VAO mVAO.bind(); diff --git a/testbed/common/Sphere.cpp b/testbed/common/Sphere.cpp index df865980..ce8509e8 100644 --- a/testbed/common/Sphere.cpp +++ b/testbed/common/Sphere.cpp @@ -140,12 +140,10 @@ void Sphere::render(openglframework::Shader& shader, const openglframework::Matr shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - rp3d::RigidBody* rigidBody = static_cast(mBody); - if (rigidBody != nullptr) { - openglframework::Color currentColor = rigidBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); - } + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + openglframework::Color currentColor = rigidBody != nullptr && rigidBody->isSleeping() ? mSleepingColor : mColor; + openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); + shader.setVector4Uniform("vertexColor", color, false); // Bind the VAO mVAO.bind();