diff --git a/CMakeLists.txt b/CMakeLists.txt index 2057916f..b9c20ad2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,6 @@ SET (REACTPHYSICS3D_HEADERS "src/configuration.h" "src/decimal.h" "src/reactphysics3d.h" - "src/body/Body.h" "src/body/CollisionBody.h" "src/body/RigidBody.h" "src/collision/ContactPointInfo.h" @@ -175,7 +174,6 @@ SET (REACTPHYSICS3D_HEADERS # Source files SET (REACTPHYSICS3D_SOURCES - "src/body/Body.cpp" "src/body/CollisionBody.cpp" "src/body/RigidBody.cpp" "src/collision/broadphase/DynamicAABBTree.cpp" diff --git a/src/body/Body.cpp b/src/body/Body.cpp deleted file mode 100644 index f0d362a9..00000000 --- a/src/body/Body.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/******************************************************************************** -* 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 "Body.h" -#include "engine/CollisionWorld.h" -#include "collision/shapes/CollisionShape.h" -#include "utils/Logger.h" - -// We want to use the ReactPhysics3D namespace -using namespace reactphysics3d; - -// Constructor -/** - * @param id ID of the new body - */ -Body::Body(Entity entity, CollisionWorld& world) - : mEntity(entity), mWorld(world) { - -#ifdef IS_LOGGING_ACTIVE - mLogger = nullptr; -#endif - -} - -// Set whether or not the body is active -/// An inactive body does not participate in collision detection, -/// is not simulated and will not be hit in a ray casting query. -/// A body is active by default. If you set this -/// value to "false", all the proxy shapes of this body will be -/// removed from the broad-phase. If you set this value to "true", -/// all the proxy shapes will be added to the broad-phase. A joint -/// connected to an inactive body will also be inactive. -/** - * @param isActive True if you want to activate the body - */ -void Body::setIsActive(bool isActive) { - - setIsSleeping(!isActive); - - mWorld.mBodyComponents.setIsActive(mEntity, isActive); - - RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, - "Body " + std::to_string(mEntity.id) + ": Set isActive=" + - (isActive ? "true" : "false")); -} - -// Set the variable to know whether or not the body is sleeping -void Body::setIsSleeping(bool isSleeping) { - - bool isBodySleeping = mWorld.mBodyComponents.getIsSleeping(mEntity); - - // If the body is not active, do nothing (it is sleeping) - if (!mWorld.mBodyComponents.getIsActive(mEntity)) { - assert(isBodySleeping); - return; - } - - if (isSleeping) { - mWorld.mBodyComponents.setSleepTime(mEntity, decimal(0.0)); - } - else { - if (isBodySleeping) { - mWorld.mBodyComponents.setSleepTime(mEntity, decimal(0.0)); - } - } - - if (isBodySleeping != isSleeping) { - - mWorld.mBodyComponents.setIsSleeping(mEntity, isSleeping); - - RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, - "Body " + std::to_string(mEntity.id) + ": Set isSleeping=" + - (isSleeping ? "true" : "false")); - } -} - -// Set whether or not the body is allowed to go to sleep -/** - * @param isAllowedToSleep True if the body is allowed to sleep - */ -void Body::setIsAllowedToSleep(bool isAllowedToSleep) { - - mWorld.mBodyComponents.setIsAllowedToSleep(mEntity, isAllowedToSleep); - - if (!isAllowedToSleep) setIsSleeping(false); - - RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, - "Body " + std::to_string(mEntity.id) + ": Set isAllowedToSleep=" + - (isAllowedToSleep ? "true" : "false")); -} - -// Return whether or not the body is allowed to sleep -/** - * @return True if the body is allowed to sleep and false otherwise - */ -bool Body::isAllowedToSleep() const { - return mWorld.mBodyComponents.getIsAllowedToSleep(mEntity); -} - -// Return whether or not the body is sleeping -/** - * @return True if the body is currently sleeping and false otherwise - */ -bool Body::isSleeping() const { - return mWorld.mBodyComponents.getIsSleeping(mEntity); -} - -// Return true if the body is active -/** - * @return True if the body currently active and false otherwise - */ -bool Body::isActive() const { - return mWorld.mBodyComponents.getIsActive(mEntity); -} - -// Return a pointer to the user data attached to this body -/** - * @return A pointer to the user data you have attached to the body - */ -void* Body::getUserData() const { - return mWorld.mBodyComponents.getUserData(mEntity); -} - -// Attach user data to this body -/** - * @param userData A pointer to the user data you want to attach to the body - */ -void Body::setUserData(void* userData) { - mWorld.mBodyComponents.setUserData(mEntity, userData); -} diff --git a/src/body/Body.h b/src/body/Body.h deleted file mode 100644 index 6edbf3c5..00000000 --- a/src/body/Body.h +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************** -* 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_H -#define REACTPHYSICS3D_BODY_H - -// Libraries -#include -#include "configuration.h" -#include "engine/Entity.h" - -/// Namespace reactphysics3d -namespace reactphysics3d { - -// Declarations -class Logger; -class CollisionWorld; - -// TODO : Make this class abstract -// Class Body -/** - * This class to represent a body of the physics engine. You should not - * instantiante this class but instantiate the CollisionBody or RigidBody - * classes instead. - */ -class Body { - - protected : - - // -------------------- Attributes -------------------- // - - /// Identifier of the entity in the ECS - Entity mEntity; - - /// Reference to the world the body belongs to - CollisionWorld& mWorld; - -#ifdef IS_LOGGING_ACTIVE - - /// Logger - Logger* mLogger; -#endif - - // -------------------- Methods -------------------- // - - /// Set the variable to know whether or not the body is sleeping - virtual void setIsSleeping(bool isSleeping); - - public : - - // -------------------- Methods -------------------- // - - /// Constructor - Body(Entity entity, CollisionWorld& world); - - /// Deleted copy-constructor - Body(const Body& body) = delete; - - /// Deleted assignment operator - Body& operator=(const Body& body) = delete; - - /// Destructor - virtual ~Body() = default; - - /// Return the corresponding entity of the body - Entity getEntity() const; - - /// Return whether or not the body is allowed to sleep - bool isAllowedToSleep() const; - - /// Set whether or not the body is allowed to go to sleep - void setIsAllowedToSleep(bool isAllowedToSleep); - - /// Return whether or not the body is sleeping - bool isSleeping() const; - - /// Return true if the body is active - bool isActive() const; - - /// Set whether or not the body is active - virtual void setIsActive(bool isActive); - - /// Return a pointer to the user data attached to this body - void* getUserData() const; - - /// Attach user data to this body - void setUserData(void* userData); - -#ifdef IS_LOGGING_ACTIVE - - /// Set the logger - void setLogger(Logger* logger); -#endif - - // -------------------- Friendship -------------------- // - - friend class DynamicsWorld; -}; - -// Return the corresponding entity of the body -/** - * @return The entity of the body - */ -inline Entity Body::getEntity() const { - return mEntity; -} - -#ifdef IS_LOGGING_ACTIVE - -// Set the logger -inline void Body::setLogger(Logger* logger) { - mLogger = logger; -} - -#endif - -} - -#endif diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 9b99cde1..80cd0e7d 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -40,7 +40,11 @@ using namespace reactphysics3d; * @param id ID of the body */ CollisionBody::CollisionBody(CollisionWorld& world, Entity entity) - : Body(entity, world), mType(BodyType::DYNAMIC) { + : mEntity(entity), mWorld(world) { + +#ifdef IS_LOGGING_ACTIVE + mLogger = nullptr; +#endif #ifdef IS_PROFILING_ACTIVE mProfiler = nullptr; @@ -230,7 +234,7 @@ void CollisionBody::setIsActive(bool isActive) { // If the state does not change if (mWorld.mBodyComponents.getIsActive(mEntity) == isActive) return; - Body::setIsActive(isActive); + mWorld.mBodyComponents.setIsActive(mEntity, isActive); // If we have to activate the body if (isActive) { @@ -382,9 +386,6 @@ void CollisionBody::setTransform(const Transform& transform) { // TODO : Make sure this method is never called from the internal physics engine - // Awake the body if it is sleeping - setIsSleeping(false); - // Update the transform of the body mWorld.mTransformComponents.setTransform(mEntity, transform); @@ -395,15 +396,28 @@ void CollisionBody::setTransform(const Transform& transform) { "Body " + std::to_string(mEntity.id) + ": Set transform=" + transform.to_string()); } -// Set the variable to know whether or not the body is sleeping -void CollisionBody::setIsSleeping(bool isSleeping) { +// Return true if the body is active +/** + * @return True if the body currently active and false otherwise + */ +bool CollisionBody::isActive() const { + return mWorld.mBodyComponents.getIsActive(mEntity); +} - if (mWorld.mBodyComponents.getIsSleeping(mEntity) == isSleeping) return; +// Return a pointer to the user data attached to this body +/** + * @return A pointer to the user data you have attached to the body + */ +void* CollisionBody::getUserData() const { + return mWorld.mBodyComponents.getUserData(mEntity); +} - Body::setIsSleeping(isSleeping); - - // Notify all the components - mWorld.notifyBodyDisabled(mEntity, isSleeping); +// Attach user data to this body +/** + * @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); } // Return the world-space coordinates of a point given the local-space coordinates of the body @@ -441,31 +455,3 @@ Vector3 CollisionBody::getLocalPoint(const Vector3& worldPoint) const { Vector3 CollisionBody::getLocalVector(const Vector3& worldVector) const { return mWorld.mTransformComponents.getTransform(mEntity).getOrientation().getInverse() * worldVector; } - -// Set the type of the body -/// The type of the body can either STATIC, KINEMATIC or DYNAMIC as described bellow: -/// STATIC : A static body has infinite mass, zero velocity but the position can be -/// changed manually. A static body does not collide with other static or kinematic bodies. -/// KINEMATIC : A kinematic body has infinite mass, the velocity can be changed manually and its -/// position is computed by the physics engine. A kinematic body does not collide with -/// other static or kinematic bodies. -/// DYNAMIC : A dynamic body has non-zero mass, non-zero velocity determined by forces and its -/// position is determined by the physics engine. A dynamic body can collide with other -/// dynamic, static or kinematic bodies. -/** - * @param type The type of the body (STATIC, KINEMATIC, DYNAMIC) - */ -void CollisionBody::setType(BodyType type) { - mType = type; - - if (mType == BodyType::STATIC) { - - // Update the broad-phase state of the body - updateBroadPhaseState(); - } - - RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, - "Body " + std::to_string(mEntity.id) + ": Set type=" + - (mType == BodyType::STATIC ? "Static" : (mType == BodyType::DYNAMIC ? "Dynamic" : "Kinematic"))); -} - diff --git a/src/body/CollisionBody.h b/src/body/CollisionBody.h index a2b802dd..95d4b913 100644 --- a/src/body/CollisionBody.h +++ b/src/body/CollisionBody.h @@ -28,7 +28,7 @@ // Libraries #include -#include "Body.h" +#include "engine/Entity.h" #include "collision/shapes/AABB.h" #include "mathematics/Transform.h" #include "configuration.h" @@ -44,32 +44,30 @@ class CollisionShape; struct RaycastInfo; class PoolAllocator; class Profiler; - -/// Enumeration for the type of a body -/// STATIC : A static body has infinite mass, zero velocity but the position can be -/// changed manually. A static body does not collide with other static or kinematic bodies. -/// KINEMATIC : A kinematic body has infinite mass, the velocity can be changed manually and its -/// position is computed by the physics engine. A kinematic body does not collide with -/// other static or kinematic bodies. -/// DYNAMIC : A dynamic body has non-zero mass, non-zero velocity determined by forces and its -/// position is determined by the physics engine. A dynamic body can collide with other -/// dynamic, static or kinematic bodies. -enum class BodyType {STATIC, KINEMATIC, DYNAMIC}; +class Logger; // Class CollisionBody /** * This class represents a body that is able to collide with others - * bodies. This class inherits from the Body class. + * bodies. */ -class CollisionBody : public Body { +class CollisionBody { protected : // -------------------- Attributes -------------------- // - // TODO : Move this into the dynamics components - /// Type of body (static, kinematic or dynamic) - BodyType mType; + /// Identifier of the entity in the ECS + Entity mEntity; + + /// Reference to the world the body belongs to + CollisionWorld& mWorld; + +#ifdef IS_LOGGING_ACTIVE + + /// Logger + Logger* mLogger; +#endif #ifdef IS_PROFILING_ACTIVE @@ -90,9 +88,6 @@ class CollisionBody : public Body { /// (as if the body has moved). void askForBroadPhaseCollisionCheck() const; - /// Set the variable to know whether or not the body is sleeping - virtual void setIsSleeping(bool isSleeping) override; - public : // -------------------- Methods -------------------- // @@ -101,7 +96,7 @@ class CollisionBody : public Body { CollisionBody(CollisionWorld& world, Entity entity); /// Destructor - virtual ~CollisionBody() override; + virtual ~CollisionBody(); /// Deleted copy-constructor CollisionBody(const CollisionBody& body) = delete; @@ -109,14 +104,20 @@ class CollisionBody : public Body { /// Deleted assignment operator CollisionBody& operator=(const CollisionBody& body) = delete; - /// Return the type of the body - BodyType getType() const; + /// Return the corresponding entity of the body + Entity getEntity() const; - /// Set the type of the body - void setType(BodyType type); + /// Return true if the body is active + bool isActive() const; + + /// Return a pointer to the user data attached to this body + void* getUserData() const; + + /// Attach user data to this body + void setUserData(void* userData); /// Set whether or not the body is active - virtual void setIsActive(bool isActive) override; + virtual void setIsActive(bool isActive); /// Return the current position and orientation const Transform& getTransform() const; @@ -125,8 +126,7 @@ class CollisionBody : public Body { virtual void setTransform(const Transform& transform); /// Add a collision shape to the body. - virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, - const Transform& transform); + virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, const Transform& transform); /// Remove a collision shape from the body virtual void removeCollisionShape(ProxyShape *proxyShape); @@ -164,6 +164,12 @@ class CollisionBody : public Body { /// Return the body local-space coordinates of a vector given in the world-space coordinates Vector3 getLocalVector(const Vector3& worldVector) const; +#ifdef IS_LOGGING_ACTIVE + + /// Set the logger + void setLogger(Logger* logger); +#endif + #ifdef IS_PROFILING_ACTIVE /// Set the profiler @@ -181,14 +187,6 @@ class CollisionBody : public Body { friend class ProxyShape; }; -// Return the type of the body -/** - * @return the type of the body (STATIC, KINEMATIC, DYNAMIC) - */ -inline BodyType CollisionBody::getType() const { - return mType; -} - /// Test if the collision body overlaps with a given AABB /** * @param worldAABB The AABB (in world-space coordinates) that will be used to test overlap @@ -198,6 +196,23 @@ inline bool CollisionBody::testAABBOverlap(const AABB& worldAABB) const { return worldAABB.testCollision(getAABB()); } +// Return the corresponding entity of the body +/** + * @return The entity of the body + */ +inline Entity CollisionBody::getEntity() const { + return mEntity; +} + +#ifdef IS_LOGGING_ACTIVE + +// Set the logger +inline void CollisionBody::setLogger(Logger* logger) { + mLogger = logger; +} + +#endif + #ifdef IS_PROFILING_ACTIVE // Set the profiler diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index 158da8d4..fb6d73f5 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -55,6 +55,11 @@ RigidBody::~RigidBody() { assert(mJointsList == nullptr); } +// Return the type of the body +BodyType RigidBody::getType() const { + return mWorld.mDynamicsComponents.getBodyType(mEntity); +} + // Set the type of the body /// The type of the body can either STATIC, KINEMATIC or DYNAMIC as described bellow: /// STATIC : A static body has infinite mass, zero velocity but the position can be @@ -70,15 +75,15 @@ RigidBody::~RigidBody() { */ void RigidBody::setType(BodyType type) { - if (mType == type) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) == type) return; - CollisionBody::setType(type); + mWorld.mDynamicsComponents.setBodyType(mEntity, type); // Recompute the total mass, center of mass and inertia tensor recomputeMassInformation(); // If it is a static body - if (mType == BodyType::STATIC) { + if (type == BodyType::STATIC) { // Reset the velocity to zero mWorld.mDynamicsComponents.setLinearVelocity(mEntity, Vector3::zero()); @@ -86,7 +91,7 @@ void RigidBody::setType(BodyType type) { } // If it is a static or a kinematic body - if (mType == BodyType::STATIC || mType == BodyType::KINEMATIC) { + if (type == BodyType::STATIC || type == BodyType::KINEMATIC) { // Reset the inverse mass and inverse inertia tensor to zero mWorld.mDynamicsComponents.setMassInverse(mEntity, decimal(0)); @@ -114,6 +119,10 @@ void RigidBody::setType(BodyType type) { // Reset the force and torque on the body mWorld.mDynamicsComponents.setExternalForce(mEntity, Vector3::zero()); mWorld.mDynamicsComponents.setExternalTorque(mEntity, Vector3::zero()); + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set type=" + + (type == BodyType::STATIC ? "Static" : (type == BodyType::DYNAMIC ? "Dynamic" : "Kinematic"))); } // Get the inverse local inertia tensor of the body (in body coordinates) @@ -159,7 +168,7 @@ decimal RigidBody::getMass() const { void RigidBody::applyForce(const Vector3& force, const Vector3& point) { // If it is not a dynamic body, we do nothing - if (mType != BodyType::DYNAMIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Awake the body if it was sleeping if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { @@ -188,7 +197,7 @@ void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) { mUserInertiaTensorLocalInverse = inertiaTensorLocal.getInverse(); mIsInertiaTensorSetByUser = true; - if (mType != BodyType::DYNAMIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Compute the inverse local inertia tensor mWorld.mDynamicsComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse); @@ -211,7 +220,7 @@ void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) { void RigidBody::applyForceToCenterOfMass(const Vector3& force) { // If it is not a dynamic body, we do nothing - if (mType != BodyType::DYNAMIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Awake the body if it was sleeping if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { @@ -251,7 +260,7 @@ void RigidBody::setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTens mUserInertiaTensorLocalInverse = inverseInertiaTensorLocal; mIsInertiaTensorSetByUser = true; - if (mType != BodyType::DYNAMIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Compute the inverse local inertia tensor mWorld.mDynamicsComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse); @@ -274,7 +283,7 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) { // TODO : Check if we need to update the postion of the body here at the end (transform of the body) - if (mType != BodyType::DYNAMIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; mIsCenterOfMassSetByUser = true; @@ -302,7 +311,7 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) { */ void RigidBody::setMass(decimal mass) { - if (mType != BodyType::DYNAMIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; mWorld.mDynamicsComponents.setInitMass(mEntity, mass); @@ -524,7 +533,7 @@ void RigidBody::setMaterial(const Material& material) { void RigidBody::setLinearVelocity(const Vector3& linearVelocity) { // If it is a static body, we do nothing - if (mType == BodyType::STATIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) == BodyType::STATIC) return; // Update the linear velocity of the current body state mWorld.mDynamicsComponents.setLinearVelocity(mEntity, linearVelocity); @@ -547,7 +556,7 @@ void RigidBody::setAngularVelocity(const Vector3& angularVelocity) { // TODO : Make sure this method is not called from the internal physics engine // If it is a static body, we do nothing - if (mType == BodyType::STATIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) == BodyType::STATIC) return; // Set the angular velocity mWorld.mDynamicsComponents.setAngularVelocity(mEntity, angularVelocity); @@ -588,6 +597,9 @@ void RigidBody::setTransform(const Transform& transform) { // Update the world inverse inertia tensor updateInertiaTensorInverseWorld(); + + // Awake the body if it is sleeping + setIsSleeping(false); } // Recompute the center of mass, total mass and inertia tensor of the body using all @@ -605,12 +617,13 @@ void RigidBody::recomputeMassInformation() { const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); // If it is a STATIC or a KINEMATIC body - if (mType == BodyType::STATIC || mType == BodyType::KINEMATIC) { + BodyType type = mWorld.mDynamicsComponents.getBodyType(mEntity); + if (type == BodyType::STATIC || type == BodyType::KINEMATIC) { mWorld.mDynamicsComponents.setCenterOfMassWorld(mEntity, transform.getPosition()); return; } - assert(mType == BodyType::DYNAMIC); + assert(mWorld.mDynamicsComponents.getBodyType(mEntity) == BodyType::DYNAMIC); // Compute the total mass of the body const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); @@ -723,7 +736,7 @@ bool RigidBody::isGravityEnabled() const { void RigidBody::applyTorque(const Vector3& torque) { // If it is not a dynamic body, we do nothing - if (mType != BodyType::DYNAMIC) return; + if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; // Awake the body if it was sleeping if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { @@ -738,7 +751,29 @@ void RigidBody::applyTorque(const Vector3& torque) { // Set the variable to know whether or not the body is sleeping void RigidBody::setIsSleeping(bool isSleeping) { - CollisionBody::setIsSleeping(isSleeping); + bool isBodySleeping = mWorld.mBodyComponents.getIsSleeping(mEntity); + + if (isBodySleeping == isSleeping) return; + + // If the body is not active, do nothing (it is sleeping) + if (!mWorld.mBodyComponents.getIsActive(mEntity)) { + assert(isBodySleeping); + return; + } + + if (isSleeping) { + mWorld.mBodyComponents.setSleepTime(mEntity, decimal(0.0)); + } + else { + if (isBodySleeping) { + mWorld.mBodyComponents.setSleepTime(mEntity, decimal(0.0)); + } + } + + mWorld.mBodyComponents.setIsSleeping(mEntity, isSleeping); + + // Notify all the components + mWorld.notifyBodyDisabled(mEntity, isSleeping); if (isSleeping) { @@ -747,6 +782,56 @@ void RigidBody::setIsSleeping(bool isSleeping) { mWorld.mDynamicsComponents.setExternalForce(mEntity, Vector3::zero()); mWorld.mDynamicsComponents.setExternalTorque(mEntity, Vector3::zero()); } + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set isSleeping=" + + (isSleeping ? "true" : "false")); + +} + +// Set whether or not the body is allowed to go to sleep +/** + * @param isAllowedToSleep True if the body is allowed to sleep + */ +void RigidBody::setIsAllowedToSleep(bool isAllowedToSleep) { + + mWorld.mBodyComponents.setIsAllowedToSleep(mEntity, isAllowedToSleep); + + if (!isAllowedToSleep) setIsSleeping(false); + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set isAllowedToSleep=" + + (isAllowedToSleep ? "true" : "false")); +} + +// Return whether or not the body is allowed to sleep +/** + * @return True if the body is allowed to sleep and false otherwise + */ +bool RigidBody::isAllowedToSleep() const { + return mWorld.mBodyComponents.getIsAllowedToSleep(mEntity); +} + +// Return whether or not the body is sleeping +/** + * @return True if the body is currently sleeping and false otherwise + */ +bool RigidBody::isSleeping() const { + return mWorld.mBodyComponents.getIsSleeping(mEntity); +} + +// Set whether or not the body is active +/** + * @param isActive True if you want to activate the body + */ +void RigidBody::setIsActive(bool isActive) { + + // If the state does not change + if (mWorld.mBodyComponents.getIsActive(mEntity) == isActive) return; + + setIsSleeping(!isActive); + + CollisionBody::setIsActive(isActive); } #ifdef IS_PROFILING_ACTIVE diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h index 022bea9c..6e2c9d9a 100644 --- a/src/body/RigidBody.h +++ b/src/body/RigidBody.h @@ -40,6 +40,7 @@ struct JointListElement; class Joint; class DynamicsWorld; class MemoryManager; +enum class BodyType; // Class RigidBody /** @@ -82,7 +83,7 @@ class RigidBody : public CollisionBody { void updateInertiaTensorInverseWorld(); /// Set the variable to know whether or not the body is sleeping - virtual void setIsSleeping(bool isSleeping) override; + void setIsSleeping(bool isSleeping); public : @@ -100,9 +101,6 @@ class RigidBody : public CollisionBody { /// Deleted assignment operator RigidBody& operator=(const RigidBody& body) = delete; - /// Set the type of the body (static, kinematic or dynamic) - void setType(BodyType type); - /// Set the current position and orientation virtual void setTransform(const Transform& transform) override; @@ -139,6 +137,12 @@ class RigidBody : public CollisionBody { /// Set the mass of the rigid body void setMass(decimal mass); + /// Return the type of the body + BodyType getType() const; + + /// Set the type of the body + void setType(BodyType type); + /// Return true if the gravity needs to be applied to this rigid body bool isGravityEnabled() const; @@ -178,6 +182,18 @@ class RigidBody : public CollisionBody { /// Apply an external torque to the body. void applyTorque(const Vector3& torque); + /// Return whether or not the body is allowed to sleep + bool isAllowedToSleep() const; + + /// Set whether or not the body is allowed to go to sleep + void setIsAllowedToSleep(bool isAllowedToSleep); + + /// Return whether or not the body is sleeping + bool isSleeping() const; + + /// Set whether or not the body is active + virtual void setIsActive(bool isActive) override; + /// Add a collision shape to the body. virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, const Transform& transform, diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index 617fe2ac..14937350 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -27,7 +27,6 @@ #include "CollisionDetection.h" #include "engine/CollisionWorld.h" #include "collision/OverlapCallback.h" -#include "body/Body.h" #include "collision/shapes/BoxShape.h" #include "collision/shapes/ConcaveShape.h" #include "collision/ContactManifoldInfo.h" @@ -238,9 +237,14 @@ void CollisionDetection::computeMiddlePhase(OverlappingPairMap& overlappingPairs const Entity body1Entity = body1->getEntity(); const Entity body2Entity = body2->getEntity(); + const bool isStaticRigidBody1 = mWorld->mDynamicsComponents.hasComponent(body1Entity) && + mWorld->mDynamicsComponents.getBodyType(body1Entity) == BodyType::STATIC; + const bool isStaticRigidBody2 = mWorld->mDynamicsComponents.hasComponent(body2Entity) && + 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) && body1->getType() != BodyType::STATIC; - bool isBody2Active = !mWorld->mBodyComponents.getIsEntityDisabled(body2Entity) && body2->getType() != BodyType::STATIC; + bool isBody1Active = !mWorld->mBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1; + bool isBody2Active = !mWorld->mBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2; if (!isBody1Active && !isBody2Active) continue; // Check if the bodies are in the set of bodies that cannot collide between each other diff --git a/src/collision/ProxyShape.cpp b/src/collision/ProxyShape.cpp index cbb34788..2bbfb6f9 100644 --- a/src/collision/ProxyShape.cpp +++ b/src/collision/ProxyShape.cpp @@ -115,10 +115,12 @@ void ProxyShape::setLocalToBodyTransform(const Transform& transform) { // TODO : Make sure this method is never called by the internal physics engine - //mLocalToBodyTransform = transform; mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(mEntity, transform); - mBody->setIsSleeping(false); + RigidBody* rigidBody = static_cast(mBody); + if (rigidBody != nullptr) { + mBody->mWorld.mBodyComponents.setIsSleeping(mBody->getEntity(), false); + } mBody->mWorld.mCollisionDetection.updateProxyShape(mEntity); diff --git a/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h b/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h index d8b69bca..a6d41e0f 100644 --- a/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h +++ b/src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h @@ -35,7 +35,6 @@ namespace reactphysics3d { // Declarations struct CapsuleVsCapsuleNarrowPhaseInfoBatch; -class Body; class ContactPoint; // Class CapsuleVsCapsuleAlgorithm diff --git a/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h b/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h index 53b5ca56..e73e547e 100644 --- a/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h +++ b/src/collision/narrowphase/CapsuleVsConvexPolyhedronAlgorithm.h @@ -34,7 +34,6 @@ namespace reactphysics3d { // Declarations class ContactPoint; -class Body; // Class CapsuleVsConvexPolyhedronAlgorithm /** diff --git a/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h b/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h index 6e43e76b..e530c129 100644 --- a/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h +++ b/src/collision/narrowphase/ConvexPolyhedronVsConvexPolyhedronAlgorithm.h @@ -33,7 +33,6 @@ namespace reactphysics3d { // Declarations -class Body; class ContactPoint; // Class ConvexPolyhedronVsConvexPolyhedronAlgorithm diff --git a/src/collision/narrowphase/NarrowPhaseAlgorithm.h b/src/collision/narrowphase/NarrowPhaseAlgorithm.h index 3b7f68a2..6cae33fa 100644 --- a/src/collision/narrowphase/NarrowPhaseAlgorithm.h +++ b/src/collision/narrowphase/NarrowPhaseAlgorithm.h @@ -33,7 +33,6 @@ namespace reactphysics3d { class CollisionDetection; -class Body; class ContactManifoldInfo; class PoolAllocator; class OverlappingPair; diff --git a/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h b/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h index 25926fce..3780331e 100644 --- a/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h +++ b/src/collision/narrowphase/SphereVsCapsuleAlgorithm.h @@ -34,7 +34,6 @@ namespace reactphysics3d { // Declarations -class Body; class ContactPoint; struct SphereVsCapsuleNarrowPhaseInfoBatch; diff --git a/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h b/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h index 793dc48a..b6b132f6 100644 --- a/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h +++ b/src/collision/narrowphase/SphereVsConvexPolyhedronAlgorithm.h @@ -34,7 +34,6 @@ namespace reactphysics3d { // Declarations class ContactPoint; -class Body; // Class SphereVsConvexPolyhedronAlgorithm /** diff --git a/src/collision/narrowphase/SphereVsSphereAlgorithm.h b/src/collision/narrowphase/SphereVsSphereAlgorithm.h index 5e9554b4..2d625c6f 100644 --- a/src/collision/narrowphase/SphereVsSphereAlgorithm.h +++ b/src/collision/narrowphase/SphereVsSphereAlgorithm.h @@ -35,7 +35,6 @@ namespace reactphysics3d { // Declarations class ContactPoint; struct SphereVsSphereNarrowPhaseInfoBatch; -class Body; // Class SphereVsSphereAlgorithm /** diff --git a/src/components/BodyComponents.cpp b/src/components/BodyComponents.cpp index bf49cc62..65541b3d 100644 --- a/src/components/BodyComponents.cpp +++ b/src/components/BodyComponents.cpp @@ -34,7 +34,7 @@ using namespace reactphysics3d; // Constructor BodyComponents::BodyComponents(MemoryAllocator& allocator) - :Components(allocator, sizeof(Entity) + sizeof(Body*) + sizeof(List) + + :Components(allocator, sizeof(Entity) + sizeof(CollisionBody*) + sizeof(List) + sizeof(bool) + sizeof(bool) + sizeof(bool) + sizeof(decimal) + sizeof(void*)) { @@ -56,7 +56,7 @@ void BodyComponents::allocate(uint32 nbComponentsToAllocate) { // New pointers to components data Entity* newBodiesEntities = static_cast(newBuffer); - Body** newBodies = reinterpret_cast(newBodiesEntities + nbComponentsToAllocate); + CollisionBody** newBodies = reinterpret_cast(newBodiesEntities + nbComponentsToAllocate); List* newProxyShapes = reinterpret_cast*>(newBodies + nbComponentsToAllocate); bool* newIsAllowedToSleep = reinterpret_cast(newProxyShapes + nbComponentsToAllocate); bool* newIsActive = reinterpret_cast(newIsAllowedToSleep + nbComponentsToAllocate); @@ -69,7 +69,7 @@ void BodyComponents::allocate(uint32 nbComponentsToAllocate) { // Copy component data from the previous buffer to the new one memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity)); - memcpy(newBodies, mBodies, mNbComponents * sizeof(Body*)); + memcpy(newBodies, mBodies, mNbComponents * sizeof(CollisionBody*)); memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(List)); memcpy(newIsAllowedToSleep, mIsAllowedToSleep, mNbComponents * sizeof(bool)); memcpy(newIsActive, mIsActive, mNbComponents * sizeof(bool)); @@ -150,7 +150,7 @@ void BodyComponents::swapComponents(uint32 index1, uint32 index2) { // Copy component 1 data Entity entity1(mBodiesEntities[index1]); - Body* body1 = mBodies[index1]; + CollisionBody* body1 = mBodies[index1]; List proxyShapes1(mProxyShapes[index1]); bool isAllowedToSleep1 = mIsAllowedToSleep[index1]; bool isActive1 = mIsActive[index1]; diff --git a/src/components/BodyComponents.h b/src/components/BodyComponents.h index e84e4f88..b99ac1f9 100644 --- a/src/components/BodyComponents.h +++ b/src/components/BodyComponents.h @@ -38,7 +38,7 @@ namespace reactphysics3d { // Class declarations class MemoryAllocator; class EntityManager; -class Body; +class CollisionBody; // Class BodyComponents /** @@ -55,7 +55,7 @@ class BodyComponents : public Components { Entity* mBodiesEntities; /// Array of pointers to the corresponding bodies - Body** mBodies; + CollisionBody** mBodies; /// Array with the list of proxy-shapes of each body List* mProxyShapes; @@ -69,7 +69,7 @@ class BodyComponents : public Components { /// Array of boolean values to know if the body is sleeping bool* mIsSleeping; - /// Array with values for elapsed time since the body velocity was bellow the sleep velocity + /// 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 @@ -94,10 +94,10 @@ class BodyComponents : public Components { /// Structure for the data of a body component struct BodyComponent { - Body* body; + CollisionBody* body; /// Constructor - BodyComponent(Body* body) : body(body) { + BodyComponent(CollisionBody* body) : body(body) { } }; @@ -120,7 +120,7 @@ class BodyComponents : public Components { void removeProxyShapeFromBody(Entity bodyEntity, Entity proxyShapeEntity); /// Return a pointer to a body - Body* getBody(Entity bodyEntity); + CollisionBody* getBody(Entity bodyEntity); /// Return the list of proxy-shapes of a body const List& getProxyShapes(Entity bodyEntity) const; @@ -173,7 +173,7 @@ inline void BodyComponents::removeProxyShapeFromBody(Entity bodyEntity, Entity p } // Return a pointer to a body -inline Body* BodyComponents::getBody(Entity bodyEntity) { +inline CollisionBody *BodyComponents::getBody(Entity bodyEntity) { assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); diff --git a/src/components/DynamicsComponents.cpp b/src/components/DynamicsComponents.cpp index 8350ae2f..3af49c75 100644 --- a/src/components/DynamicsComponents.cpp +++ b/src/components/DynamicsComponents.cpp @@ -39,7 +39,7 @@ DynamicsComponents::DynamicsComponents(MemoryAllocator& allocator) sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(Matrix3x3) + sizeof(Matrix3x3) + sizeof(Vector3) + sizeof(Quaternion) + sizeof(Vector3) + sizeof(Vector3) + sizeof(bool) + - sizeof(bool)) { + sizeof(bool) + sizeof(BodyType)) { // Allocate memory for the components data allocate(INIT_NB_ALLOCATED_COMPONENTS); @@ -79,6 +79,7 @@ void DynamicsComponents::allocate(uint32 nbComponentsToAllocate) { Vector3* newCentersOfMassWorld = reinterpret_cast(newCentersOfMassLocal + nbComponentsToAllocate); bool* newIsGravityEnabled = reinterpret_cast(newCentersOfMassWorld + nbComponentsToAllocate); bool* newIsAlreadyInIsland = reinterpret_cast(newIsGravityEnabled + nbComponentsToAllocate); + BodyType* newBodyTypes = reinterpret_cast(newIsAlreadyInIsland + nbComponentsToAllocate); // If there was already components before if (mNbComponents > 0) { @@ -105,6 +106,7 @@ void DynamicsComponents::allocate(uint32 nbComponentsToAllocate) { memcpy(newCentersOfMassWorld, mCentersOfMassWorld, mNbComponents * sizeof(Vector3)); memcpy(newIsGravityEnabled, mIsGravityEnabled, mNbComponents * sizeof(bool)); memcpy(newIsAlreadyInIsland, mIsAlreadyInIsland, mNbComponents * sizeof(bool)); + memcpy(newBodyTypes, mBodyTypes, mNbComponents * sizeof(BodyType)); // Deallocate previous memory mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize); @@ -132,6 +134,8 @@ void DynamicsComponents::allocate(uint32 nbComponentsToAllocate) { mCentersOfMassWorld = newCentersOfMassWorld; mIsGravityEnabled = newIsGravityEnabled; mIsAlreadyInIsland = newIsAlreadyInIsland; + mBodyTypes = newBodyTypes; + mNbAllocatedComponents = nbComponentsToAllocate; } @@ -163,6 +167,7 @@ void DynamicsComponents::addComponent(Entity bodyEntity, bool isSleeping, const new (mCentersOfMassWorld + index) Vector3(component.worldPosition); mIsGravityEnabled[index] = true; mIsAlreadyInIsland[index] = false; + mBodyTypes[index] = component.bodyType; // Map the entity with the new component lookup index mMapEntityToComponentIndex.add(Pair(bodyEntity, index)); @@ -201,6 +206,7 @@ void DynamicsComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) new (mCentersOfMassWorld + destIndex) Vector3(mCentersOfMassWorld[srcIndex]); mIsGravityEnabled[destIndex] = mIsGravityEnabled[srcIndex]; mIsAlreadyInIsland[destIndex] = mIsAlreadyInIsland[srcIndex]; + mBodyTypes[destIndex] = mBodyTypes[srcIndex]; // Destroy the source component destroyComponent(srcIndex); @@ -241,6 +247,7 @@ void DynamicsComponents::swapComponents(uint32 index1, uint32 index2) { Vector3 centerOfMassWorld1 = mCentersOfMassWorld[index1]; bool isGravityEnabled1 = mIsGravityEnabled[index1]; bool isAlreadyInIsland1 = mIsAlreadyInIsland[index1]; + BodyType bodyType1 = mBodyTypes[index1]; // Destroy component 1 destroyComponent(index1); @@ -269,6 +276,7 @@ void DynamicsComponents::swapComponents(uint32 index1, uint32 index2) { mCentersOfMassWorld[index2] = centerOfMassWorld1; mIsGravityEnabled[index2] = isGravityEnabled1; mIsAlreadyInIsland[index2] = isAlreadyInIsland1; + mBodyTypes[index2] = bodyType1; // Update the entity to component index mapping mMapEntityToComponentIndex.add(Pair(entity1, index2)); diff --git a/src/components/DynamicsComponents.h b/src/components/DynamicsComponents.h index 8cbe2135..cf6f37a0 100644 --- a/src/components/DynamicsComponents.h +++ b/src/components/DynamicsComponents.h @@ -40,10 +40,22 @@ namespace reactphysics3d { class MemoryAllocator; class EntityManager; +/// Enumeration for the type of a body +/// STATIC : A static body has infinite mass, zero velocity but the position can be +/// changed manually. A static body does not collide with other static or kinematic bodies. +/// KINEMATIC : A kinematic body has infinite mass, the velocity can be changed manually and its +/// position is computed by the physics engine. A kinematic body does not collide with +/// other static or kinematic bodies. +/// DYNAMIC : A dynamic body has non-zero mass, non-zero velocity determined by forces and its +/// position is determined by the physics engine. A dynamic body can collide with other +/// dynamic, static or kinematic bodies. +enum class BodyType {STATIC, KINEMATIC, DYNAMIC}; + // Class DynamicsComponents /** * This class represent the component of the ECS that contains the variables concerning dynamics - * like velocities. + * like velocities. A rigid body that is not static always has a dynamics component. A rigid body + * that is static does not have one because it is not simulated by dynamics. */ class DynamicsComponents : public Components { @@ -114,6 +126,9 @@ class DynamicsComponents : public Components { /// Array with the boolean value to know if the body has already been added into an island bool* mIsAlreadyInIsland; + /// Array with the type of bodies (static, kinematic or dynamic) + BodyType* mBodyTypes; + // -------------------- Methods -------------------- // /// Allocate memory for a given number of components @@ -135,9 +150,11 @@ class DynamicsComponents : public Components { const Vector3& worldPosition; + BodyType bodyType; + /// Constructor - DynamicsComponent(const Vector3& worldPosition) - : worldPosition(worldPosition) { + DynamicsComponent(const Vector3& worldPosition, BodyType bodyType) + : worldPosition(worldPosition), bodyType(bodyType) { } }; @@ -268,10 +285,16 @@ class DynamicsComponents : public Components { void setCenterOfMassWorld(Entity bodyEntity, const Vector3& centerOfMassWorld); /// Set the value to know if the gravity is enabled for this entity - bool setIsGravityEnabled(Entity bodyEntity, bool isGravityEnabled); + void setIsGravityEnabled(Entity bodyEntity, bool isGravityEnabled); /// Set the value to know if the entity is already in an island - bool setIsAlreadyInIsland(Entity bodyEntity, bool isAlreadyInIsland); + void setIsAlreadyInIsland(Entity bodyEntity, bool isAlreadyInIsland); + + /// Return the body type of a body + BodyType getBodyType(Entity bodyEntity); + + /// Set the body type of a body + void setBodyType(Entity bodyEntity, BodyType bodyType); // -------------------- Friendship -------------------- // @@ -282,7 +305,6 @@ class DynamicsComponents : public Components { friend class FixedJoint; friend class HingeJoint; friend class SliderJoint; - }; // Return the linear velocity of an entity @@ -590,7 +612,7 @@ inline bool DynamicsComponents::getIsAlreadyInIsland(Entity bodyEntity) const { } // Set the value to know if the gravity is enabled for this entity -inline bool DynamicsComponents::setIsGravityEnabled(Entity bodyEntity, bool isGravityEnabled) { +inline void DynamicsComponents::setIsGravityEnabled(Entity bodyEntity, bool isGravityEnabled) { assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); @@ -598,13 +620,29 @@ inline bool DynamicsComponents::setIsGravityEnabled(Entity bodyEntity, bool isGr } /// Set the value to know if the entity is already in an island -inline bool DynamicsComponents::setIsAlreadyInIsland(Entity bodyEntity, bool isAlreadyInIsland) { +inline void DynamicsComponents::setIsAlreadyInIsland(Entity bodyEntity, bool isAlreadyInIsland) { assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); mIsAlreadyInIsland[mMapEntityToComponentIndex[bodyEntity]] = isAlreadyInIsland; } +// Return the body type of a body +inline BodyType DynamicsComponents::getBodyType(Entity bodyEntity) { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + return mBodyTypes[mMapEntityToComponentIndex[bodyEntity]]; +} + +// Set the body type of a body +inline void DynamicsComponents::setBodyType(Entity bodyEntity, BodyType bodyType) { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + mBodyTypes[mMapEntityToComponentIndex[bodyEntity]] = bodyType; +} + } #endif diff --git a/src/engine/CollisionWorld.h b/src/engine/CollisionWorld.h index 6868d26e..aef8201d 100644 --- a/src/engine/CollisionWorld.h +++ b/src/engine/CollisionWorld.h @@ -196,7 +196,6 @@ class CollisionWorld { // -------------------- Friendship -------------------- // friend class CollisionDetection; - friend class Body; friend class CollisionBody; friend class RigidBody; friend class ProxyShape; diff --git a/src/engine/DynamicsWorld.cpp b/src/engine/DynamicsWorld.cpp index c27661bc..958dd7e6 100644 --- a/src/engine/DynamicsWorld.cpp +++ b/src/engine/DynamicsWorld.cpp @@ -376,7 +376,8 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) { Entity entity = mEntityManager.createEntity(); mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform)); - mDynamicsComponents.addComponent(entity, false, DynamicsComponents::DynamicsComponent(transform.getPosition())); + mDynamicsComponents.addComponent(entity, false, DynamicsComponents::DynamicsComponent(transform.getPosition(), + BodyType::DYNAMIC)); // Create the rigid body RigidBody* rigidBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, @@ -655,9 +656,7 @@ void DynamicsWorld::createIslands() { if (mDynamicsComponents.mIsAlreadyInIsland[b]) continue; // If the body is static, we go to the next body - // TODO : Do not use pointer to rigid body here (maybe move getType() into a component) - CollisionBody* body = static_cast(mBodyComponents.getBody(mDynamicsComponents.mBodies[b])); - if (body->getType() == BodyType::STATIC) continue; + if (mDynamicsComponents.mBodyTypes[b] == BodyType::STATIC) continue; // Reset the stack of bodies to visit bodyEntityIndicesToVisit.clear(); @@ -678,14 +677,14 @@ void DynamicsWorld::createIslands() { // Add the body into the island mIslands.bodyEntities[islandIndex].add(bodyToVisitEntity); - // If the current body is static, we do not want to perform the DFS - // search across that body // TODO : Do not use pointer to rigid body here (maybe move getType() into a component) RigidBody* rigidBodyToVisit = static_cast(mBodyComponents.getBody(bodyToVisitEntity)); // Awake the body if it is sleeping rigidBodyToVisit->setIsSleeping(false); + // If the current body is static, we do not want to perform the DFS + // search across that body if (rigidBodyToVisit->getType() == BodyType::STATIC) continue; // If the body is involved in contacts with other bodies @@ -768,10 +767,7 @@ void DynamicsWorld::createIslands() { // can also be included in the other islands for (uint j=0; j < mDynamicsComponents.getNbEnabledComponents(); j++) { - // If the body is static, we go to the next body - // TODO : Do not use pointer to rigid body here (maybe move getType() into a component) - CollisionBody* body = static_cast(mBodyComponents.getBody(mDynamicsComponents.mBodies[j])); - if (body->getType() == BodyType::STATIC) { + if (mDynamicsComponents.mBodyTypes[j] == BodyType::STATIC) { mDynamicsComponents.mIsAlreadyInIsland[j] = false; } } @@ -805,16 +801,16 @@ void DynamicsWorld::updateSleepingBodies() { const Entity bodyEntity = mIslands.bodyEntities[i][b]; - // TODO : We should not have to do this cast here to get type of body - CollisionBody* body = static_cast(mBodyComponents.getBody(bodyEntity)); + // TODO : We should use a RigidBody* type here + CollisionBody* body = mBodyComponents.getBody(bodyEntity); // Skip static bodies - if (body->getType() == BodyType::STATIC) continue; + if (mDynamicsComponents.getBodyType(body->getEntity()) == BodyType::STATIC) continue; // If the body is velocity is large enough to stay awake if (mDynamicsComponents.getLinearVelocity(bodyEntity).lengthSquare() > sleepLinearVelocitySquare || mDynamicsComponents.getAngularVelocity(bodyEntity).lengthSquare() > sleepAngularVelocitySquare || - !body->isAllowedToSleep()) { + !mBodyComponents.getIsAllowedToSleep(body->getEntity())) { // Reset the sleep time of the body mBodyComponents.setSleepTime(body->getEntity(), decimal(0.0)); @@ -840,8 +836,9 @@ void DynamicsWorld::updateSleepingBodies() { // Put all the bodies of the island to sleep for (uint b=0; b < mIslands.bodyEntities[i].size(); b++) { + // TODO : We should use a RigidBody* type here (remove the cast) const Entity bodyEntity = mIslands.bodyEntities[i][b]; - CollisionBody* body = static_cast(mBodyComponents.getBody(bodyEntity)); + RigidBody* body = static_cast(mBodyComponents.getBody(bodyEntity)); body->setIsSleeping(true); } } diff --git a/testbed/common/Box.cpp b/testbed/common/Box.cpp index 6d685086..44df49cf 100644 --- a/testbed/common/Box.cpp +++ b/testbed/common/Box.cpp @@ -160,9 +160,12 @@ void Box::render(openglframework::Shader& shader, const openglframework::Matrix4 shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); + 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); + } // Bind the VAO mVAO.bind(); diff --git a/testbed/common/Capsule.cpp b/testbed/common/Capsule.cpp index 160030b7..f7c18300 100644 --- a/testbed/common/Capsule.cpp +++ b/testbed/common/Capsule.cpp @@ -141,9 +141,12 @@ void Capsule::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); + 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); + } // Bind the VAO mVAO.bind(); diff --git a/testbed/common/ConcaveMesh.cpp b/testbed/common/ConcaveMesh.cpp index 553a83ca..45fdd73c 100644 --- a/testbed/common/ConcaveMesh.cpp +++ b/testbed/common/ConcaveMesh.cpp @@ -150,9 +150,12 @@ void ConcaveMesh::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); + 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); + } // Bind the VAO mVAO.bind(); diff --git a/testbed/common/ConvexMesh.cpp b/testbed/common/ConvexMesh.cpp index 95e41dd1..d590104a 100644 --- a/testbed/common/ConvexMesh.cpp +++ b/testbed/common/ConvexMesh.cpp @@ -160,9 +160,12 @@ void ConvexMesh::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); + 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); + } // Bind the VAO mVAO.bind(); diff --git a/testbed/common/Dumbbell.cpp b/testbed/common/Dumbbell.cpp index 866c35b1..ea285b0b 100644 --- a/testbed/common/Dumbbell.cpp +++ b/testbed/common/Dumbbell.cpp @@ -178,9 +178,12 @@ void Dumbbell::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); + 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); + } // Bind the VAO mVAO.bind(); diff --git a/testbed/common/HeightField.cpp b/testbed/common/HeightField.cpp index b1077fad..5ea7243b 100644 --- a/testbed/common/HeightField.cpp +++ b/testbed/common/HeightField.cpp @@ -132,9 +132,12 @@ void HeightField::render(openglframework::Shader& shader, shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); + 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); + } // Bind the VAO mVAO.bind(); diff --git a/testbed/common/Sphere.cpp b/testbed/common/Sphere.cpp index 15375e05..df865980 100644 --- a/testbed/common/Sphere.cpp +++ b/testbed/common/Sphere.cpp @@ -140,9 +140,12 @@ void Sphere::render(openglframework::Shader& shader, const openglframework::Matr shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color - openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; - openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); - shader.setVector4Uniform("vertexColor", color, false); + 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); + } // Bind the VAO mVAO.bind();