Remove Body class

This commit is contained in:
Daniel Chappuis 2019-07-15 17:38:20 +02:00
parent 16f564edea
commit 569964e365
29 changed files with 329 additions and 461 deletions

View File

@ -77,7 +77,6 @@ SET (REACTPHYSICS3D_HEADERS
"src/configuration.h" "src/configuration.h"
"src/decimal.h" "src/decimal.h"
"src/reactphysics3d.h" "src/reactphysics3d.h"
"src/body/Body.h"
"src/body/CollisionBody.h" "src/body/CollisionBody.h"
"src/body/RigidBody.h" "src/body/RigidBody.h"
"src/collision/ContactPointInfo.h" "src/collision/ContactPointInfo.h"
@ -175,7 +174,6 @@ SET (REACTPHYSICS3D_HEADERS
# Source files # Source files
SET (REACTPHYSICS3D_SOURCES SET (REACTPHYSICS3D_SOURCES
"src/body/Body.cpp"
"src/body/CollisionBody.cpp" "src/body/CollisionBody.cpp"
"src/body/RigidBody.cpp" "src/body/RigidBody.cpp"
"src/collision/broadphase/DynamicAABBTree.cpp" "src/collision/broadphase/DynamicAABBTree.cpp"

View File

@ -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);
}

View File

@ -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 <cassert>
#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

View File

@ -40,7 +40,11 @@ using namespace reactphysics3d;
* @param id ID of the body * @param id ID of the body
*/ */
CollisionBody::CollisionBody(CollisionWorld& world, Entity entity) 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 #ifdef IS_PROFILING_ACTIVE
mProfiler = nullptr; mProfiler = nullptr;
@ -230,7 +234,7 @@ void CollisionBody::setIsActive(bool isActive) {
// If the state does not change // If the state does not change
if (mWorld.mBodyComponents.getIsActive(mEntity) == isActive) return; if (mWorld.mBodyComponents.getIsActive(mEntity) == isActive) return;
Body::setIsActive(isActive); mWorld.mBodyComponents.setIsActive(mEntity, isActive);
// If we have to activate the body // If we have to activate the body
if (isActive) { 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 // 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 // Update the transform of the body
mWorld.mTransformComponents.setTransform(mEntity, transform); 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()); "Body " + std::to_string(mEntity.id) + ": Set transform=" + transform.to_string());
} }
// Set the variable to know whether or not the body is sleeping // Return true if the body is active
void CollisionBody::setIsSleeping(bool isSleeping) { /**
* @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); // Attach user data to this body
/**
// Notify all the components * @param userData A pointer to the user data you want to attach to the body
mWorld.notifyBodyDisabled(mEntity, isSleeping); */
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 // 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 { Vector3 CollisionBody::getLocalVector(const Vector3& worldVector) const {
return mWorld.mTransformComponents.getTransform(mEntity).getOrientation().getInverse() * worldVector; 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")));
}

View File

@ -28,7 +28,7 @@
// Libraries // Libraries
#include <cassert> #include <cassert>
#include "Body.h" #include "engine/Entity.h"
#include "collision/shapes/AABB.h" #include "collision/shapes/AABB.h"
#include "mathematics/Transform.h" #include "mathematics/Transform.h"
#include "configuration.h" #include "configuration.h"
@ -44,32 +44,30 @@ class CollisionShape;
struct RaycastInfo; struct RaycastInfo;
class PoolAllocator; class PoolAllocator;
class Profiler; class Profiler;
class Logger;
/// 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 CollisionBody // Class CollisionBody
/** /**
* This class represents a body that is able to collide with others * 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 : protected :
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
// TODO : Move this into the dynamics components /// Identifier of the entity in the ECS
/// Type of body (static, kinematic or dynamic) Entity mEntity;
BodyType mType;
/// Reference to the world the body belongs to
CollisionWorld& mWorld;
#ifdef IS_LOGGING_ACTIVE
/// Logger
Logger* mLogger;
#endif
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
@ -90,9 +88,6 @@ class CollisionBody : public Body {
/// (as if the body has moved). /// (as if the body has moved).
void askForBroadPhaseCollisionCheck() const; void askForBroadPhaseCollisionCheck() const;
/// Set the variable to know whether or not the body is sleeping
virtual void setIsSleeping(bool isSleeping) override;
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -101,7 +96,7 @@ class CollisionBody : public Body {
CollisionBody(CollisionWorld& world, Entity entity); CollisionBody(CollisionWorld& world, Entity entity);
/// Destructor /// Destructor
virtual ~CollisionBody() override; virtual ~CollisionBody();
/// Deleted copy-constructor /// Deleted copy-constructor
CollisionBody(const CollisionBody& body) = delete; CollisionBody(const CollisionBody& body) = delete;
@ -109,14 +104,20 @@ class CollisionBody : public Body {
/// Deleted assignment operator /// Deleted assignment operator
CollisionBody& operator=(const CollisionBody& body) = delete; CollisionBody& operator=(const CollisionBody& body) = delete;
/// Return the type of the body /// Return the corresponding entity of the body
BodyType getType() const; Entity getEntity() const;
/// Set the type of the body /// Return true if the body is active
void setType(BodyType type); 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 /// 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 /// Return the current position and orientation
const Transform& getTransform() const; const Transform& getTransform() const;
@ -125,8 +126,7 @@ class CollisionBody : public Body {
virtual void setTransform(const Transform& transform); virtual void setTransform(const Transform& transform);
/// Add a collision shape to the body. /// Add a collision shape to the body.
virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, const Transform& transform);
const Transform& transform);
/// Remove a collision shape from the body /// Remove a collision shape from the body
virtual void removeCollisionShape(ProxyShape *proxyShape); 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 /// Return the body local-space coordinates of a vector given in the world-space coordinates
Vector3 getLocalVector(const Vector3& worldVector) const; Vector3 getLocalVector(const Vector3& worldVector) const;
#ifdef IS_LOGGING_ACTIVE
/// Set the logger
void setLogger(Logger* logger);
#endif
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
/// Set the profiler /// Set the profiler
@ -181,14 +187,6 @@ class CollisionBody : public Body {
friend class ProxyShape; 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 /// 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 * @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 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 #ifdef IS_PROFILING_ACTIVE
// Set the profiler // Set the profiler

View File

@ -55,6 +55,11 @@ RigidBody::~RigidBody() {
assert(mJointsList == nullptr); assert(mJointsList == nullptr);
} }
// Return the type of the body
BodyType RigidBody::getType() const {
return mWorld.mDynamicsComponents.getBodyType(mEntity);
}
// Set the type of the body // Set the type of the body
/// The type of the body can either STATIC, KINEMATIC or DYNAMIC as described bellow: /// 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 /// 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) { 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 // Recompute the total mass, center of mass and inertia tensor
recomputeMassInformation(); recomputeMassInformation();
// If it is a static body // If it is a static body
if (mType == BodyType::STATIC) { if (type == BodyType::STATIC) {
// Reset the velocity to zero // Reset the velocity to zero
mWorld.mDynamicsComponents.setLinearVelocity(mEntity, Vector3::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 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 // Reset the inverse mass and inverse inertia tensor to zero
mWorld.mDynamicsComponents.setMassInverse(mEntity, decimal(0)); mWorld.mDynamicsComponents.setMassInverse(mEntity, decimal(0));
@ -114,6 +119,10 @@ void RigidBody::setType(BodyType type) {
// Reset the force and torque on the body // Reset the force and torque on the body
mWorld.mDynamicsComponents.setExternalForce(mEntity, Vector3::zero()); mWorld.mDynamicsComponents.setExternalForce(mEntity, Vector3::zero());
mWorld.mDynamicsComponents.setExternalTorque(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) // 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) { void RigidBody::applyForce(const Vector3& force, const Vector3& point) {
// If it is not a dynamic body, we do nothing // 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 // Awake the body if it was sleeping
if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { if (mWorld.mBodyComponents.getIsSleeping(mEntity)) {
@ -188,7 +197,7 @@ void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
mUserInertiaTensorLocalInverse = inertiaTensorLocal.getInverse(); mUserInertiaTensorLocalInverse = inertiaTensorLocal.getInverse();
mIsInertiaTensorSetByUser = true; mIsInertiaTensorSetByUser = true;
if (mType != BodyType::DYNAMIC) return; if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return;
// Compute the inverse local inertia tensor // Compute the inverse local inertia tensor
mWorld.mDynamicsComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse); mWorld.mDynamicsComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse);
@ -211,7 +220,7 @@ void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
void RigidBody::applyForceToCenterOfMass(const Vector3& force) { void RigidBody::applyForceToCenterOfMass(const Vector3& force) {
// If it is not a dynamic body, we do nothing // 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 // Awake the body if it was sleeping
if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { if (mWorld.mBodyComponents.getIsSleeping(mEntity)) {
@ -251,7 +260,7 @@ void RigidBody::setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTens
mUserInertiaTensorLocalInverse = inverseInertiaTensorLocal; mUserInertiaTensorLocalInverse = inverseInertiaTensorLocal;
mIsInertiaTensorSetByUser = true; mIsInertiaTensorSetByUser = true;
if (mType != BodyType::DYNAMIC) return; if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return;
// Compute the inverse local inertia tensor // Compute the inverse local inertia tensor
mWorld.mDynamicsComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse); 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) // 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; mIsCenterOfMassSetByUser = true;
@ -302,7 +311,7 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) {
*/ */
void RigidBody::setMass(decimal mass) { void RigidBody::setMass(decimal mass) {
if (mType != BodyType::DYNAMIC) return; if (mWorld.mDynamicsComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return;
mWorld.mDynamicsComponents.setInitMass(mEntity, mass); mWorld.mDynamicsComponents.setInitMass(mEntity, mass);
@ -524,7 +533,7 @@ void RigidBody::setMaterial(const Material& material) {
void RigidBody::setLinearVelocity(const Vector3& linearVelocity) { void RigidBody::setLinearVelocity(const Vector3& linearVelocity) {
// If it is a static body, we do nothing // 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 // Update the linear velocity of the current body state
mWorld.mDynamicsComponents.setLinearVelocity(mEntity, linearVelocity); 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 // TODO : Make sure this method is not called from the internal physics engine
// If it is a static body, we do nothing // 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 // Set the angular velocity
mWorld.mDynamicsComponents.setAngularVelocity(mEntity, angularVelocity); mWorld.mDynamicsComponents.setAngularVelocity(mEntity, angularVelocity);
@ -588,6 +597,9 @@ void RigidBody::setTransform(const Transform& transform) {
// Update the world inverse inertia tensor // Update the world inverse inertia tensor
updateInertiaTensorInverseWorld(); 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 // 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); const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
// If it is a STATIC or a KINEMATIC body // 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()); mWorld.mDynamicsComponents.setCenterOfMassWorld(mEntity, transform.getPosition());
return; return;
} }
assert(mType == BodyType::DYNAMIC); assert(mWorld.mDynamicsComponents.getBodyType(mEntity) == BodyType::DYNAMIC);
// Compute the total mass of the body // Compute the total mass of the body
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
@ -723,7 +736,7 @@ bool RigidBody::isGravityEnabled() const {
void RigidBody::applyTorque(const Vector3& torque) { void RigidBody::applyTorque(const Vector3& torque) {
// If it is not a dynamic body, we do nothing // 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 // Awake the body if it was sleeping
if (mWorld.mBodyComponents.getIsSleeping(mEntity)) { 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 // Set the variable to know whether or not the body is sleeping
void RigidBody::setIsSleeping(bool isSleeping) { 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) { if (isSleeping) {
@ -747,6 +782,56 @@ void RigidBody::setIsSleeping(bool isSleeping) {
mWorld.mDynamicsComponents.setExternalForce(mEntity, Vector3::zero()); mWorld.mDynamicsComponents.setExternalForce(mEntity, Vector3::zero());
mWorld.mDynamicsComponents.setExternalTorque(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 #ifdef IS_PROFILING_ACTIVE

View File

@ -40,6 +40,7 @@ struct JointListElement;
class Joint; class Joint;
class DynamicsWorld; class DynamicsWorld;
class MemoryManager; class MemoryManager;
enum class BodyType;
// Class RigidBody // Class RigidBody
/** /**
@ -82,7 +83,7 @@ class RigidBody : public CollisionBody {
void updateInertiaTensorInverseWorld(); void updateInertiaTensorInverseWorld();
/// Set the variable to know whether or not the body is sleeping /// Set the variable to know whether or not the body is sleeping
virtual void setIsSleeping(bool isSleeping) override; void setIsSleeping(bool isSleeping);
public : public :
@ -100,9 +101,6 @@ class RigidBody : public CollisionBody {
/// Deleted assignment operator /// Deleted assignment operator
RigidBody& operator=(const RigidBody& body) = delete; 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 /// Set the current position and orientation
virtual void setTransform(const Transform& transform) override; virtual void setTransform(const Transform& transform) override;
@ -139,6 +137,12 @@ class RigidBody : public CollisionBody {
/// Set the mass of the rigid body /// Set the mass of the rigid body
void setMass(decimal mass); 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 /// Return true if the gravity needs to be applied to this rigid body
bool isGravityEnabled() const; bool isGravityEnabled() const;
@ -178,6 +182,18 @@ class RigidBody : public CollisionBody {
/// Apply an external torque to the body. /// Apply an external torque to the body.
void applyTorque(const Vector3& torque); 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. /// Add a collision shape to the body.
virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape,
const Transform& transform, const Transform& transform,

View File

@ -27,7 +27,6 @@
#include "CollisionDetection.h" #include "CollisionDetection.h"
#include "engine/CollisionWorld.h" #include "engine/CollisionWorld.h"
#include "collision/OverlapCallback.h" #include "collision/OverlapCallback.h"
#include "body/Body.h"
#include "collision/shapes/BoxShape.h" #include "collision/shapes/BoxShape.h"
#include "collision/shapes/ConcaveShape.h" #include "collision/shapes/ConcaveShape.h"
#include "collision/ContactManifoldInfo.h" #include "collision/ContactManifoldInfo.h"
@ -238,9 +237,14 @@ void CollisionDetection::computeMiddlePhase(OverlappingPairMap& overlappingPairs
const Entity body1Entity = body1->getEntity(); const Entity body1Entity = body1->getEntity();
const Entity body2Entity = body2->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 // 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 isBody1Active = !mWorld->mBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
bool isBody2Active = !mWorld->mBodyComponents.getIsEntityDisabled(body2Entity) && body2->getType() != BodyType::STATIC; bool isBody2Active = !mWorld->mBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
if (!isBody1Active && !isBody2Active) continue; if (!isBody1Active && !isBody2Active) continue;
// Check if the bodies are in the set of bodies that cannot collide between each other // Check if the bodies are in the set of bodies that cannot collide between each other

View File

@ -115,10 +115,12 @@ void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
// TODO : Make sure this method is never called by the internal physics engine // TODO : Make sure this method is never called by the internal physics engine
//mLocalToBodyTransform = transform;
mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(mEntity, transform); mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(mEntity, transform);
mBody->setIsSleeping(false); RigidBody* rigidBody = static_cast<RigidBody*>(mBody);
if (rigidBody != nullptr) {
mBody->mWorld.mBodyComponents.setIsSleeping(mBody->getEntity(), false);
}
mBody->mWorld.mCollisionDetection.updateProxyShape(mEntity); mBody->mWorld.mCollisionDetection.updateProxyShape(mEntity);

View File

@ -35,7 +35,6 @@ namespace reactphysics3d {
// Declarations // Declarations
struct CapsuleVsCapsuleNarrowPhaseInfoBatch; struct CapsuleVsCapsuleNarrowPhaseInfoBatch;
class Body;
class ContactPoint; class ContactPoint;
// Class CapsuleVsCapsuleAlgorithm // Class CapsuleVsCapsuleAlgorithm

View File

@ -34,7 +34,6 @@ namespace reactphysics3d {
// Declarations // Declarations
class ContactPoint; class ContactPoint;
class Body;
// Class CapsuleVsConvexPolyhedronAlgorithm // Class CapsuleVsConvexPolyhedronAlgorithm
/** /**

View File

@ -33,7 +33,6 @@
namespace reactphysics3d { namespace reactphysics3d {
// Declarations // Declarations
class Body;
class ContactPoint; class ContactPoint;
// Class ConvexPolyhedronVsConvexPolyhedronAlgorithm // Class ConvexPolyhedronVsConvexPolyhedronAlgorithm

View File

@ -33,7 +33,6 @@
namespace reactphysics3d { namespace reactphysics3d {
class CollisionDetection; class CollisionDetection;
class Body;
class ContactManifoldInfo; class ContactManifoldInfo;
class PoolAllocator; class PoolAllocator;
class OverlappingPair; class OverlappingPair;

View File

@ -34,7 +34,6 @@
namespace reactphysics3d { namespace reactphysics3d {
// Declarations // Declarations
class Body;
class ContactPoint; class ContactPoint;
struct SphereVsCapsuleNarrowPhaseInfoBatch; struct SphereVsCapsuleNarrowPhaseInfoBatch;

View File

@ -34,7 +34,6 @@ namespace reactphysics3d {
// Declarations // Declarations
class ContactPoint; class ContactPoint;
class Body;
// Class SphereVsConvexPolyhedronAlgorithm // Class SphereVsConvexPolyhedronAlgorithm
/** /**

View File

@ -35,7 +35,6 @@ namespace reactphysics3d {
// Declarations // Declarations
class ContactPoint; class ContactPoint;
struct SphereVsSphereNarrowPhaseInfoBatch; struct SphereVsSphereNarrowPhaseInfoBatch;
class Body;
// Class SphereVsSphereAlgorithm // Class SphereVsSphereAlgorithm
/** /**

View File

@ -34,7 +34,7 @@ using namespace reactphysics3d;
// Constructor // Constructor
BodyComponents::BodyComponents(MemoryAllocator& allocator) BodyComponents::BodyComponents(MemoryAllocator& allocator)
:Components(allocator, sizeof(Entity) + sizeof(Body*) + sizeof(List<Entity>) + :Components(allocator, sizeof(Entity) + sizeof(CollisionBody*) + sizeof(List<Entity>) +
sizeof(bool) + sizeof(bool) + sizeof(bool) + sizeof(decimal) + sizeof(bool) + sizeof(bool) + sizeof(bool) + sizeof(decimal) +
sizeof(void*)) { sizeof(void*)) {
@ -56,7 +56,7 @@ void BodyComponents::allocate(uint32 nbComponentsToAllocate) {
// New pointers to components data // New pointers to components data
Entity* newBodiesEntities = static_cast<Entity*>(newBuffer); Entity* newBodiesEntities = static_cast<Entity*>(newBuffer);
Body** newBodies = reinterpret_cast<Body**>(newBodiesEntities + nbComponentsToAllocate); CollisionBody** newBodies = reinterpret_cast<CollisionBody**>(newBodiesEntities + nbComponentsToAllocate);
List<Entity>* newProxyShapes = reinterpret_cast<List<Entity>*>(newBodies + nbComponentsToAllocate); List<Entity>* newProxyShapes = reinterpret_cast<List<Entity>*>(newBodies + nbComponentsToAllocate);
bool* newIsAllowedToSleep = reinterpret_cast<bool*>(newProxyShapes + nbComponentsToAllocate); bool* newIsAllowedToSleep = reinterpret_cast<bool*>(newProxyShapes + nbComponentsToAllocate);
bool* newIsActive = reinterpret_cast<bool*>(newIsAllowedToSleep + nbComponentsToAllocate); bool* newIsActive = reinterpret_cast<bool*>(newIsAllowedToSleep + nbComponentsToAllocate);
@ -69,7 +69,7 @@ void BodyComponents::allocate(uint32 nbComponentsToAllocate) {
// Copy component data from the previous buffer to the new one // Copy component data from the previous buffer to the new one
memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity)); memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity));
memcpy(newBodies, mBodies, mNbComponents * sizeof(Body*)); memcpy(newBodies, mBodies, mNbComponents * sizeof(CollisionBody*));
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(List<Entity>)); memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(List<Entity>));
memcpy(newIsAllowedToSleep, mIsAllowedToSleep, mNbComponents * sizeof(bool)); memcpy(newIsAllowedToSleep, mIsAllowedToSleep, mNbComponents * sizeof(bool));
memcpy(newIsActive, mIsActive, mNbComponents * sizeof(bool)); memcpy(newIsActive, mIsActive, mNbComponents * sizeof(bool));
@ -150,7 +150,7 @@ void BodyComponents::swapComponents(uint32 index1, uint32 index2) {
// Copy component 1 data // Copy component 1 data
Entity entity1(mBodiesEntities[index1]); Entity entity1(mBodiesEntities[index1]);
Body* body1 = mBodies[index1]; CollisionBody* body1 = mBodies[index1];
List<Entity> proxyShapes1(mProxyShapes[index1]); List<Entity> proxyShapes1(mProxyShapes[index1]);
bool isAllowedToSleep1 = mIsAllowedToSleep[index1]; bool isAllowedToSleep1 = mIsAllowedToSleep[index1];
bool isActive1 = mIsActive[index1]; bool isActive1 = mIsActive[index1];

View File

@ -38,7 +38,7 @@ namespace reactphysics3d {
// Class declarations // Class declarations
class MemoryAllocator; class MemoryAllocator;
class EntityManager; class EntityManager;
class Body; class CollisionBody;
// Class BodyComponents // Class BodyComponents
/** /**
@ -55,7 +55,7 @@ class BodyComponents : public Components {
Entity* mBodiesEntities; Entity* mBodiesEntities;
/// Array of pointers to the corresponding bodies /// Array of pointers to the corresponding bodies
Body** mBodies; CollisionBody** mBodies;
/// Array with the list of proxy-shapes of each body /// Array with the list of proxy-shapes of each body
List<Entity>* mProxyShapes; List<Entity>* mProxyShapes;
@ -69,7 +69,7 @@ class BodyComponents : public Components {
/// Array of boolean values to know if the body is sleeping /// Array of boolean values to know if the body is sleeping
bool* mIsSleeping; 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; decimal* mSleepTimes;
/// Array of pointers that can be used to attach user data to the body /// 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 /// Structure for the data of a body component
struct BodyComponent { struct BodyComponent {
Body* body; CollisionBody* body;
/// Constructor /// 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); void removeProxyShapeFromBody(Entity bodyEntity, Entity proxyShapeEntity);
/// Return a pointer to a body /// Return a pointer to a body
Body* getBody(Entity bodyEntity); CollisionBody* getBody(Entity bodyEntity);
/// Return the list of proxy-shapes of a body /// Return the list of proxy-shapes of a body
const List<Entity>& getProxyShapes(Entity bodyEntity) const; const List<Entity>& getProxyShapes(Entity bodyEntity) const;
@ -173,7 +173,7 @@ inline void BodyComponents::removeProxyShapeFromBody(Entity bodyEntity, Entity p
} }
// Return a pointer to a body // Return a pointer to a body
inline Body* BodyComponents::getBody(Entity bodyEntity) { inline CollisionBody *BodyComponents::getBody(Entity bodyEntity) {
assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); assert(mMapEntityToComponentIndex.containsKey(bodyEntity));

View File

@ -39,7 +39,7 @@ DynamicsComponents::DynamicsComponents(MemoryAllocator& allocator)
sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(decimal) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(decimal) +
sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(Matrix3x3) + sizeof(Matrix3x3) + sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(Matrix3x3) + sizeof(Matrix3x3) +
sizeof(Vector3) + sizeof(Quaternion) + sizeof(Vector3) + sizeof(Vector3) + sizeof(bool) + sizeof(Vector3) + sizeof(Quaternion) + sizeof(Vector3) + sizeof(Vector3) + sizeof(bool) +
sizeof(bool)) { sizeof(bool) + sizeof(BodyType)) {
// Allocate memory for the components data // Allocate memory for the components data
allocate(INIT_NB_ALLOCATED_COMPONENTS); allocate(INIT_NB_ALLOCATED_COMPONENTS);
@ -79,6 +79,7 @@ void DynamicsComponents::allocate(uint32 nbComponentsToAllocate) {
Vector3* newCentersOfMassWorld = reinterpret_cast<Vector3*>(newCentersOfMassLocal + nbComponentsToAllocate); Vector3* newCentersOfMassWorld = reinterpret_cast<Vector3*>(newCentersOfMassLocal + nbComponentsToAllocate);
bool* newIsGravityEnabled = reinterpret_cast<bool*>(newCentersOfMassWorld + nbComponentsToAllocate); bool* newIsGravityEnabled = reinterpret_cast<bool*>(newCentersOfMassWorld + nbComponentsToAllocate);
bool* newIsAlreadyInIsland = reinterpret_cast<bool*>(newIsGravityEnabled + nbComponentsToAllocate); bool* newIsAlreadyInIsland = reinterpret_cast<bool*>(newIsGravityEnabled + nbComponentsToAllocate);
BodyType* newBodyTypes = reinterpret_cast<BodyType*>(newIsAlreadyInIsland + nbComponentsToAllocate);
// If there was already components before // If there was already components before
if (mNbComponents > 0) { if (mNbComponents > 0) {
@ -105,6 +106,7 @@ void DynamicsComponents::allocate(uint32 nbComponentsToAllocate) {
memcpy(newCentersOfMassWorld, mCentersOfMassWorld, mNbComponents * sizeof(Vector3)); memcpy(newCentersOfMassWorld, mCentersOfMassWorld, mNbComponents * sizeof(Vector3));
memcpy(newIsGravityEnabled, mIsGravityEnabled, mNbComponents * sizeof(bool)); memcpy(newIsGravityEnabled, mIsGravityEnabled, mNbComponents * sizeof(bool));
memcpy(newIsAlreadyInIsland, mIsAlreadyInIsland, mNbComponents * sizeof(bool)); memcpy(newIsAlreadyInIsland, mIsAlreadyInIsland, mNbComponents * sizeof(bool));
memcpy(newBodyTypes, mBodyTypes, mNbComponents * sizeof(BodyType));
// Deallocate previous memory // Deallocate previous memory
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize); mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize);
@ -132,6 +134,8 @@ void DynamicsComponents::allocate(uint32 nbComponentsToAllocate) {
mCentersOfMassWorld = newCentersOfMassWorld; mCentersOfMassWorld = newCentersOfMassWorld;
mIsGravityEnabled = newIsGravityEnabled; mIsGravityEnabled = newIsGravityEnabled;
mIsAlreadyInIsland = newIsAlreadyInIsland; mIsAlreadyInIsland = newIsAlreadyInIsland;
mBodyTypes = newBodyTypes;
mNbAllocatedComponents = nbComponentsToAllocate; mNbAllocatedComponents = nbComponentsToAllocate;
} }
@ -163,6 +167,7 @@ void DynamicsComponents::addComponent(Entity bodyEntity, bool isSleeping, const
new (mCentersOfMassWorld + index) Vector3(component.worldPosition); new (mCentersOfMassWorld + index) Vector3(component.worldPosition);
mIsGravityEnabled[index] = true; mIsGravityEnabled[index] = true;
mIsAlreadyInIsland[index] = false; mIsAlreadyInIsland[index] = false;
mBodyTypes[index] = component.bodyType;
// Map the entity with the new component lookup index // Map the entity with the new component lookup index
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(bodyEntity, index)); mMapEntityToComponentIndex.add(Pair<Entity, uint32>(bodyEntity, index));
@ -201,6 +206,7 @@ void DynamicsComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex)
new (mCentersOfMassWorld + destIndex) Vector3(mCentersOfMassWorld[srcIndex]); new (mCentersOfMassWorld + destIndex) Vector3(mCentersOfMassWorld[srcIndex]);
mIsGravityEnabled[destIndex] = mIsGravityEnabled[srcIndex]; mIsGravityEnabled[destIndex] = mIsGravityEnabled[srcIndex];
mIsAlreadyInIsland[destIndex] = mIsAlreadyInIsland[srcIndex]; mIsAlreadyInIsland[destIndex] = mIsAlreadyInIsland[srcIndex];
mBodyTypes[destIndex] = mBodyTypes[srcIndex];
// Destroy the source component // Destroy the source component
destroyComponent(srcIndex); destroyComponent(srcIndex);
@ -241,6 +247,7 @@ void DynamicsComponents::swapComponents(uint32 index1, uint32 index2) {
Vector3 centerOfMassWorld1 = mCentersOfMassWorld[index1]; Vector3 centerOfMassWorld1 = mCentersOfMassWorld[index1];
bool isGravityEnabled1 = mIsGravityEnabled[index1]; bool isGravityEnabled1 = mIsGravityEnabled[index1];
bool isAlreadyInIsland1 = mIsAlreadyInIsland[index1]; bool isAlreadyInIsland1 = mIsAlreadyInIsland[index1];
BodyType bodyType1 = mBodyTypes[index1];
// Destroy component 1 // Destroy component 1
destroyComponent(index1); destroyComponent(index1);
@ -269,6 +276,7 @@ void DynamicsComponents::swapComponents(uint32 index1, uint32 index2) {
mCentersOfMassWorld[index2] = centerOfMassWorld1; mCentersOfMassWorld[index2] = centerOfMassWorld1;
mIsGravityEnabled[index2] = isGravityEnabled1; mIsGravityEnabled[index2] = isGravityEnabled1;
mIsAlreadyInIsland[index2] = isAlreadyInIsland1; mIsAlreadyInIsland[index2] = isAlreadyInIsland1;
mBodyTypes[index2] = bodyType1;
// Update the entity to component index mapping // Update the entity to component index mapping
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2)); mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2));

View File

@ -40,10 +40,22 @@ namespace reactphysics3d {
class MemoryAllocator; class MemoryAllocator;
class EntityManager; 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 // Class DynamicsComponents
/** /**
* This class represent the component of the ECS that contains the variables concerning dynamics * 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 { 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 /// Array with the boolean value to know if the body has already been added into an island
bool* mIsAlreadyInIsland; bool* mIsAlreadyInIsland;
/// Array with the type of bodies (static, kinematic or dynamic)
BodyType* mBodyTypes;
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Allocate memory for a given number of components /// Allocate memory for a given number of components
@ -135,9 +150,11 @@ class DynamicsComponents : public Components {
const Vector3& worldPosition; const Vector3& worldPosition;
BodyType bodyType;
/// Constructor /// Constructor
DynamicsComponent(const Vector3& worldPosition) DynamicsComponent(const Vector3& worldPosition, BodyType bodyType)
: worldPosition(worldPosition) { : worldPosition(worldPosition), bodyType(bodyType) {
} }
}; };
@ -268,10 +285,16 @@ class DynamicsComponents : public Components {
void setCenterOfMassWorld(Entity bodyEntity, const Vector3& centerOfMassWorld); void setCenterOfMassWorld(Entity bodyEntity, const Vector3& centerOfMassWorld);
/// Set the value to know if the gravity is enabled for this entity /// 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 /// 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 -------------------- // // -------------------- Friendship -------------------- //
@ -282,7 +305,6 @@ class DynamicsComponents : public Components {
friend class FixedJoint; friend class FixedJoint;
friend class HingeJoint; friend class HingeJoint;
friend class SliderJoint; friend class SliderJoint;
}; };
// Return the linear velocity of an entity // 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 // 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)); 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 /// 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)); assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
mIsAlreadyInIsland[mMapEntityToComponentIndex[bodyEntity]] = isAlreadyInIsland; 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 #endif

View File

@ -196,7 +196,6 @@ class CollisionWorld {
// -------------------- Friendship -------------------- // // -------------------- Friendship -------------------- //
friend class CollisionDetection; friend class CollisionDetection;
friend class Body;
friend class CollisionBody; friend class CollisionBody;
friend class RigidBody; friend class RigidBody;
friend class ProxyShape; friend class ProxyShape;

View File

@ -376,7 +376,8 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
Entity entity = mEntityManager.createEntity(); Entity entity = mEntityManager.createEntity();
mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform)); 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 // Create the rigid body
RigidBody* rigidBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, RigidBody* rigidBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
@ -655,9 +656,7 @@ void DynamicsWorld::createIslands() {
if (mDynamicsComponents.mIsAlreadyInIsland[b]) continue; if (mDynamicsComponents.mIsAlreadyInIsland[b]) continue;
// If the body is static, we go to the next body // 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) if (mDynamicsComponents.mBodyTypes[b] == BodyType::STATIC) continue;
CollisionBody* body = static_cast<CollisionBody*>(mBodyComponents.getBody(mDynamicsComponents.mBodies[b]));
if (body->getType() == BodyType::STATIC) continue;
// Reset the stack of bodies to visit // Reset the stack of bodies to visit
bodyEntityIndicesToVisit.clear(); bodyEntityIndicesToVisit.clear();
@ -678,14 +677,14 @@ void DynamicsWorld::createIslands() {
// Add the body into the island // Add the body into the island
mIslands.bodyEntities[islandIndex].add(bodyToVisitEntity); 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) // TODO : Do not use pointer to rigid body here (maybe move getType() into a component)
RigidBody* rigidBodyToVisit = static_cast<RigidBody*>(mBodyComponents.getBody(bodyToVisitEntity)); RigidBody* rigidBodyToVisit = static_cast<RigidBody*>(mBodyComponents.getBody(bodyToVisitEntity));
// Awake the body if it is sleeping // Awake the body if it is sleeping
rigidBodyToVisit->setIsSleeping(false); 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 (rigidBodyToVisit->getType() == BodyType::STATIC) continue;
// If the body is involved in contacts with other bodies // 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 // can also be included in the other islands
for (uint j=0; j < mDynamicsComponents.getNbEnabledComponents(); j++) { for (uint j=0; j < mDynamicsComponents.getNbEnabledComponents(); j++) {
// If the body is static, we go to the next body if (mDynamicsComponents.mBodyTypes[j] == BodyType::STATIC) {
// TODO : Do not use pointer to rigid body here (maybe move getType() into a component)
CollisionBody* body = static_cast<CollisionBody*>(mBodyComponents.getBody(mDynamicsComponents.mBodies[j]));
if (body->getType() == BodyType::STATIC) {
mDynamicsComponents.mIsAlreadyInIsland[j] = false; mDynamicsComponents.mIsAlreadyInIsland[j] = false;
} }
} }
@ -805,16 +801,16 @@ void DynamicsWorld::updateSleepingBodies() {
const Entity bodyEntity = mIslands.bodyEntities[i][b]; const Entity bodyEntity = mIslands.bodyEntities[i][b];
// TODO : We should not have to do this cast here to get type of body // TODO : We should use a RigidBody* type here
CollisionBody* body = static_cast<CollisionBody*>(mBodyComponents.getBody(bodyEntity)); CollisionBody* body = mBodyComponents.getBody(bodyEntity);
// Skip static bodies // 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 the body is velocity is large enough to stay awake
if (mDynamicsComponents.getLinearVelocity(bodyEntity).lengthSquare() > sleepLinearVelocitySquare || if (mDynamicsComponents.getLinearVelocity(bodyEntity).lengthSquare() > sleepLinearVelocitySquare ||
mDynamicsComponents.getAngularVelocity(bodyEntity).lengthSquare() > sleepAngularVelocitySquare || mDynamicsComponents.getAngularVelocity(bodyEntity).lengthSquare() > sleepAngularVelocitySquare ||
!body->isAllowedToSleep()) { !mBodyComponents.getIsAllowedToSleep(body->getEntity())) {
// Reset the sleep time of the body // Reset the sleep time of the body
mBodyComponents.setSleepTime(body->getEntity(), decimal(0.0)); mBodyComponents.setSleepTime(body->getEntity(), decimal(0.0));
@ -840,8 +836,9 @@ void DynamicsWorld::updateSleepingBodies() {
// Put all the bodies of the island to sleep // Put all the bodies of the island to sleep
for (uint b=0; b < mIslands.bodyEntities[i].size(); b++) { 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]; const Entity bodyEntity = mIslands.bodyEntities[i][b];
CollisionBody* body = static_cast<CollisionBody*>(mBodyComponents.getBody(bodyEntity)); RigidBody* body = static_cast<RigidBody*>(mBodyComponents.getBody(bodyEntity));
body->setIsSleeping(true); body->setIsSleeping(true);
} }
} }

View File

@ -160,9 +160,12 @@ void Box::render(openglframework::Shader& shader, const openglframework::Matrix4
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; rp3d::RigidBody* rigidBody = static_cast<rp3d::RigidBody*>(mBody);
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); if (rigidBody != nullptr) {
shader.setVector4Uniform("vertexColor", color, false); 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 // Bind the VAO
mVAO.bind(); mVAO.bind();

View File

@ -141,9 +141,12 @@ void Capsule::render(openglframework::Shader& shader,
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; rp3d::RigidBody* rigidBody = static_cast<rp3d::RigidBody*>(mBody);
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); if (rigidBody != nullptr) {
shader.setVector4Uniform("vertexColor", color, false); 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 // Bind the VAO
mVAO.bind(); mVAO.bind();

View File

@ -150,9 +150,12 @@ void ConcaveMesh::render(openglframework::Shader& shader,
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; rp3d::RigidBody* rigidBody = static_cast<rp3d::RigidBody*>(mBody);
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); if (rigidBody != nullptr) {
shader.setVector4Uniform("vertexColor", color, false); 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 // Bind the VAO
mVAO.bind(); mVAO.bind();

View File

@ -160,9 +160,12 @@ void ConvexMesh::render(openglframework::Shader& shader,
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; rp3d::RigidBody* rigidBody = static_cast<rp3d::RigidBody*>(mBody);
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); if (rigidBody != nullptr) {
shader.setVector4Uniform("vertexColor", color, false); 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 // Bind the VAO
mVAO.bind(); mVAO.bind();

View File

@ -178,9 +178,12 @@ void Dumbbell::render(openglframework::Shader& shader,
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; rp3d::RigidBody* rigidBody = static_cast<rp3d::RigidBody*>(mBody);
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); if (rigidBody != nullptr) {
shader.setVector4Uniform("vertexColor", color, false); 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 // Bind the VAO
mVAO.bind(); mVAO.bind();

View File

@ -132,9 +132,12 @@ void HeightField::render(openglframework::Shader& shader,
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; rp3d::RigidBody* rigidBody = static_cast<rp3d::RigidBody*>(mBody);
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); if (rigidBody != nullptr) {
shader.setVector4Uniform("vertexColor", color, false); 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 // Bind the VAO
mVAO.bind(); mVAO.bind();

View File

@ -140,9 +140,12 @@ void Sphere::render(openglframework::Shader& shader, const openglframework::Matr
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor; rp3d::RigidBody* rigidBody = static_cast<rp3d::RigidBody*>(mBody);
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); if (rigidBody != nullptr) {
shader.setVector4Uniform("vertexColor", color, false); 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 // Bind the VAO
mVAO.bind(); mVAO.bind();