ephysics/ephysics/body/CollisionBody.hpp

210 lines
9.4 KiB
C++

/** @file
* Original ReactPhysics3D C++ library by Daniel Chappuis <http://www.reactphysics3d.com/> This code is re-licensed with permission from ReactPhysics3D author.
* @author Daniel CHAPPUIS
* @author Edouard DUPIN
* @copyright 2010-2016, Daniel Chappuis
* @copyright 2017, Edouard DUPIN
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ephysics/body/Body.hpp>
#include <etk/math/Transform3D.hpp>
#include <ephysics/collision/shapes/AABB.hpp>
#include <ephysics/collision/shapes/CollisionShape.hpp>
#include <ephysics/collision/RaycastInfo.hpp>
#include <ephysics/configuration.hpp>
namespace ephysics {
struct ContactManifoldListElement;
class ProxyShape;
class CollisionWorld;
/**
* @brief Define the type of the body
*/
enum BodyType {
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.
};
/**
* @brief This class represents a body that is able to collide with others bodies. This class inherits from the Body class.
*/
class CollisionBody : public Body {
protected :
BodyType m_type; //!< Type of body (static, kinematic or dynamic)
etk::Transform3D m_transform; //!< Position and orientation of the body
ProxyShape* m_proxyCollisionShapes; //!< First element of the linked list of proxy collision shapes of this body
uint32_t m_numberCollisionShapes; //!< Number of collision shapes
ContactManifoldListElement* m_contactManifoldsList; //!< First element of the linked list of contact manifolds involving this body
CollisionWorld& m_world; //!< Reference to the world the body belongs to
/// Private copy-constructor
CollisionBody(const CollisionBody& _body) = delete;
/// Private assignment operator
CollisionBody& operator=(const CollisionBody& _body) = delete;
/**
* @brief Reset the contact manifold lists
*/
void resetContactManifoldsList();
/**
* @brief Remove all the collision shapes
*/
void removeAllCollisionShapes();
/**
* @brief Update the broad-phase state for this body (because it has moved for instance)
*/
virtual void updateBroadPhaseState() const;
/**
* @brief Update the broad-phase state of a proxy collision shape of the body
*/
void updateProxyShapeInBroadPhase(ProxyShape* _proxyShape, bool _forceReinsert = false) const;
/**
* @brief Ask the broad-phase to test again the collision shapes of the body for collision (as if the body has moved).
*/
void askForBroadPhaseCollisionCheck() const;
/**
* @brief Reset the m_isAlreadyInIsland variable of the body and contact manifolds.
* This method also returns the number of contact manifolds of the body.
*/
int32_t resetIsAlreadyInIslandAndCountManifolds();
public :
/**
* @brief Constructor
* @param[in] _transform The transform of the body
* @param[in] _world The physics world where the body is created
* @param[in] _id ID of the body
*/
CollisionBody(const etk::Transform3D& _transform, CollisionWorld& _world, bodyindex _id);
/**
* @brief Destructor
*/
virtual ~CollisionBody();
/**
* @brief Return the type of the body
* @return the type of the body (STATIC, KINEMATIC, DYNAMIC)
*/
BodyType getType() const {
return m_type;
}
/**
* @brief Set the type of the body
* @param[in] type The type of the body (STATIC, KINEMATIC, DYNAMIC)
*/
virtual void setType(BodyType _type);
/**
* @brief Set whether or not the body is active
* @param[in] _isActive True if you want to activate the body
*/
virtual void setIsActive(bool _isActive);
/**
* @brief Return the current position and orientation
* @return The current transformation of the body that transforms the local-space of the body int32_to world-space
*/
const etk::Transform3D& getTransform() const {
return m_transform;
}
/**
* @brief Set the current position and orientation
* @param 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 Add a collision shape to the body. Note that you can share a collision shape between several bodies using the same collision shape instance to
* when you add the shape to the different bodies. Do not forget to delete the collision shape you have created at the end of your program.
*
* 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 A pointer to 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 int32_to the local-space of the body
* @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);
/**
* @brief Remove a collision shape from the body
* To remove a collision shape, you need to specify the pointer to the proxy shape that has been returned when you have added the collision shape to the body
* @param[in] _proxyShape The pointer of the proxy shape you want to remove
*/
virtual void removeCollisionShape(const ProxyShape* _proxyShape);
/**
* @brief Get the first element of the linked list of contact manifolds involving this body
* @return A pointer to the first element of the linked-list with the contact manifolds of this body
*/
const ContactManifoldListElement* getContactManifoldsList() const {
return m_contactManifoldsList;
}
/**
* @brief Return true if a point is inside the collision body
* This method returns true if a point is inside any collision shape of the body
* @param[in] _worldPoint The point to test (in world-space coordinates)
* @return True if the point is inside the body
*/
bool testPointInside(const vec3& _worldPoint) const;
/**
* @brief Raycast method with feedback information
* The method returns the closest hit among all the collision shapes of the body
* @param[in] _ray The ray used to raycast agains the body
* @param[out] _raycastInfo Structure that contains the result of the raycasting (valid only if the method returned true)
* @return True if the ray hit the body and false otherwise
*/
bool raycast(const Ray& _ray, RaycastInfo& _raycastInfo);
/**
* @brief Compute and return the AABB of the body by merging all proxy shapes AABBs
* @return The axis-aligned bounding box (AABB) of the body in world-space coordinates
*/
AABB getAABB() const;
/**
* @brief Get the linked list of proxy shapes of that body
* @return The pointer of the first proxy shape of the linked-list of all the
* proxy shapes of the body
*/
ProxyShape* getProxyShapesList() {
return m_proxyCollisionShapes;
}
/**
* @brief Get the linked list of proxy shapes of that body
* @return The pointer of the first proxy shape of the linked-list of all the proxy shapes of the body
*/
const ProxyShape* getProxyShapesList() const {
return m_proxyCollisionShapes;
}
/**
* @brief Get the world-space coordinates of a point given the local-space coordinates of the body
* @param[in] _localPoint A point in the local-space coordinates of the body
* @return The point in world-space coordinates
*/
vec3 getWorldPoint(const vec3& _localPoint) const {
return m_transform * _localPoint;
}
/**
* @brief Get the world-space vector of a vector given in local-space coordinates of the body
* @param[in] _localVector A vector in the local-space coordinates of the body
* @return The vector in world-space coordinates
*/
vec3 getWorldVector(const vec3& _localVector) const {
return m_transform.getOrientation() * _localVector;
}
/**
* @brief Get the body local-space coordinates of a point given in the world-space coordinates
* @param[in] _worldPoint A point in world-space coordinates
* @return The point in the local-space coordinates of the body
*/
vec3 getLocalPoint(const vec3& _worldPoint) const {
return m_transform.getInverse() * _worldPoint;
}
/**
* @brief Get the body local-space coordinates of a vector given in the world-space coordinates
* @param[in] _worldVector A vector in world-space coordinates
* @return The vector in the local-space coordinates of the body
*/
vec3 getLocalVector(const vec3& _worldVector) const {
return m_transform.getOrientation().getInverse() * _worldVector;
}
friend class CollisionWorld;
friend class DynamicsWorld;
friend class CollisionDetection;
friend class BroadPhaseAlgorithm;
friend class ConvexMeshShape;
friend class ProxyShape;
};
}