297 lines
13 KiB
C++
297 lines
13 KiB
C++
/** @file
|
|
* @author Daniel Chappuis
|
|
* @copyright 2010-2016 Daniel Chappuis
|
|
* @license BSD 3 clauses (see license file)
|
|
*/
|
|
#pragma once
|
|
|
|
#include <cassert>
|
|
#include <ephysics/body/CollisionBody.hpp>
|
|
#include <ephysics/engine/Material.hpp>
|
|
#include <ephysics/mathematics/mathematics.hpp>
|
|
#include <ephysics/memory/MemoryAllocator.hpp>
|
|
|
|
namespace ephysics {
|
|
|
|
// Class declarations
|
|
struct JointListElement;
|
|
class Joint;
|
|
class DynamicsWorld;
|
|
|
|
/**
|
|
* @brief This class represents a rigid body of the physics
|
|
* engine. A rigid body is a non-deformable body that
|
|
* has a constant mass. This class inherits from the
|
|
* CollisionBody class.
|
|
*/
|
|
class RigidBody : public CollisionBody {
|
|
protected :
|
|
float m_initMass; //!< Intial mass of the body
|
|
vec3 m_centerOfMassLocal; //!< Center of mass of the body in local-space coordinates. The center of mass can therefore be different from the body origin
|
|
vec3 m_centerOfMassWorld; //!< Center of mass of the body in world-space coordinates
|
|
vec3 m_linearVelocity; //!< Linear velocity of the body
|
|
vec3 m_angularVelocity; //!< Angular velocity of the body
|
|
vec3 m_externalForce; //!< Current external force on the body
|
|
vec3 m_externalTorque; //!< Current external torque on the body
|
|
etk::Matrix3x3 m_inertiaTensorLocal; //!< Local inertia tensor of the body (in local-space) with respect to the center of mass of the body
|
|
etk::Matrix3x3 m_inertiaTensorLocalInverse; //!< Inverse of the inertia tensor of the body
|
|
float m_massInverse; //!< Inverse of the mass of the body
|
|
bool m_isGravityEnabled; //!< True if the gravity needs to be applied to this rigid body
|
|
Material m_material; //!< Material properties of the rigid body
|
|
float m_linearDamping; //!< Linear velocity damping factor
|
|
float m_angularDamping; //!< Angular velocity damping factor
|
|
JointListElement* m_jointsList; //!< First element of the linked list of joints involving this body
|
|
/// Private copy-constructor
|
|
RigidBody(const RigidBody& body);
|
|
/// Private assignment operator
|
|
RigidBody& operator=(const RigidBody& body);
|
|
/**
|
|
* @brief Remove a joint from the joints list
|
|
*/
|
|
void removeJointFrom_jointsList(MemoryAllocator& _memoryAllocator, const Joint* _joint);
|
|
/**
|
|
* @brief Update the transform of the body after a change of the center of mass
|
|
*/
|
|
void updateTransformWithCenterOfMass() {
|
|
// Translate the body according to the translation of the center of mass position
|
|
m_transform.setPosition(m_centerOfMassWorld - m_transform.getOrientation() * m_centerOfMassLocal);
|
|
}
|
|
void updateBroadPhaseState() const override;
|
|
public :
|
|
/**
|
|
* @brief Constructor
|
|
* @param transform The transformation of the body
|
|
* @param world The world where the body has been added
|
|
* @param id The ID of the body
|
|
*/
|
|
RigidBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id);
|
|
/**
|
|
* @brief Virtual Destructor
|
|
*/
|
|
virtual ~RigidBody();
|
|
void setType(BodyType _type) override;
|
|
/**
|
|
* @brief Set the current position and orientation
|
|
* @param[in] _transform The transformation of the body that transforms the local-space of the body int32_to world-space
|
|
*/
|
|
virtual void setTransform(const etk::Transform3D& _transform);
|
|
/**
|
|
* @brief Get the mass of the body
|
|
* @return The mass (in kilograms) of the body
|
|
*/
|
|
float getMass() const {
|
|
return m_initMass;
|
|
}
|
|
/**
|
|
* @brief Get the linear velocity
|
|
* @return The linear velocity vector of the body
|
|
*/
|
|
vec3 getLinearVelocity() const {
|
|
return m_linearVelocity;
|
|
}
|
|
/**
|
|
* @brief Set the linear velocity of the rigid body.
|
|
* @param[in] _linearVelocity Linear velocity vector of the body
|
|
*/
|
|
void setLinearVelocity(const vec3& _linearVelocity);
|
|
/**
|
|
* @brief Get the angular velocity of the body
|
|
* @return The angular velocity vector of the body
|
|
*/
|
|
vec3 getAngularVelocity() const {
|
|
return m_angularVelocity;
|
|
}
|
|
/**
|
|
* @brief Set the angular velocity.
|
|
* @param[in] _angularVelocity The angular velocity vector of the body
|
|
*/
|
|
void setAngularVelocity(const vec3& _angularVelocity);
|
|
/**
|
|
* @brief Set the variable to know whether or not the body is sleeping
|
|
* @param[in] _isSleeping New sleeping state of the body
|
|
*/
|
|
virtual void setIsSleeping(bool _isSleeping);
|
|
/**
|
|
* @brief Get the local inertia tensor of the body (in local-space coordinates)
|
|
* @return The 3x3 inertia tensor matrix of the body
|
|
*/
|
|
const etk::Matrix3x3& getInertiaTensorLocal() const {
|
|
return m_inertiaTensorLocal;
|
|
}
|
|
/**
|
|
* @brief Set the local inertia tensor of the body (in local-space coordinates)
|
|
* @param[in] _inertiaTensorLocal The 3x3 inertia tensor matrix of the body in local-space coordinates
|
|
*/
|
|
void setInertiaTensorLocal(const etk::Matrix3x3& inertiaTensorLocal);
|
|
/**
|
|
* @brief Set the local center of mass of the body (in local-space coordinates)
|
|
* @param[in] _centerOfMassLocal The center of mass of the body in local-space coordinates
|
|
*/
|
|
void setCenterOfMassLocal(const vec3& centerOfMassLocal);
|
|
/**
|
|
* @brief Set the mass of the rigid body
|
|
* @param[in] _mass The mass (in kilograms) of the body
|
|
*/
|
|
void setMass(float _mass);
|
|
/**
|
|
* @brief Get the inertia tensor in world coordinates.
|
|
* The inertia tensor I_w in world coordinates is computed
|
|
* with the local inertia tensor I_b in body coordinates
|
|
* by I_w = R * I_b * R^T
|
|
* where R is the rotation matrix (and R^T its transpose) of
|
|
* the current orientation quaternion of the body
|
|
* @return The 3x3 inertia tensor matrix of the body in world-space coordinates
|
|
*/
|
|
etk::Matrix3x3 getInertiaTensorWorld() const {
|
|
// Compute and return the inertia tensor in world coordinates
|
|
return m_transform.getOrientation().getMatrix() * m_inertiaTensorLocal *
|
|
m_transform.getOrientation().getMatrix().getTranspose();
|
|
}
|
|
/**
|
|
* @brief Get the inverse of the inertia tensor in world coordinates.
|
|
* The inertia tensor I_w in world coordinates is computed with the
|
|
* local inverse inertia tensor I_b^-1 in body coordinates
|
|
* by I_w = R * I_b^-1 * R^T
|
|
* where R is the rotation matrix (and R^T its transpose) of the
|
|
* current orientation quaternion of the body
|
|
* @return The 3x3 inverse inertia tensor matrix of the body in world-space coordinates
|
|
*/
|
|
etk::Matrix3x3 getInertiaTensorInverseWorld() const {
|
|
// TODO : DO NOT RECOMPUTE THE MATRIX MULTIPLICATION EVERY TIME. WE NEED TO STORE THE
|
|
// INVERSE WORLD TENSOR IN THE CLASS AND UPLDATE IT WHEN THE ORIENTATION OF THE BODY CHANGES
|
|
// Compute and return the inertia tensor in world coordinates
|
|
return m_transform.getOrientation().getMatrix() * m_inertiaTensorLocalInverse *
|
|
m_transform.getOrientation().getMatrix().getTranspose();
|
|
}
|
|
/**
|
|
* @brief get the need of gravity appling to this rigid body
|
|
* @return True if the gravity is applied to the body
|
|
*/
|
|
bool isGravityEnabled() const {
|
|
return m_isGravityEnabled;
|
|
}
|
|
/**
|
|
* @brief Set the variable to know if the gravity is applied to this rigid body
|
|
* @param[in] _isEnabled True if you want the gravity to be applied to this body
|
|
*/
|
|
void enableGravity(bool _isEnabled) {
|
|
m_isGravityEnabled = _isEnabled;
|
|
}
|
|
/**
|
|
* @brief get a reference to the material properties of the rigid body
|
|
* @return A reference to the material of the body
|
|
*/
|
|
Material& getMaterial() {
|
|
return m_material;
|
|
}
|
|
/**
|
|
* @brief Set a new material for this rigid body
|
|
* @param[in] _material The material you want to set to the body
|
|
*/
|
|
void setMaterial(const Material& _material) {
|
|
m_material = _material;
|
|
}
|
|
/**
|
|
* @brief Get the linear velocity damping factor
|
|
* @return The linear damping factor of this body
|
|
*/
|
|
float getLinearDamping() const {
|
|
return m_linearDamping;
|
|
}
|
|
/**
|
|
* @brief Set the linear damping factor. This is the ratio of the linear velocity that the body will lose every at seconds of simulation.
|
|
* @param[in] _linearDamping The linear damping factor of this body
|
|
*/
|
|
void setLinearDamping(float _linearDamping) {
|
|
assert(_linearDamping >= 0.0f);
|
|
m_linearDamping = _linearDamping;
|
|
}
|
|
/**
|
|
* @brief Get the angular velocity damping factor
|
|
* @return The angular damping factor of this body
|
|
*/
|
|
float getAngularDamping() const {
|
|
return m_angularDamping;
|
|
}
|
|
/**
|
|
* @brief Set the angular damping factor. This is the ratio of the angular velocity that the body will lose at every seconds of simulation.
|
|
* @param[in] _angularDamping The angular damping factor of this body
|
|
*/
|
|
void setAngularDamping(float _angularDamping) {
|
|
assert(_angularDamping >= 0.0f);
|
|
m_angularDamping = _angularDamping;
|
|
}
|
|
/**
|
|
* @brief Get the first element of the linked list of joints involving this body
|
|
* @return The first element of the linked-list of all the joints involving this body
|
|
*/
|
|
const JointListElement* getJointsList() const {
|
|
return m_jointsList;
|
|
}
|
|
/**
|
|
* @brief Get the first element of the linked list of joints involving this body
|
|
* @return The first element of the linked-list of all the joints involving this body
|
|
*/
|
|
JointListElement* getJointsList() {
|
|
return m_jointsList;
|
|
}
|
|
/**
|
|
* @brief Apply an external force to the body at its center of mass.
|
|
* If the body is sleeping, calling this method will wake it up. Note that the
|
|
* force will we added to the sum of the applied forces and that this sum will be
|
|
* reset to zero at the end of each call of the DynamicsWorld::update() method.
|
|
* You can only apply a force to a dynamic body otherwise, this method will do nothing.
|
|
* @param[in] _force The external force to apply on the center of mass of the body
|
|
*/
|
|
void applyForceToCenterOfMass(const vec3& _force);
|
|
/**
|
|
* @brief Apply an external force to the body at a given point (in world-space coordinates).
|
|
* If the point is not at the center of mass of the body, it will also
|
|
* generate some torque and therefore, change the angular velocity of the body.
|
|
* If the body is sleeping, calling this method will wake it up. Note that the
|
|
* force will we added to the sum of the applied forces and that this sum will be
|
|
* reset to zero at the end of each call of the DynamicsWorld::update() method.
|
|
* You can only apply a force to a dynamic body otherwise, this method will do nothing.
|
|
* @param[in] _force The force to apply on the body
|
|
* @param[in] _point The point where the force is applied (in world-space coordinates)
|
|
*/
|
|
void applyForce(const vec3& _force, const vec3& _point);
|
|
/**
|
|
* @brief Apply an external torque to the body.
|
|
* If the body is sleeping, calling this method will wake it up. Note that the
|
|
* force will we added to the sum of the applied torques and that this sum will be
|
|
* reset to zero at the end of each call of the DynamicsWorld::update() method.
|
|
* You can only apply a force to a dynamic body otherwise, this method will do nothing.
|
|
* @param[in] _torque The external torque to apply on the body
|
|
*/
|
|
void applyTorque(const vec3& _torque);
|
|
/**
|
|
* @brief Add a collision shape to the body.
|
|
* When you add a collision shape to the body, an intternal copy of this collision shape will be created internally.
|
|
* Therefore, you can delete it right after calling this method or use it later to add it to another body.
|
|
* This method will return a pointer to a new proxy shape. A proxy shape is an object that links a collision shape and a given body.
|
|
* You can use the returned proxy shape to get and set information about the corresponding collision shape for that body.
|
|
* @param[in] _collisionShape The collision shape you want to add to the body
|
|
* @param[in] _transform The transformation of the collision shape that transforms the local-space of the collision shape into the local-space of the body
|
|
* @param[in] _mass Mass (in kilograms) of the collision shape you want to add
|
|
* @return A pointer to the proxy shape that has been created to link the body to the new collision shape you have added.
|
|
*/
|
|
ProxyShape* addCollisionShape(CollisionShape* _collisionShape,
|
|
const etk::Transform3D& _transform,
|
|
float _mass);
|
|
virtual void removeCollisionShape(const ProxyShape* _proxyShape) override;
|
|
/**
|
|
* @brief Recompute the center of mass, total mass and inertia tensor of the body using all the collision shapes attached to the body.
|
|
*/
|
|
void recomputeMassInformation();
|
|
friend class DynamicsWorld;
|
|
friend class ContactSolver;
|
|
friend class BallAndSocketJoint;
|
|
friend class SliderJoint;
|
|
friend class HingeJoint;
|
|
friend class FixedJoint;
|
|
};
|
|
|
|
}
|
|
|