[DEV] continue renaming
This commit is contained in:
parent
6c3d49de92
commit
f9975bc8dc
@ -4,24 +4,17 @@
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/body/Body.hpp>
|
||||
#include <ephysics/collision/shapes/CollisionShape.hpp>
|
||||
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace ephysics;
|
||||
|
||||
// Constructor
|
||||
/**
|
||||
* @param id ID of the new body
|
||||
*/
|
||||
Body::Body(bodyindex id)
|
||||
: m_id(id), m_isAlreadyInIsland(false), m_isAllowedToSleep(true), m_isActive(true),
|
||||
m_isSleeping(false), m_sleepTime(0), m_userData(NULL) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Body::~Body() {
|
||||
ephysics::Body::Body(bodyindex _id):
|
||||
m_id(_id),
|
||||
m_isAlreadyInIsland(false),
|
||||
m_isAllowedToSleep(true),
|
||||
m_isActive(true),
|
||||
m_isSleeping(false),
|
||||
m_sleepTime(0),
|
||||
m_userData(nullptr) {
|
||||
|
||||
}
|
@ -5,216 +5,159 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <ephysics/configuration.hpp>
|
||||
|
||||
/// Namespace ephysics
|
||||
namespace ephysics {
|
||||
|
||||
// TODO : Make this class abstract
|
||||
// Class Body
|
||||
/**
|
||||
* This class to represent a body of the physics engine. You should not
|
||||
* @brief 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 -------------------- //
|
||||
|
||||
/// ID of the body
|
||||
bodyindex m_id;
|
||||
|
||||
/// True if the body has already been added in an island (for sleeping technique)
|
||||
bool m_isAlreadyInIsland;
|
||||
|
||||
/// True if the body is allowed to go to sleep for better efficiency
|
||||
bool m_isAllowedToSleep;
|
||||
|
||||
/// True if 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.
|
||||
bodyindex m_id; //!< ID of the body
|
||||
bool m_isAlreadyInIsland; //!< True if the body has already been added in an island (for sleeping technique)
|
||||
bool m_isAllowedToSleep; //!< True if the body is allowed to go to sleep for better efficiency
|
||||
/**
|
||||
* @brief True if 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.
|
||||
*/
|
||||
bool m_isActive;
|
||||
|
||||
/// True if the body is sleeping (for sleeping technique)
|
||||
bool m_isSleeping;
|
||||
|
||||
/// Elapsed time since the body velocity was bellow the sleep velocity
|
||||
float m_sleepTime;
|
||||
|
||||
/// Pointer that can be used to attach user data to the body
|
||||
void* m_userData;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
bool m_isSleeping; //!< True if the body is sleeping (for sleeping technique)
|
||||
float m_sleepTime; //!< Elapsed time since the body velocity was bellow the sleep velocity
|
||||
void* m_userData; //!< Pointer that can be used to attach user data to the body
|
||||
/// Private copy-constructor
|
||||
Body(const Body& body);
|
||||
|
||||
/// Private assignment operator
|
||||
Body& operator=(const Body& body);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Body(bodyindex id);
|
||||
|
||||
/// Destructor
|
||||
virtual ~Body();
|
||||
|
||||
/// Return the ID of the body
|
||||
bodyindex getID() 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);
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// Smaller than operator
|
||||
bool operator<(const Body& body2) const;
|
||||
|
||||
/// Larger than operator
|
||||
bool operator>(const Body& body2) const;
|
||||
|
||||
/// Equal operator
|
||||
bool operator==(const Body& body2) const;
|
||||
|
||||
/// Not equal operator
|
||||
bool operator!=(const Body& body2) const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicsWorld;
|
||||
};
|
||||
|
||||
// Return the id of the body
|
||||
/**
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _id ID of the new body
|
||||
*/
|
||||
Body(bodyindex _id);
|
||||
/**
|
||||
* @brtief Virtualize Destructor
|
||||
*/
|
||||
virtual ~Body() = default;
|
||||
/**
|
||||
* @brief Return the id of the body
|
||||
* @return The ID of the body
|
||||
*/
|
||||
inline bodyindex Body::getID() const {
|
||||
bodyindex getID() const {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
// Return whether or not the body is allowed to sleep
|
||||
/**
|
||||
}
|
||||
/**
|
||||
* @brief Return whether or not the body is allowed to sleep
|
||||
* @return True if the body is allowed to sleep and false otherwise
|
||||
*/
|
||||
inline bool Body::isAllowedToSleep() const {
|
||||
bool isAllowedToSleep() const {
|
||||
return m_isAllowedToSleep;
|
||||
}
|
||||
|
||||
// Set whether or not the body is allowed to go to sleep
|
||||
/**
|
||||
* @param isAllowedToSleep True if the body is allowed to sleep
|
||||
}
|
||||
/**
|
||||
* @brief Set whether or not the body is allowed to go to sleep
|
||||
* @param[in] _isAllowedToSleep True if the body is allowed to sleep
|
||||
*/
|
||||
inline void Body::setIsAllowedToSleep(bool isAllowedToSleep) {
|
||||
m_isAllowedToSleep = isAllowedToSleep;
|
||||
|
||||
if (!m_isAllowedToSleep) setIsSleeping(false);
|
||||
}
|
||||
|
||||
// Return whether or not the body is sleeping
|
||||
/**
|
||||
void setIsAllowedToSleep(bool _isAllowedToSleep) {
|
||||
m_isAllowedToSleep = _isAllowedToSleep;
|
||||
if (!m_isAllowedToSleep) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Return whether or not the body is sleeping
|
||||
* @return True if the body is currently sleeping and false otherwise
|
||||
*/
|
||||
inline bool Body::isSleeping() const {
|
||||
bool isSleeping() const {
|
||||
return m_isSleeping;
|
||||
}
|
||||
|
||||
// Return true if the body is active
|
||||
/**
|
||||
}
|
||||
/**
|
||||
* @brief Return true if the body is active
|
||||
* @return True if the body currently active and false otherwise
|
||||
*/
|
||||
inline bool Body::isActive() const {
|
||||
bool isActive() const {
|
||||
return m_isActive;
|
||||
}
|
||||
|
||||
// Set whether or not the body is active
|
||||
/**
|
||||
* @param isActive True if you want to activate the body
|
||||
*/
|
||||
inline void Body::setIsActive(bool isActive) {
|
||||
m_isActive = isActive;
|
||||
}
|
||||
|
||||
// Set the variable to know whether or not the body is sleeping
|
||||
inline void Body::setIsSleeping(bool isSleeping) {
|
||||
|
||||
if (isSleeping) {
|
||||
m_sleepTime = 0.0f;
|
||||
}
|
||||
else {
|
||||
/**
|
||||
* @brief Set whether or not the body is active
|
||||
* @param[in] _isActive True if you want to activate the body
|
||||
*/
|
||||
void setIsActive(bool _isActive) {
|
||||
m_isActive = _isActive;
|
||||
}
|
||||
/**
|
||||
* @brief Set the variable to know whether or not the body is sleeping
|
||||
* @param[in] _isSleeping Set the new status
|
||||
*/
|
||||
void setIsSleeping(bool _isSleeping) {
|
||||
if (_isSleeping) {
|
||||
m_sleepTime = 0.0f;
|
||||
} else {
|
||||
if (m_isSleeping) {
|
||||
m_sleepTime = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
m_isSleeping = isSleeping;
|
||||
}
|
||||
|
||||
// Return a pointer to the user data attached to this body
|
||||
/**
|
||||
m_isSleeping = _isSleeping;
|
||||
}
|
||||
/**
|
||||
* @brief Return a pointer to the user data attached to this body
|
||||
* @return A pointer to the user data you have attached to the body
|
||||
*/
|
||||
inline void* Body::getUserData() const {
|
||||
void* getUserData() const {
|
||||
return m_userData;
|
||||
}
|
||||
|
||||
// Attach user data to this body
|
||||
/**
|
||||
* @param userData A pointer to the user data you want to attach to the body
|
||||
}
|
||||
/**
|
||||
* @brief Attach user data to this body
|
||||
* @param[in] _userData A pointer to the user data you want to attach to the body
|
||||
*/
|
||||
inline void Body::setUserData(void* userData) {
|
||||
m_userData = userData;
|
||||
}
|
||||
void setUserData(void* _userData) {
|
||||
m_userData = _userData;
|
||||
}
|
||||
/**
|
||||
* @brief Smaller than operator
|
||||
* @param[in] _obj Other object to compare
|
||||
* @return true if the current element is smaller
|
||||
*/
|
||||
bool operator<(const Body& _obj) const {
|
||||
return (m_id < _obj.m_id);
|
||||
}
|
||||
/**
|
||||
* @brief Larger than operator
|
||||
* @param[in] _obj Other object to compare
|
||||
* @return true if the current element is Bigger
|
||||
*/
|
||||
bool operator>(const Body& _obj) const {
|
||||
return (m_id > _obj.m_id);
|
||||
}
|
||||
/**
|
||||
* @brief Equal operator
|
||||
* @param[in] _obj Other object to compare
|
||||
* @return true if the curretn element is equal
|
||||
*/
|
||||
bool operator==(const Body& _obj) const {
|
||||
return (m_id == _obj.m_id);
|
||||
}
|
||||
/**
|
||||
* @brief Not equal operator
|
||||
* @param[in] _obj Other object to compare
|
||||
* @return true if the curretn element is NOT equal
|
||||
*/
|
||||
bool operator!=(const Body& _obj) const {
|
||||
return (m_id != _obj.m_id);
|
||||
}
|
||||
friend class DynamicsWorld;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Smaller than operator
|
||||
inline bool Body::operator<(const Body& body2) const {
|
||||
return (m_id < body2.m_id);
|
||||
}
|
||||
|
||||
// Larger than operator
|
||||
inline bool Body::operator>(const Body& body2) const {
|
||||
return (m_id > body2.m_id);
|
||||
}
|
||||
|
||||
// Equal operator
|
||||
inline bool Body::operator==(const Body& body2) const {
|
||||
return (m_id == body2.m_id);
|
||||
}
|
||||
|
||||
// Not equal operator
|
||||
inline bool Body::operator!=(const Body& body2) const {
|
||||
return (m_id != body2.m_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,21 +12,20 @@
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace ephysics;
|
||||
|
||||
// Constructor
|
||||
/**
|
||||
* @param transform The transform of the body
|
||||
* @param world The physics world where the body is created
|
||||
* @param id ID of the body
|
||||
*/
|
||||
CollisionBody::CollisionBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id)
|
||||
: Body(id), m_type(DYNAMIC), m_transform(transform), m_proxyCollisionShapes(NULL),
|
||||
m_numberCollisionShapes(0), m_contactManifoldsList(NULL), m_world(world) {
|
||||
|
||||
CollisionBody::CollisionBody(const etk::Transform3D& _transform, CollisionWorld& _world, bodyindex _id):
|
||||
Body(_id),
|
||||
m_type(DYNAMIC),
|
||||
m_transform(_transform),
|
||||
m_proxyCollisionShapes(nullptr),
|
||||
m_numberCollisionShapes(0),
|
||||
m_contactManifoldsList(nullptr),
|
||||
m_world(_world) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
CollisionBody::~CollisionBody() {
|
||||
assert(m_contactManifoldsList == NULL);
|
||||
assert(m_contactManifoldsList == nullptr);
|
||||
|
||||
// Remove all the proxy collision shapes of the body
|
||||
removeAllCollisionShapes();
|
||||
@ -41,304 +40,182 @@ inline void CollisionBody::setType(BodyType _type) {
|
||||
}
|
||||
|
||||
|
||||
// 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 collisionShape A pointer to the collision shape you want to add to the body
|
||||
* @param 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* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
|
||||
const etk::Transform3D& transform) {
|
||||
|
||||
ProxyShape* CollisionBody::addCollisionShape(CollisionShape* _collisionShape,
|
||||
const etk::Transform3D& _transform) {
|
||||
// Create a new proxy collision shape to attach the collision shape to the body
|
||||
ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate(
|
||||
sizeof(ProxyShape))) ProxyShape(this, collisionShape,
|
||||
transform, float(1));
|
||||
|
||||
ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate(sizeof(ProxyShape))) ProxyShape(this, _collisionShape,_transform, float(1));
|
||||
// Add it to the list of proxy collision shapes of the body
|
||||
if (m_proxyCollisionShapes == NULL) {
|
||||
if (m_proxyCollisionShapes == nullptr) {
|
||||
m_proxyCollisionShapes = proxyShape;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
proxyShape->m_next = m_proxyCollisionShapes;
|
||||
m_proxyCollisionShapes = proxyShape;
|
||||
}
|
||||
|
||||
// Compute the world-space AABB of the new collision shape
|
||||
AABB aabb;
|
||||
collisionShape->computeAABB(aabb, m_transform * transform);
|
||||
|
||||
// Notify the collision detection about this new collision shape
|
||||
_collisionShape->computeAABB(aabb, m_transform * _transform);
|
||||
m_world.m_collisionDetection.addProxyCollisionShape(proxyShape, aabb);
|
||||
|
||||
m_numberCollisionShapes++;
|
||||
|
||||
// Return a pointer to the collision shape
|
||||
return proxyShape;
|
||||
}
|
||||
|
||||
// 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 proxyShape The pointer of the proxy shape you want to remove
|
||||
*/
|
||||
void CollisionBody::removeCollisionShape(const ProxyShape* proxyShape) {
|
||||
|
||||
void CollisionBody::removeCollisionShape(const ProxyShape* _proxyShape) {
|
||||
ProxyShape* current = m_proxyCollisionShapes;
|
||||
|
||||
// If the the first proxy shape is the one to remove
|
||||
if (current == proxyShape) {
|
||||
if (current == _proxyShape) {
|
||||
m_proxyCollisionShapes = current->m_next;
|
||||
|
||||
if (m_isActive) {
|
||||
m_world.m_collisionDetection.removeProxyCollisionShape(current);
|
||||
}
|
||||
|
||||
current->~ProxyShape();
|
||||
m_world.m_memoryAllocator.release(current, sizeof(ProxyShape));
|
||||
m_numberCollisionShapes--;
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for the proxy shape that contains the collision shape in parameter
|
||||
while(current->m_next != NULL) {
|
||||
|
||||
while(current->m_next != nullptr) {
|
||||
// If we have found the collision shape to remove
|
||||
if (current->m_next == proxyShape) {
|
||||
|
||||
if (current->m_next == _proxyShape) {
|
||||
// Remove the proxy collision shape
|
||||
ProxyShape* elementToRemove = current->m_next;
|
||||
current->m_next = elementToRemove->m_next;
|
||||
|
||||
if (m_isActive) {
|
||||
m_world.m_collisionDetection.removeProxyCollisionShape(elementToRemove);
|
||||
}
|
||||
|
||||
elementToRemove->~ProxyShape();
|
||||
m_world.m_memoryAllocator.release(elementToRemove, sizeof(ProxyShape));
|
||||
m_numberCollisionShapes--;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the next element in the list
|
||||
current = current->m_next;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all the collision shapes
|
||||
|
||||
void CollisionBody::removeAllCollisionShapes() {
|
||||
|
||||
ProxyShape* current = m_proxyCollisionShapes;
|
||||
|
||||
// Look for the proxy shape that contains the collision shape in parameter
|
||||
while(current != NULL) {
|
||||
|
||||
while(current != nullptr) {
|
||||
// Remove the proxy collision shape
|
||||
ProxyShape* nextElement = current->m_next;
|
||||
|
||||
if (m_isActive) {
|
||||
m_world.m_collisionDetection.removeProxyCollisionShape(current);
|
||||
}
|
||||
|
||||
current->~ProxyShape();
|
||||
m_world.m_memoryAllocator.release(current, sizeof(ProxyShape));
|
||||
|
||||
// Get the next element in the list
|
||||
current = nextElement;
|
||||
}
|
||||
|
||||
m_proxyCollisionShapes = NULL;
|
||||
m_proxyCollisionShapes = nullptr;
|
||||
}
|
||||
|
||||
// Reset the contact manifold lists
|
||||
void CollisionBody::resetContactManifoldsList() {
|
||||
|
||||
void CollisionBody::resetContactManifoldsList() {
|
||||
// Delete the linked list of contact manifolds of that body
|
||||
ContactManifoldListElement* currentElement = m_contactManifoldsList;
|
||||
while (currentElement != NULL) {
|
||||
while (currentElement != nullptr) {
|
||||
ContactManifoldListElement* nextElement = currentElement->next;
|
||||
|
||||
// Delete the current element
|
||||
currentElement->~ContactManifoldListElement();
|
||||
m_world.m_memoryAllocator.release(currentElement, sizeof(ContactManifoldListElement));
|
||||
|
||||
currentElement = nextElement;
|
||||
}
|
||||
m_contactManifoldsList = NULL;
|
||||
m_contactManifoldsList = nullptr;
|
||||
}
|
||||
|
||||
// Update the broad-phase state for this body (because it has moved for instance)
|
||||
|
||||
void CollisionBody::updateBroadPhaseState() const {
|
||||
|
||||
// For all the proxy collision shapes of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
// Update the proxy
|
||||
updateProxyShapeInBroadPhase(shape);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the broad-phase state of a proxy collision shape of the body
|
||||
void CollisionBody::updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool forceReinsert) const {
|
||||
|
||||
// Recompute the world-space AABB of the collision shape
|
||||
void CollisionBody::updateProxyShapeInBroadPhase(ProxyShape* _proxyShape, bool _forceReinsert) const {
|
||||
AABB aabb;
|
||||
proxyShape->getCollisionShape()->computeAABB(aabb, m_transform * proxyShape->getLocalToBodyTransform());
|
||||
|
||||
// Update the broad-phase state for the proxy collision shape
|
||||
m_world.m_collisionDetection.updateProxyCollisionShape(proxyShape, aabb, vec3(0, 0, 0), forceReinsert);
|
||||
_proxyShape->getCollisionShape()->computeAABB(aabb, m_transform * _proxyShape->getLocalToBodyTransform());
|
||||
m_world.m_collisionDetection.updateProxyCollisionShape(_proxyShape, aabb, vec3(0, 0, 0), _forceReinsert);
|
||||
}
|
||||
|
||||
// Set whether or not the body is active
|
||||
/**
|
||||
* @param isActive True if you want to activate the body
|
||||
*/
|
||||
void CollisionBody::setIsActive(bool isActive) {
|
||||
|
||||
void CollisionBody::setIsActive(bool _isActive) {
|
||||
// If the state does not change
|
||||
if (m_isActive == isActive) return;
|
||||
|
||||
Body::setIsActive(isActive);
|
||||
|
||||
if (m_isActive == _isActive) {
|
||||
return;
|
||||
}
|
||||
Body::setIsActive(_isActive);
|
||||
// If we have to activate the body
|
||||
if (isActive) {
|
||||
|
||||
// For each proxy shape of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
// Compute the world-space AABB of the new collision shape
|
||||
if (_isActive == true) {
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
AABB aabb;
|
||||
shape->getCollisionShape()->computeAABB(aabb, m_transform * shape->m_localToBodyTransform);
|
||||
|
||||
// Add the proxy shape to the collision detection
|
||||
m_world.m_collisionDetection.addProxyCollisionShape(shape, aabb);
|
||||
}
|
||||
}
|
||||
else { // If we have to deactivate the body
|
||||
|
||||
// For each proxy shape of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
// Remove the proxy shape from the collision detection
|
||||
} else {
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
m_world.m_collisionDetection.removeProxyCollisionShape(shape);
|
||||
}
|
||||
|
||||
// Reset the contact manifold list of the body
|
||||
resetContactManifoldsList();
|
||||
}
|
||||
}
|
||||
|
||||
// Ask the broad-phase to test again the collision shapes of the body for collision
|
||||
// (as if the body has moved).
|
||||
|
||||
void CollisionBody::askForBroadPhaseCollisionCheck() const {
|
||||
|
||||
// For all the proxy collision shapes of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
m_world.m_collisionDetection.askForBroadPhaseCollisionCheck(shape);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 CollisionBody::resetIsAlreadyInIslandAndCountManifolds() {
|
||||
|
||||
m_isAlreadyInIsland = false;
|
||||
|
||||
int32_t nbManifolds = 0;
|
||||
|
||||
// Reset the m_isAlreadyInIsland variable of the contact manifolds for
|
||||
// this body
|
||||
// Reset the m_isAlreadyInIsland variable of the contact manifolds for this body
|
||||
ContactManifoldListElement* currentElement = m_contactManifoldsList;
|
||||
while (currentElement != NULL) {
|
||||
while (currentElement != nullptr) {
|
||||
currentElement->contactManifold->m_isAlreadyInIsland = false;
|
||||
currentElement = currentElement->next;
|
||||
nbManifolds++;
|
||||
}
|
||||
|
||||
return nbManifolds;
|
||||
}
|
||||
|
||||
// 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 worldPoint The point to test (in world-space coordinates)
|
||||
* @return True if the point is inside the body
|
||||
*/
|
||||
bool CollisionBody::testPointInside(const vec3& worldPoint) const {
|
||||
|
||||
// For each collision shape of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
// Test if the point is inside the collision shape
|
||||
if (shape->testPointInside(worldPoint)) return true;
|
||||
bool CollisionBody::testPointInside(const vec3& _worldPoint) const {
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
if (shape->testPointInside(_worldPoint)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Raycast method with feedback information
|
||||
/// The method returns the closest hit among all the collision shapes of the body
|
||||
/**
|
||||
* @param 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 CollisionBody::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
|
||||
|
||||
// If the body is not active, it cannot be hit by rays
|
||||
if (!m_isActive) return false;
|
||||
|
||||
bool CollisionBody::raycast(const Ray& _ray, RaycastInfo& _raycastInfo) {
|
||||
if (m_isActive == false) {
|
||||
return false;
|
||||
}
|
||||
bool isHit = false;
|
||||
Ray rayTemp(ray);
|
||||
|
||||
// For each collision shape of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
Ray rayTemp(_ray);
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
// Test if the ray hits the collision shape
|
||||
if (shape->raycast(rayTemp, raycastInfo)) {
|
||||
rayTemp.maxFraction = raycastInfo.hitFraction;
|
||||
if (shape->raycast(rayTemp, _raycastInfo)) {
|
||||
rayTemp.maxFraction = _raycastInfo.hitFraction;
|
||||
isHit = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isHit;
|
||||
}
|
||||
|
||||
// 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 CollisionBody::getAABB() const {
|
||||
|
||||
AABB bodyAABB;
|
||||
|
||||
if (m_proxyCollisionShapes == NULL) return bodyAABB;
|
||||
|
||||
if (m_proxyCollisionShapes == nullptr) {
|
||||
return bodyAABB;
|
||||
}
|
||||
m_proxyCollisionShapes->getCollisionShape()->computeAABB(bodyAABB, m_transform * m_proxyCollisionShapes->getLocalToBodyTransform());
|
||||
|
||||
// For each proxy shape of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes->m_next; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
// Compute the world-space AABB of the collision shape
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes->m_next; shape != nullptr; shape = shape->m_next) {
|
||||
AABB aabb;
|
||||
shape->getCollisionShape()->computeAABB(aabb, m_transform * shape->getLocalToBodyTransform());
|
||||
|
||||
// Merge the proxy shape AABB with the current body AABB
|
||||
bodyAABB.mergeWithAABB(aabb);
|
||||
}
|
||||
|
||||
return bodyAABB;
|
||||
}
|
||||
|
||||
|
@ -16,257 +16,199 @@
|
||||
#include <ephysics/memory/MemoryAllocator.hpp>
|
||||
#include <ephysics/configuration.hpp>
|
||||
|
||||
/// Namespace ephysics
|
||||
namespace ephysics {
|
||||
|
||||
// Class declarations
|
||||
struct ContactManifoldListElement;
|
||||
class ProxyShape;
|
||||
class CollisionWorld;
|
||||
|
||||
/// 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 BodyType {STATIC, KINEMATIC, DYNAMIC};
|
||||
|
||||
// Class CollisionBody
|
||||
/**
|
||||
* This class represents a body that is able to collide with others
|
||||
* bodies. This class inherits from the Body class.
|
||||
struct ContactManifoldListElement;
|
||||
class ProxyShape;
|
||||
class CollisionWorld;
|
||||
/**
|
||||
* @brief Define the type of the body
|
||||
*/
|
||||
class CollisionBody : public 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 :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Type of body (static, kinematic or dynamic)
|
||||
BodyType m_type;
|
||||
|
||||
/// Position and orientation of the body
|
||||
etk::Transform3D m_transform;
|
||||
|
||||
/// First element of the linked list of proxy collision shapes of this body
|
||||
ProxyShape* m_proxyCollisionShapes;
|
||||
|
||||
/// Number of collision shapes
|
||||
uint32_t m_numberCollisionShapes;
|
||||
|
||||
/// First element of the linked list of contact manifolds involving this body
|
||||
ContactManifoldListElement* m_contactManifoldsList;
|
||||
|
||||
/// Reference to the world the body belongs to
|
||||
CollisionWorld& m_world;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
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);
|
||||
|
||||
CollisionBody(const CollisionBody& _body) = delete;
|
||||
/// Private assignment operator
|
||||
CollisionBody& operator=(const CollisionBody& body);
|
||||
|
||||
/// Reset the contact manifold lists
|
||||
CollisionBody& operator=(const CollisionBody& _body) = delete;
|
||||
/**
|
||||
* @brief Reset the contact manifold lists
|
||||
*/
|
||||
void resetContactManifoldsList();
|
||||
|
||||
/// Remove all the collision shapes
|
||||
/**
|
||||
* @brief Remove all the collision shapes
|
||||
*/
|
||||
void removeAllCollisionShapes();
|
||||
|
||||
/// Update the broad-phase state for this body (because it has moved for instance)
|
||||
/**
|
||||
* @brief Update the broad-phase state for this body (because it has moved for instance)
|
||||
*/
|
||||
virtual void updateBroadPhaseState() const;
|
||||
|
||||
/// Update the broad-phase state of a proxy collision shape of the body
|
||||
void updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool forceReinsert = false) const;
|
||||
|
||||
/// Ask the broad-phase to test again the collision shapes of the body for collision
|
||||
/// (as if the body has moved).
|
||||
/**
|
||||
* @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;
|
||||
|
||||
/// Reset the m_isAlreadyInIsland variable of the body and contact manifolds
|
||||
/**
|
||||
* @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 :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
CollisionBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id);
|
||||
|
||||
/// Destructor
|
||||
/**
|
||||
* @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();
|
||||
|
||||
/// Return the type of the body
|
||||
BodyType getType() const;
|
||||
/**
|
||||
* @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
|
||||
* 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[in] type The type of the body (STATIC, KINEMATIC, DYNAMIC)
|
||||
*/
|
||||
virtual void setType(BodyType _type);
|
||||
|
||||
/// Set whether or not the body is active
|
||||
virtual void setIsActive(bool isActive);
|
||||
|
||||
/// Return the current position and orientation
|
||||
const etk::Transform3D& getTransform() const;
|
||||
|
||||
/// Set the current position and orientation
|
||||
virtual void setTransform(const etk::Transform3D& transform);
|
||||
|
||||
/// Add a collision shape to the body.
|
||||
virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape,
|
||||
const etk::Transform3D& transform);
|
||||
|
||||
/// Remove a collision shape from the body
|
||||
virtual void removeCollisionShape(const ProxyShape* proxyShape);
|
||||
|
||||
/// Return the first element of the linked list of contact manifolds involving this body
|
||||
const ContactManifoldListElement* getContactManifoldsList() const;
|
||||
|
||||
/// Return true if a point is inside the collision body
|
||||
bool testPointInside(const vec3& worldPoint) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
bool raycast(const Ray& ray, RaycastInfo& raycastInfo);
|
||||
|
||||
/// Compute and return the AABB of the body by merging all proxy shapes AABBs
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
void setTransform(const etk::Transform3D& _transform) {
|
||||
m_transform = _transform;
|
||||
updateBroadPhaseState();
|
||||
}
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
virtual 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;
|
||||
|
||||
/// Return the linked list of proxy shapes of that body
|
||||
ProxyShape* getProxyShapesList();
|
||||
|
||||
/// Return the linked list of proxy shapes of that body
|
||||
const ProxyShape* getProxyShapesList() const;
|
||||
|
||||
/// Return the world-space coordinates of a point given the local-space coordinates of the body
|
||||
vec3 getWorldPoint(const vec3& localPoint) const;
|
||||
|
||||
/// Return the world-space vector of a vector given in local-space coordinates of the body
|
||||
vec3 getWorldVector(const vec3& localVector) const;
|
||||
|
||||
/// Return the body local-space coordinates of a point given in the world-space coordinates
|
||||
vec3 getLocalPoint(const vec3& worldPoint) const;
|
||||
|
||||
/// Return the body local-space coordinates of a vector given in the world-space coordinates
|
||||
vec3 getLocalVector(const vec3& worldVector) const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
/**
|
||||
* @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;
|
||||
};
|
||||
|
||||
// Return the type of the body
|
||||
/**
|
||||
* @return the type of the body (STATIC, KINEMATIC, DYNAMIC)
|
||||
*/
|
||||
inline BodyType CollisionBody::getType() const {
|
||||
return m_type;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
*/
|
||||
inline const etk::Transform3D& CollisionBody::getTransform() const {
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
// 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
|
||||
*/
|
||||
inline void CollisionBody::setTransform(const etk::Transform3D& transform) {
|
||||
|
||||
// Update the transform of the body
|
||||
m_transform = transform;
|
||||
|
||||
// Update the broad-phase state of the body
|
||||
updateBroadPhaseState();
|
||||
}
|
||||
|
||||
// Return 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
|
||||
*/
|
||||
inline const ContactManifoldListElement* CollisionBody::getContactManifoldsList() const {
|
||||
return m_contactManifoldsList;
|
||||
}
|
||||
|
||||
// Return 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
|
||||
*/
|
||||
inline ProxyShape* CollisionBody::getProxyShapesList() {
|
||||
return m_proxyCollisionShapes;
|
||||
}
|
||||
|
||||
// Return 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
|
||||
*/
|
||||
inline const ProxyShape* CollisionBody::getProxyShapesList() const {
|
||||
return m_proxyCollisionShapes;
|
||||
}
|
||||
|
||||
// Return the world-space coordinates of a point given the local-space coordinates of the body
|
||||
/**
|
||||
* @param localPoint A point in the local-space coordinates of the body
|
||||
* @return The point in world-space coordinates
|
||||
*/
|
||||
inline vec3 CollisionBody::getWorldPoint(const vec3& localPoint) const {
|
||||
return m_transform * localPoint;
|
||||
}
|
||||
|
||||
// Return the world-space vector of a vector given in local-space coordinates of the body
|
||||
/**
|
||||
* @param localVector A vector in the local-space coordinates of the body
|
||||
* @return The vector in world-space coordinates
|
||||
*/
|
||||
inline vec3 CollisionBody::getWorldVector(const vec3& localVector) const {
|
||||
return m_transform.getOrientation() * localVector;
|
||||
}
|
||||
|
||||
// Return the body local-space coordinates of a point given in the world-space coordinates
|
||||
/**
|
||||
* @param worldPoint A point in world-space coordinates
|
||||
* @return The point in the local-space coordinates of the body
|
||||
*/
|
||||
inline vec3 CollisionBody::getLocalPoint(const vec3& worldPoint) const {
|
||||
return m_transform.getInverse() * worldPoint;
|
||||
}
|
||||
|
||||
// Return the body local-space coordinates of a vector given in the world-space coordinates
|
||||
/**
|
||||
* @param worldVector A vector in world-space coordinates
|
||||
* @return The vector in the local-space coordinates of the body
|
||||
*/
|
||||
inline vec3 CollisionBody::getLocalVector(const vec3& worldVector) const {
|
||||
return m_transform.getOrientation().getInverse() * worldVector;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,23 +11,24 @@
|
||||
#include <ephysics/engine/DynamicsWorld.hpp>
|
||||
#include <ephysics/debug.hpp>
|
||||
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace ephysics;
|
||||
|
||||
|
||||
RigidBody::RigidBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id)
|
||||
: CollisionBody(transform, world, id), m_initMass(1.0f),
|
||||
m_centerOfMassLocal(0, 0, 0), m_centerOfMassWorld(transform.getPosition()),
|
||||
m_isGravityEnabled(true), m_linearDamping(0.0f), m_angularDamping(float(0.0)),
|
||||
m_jointsList(NULL) {
|
||||
|
||||
RigidBody::RigidBody(const etk::Transform3D& _transform, CollisionWorld& _world, bodyindex _id):
|
||||
CollisionBody(_transform, _world, _id),
|
||||
m_initMass(1.0f),
|
||||
m_centerOfMassLocal(0, 0, 0),
|
||||
m_centerOfMassWorld(_transform.getPosition()),
|
||||
m_isGravityEnabled(true),
|
||||
m_linearDamping(0.0f),
|
||||
m_angularDamping(float(0.0)),
|
||||
m_jointsList(nullptr) {
|
||||
// Compute the inverse mass
|
||||
m_massInverse = 1.0f / m_initMass;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
RigidBody::~RigidBody() {
|
||||
assert(m_jointsList == NULL);
|
||||
assert(m_jointsList == nullptr);
|
||||
}
|
||||
|
||||
|
||||
@ -60,37 +61,23 @@ void RigidBody::setType(BodyType _type) {
|
||||
m_externalTorque.setZero();
|
||||
}
|
||||
|
||||
// Set the local inertia tensor of the body (in local-space coordinates)
|
||||
/**
|
||||
* @param inertiaTensorLocal The 3x3 inertia tensor matrix of the body in local-space
|
||||
* coordinates
|
||||
*/
|
||||
void RigidBody::setInertiaTensorLocal(const etk::Matrix3x3& inertiaTensorLocal) {
|
||||
|
||||
if (m_type != DYNAMIC) return;
|
||||
|
||||
m_inertiaTensorLocal = inertiaTensorLocal;
|
||||
|
||||
// Compute the inverse local inertia tensor
|
||||
void RigidBody::setInertiaTensorLocal(const etk::Matrix3x3& _inertiaTensorLocal) {
|
||||
if (m_type != DYNAMIC) {
|
||||
return;
|
||||
}
|
||||
m_inertiaTensorLocal = _inertiaTensorLocal;
|
||||
m_inertiaTensorLocalInverse = m_inertiaTensorLocal.getInverse();
|
||||
}
|
||||
|
||||
// Set the local center of mass of the body (in local-space coordinates)
|
||||
/**
|
||||
* @param centerOfMassLocal The center of mass of the body in local-space
|
||||
* coordinates
|
||||
*/
|
||||
void RigidBody::setCenterOfMassLocal(const vec3& centerOfMassLocal) {
|
||||
|
||||
if (m_type != DYNAMIC) return;
|
||||
|
||||
void RigidBody::setCenterOfMassLocal(const vec3& _centerOfMassLocal) {
|
||||
if (m_type != DYNAMIC) {
|
||||
return;
|
||||
}
|
||||
const vec3 oldCenterOfMass = m_centerOfMassWorld;
|
||||
m_centerOfMassLocal = centerOfMassLocal;
|
||||
|
||||
// Compute the center of mass in world-space coordinates
|
||||
m_centerOfMassLocal = _centerOfMassLocal;
|
||||
m_centerOfMassWorld = m_transform * m_centerOfMassLocal;
|
||||
|
||||
// Update the linear velocity of the center of mass
|
||||
m_linearVelocity += m_angularVelocity.cross(m_centerOfMassWorld - oldCenterOfMass);
|
||||
}
|
||||
|
||||
@ -108,24 +95,24 @@ void RigidBody::setMass(float _mass) {
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody::removeJointFrom_jointsList(MemoryAllocator& memoryAllocator, const Joint* joint) {
|
||||
assert(joint != nullptr);
|
||||
void RigidBody::removeJointFrom_jointsList(MemoryAllocator& _memoryAllocator, const Joint* _joint) {
|
||||
assert(_joint != nullptr);
|
||||
assert(m_jointsList != nullptr);
|
||||
// Remove the joint from the linked list of the joints of the first body
|
||||
if (m_jointsList->joint == joint) { // If the first element is the one to remove
|
||||
if (m_jointsList->joint == _joint) { // If the first element is the one to remove
|
||||
JointListElement* elementToRemove = m_jointsList;
|
||||
m_jointsList = elementToRemove->next;
|
||||
elementToRemove->~JointListElement();
|
||||
memoryAllocator.release(elementToRemove, sizeof(JointListElement));
|
||||
_memoryAllocator.release(elementToRemove, sizeof(JointListElement));
|
||||
}
|
||||
else { // If the element to remove is not the first one in the list
|
||||
JointListElement* currentElement = m_jointsList;
|
||||
while (currentElement->next != nullptr) {
|
||||
if (currentElement->next->joint == joint) {
|
||||
if (currentElement->next->joint == _joint) {
|
||||
JointListElement* elementToRemove = currentElement->next;
|
||||
currentElement->next = elementToRemove->next;
|
||||
elementToRemove->~JointListElement();
|
||||
memoryAllocator.release(elementToRemove, sizeof(JointListElement));
|
||||
_memoryAllocator.release(elementToRemove, sizeof(JointListElement));
|
||||
break;
|
||||
}
|
||||
currentElement = currentElement->next;
|
||||
@ -133,68 +120,32 @@ void RigidBody::removeJointFrom_jointsList(MemoryAllocator& memoryAllocator, con
|
||||
}
|
||||
}
|
||||
|
||||
// Add a collision shape to the body.
|
||||
/// When you add a collision shape to the body, an int32_ternal copy of this
|
||||
/// collision shape will be created int32_ternally. 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 collisionShape The collision shape you want to add to the body
|
||||
* @param transform The transformation of the collision shape that transforms the
|
||||
* local-space of the collision shape int32_to the local-space of the body
|
||||
* @param 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* RigidBody::addCollisionShape(CollisionShape* collisionShape,
|
||||
const etk::Transform3D& transform,
|
||||
float mass) {
|
||||
|
||||
assert(mass > 0.0f);
|
||||
|
||||
ProxyShape* RigidBody::addCollisionShape(CollisionShape* _collisionShape,
|
||||
const etk::Transform3D& _transform,
|
||||
float _mass) {
|
||||
assert(_mass > 0.0f);
|
||||
// Create a new proxy collision shape to attach the collision shape to the body
|
||||
ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate(
|
||||
sizeof(ProxyShape))) ProxyShape(this, collisionShape,
|
||||
transform, mass);
|
||||
|
||||
ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate(sizeof(ProxyShape))) ProxyShape(this, _collisionShape, _transform, _mass);
|
||||
// Add it to the list of proxy collision shapes of the body
|
||||
if (m_proxyCollisionShapes == NULL) {
|
||||
if (m_proxyCollisionShapes == nullptr) {
|
||||
m_proxyCollisionShapes = proxyShape;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
proxyShape->m_next = m_proxyCollisionShapes;
|
||||
m_proxyCollisionShapes = proxyShape;
|
||||
}
|
||||
|
||||
// Compute the world-space AABB of the new collision shape
|
||||
AABB aabb;
|
||||
collisionShape->computeAABB(aabb, m_transform * transform);
|
||||
|
||||
_collisionShape->computeAABB(aabb, m_transform * _transform);
|
||||
// Notify the collision detection about this new collision shape
|
||||
m_world.m_collisionDetection.addProxyCollisionShape(proxyShape, aabb);
|
||||
|
||||
m_numberCollisionShapes++;
|
||||
|
||||
// Recompute the center of mass, total mass and inertia tensor of the body with the new
|
||||
// collision shape
|
||||
recomputeMassInformation();
|
||||
|
||||
// Return a pointer to the proxy collision shape
|
||||
return proxyShape;
|
||||
}
|
||||
|
||||
// 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 proxyShape The pointer of the proxy shape you want to remove
|
||||
*/
|
||||
void RigidBody::removeCollisionShape(const ProxyShape* proxyShape) {
|
||||
CollisionBody::removeCollisionShape(proxyShape);
|
||||
void RigidBody::removeCollisionShape(const ProxyShape* _proxyShape) {
|
||||
CollisionBody::removeCollisionShape(_proxyShape);
|
||||
recomputeMassInformation();
|
||||
}
|
||||
|
||||
@ -241,8 +192,6 @@ void RigidBody::setTransform(const etk::Transform3D& _transform) {
|
||||
updateBroadPhaseState();
|
||||
}
|
||||
|
||||
// Recompute the center of mass, total mass and inertia tensor of the body using all
|
||||
// the collision shapes attached to the body.
|
||||
void RigidBody::recomputeMassInformation() {
|
||||
m_initMass = 0.0f;
|
||||
m_massInverse = 0.0f;
|
||||
@ -300,21 +249,16 @@ void RigidBody::recomputeMassInformation() {
|
||||
|
||||
|
||||
void RigidBody::updateBroadPhaseState() const {
|
||||
|
||||
PROFILE("RigidBody::updateBroadPhaseState()");
|
||||
|
||||
DynamicsWorld& world = static_cast<DynamicsWorld&>(m_world);
|
||||
const vec3 displacement = world.m_timeStep * m_linearVelocity;
|
||||
|
||||
// For all the proxy collision shapes of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
|
||||
// Recompute the world-space AABB of the collision shape
|
||||
AABB aabb;
|
||||
EPHY_ERROR(" : " << aabb.getMin() << " " << aabb.getMax());
|
||||
shape->getCollisionShape()->computeAABB(aabb, m_transform *shape->getLocalToBodyTransform());
|
||||
EPHY_ERROR(" : " << aabb.getMin() << " " << aabb.getMax());
|
||||
|
||||
// Update the broad-phase state for the proxy collision shape
|
||||
m_world.m_collisionDetection.updateProxyCollisionShape(shape, aabb, displacement);
|
||||
}
|
||||
@ -322,41 +266,32 @@ void RigidBody::updateBroadPhaseState() const {
|
||||
|
||||
|
||||
void RigidBody::applyForceToCenterOfMass(const vec3& _force) {
|
||||
// If it is not a dynamic body, we do nothing
|
||||
if (m_type != DYNAMIC) {
|
||||
return;
|
||||
}
|
||||
// Awake the body if it was sleeping
|
||||
if (m_isSleeping) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
// Add the force
|
||||
m_externalForce += _force;
|
||||
}
|
||||
|
||||
void RigidBody::applyForce(const vec3& _force, const vec3& _point) {
|
||||
// If it is not a dynamic body, we do nothing
|
||||
if (m_type != DYNAMIC) {
|
||||
return;
|
||||
}
|
||||
// Awake the body if it was sleeping
|
||||
if (m_isSleeping) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
// Add the force and torque
|
||||
m_externalForce += _force;
|
||||
m_externalTorque += (_point - m_centerOfMassWorld).cross(_force);
|
||||
}
|
||||
|
||||
void RigidBody::applyTorque(const vec3& _torque) {
|
||||
// If it is not a dynamic body, we do nothing
|
||||
if (m_type != DYNAMIC) {
|
||||
return;
|
||||
}
|
||||
// Awake the body if it was sleeping
|
||||
if (m_isSleeping) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
// Add the torque
|
||||
m_externalTorque += _torque;
|
||||
}
|
@ -13,18 +13,18 @@
|
||||
|
||||
namespace ephysics {
|
||||
|
||||
// Class declarations
|
||||
struct JointListElement;
|
||||
class Joint;
|
||||
class DynamicsWorld;
|
||||
// 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 {
|
||||
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
|
||||
@ -43,10 +43,8 @@ class RigidBody : public CollisionBody {
|
||||
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
|
||||
*/
|
||||
@ -70,8 +68,9 @@ class RigidBody : public CollisionBody {
|
||||
* @param id The ID of the body
|
||||
*/
|
||||
RigidBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id);
|
||||
|
||||
/// Destructor
|
||||
/**
|
||||
* @brief Virtual Destructor
|
||||
*/
|
||||
virtual ~RigidBody();
|
||||
void setType(BodyType _type); // TODO: override
|
||||
/**
|
||||
@ -122,18 +121,21 @@ class RigidBody : public CollisionBody {
|
||||
const etk::Matrix3x3& getInertiaTensorLocal() const {
|
||||
return m_inertiaTensorLocal;
|
||||
}
|
||||
|
||||
/// Set the local inertia tensor of the body (in body coordinates)
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/// Set the local center of mass of the body (in local-space coordinates)
|
||||
/**
|
||||
* @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
|
||||
@ -148,7 +150,6 @@ class RigidBody : public CollisionBody {
|
||||
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
|
||||
@ -267,39 +268,37 @@ class RigidBody : public CollisionBody {
|
||||
* @param[in] _torque The external torque to apply on the body
|
||||
*/
|
||||
void applyTorque(const vec3& _torque);
|
||||
|
||||
/// Add a collision shape to the body.
|
||||
virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape,
|
||||
const etk::Transform3D& transform,
|
||||
float mass);
|
||||
|
||||
/// Remove a collision shape from the body
|
||||
virtual void removeCollisionShape(const ProxyShape* proxyShape);
|
||||
|
||||
/// Recompute the center of mass, total mass and inertia tensor of the body using all
|
||||
/// the collision shapes attached to the body.
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
virtual ProxyShape* addCollisionShape(CollisionShape* _collisionShape,
|
||||
const etk::Transform3D& _transform,
|
||||
float _mass);
|
||||
/**
|
||||
* @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 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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/collision/broadphase/BroadPhaseAlgorithm.hpp>
|
||||
#include <ephysics/engine/OverlappingPair.hpp>
|
||||
@ -18,206 +17,136 @@
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Declarations
|
||||
class BroadPhaseAlgorithm;
|
||||
class CollisionWorld;
|
||||
class CollisionCallback;
|
||||
|
||||
// Class TestCollisionBetweenShapesCallback
|
||||
class TestCollisionBetweenShapesCallback : public NarrowPhaseCallback {
|
||||
class BroadPhaseAlgorithm;
|
||||
class CollisionWorld;
|
||||
class CollisionCallback;
|
||||
|
||||
class TestCollisionBetweenShapesCallback : public NarrowPhaseCallback {
|
||||
private:
|
||||
|
||||
CollisionCallback* m_collisionCallback;
|
||||
|
||||
CollisionCallback* m_collisionCallback; //!<
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
TestCollisionBetweenShapesCallback(CollisionCallback* callback)
|
||||
: m_collisionCallback(callback) {
|
||||
TestCollisionBetweenShapesCallback(CollisionCallback* _callback):
|
||||
m_collisionCallback(_callback) {
|
||||
|
||||
}
|
||||
|
||||
// Called by a narrow-phase collision algorithm when a new contact has been found
|
||||
virtual void notifyContact(OverlappingPair* overlappingPair,
|
||||
const ContactPointInfo& contactInfo);
|
||||
};
|
||||
virtual void notifyContact(OverlappingPair* _overlappingPair,
|
||||
const ContactPointInfo& _contactInfo);
|
||||
};
|
||||
|
||||
// Class CollisionDetection
|
||||
/**
|
||||
* This class computes the collision detection algorithms. We first
|
||||
/**
|
||||
* @brief It computes the collision detection algorithms. We first
|
||||
* perform a broad-phase algorithm to know which pairs of bodies can
|
||||
* collide and then we run a narrow-phase algorithm to compute the
|
||||
* collision contacts between bodies.
|
||||
*/
|
||||
class CollisionDetection : public NarrowPhaseCallback {
|
||||
|
||||
class CollisionDetection : public NarrowPhaseCallback {
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Collision Detection Dispatch configuration
|
||||
CollisionDispatch* m_collisionDispatch;
|
||||
|
||||
/// Default collision dispatch configuration
|
||||
DefaultCollisionDispatch m_defaultCollisionDispatch;
|
||||
|
||||
/// Collision detection matrix (algorithms to use)
|
||||
NarrowPhaseAlgorithm* m_collisionMatrix[NB_COLLISION_SHAPE_TYPES][NB_COLLISION_SHAPE_TYPES];
|
||||
|
||||
/// Reference to the memory allocator
|
||||
MemoryAllocator& m_memoryAllocator;
|
||||
|
||||
/// Pointer to the physics world
|
||||
CollisionWorld* m_world;
|
||||
|
||||
/// Broad-phase overlapping pairs
|
||||
std::map<overlappingpairid, OverlappingPair*> m_overlappingPairs;
|
||||
|
||||
/// Overlapping pairs in contact (during the current Narrow-phase collision detection)
|
||||
std::map<overlappingpairid, OverlappingPair*> m_contactOverlappingPairs;
|
||||
|
||||
/// Broad-phase algorithm
|
||||
BroadPhaseAlgorithm m_broadPhaseAlgorithm;
|
||||
|
||||
/// Narrow-phase GJK algorithm
|
||||
CollisionDispatch* m_collisionDispatch; //!< Collision Detection Dispatch configuration
|
||||
DefaultCollisionDispatch m_defaultCollisionDispatch; //!< Default collision dispatch configuration
|
||||
NarrowPhaseAlgorithm* m_collisionMatrix[NB_COLLISION_SHAPE_TYPES][NB_COLLISION_SHAPE_TYPES]; //!< Collision detection matrix (algorithms to use)
|
||||
MemoryAllocator& m_memoryAllocator; //!< Reference to the memory allocator
|
||||
CollisionWorld* m_world; //!< Pointer to the physics world
|
||||
std::map<overlappingpairid, OverlappingPair*> m_overlappingPairs; //!< Broad-phase overlapping pairs
|
||||
std::map<overlappingpairid, OverlappingPair*> m_contactOverlappingPairs; //!< Overlapping pairs in contact (during the current Narrow-phase collision detection)
|
||||
BroadPhaseAlgorithm m_broadPhaseAlgorithm; //!< Broad-phase algorithm
|
||||
// TODO : Delete this
|
||||
GJKAlgorithm m_narrowPhaseGJKAlgorithm;
|
||||
|
||||
/// Set of pair of bodies that cannot collide between each other
|
||||
std::set<bodyindexpair> m_noCollisionPairs;
|
||||
|
||||
/// True if some collision shapes have been added previously
|
||||
bool m_isCollisionShapesAdded;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
GJKAlgorithm m_narrowPhaseGJKAlgorithm; //!< Narrow-phase GJK algorithm
|
||||
std::set<bodyindexpair> m_noCollisionPairs; //!< Set of pair of bodies that cannot collide between each other
|
||||
bool m_isCollisionShapesAdded; //!< True if some collision shapes have been added previously
|
||||
/// Private copy-constructor
|
||||
CollisionDetection(const CollisionDetection& collisionDetection);
|
||||
|
||||
CollisionDetection(const CollisionDetection& _collisionDetection);
|
||||
/// Private assignment operator
|
||||
CollisionDetection& operator=(const CollisionDetection& collisionDetection);
|
||||
|
||||
CollisionDetection& operator=(const CollisionDetection& _collisionDetection);
|
||||
/// Compute the broad-phase collision detection
|
||||
void computeBroadPhase();
|
||||
|
||||
/// Compute the narrow-phase collision detection
|
||||
void computeNarrowPhase();
|
||||
|
||||
/// Add a contact manifold to the linked list of contact manifolds of the two bodies
|
||||
/// involed in the corresponding contact.
|
||||
void addContactManifoldToBody(OverlappingPair* pair);
|
||||
|
||||
void addContactManifoldToBody(OverlappingPair* _pair);
|
||||
/// Delete all the contact points in the currently overlapping pairs
|
||||
void clearContactPoints();
|
||||
|
||||
/// Fill-in the collision detection matrix
|
||||
void fillInCollisionMatrix();
|
||||
|
||||
/// Add all the contact manifold of colliding pairs to their bodies
|
||||
void addAllContactManifoldsToBodies();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
CollisionDetection(CollisionWorld* world, MemoryAllocator& memoryAllocator);
|
||||
|
||||
CollisionDetection(CollisionWorld* _world, MemoryAllocator& _memoryAllocator);
|
||||
/// Destructor
|
||||
~CollisionDetection();
|
||||
|
||||
/// Set the collision dispatch configuration
|
||||
void setCollisionDispatch(CollisionDispatch* collisionDispatch);
|
||||
|
||||
void setCollisionDispatch(CollisionDispatch* _collisionDispatch);
|
||||
/// Return the Narrow-phase collision detection algorithm to use between two types of shapes
|
||||
NarrowPhaseAlgorithm* getCollisionAlgorithm(CollisionShapeType shape1Type,
|
||||
CollisionShapeType shape2Type) const;
|
||||
|
||||
NarrowPhaseAlgorithm* getCollisionAlgorithm(CollisionShapeType _shape1Type,
|
||||
CollisionShapeType _shape2Type) const;
|
||||
/// Add a proxy collision shape to the collision detection
|
||||
void addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb);
|
||||
|
||||
void addProxyCollisionShape(ProxyShape* _proxyShape, const AABB& _aabb);
|
||||
/// Remove a proxy collision shape from the collision detection
|
||||
void removeProxyCollisionShape(ProxyShape* proxyShape);
|
||||
|
||||
void removeProxyCollisionShape(ProxyShape* _proxyShape);
|
||||
/// Update a proxy collision shape (that has moved for instance)
|
||||
void updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb,
|
||||
const vec3& displacement = vec3(0, 0, 0), bool forceReinsert = false);
|
||||
|
||||
void updateProxyCollisionShape(ProxyShape* _shape,
|
||||
const AABB& _aabb,
|
||||
const vec3& _displacement = vec3(0, 0, 0),
|
||||
bool _forceReinsert = false);
|
||||
/// Add a pair of bodies that cannot collide with each other
|
||||
void addNoCollisionPair(CollisionBody* body1, CollisionBody* body2);
|
||||
|
||||
void addNoCollisionPair(CollisionBody* _body1, CollisionBody* _body2);
|
||||
/// Remove a pair of bodies that cannot collide with each other
|
||||
void removeNoCollisionPair(CollisionBody* body1, CollisionBody* body2);
|
||||
|
||||
void removeNoCollisionPair(CollisionBody* _body1, CollisionBody* _body2);
|
||||
/// Ask for a collision shape to be tested again during broad-phase.
|
||||
void askForBroadPhaseCollisionCheck(ProxyShape* shape);
|
||||
|
||||
void askForBroadPhaseCollisionCheck(ProxyShape* _shape);
|
||||
/// Compute the collision detection
|
||||
void computeCollisionDetection();
|
||||
|
||||
/// Compute the collision detection
|
||||
void testCollisionBetweenShapes(CollisionCallback* callback,
|
||||
const std::set<uint32_t>& shapes1,
|
||||
const std::set<uint32_t>& shapes2);
|
||||
|
||||
void testCollisionBetweenShapes(CollisionCallback* _callback,
|
||||
const std::set<uint32_t>& _shapes1,
|
||||
const std::set<uint32_t>& _shapes2);
|
||||
/// Report collision between two sets of shapes
|
||||
void reportCollisionBetweenShapes(CollisionCallback* callback,
|
||||
const std::set<uint32_t>& shapes1,
|
||||
const std::set<uint32_t>& shapes2) ;
|
||||
|
||||
void reportCollisionBetweenShapes(CollisionCallback* _callback,
|
||||
const std::set<uint32_t>& _shapes1,
|
||||
const std::set<uint32_t>& _shapes2) ;
|
||||
/// Ray casting method
|
||||
void raycast(RaycastCallback* raycastCallback, const Ray& ray,
|
||||
unsigned short raycastWithCategoryMaskBits) const;
|
||||
|
||||
void raycast(RaycastCallback* _raycastCallback,
|
||||
const Ray& _ray,
|
||||
unsigned short _raycastWithCategoryMaskBits) const;
|
||||
/// Test if the AABBs of two bodies overlap
|
||||
bool testAABBOverlap(const CollisionBody* body1,
|
||||
const CollisionBody* body2) const;
|
||||
|
||||
bool testAABBOverlap(const CollisionBody* _body1,
|
||||
const CollisionBody* _body2) const;
|
||||
/// Test if the AABBs of two proxy shapes overlap
|
||||
bool testAABBOverlap(const ProxyShape* shape1,
|
||||
const ProxyShape* shape2) const;
|
||||
|
||||
bool testAABBOverlap(const ProxyShape* _shape1,
|
||||
const ProxyShape* _shape2) const;
|
||||
/// Allow the broadphase to notify the collision detection about an overlapping pair.
|
||||
void broadPhaseNotifyOverlappingPair(ProxyShape* shape1, ProxyShape* shape2);
|
||||
|
||||
void broadPhaseNotifyOverlappingPair(ProxyShape* _shape1, ProxyShape* _shape2);
|
||||
/// Compute the narrow-phase collision detection
|
||||
void computeNarrowPhaseBetweenShapes(CollisionCallback* callback,
|
||||
const std::set<uint32_t>& shapes1,
|
||||
const std::set<uint32_t>& shapes2);
|
||||
|
||||
void computeNarrowPhaseBetweenShapes(CollisionCallback* _callback,
|
||||
const std::set<uint32_t>& _shapes1,
|
||||
const std::set<uint32_t>& _shapes2);
|
||||
/// Return a pointer to the world
|
||||
CollisionWorld* getWorld();
|
||||
|
||||
/// Return the world event listener
|
||||
EventListener* getWorldEventListener();
|
||||
|
||||
/// Return a reference to the world memory allocator
|
||||
MemoryAllocator& getWorldMemoryAllocator();
|
||||
|
||||
/// Called by a narrow-phase collision algorithm when a new contact has been found
|
||||
virtual void notifyContact(OverlappingPair* overlappingPair, const ContactPointInfo& contactInfo);
|
||||
|
||||
virtual void notifyContact(OverlappingPair* _overlappingPair, const ContactPointInfo& _contactInfo);
|
||||
/// Create a new contact
|
||||
void createContact(OverlappingPair* overlappingPair, const ContactPointInfo& contactInfo);
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
void createContact(OverlappingPair* _overlappingPair, const ContactPointInfo& _contactInfo);
|
||||
friend class DynamicsWorld;
|
||||
friend class ConvexMeshShape;
|
||||
};
|
||||
};
|
||||
|
||||
// Return the Narrow-phase collision detection algorithm to use between two types of shapes
|
||||
inline NarrowPhaseAlgorithm* CollisionDetection::getCollisionAlgorithm(CollisionShapeType shape1Type,
|
||||
CollisionShapeType shape2Type) const {
|
||||
NarrowPhaseAlgorithm* CollisionDetection::getCollisionAlgorithm(CollisionShapeType shape1Type, CollisionShapeType shape2Type) const {
|
||||
return m_collisionMatrix[shape1Type][shape2Type];
|
||||
}
|
||||
|
||||
// Set the collision dispatch configuration
|
||||
inline void CollisionDetection::setCollisionDispatch(CollisionDispatch* collisionDispatch) {
|
||||
void CollisionDetection::setCollisionDispatch(CollisionDispatch* collisionDispatch) {
|
||||
m_collisionDispatch = collisionDispatch;
|
||||
|
||||
m_collisionDispatch->init(this, &m_memoryAllocator);
|
||||
@ -227,7 +156,7 @@ inline void CollisionDetection::setCollisionDispatch(CollisionDispatch* collisio
|
||||
}
|
||||
|
||||
// Add a body to the collision detection
|
||||
inline void CollisionDetection::addProxyCollisionShape(ProxyShape* proxyShape,
|
||||
void CollisionDetection::addProxyCollisionShape(ProxyShape* proxyShape,
|
||||
const AABB& aabb) {
|
||||
|
||||
// Add the body to the broad-phase
|
||||
@ -237,13 +166,13 @@ inline void CollisionDetection::addProxyCollisionShape(ProxyShape* proxyShape,
|
||||
}
|
||||
|
||||
// Add a pair of bodies that cannot collide with each other
|
||||
inline void CollisionDetection::addNoCollisionPair(CollisionBody* body1,
|
||||
void CollisionDetection::addNoCollisionPair(CollisionBody* body1,
|
||||
CollisionBody* body2) {
|
||||
m_noCollisionPairs.insert(OverlappingPair::computeBodiesIndexPair(body1, body2));
|
||||
}
|
||||
|
||||
// Remove a pair of bodies that cannot collide with each other
|
||||
inline void CollisionDetection::removeNoCollisionPair(CollisionBody* body1,
|
||||
void CollisionDetection::removeNoCollisionPair(CollisionBody* body1,
|
||||
CollisionBody* body2) {
|
||||
m_noCollisionPairs.erase(OverlappingPair::computeBodiesIndexPair(body1, body2));
|
||||
}
|
||||
@ -251,18 +180,18 @@ inline void CollisionDetection::removeNoCollisionPair(CollisionBody* body1,
|
||||
// Ask for a collision shape to be tested again during broad-phase.
|
||||
/// We simply put the shape in the list of collision shape that have moved in the
|
||||
/// previous frame so that it is tested for collision again in the broad-phase.
|
||||
inline void CollisionDetection::askForBroadPhaseCollisionCheck(ProxyShape* shape) {
|
||||
void CollisionDetection::askForBroadPhaseCollisionCheck(ProxyShape* shape) {
|
||||
m_broadPhaseAlgorithm.addMovedCollisionShape(shape->m_broadPhaseID);
|
||||
}
|
||||
|
||||
// Update a proxy collision shape (that has moved for instance)
|
||||
inline void CollisionDetection::updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb,
|
||||
void CollisionDetection::updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb,
|
||||
const vec3& displacement, bool forceReinsert) {
|
||||
m_broadPhaseAlgorithm.updateProxyCollisionShape(shape, aabb, displacement);
|
||||
}
|
||||
|
||||
// Ray casting method
|
||||
inline void CollisionDetection::raycast(RaycastCallback* raycastCallback,
|
||||
void CollisionDetection::raycast(RaycastCallback* raycastCallback,
|
||||
const Ray& ray,
|
||||
unsigned short raycastWithCategoryMaskBits) const {
|
||||
|
||||
@ -276,7 +205,7 @@ inline void CollisionDetection::raycast(RaycastCallback* raycastCallback,
|
||||
}
|
||||
|
||||
// Test if the AABBs of two proxy shapes overlap
|
||||
inline bool CollisionDetection::testAABBOverlap(const ProxyShape* shape1,
|
||||
bool CollisionDetection::testAABBOverlap(const ProxyShape* shape1,
|
||||
const ProxyShape* shape2) const {
|
||||
|
||||
// If one of the shape's body is not active, we return no overlap
|
||||
@ -288,7 +217,7 @@ inline bool CollisionDetection::testAABBOverlap(const ProxyShape* shape1,
|
||||
}
|
||||
|
||||
// Return a pointer to the world
|
||||
inline CollisionWorld* CollisionDetection::getWorld() {
|
||||
CollisionWorld* CollisionDetection::getWorld() {
|
||||
return m_world;
|
||||
}
|
||||
|
||||
|
@ -5,51 +5,35 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <vector>
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/collision/ProxyShape.hpp>
|
||||
#include <ephysics/constraint/ContactPoint.hpp>
|
||||
#include <ephysics/memory/MemoryAllocator.hpp>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Constants
|
||||
const uint32_t MAX_CONTACT_POINTS_IN_MANIFOLD = 4; // Maximum number of contacts in the manifold
|
||||
const uint32_t MAX_CONTACT_POINTS_IN_MANIFOLD = 4; //!< Maximum number of contacts in the manifold
|
||||
|
||||
// Class declarations
|
||||
class ContactManifold;
|
||||
class ContactManifold;
|
||||
|
||||
// Structure ContactManifoldListElement
|
||||
/**
|
||||
* This structure represents a single element of a linked list of contact manifolds
|
||||
/**
|
||||
* @brief This structure represents a single element of a linked list of contact manifolds
|
||||
*/
|
||||
struct ContactManifoldListElement {
|
||||
|
||||
struct ContactManifoldListElement {
|
||||
public:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Pointer to the actual contact manifold
|
||||
ContactManifold* contactManifold;
|
||||
|
||||
/// Next element of the list
|
||||
ContactManifoldListElement* next;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactManifoldListElement(ContactManifold* initContactManifold,
|
||||
ContactManifoldListElement* initNext)
|
||||
:contactManifold(initContactManifold), next(initNext) {
|
||||
ContactManifold* contactManifold; //!< Pointer to the actual contact manifold
|
||||
ContactManifoldListElement* next; //!< Next element of the list
|
||||
ContactManifoldListElement(ContactManifold* _initContactManifold,
|
||||
ContactManifoldListElement* _initNext):
|
||||
contactManifold(_initContactManifold),
|
||||
next(_initNext) {
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Class ContactManifold
|
||||
/**
|
||||
* This class represents the set of contact points between two bodies.
|
||||
/**
|
||||
* @brief This class represents the set of contact points between two bodies.
|
||||
* The contact manifold is implemented in a way to cache the contact
|
||||
* points among the frames for better stability following the
|
||||
* "Contact Generation" presentation of Erwin Coumans at GDC 2010
|
||||
@ -62,279 +46,209 @@ struct ContactManifoldListElement {
|
||||
* points producing the larger area (for a more stable contact manifold).
|
||||
* The new added point is always kept.
|
||||
*/
|
||||
class ContactManifold {
|
||||
|
||||
class ContactManifold {
|
||||
private:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Pointer to the first proxy shape of the contact
|
||||
ProxyShape* m_shape1;
|
||||
|
||||
/// Pointer to the second proxy shape of the contact
|
||||
ProxyShape* m_shape2;
|
||||
|
||||
/// Contact points in the manifold
|
||||
ContactPoint* m_contactPoints[MAX_CONTACT_POINTS_IN_MANIFOLD];
|
||||
|
||||
/// Normal direction Id (Unique Id representing the normal direction)
|
||||
int16_t m_normalDirectionId;
|
||||
|
||||
/// Number of contacts in the cache
|
||||
uint32_t m_nbContactPoints;
|
||||
|
||||
/// First friction vector of the contact manifold
|
||||
vec3 m_frictionVector1;
|
||||
|
||||
/// Second friction vector of the contact manifold
|
||||
vec3 m_frictionvec2;
|
||||
|
||||
/// First friction constraint accumulated impulse
|
||||
float m_frictionImpulse1;
|
||||
|
||||
/// Second friction constraint accumulated impulse
|
||||
float m_frictionImpulse2;
|
||||
|
||||
/// Twist friction constraint accumulated impulse
|
||||
float m_frictionTwistImpulse;
|
||||
|
||||
/// Accumulated rolling resistance impulse
|
||||
vec3 m_rollingResistanceImpulse;
|
||||
|
||||
/// True if the contact manifold has already been added int32_to an island
|
||||
bool m_isAlreadyInIsland;
|
||||
|
||||
/// Reference to the memory allocator
|
||||
MemoryAllocator& m_memoryAllocator;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
ProxyShape* m_shape1; //!< Pointer to the first proxy shape of the contact
|
||||
ProxyShape* m_shape2; //!< Pointer to the second proxy shape of the contact
|
||||
ContactPoint* m_contactPoints[MAX_CONTACT_POINTS_IN_MANIFOLD]; //!< Contact points in the manifold
|
||||
int16_t m_normalDirectionId; //!< Normal direction Id (Unique Id representing the normal direction)
|
||||
uint32_t m_nbContactPoints; //!< Number of contacts in the cache
|
||||
vec3 m_frictionVector1; //!< First friction vector of the contact manifold
|
||||
vec3 m_frictionvec2; //!< Second friction vector of the contact manifold
|
||||
float m_frictionImpulse1; //!< First friction constraint accumulated impulse
|
||||
float m_frictionImpulse2; //!< Second friction constraint accumulated impulse
|
||||
float m_frictionTwistImpulse; //!< Twist friction constraint accumulated impulse
|
||||
vec3 m_rollingResistanceImpulse; //!< Accumulated rolling resistance impulse
|
||||
bool m_isAlreadyInIsland; //!< True if the contact manifold has already been added int32_to an island
|
||||
MemoryAllocator& m_memoryAllocator; //!< Reference to the memory allocator
|
||||
/// Private copy-constructor
|
||||
ContactManifold(const ContactManifold& contactManifold);
|
||||
|
||||
ContactManifold(const ContactManifold& _contactManifold) = delete;
|
||||
/// Private assignment operator
|
||||
ContactManifold& operator=(const ContactManifold& contactManifold);
|
||||
|
||||
ContactManifold& operator=(const ContactManifold& _contactManifold) = delete;
|
||||
/// Return the index of maximum area
|
||||
int32_t getMaxArea(float area0, float area1, float area2, float area3) const;
|
||||
|
||||
int32_t getMaxArea(float _area0, float _area1, float _area2, float _area3) const;
|
||||
/// Return the index of the contact with the larger penetration depth.
|
||||
int32_t getIndexOfDeepestPenetration(ContactPoint* newContact) const;
|
||||
|
||||
int32_t getIndexOfDeepestPenetration(ContactPoint* _newContact) const;
|
||||
/// Return the index that will be removed.
|
||||
int32_t getIndexToRemove(int32_t indexMaxPenetration, const vec3& newPoint) const;
|
||||
|
||||
int32_t getIndexToRemove(int32_t _indexMaxPenetration, const vec3& _newPoint) const;
|
||||
/// Remove a contact point from the manifold
|
||||
void removeContactPoint(uint32_t index);
|
||||
|
||||
void removeContactPoint(uint32_t _index);
|
||||
/// Return true if the contact manifold has already been added int32_to an island
|
||||
bool isAlreadyInIsland() const;
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactManifold(ProxyShape* shape1, ProxyShape* shape2,
|
||||
MemoryAllocator& memoryAllocator, int16_t normalDirectionId);
|
||||
|
||||
ContactManifold(ProxyShape* _shape1,
|
||||
ProxyShape* _shape2,
|
||||
MemoryAllocator& _memoryAllocator,
|
||||
int16_t _normalDirectionId);
|
||||
/// Destructor
|
||||
~ContactManifold();
|
||||
|
||||
/// Return a pointer to the first proxy shape of the contact
|
||||
ProxyShape* getShape1() const;
|
||||
|
||||
/// Return a pointer to the second proxy shape of the contact
|
||||
ProxyShape* getShape2() const;
|
||||
|
||||
/// Return a pointer to the first body of the contact manifold
|
||||
CollisionBody* getBody1() const;
|
||||
|
||||
/// Return a pointer to the second body of the contact manifold
|
||||
CollisionBody* getBody2() const;
|
||||
|
||||
/// Return the normal direction Id
|
||||
int16_t getNormalDirectionId() const;
|
||||
|
||||
/// Add a contact point to the manifold
|
||||
void addContactPoint(ContactPoint* contact);
|
||||
|
||||
void addContactPoint(ContactPoint* _contact);
|
||||
/// Update the contact manifold.
|
||||
void update(const etk::Transform3D& transform1, const etk::Transform3D& transform2);
|
||||
|
||||
void update(const etk::Transform3D& _transform1,
|
||||
const etk::Transform3D& _transform2);
|
||||
/// Clear the contact manifold
|
||||
void clear();
|
||||
|
||||
/// Return the number of contact points in the manifold
|
||||
uint32_t getNbContactPoints() const;
|
||||
|
||||
/// Return the first friction vector at the center of the contact manifold
|
||||
const vec3& getFrictionVector1() const;
|
||||
|
||||
/// set the first friction vector at the center of the contact manifold
|
||||
void setFrictionVector1(const vec3& m_frictionVector1);
|
||||
|
||||
void setFrictionVector1(const vec3& _frictionVector1);
|
||||
/// Return the second friction vector at the center of the contact manifold
|
||||
const vec3& getFrictionvec2() const;
|
||||
|
||||
/// set the second friction vector at the center of the contact manifold
|
||||
void setFrictionvec2(const vec3& m_frictionvec2);
|
||||
|
||||
void setFrictionvec2(const vec3& _frictionvec2);
|
||||
/// Return the first friction accumulated impulse
|
||||
float getFrictionImpulse1() const;
|
||||
|
||||
/// Set the first friction accumulated impulse
|
||||
void setFrictionImpulse1(float frictionImpulse1);
|
||||
|
||||
void setFrictionImpulse1(float _frictionImpulse1);
|
||||
/// Return the second friction accumulated impulse
|
||||
float getFrictionImpulse2() const;
|
||||
|
||||
/// Set the second friction accumulated impulse
|
||||
void setFrictionImpulse2(float frictionImpulse2);
|
||||
|
||||
void setFrictionImpulse2(float _frictionImpulse2);
|
||||
/// Return the friction twist accumulated impulse
|
||||
float getFrictionTwistImpulse() const;
|
||||
|
||||
/// Set the friction twist accumulated impulse
|
||||
void setFrictionTwistImpulse(float frictionTwistImpulse);
|
||||
|
||||
void setFrictionTwistImpulse(float _frictionTwistImpulse);
|
||||
/// Set the accumulated rolling resistance impulse
|
||||
void setRollingResistanceImpulse(const vec3& rollingResistanceImpulse);
|
||||
|
||||
void setRollingResistanceImpulse(const vec3& _rollingResistanceImpulse);
|
||||
/// Return a contact point of the manifold
|
||||
ContactPoint* getContactPoint(uint32_t index) const;
|
||||
|
||||
ContactPoint* getContactPoint(uint32_t _index) const;
|
||||
/// Return the normalized averaged normal vector
|
||||
vec3 getAverageContactNormal() const;
|
||||
|
||||
/// Return the largest depth of all the contact points
|
||||
float getLargestContactDepth() const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicsWorld;
|
||||
friend class Island;
|
||||
friend class CollisionBody;
|
||||
};
|
||||
};
|
||||
|
||||
// Return a pointer to the first proxy shape of the contact
|
||||
inline ProxyShape* ContactManifold::getShape1() const {
|
||||
ProxyShape* ContactManifold::getShape1() const {
|
||||
return m_shape1;
|
||||
}
|
||||
|
||||
// Return a pointer to the second proxy shape of the contact
|
||||
inline ProxyShape* ContactManifold::getShape2() const {
|
||||
ProxyShape* ContactManifold::getShape2() const {
|
||||
return m_shape2;
|
||||
}
|
||||
|
||||
// Return a pointer to the first body of the contact manifold
|
||||
inline CollisionBody* ContactManifold::getBody1() const {
|
||||
CollisionBody* ContactManifold::getBody1() const {
|
||||
return m_shape1->getBody();
|
||||
}
|
||||
|
||||
// Return a pointer to the second body of the contact manifold
|
||||
inline CollisionBody* ContactManifold::getBody2() const {
|
||||
CollisionBody* ContactManifold::getBody2() const {
|
||||
return m_shape2->getBody();
|
||||
}
|
||||
|
||||
// Return the normal direction Id
|
||||
inline int16_t ContactManifold::getNormalDirectionId() const {
|
||||
int16_t ContactManifold::getNormalDirectionId() const {
|
||||
return m_normalDirectionId;
|
||||
}
|
||||
|
||||
// Return the number of contact points in the manifold
|
||||
inline uint32_t ContactManifold::getNbContactPoints() const {
|
||||
uint32_t ContactManifold::getNbContactPoints() const {
|
||||
return m_nbContactPoints;
|
||||
}
|
||||
|
||||
// Return the first friction vector at the center of the contact manifold
|
||||
inline const vec3& ContactManifold::getFrictionVector1() const {
|
||||
const vec3& ContactManifold::getFrictionVector1() const {
|
||||
return m_frictionVector1;
|
||||
}
|
||||
|
||||
// set the first friction vector at the center of the contact manifold
|
||||
inline void ContactManifold::setFrictionVector1(const vec3& frictionVector1) {
|
||||
void ContactManifold::setFrictionVector1(const vec3& frictionVector1) {
|
||||
m_frictionVector1 = frictionVector1;
|
||||
}
|
||||
|
||||
// Return the second friction vector at the center of the contact manifold
|
||||
inline const vec3& ContactManifold::getFrictionvec2() const {
|
||||
const vec3& ContactManifold::getFrictionvec2() const {
|
||||
return m_frictionvec2;
|
||||
}
|
||||
|
||||
// set the second friction vector at the center of the contact manifold
|
||||
inline void ContactManifold::setFrictionvec2(const vec3& frictionvec2) {
|
||||
void ContactManifold::setFrictionvec2(const vec3& frictionvec2) {
|
||||
m_frictionvec2 = frictionvec2;
|
||||
}
|
||||
|
||||
// Return the first friction accumulated impulse
|
||||
inline float ContactManifold::getFrictionImpulse1() const {
|
||||
float ContactManifold::getFrictionImpulse1() const {
|
||||
return m_frictionImpulse1;
|
||||
}
|
||||
|
||||
// Set the first friction accumulated impulse
|
||||
inline void ContactManifold::setFrictionImpulse1(float frictionImpulse1) {
|
||||
void ContactManifold::setFrictionImpulse1(float frictionImpulse1) {
|
||||
m_frictionImpulse1 = frictionImpulse1;
|
||||
}
|
||||
|
||||
// Return the second friction accumulated impulse
|
||||
inline float ContactManifold::getFrictionImpulse2() const {
|
||||
float ContactManifold::getFrictionImpulse2() const {
|
||||
return m_frictionImpulse2;
|
||||
}
|
||||
|
||||
// Set the second friction accumulated impulse
|
||||
inline void ContactManifold::setFrictionImpulse2(float frictionImpulse2) {
|
||||
void ContactManifold::setFrictionImpulse2(float frictionImpulse2) {
|
||||
m_frictionImpulse2 = frictionImpulse2;
|
||||
}
|
||||
|
||||
// Return the friction twist accumulated impulse
|
||||
inline float ContactManifold::getFrictionTwistImpulse() const {
|
||||
float ContactManifold::getFrictionTwistImpulse() const {
|
||||
return m_frictionTwistImpulse;
|
||||
}
|
||||
|
||||
// Set the friction twist accumulated impulse
|
||||
inline void ContactManifold::setFrictionTwistImpulse(float frictionTwistImpulse) {
|
||||
void ContactManifold::setFrictionTwistImpulse(float frictionTwistImpulse) {
|
||||
m_frictionTwistImpulse = frictionTwistImpulse;
|
||||
}
|
||||
|
||||
// Set the accumulated rolling resistance impulse
|
||||
inline void ContactManifold::setRollingResistanceImpulse(const vec3& rollingResistanceImpulse) {
|
||||
void ContactManifold::setRollingResistanceImpulse(const vec3& rollingResistanceImpulse) {
|
||||
m_rollingResistanceImpulse = rollingResistanceImpulse;
|
||||
}
|
||||
|
||||
// Return a contact point of the manifold
|
||||
inline ContactPoint* ContactManifold::getContactPoint(uint32_t index) const {
|
||||
ContactPoint* ContactManifold::getContactPoint(uint32_t index) const {
|
||||
assert(index < m_nbContactPoints);
|
||||
return m_contactPoints[index];
|
||||
}
|
||||
|
||||
// Return true if the contact manifold has already been added int32_to an island
|
||||
inline bool ContactManifold::isAlreadyInIsland() const {
|
||||
bool ContactManifold::isAlreadyInIsland() const {
|
||||
return m_isAlreadyInIsland;
|
||||
}
|
||||
|
||||
// Return the normalized averaged normal vector
|
||||
inline vec3 ContactManifold::getAverageContactNormal() const {
|
||||
vec3 ContactManifold::getAverageContactNormal() const {
|
||||
vec3 averageNormal;
|
||||
|
||||
for (uint32_t i=0; i<m_nbContactPoints; i++) {
|
||||
averageNormal += m_contactPoints[i]->getNormal();
|
||||
}
|
||||
|
||||
return averageNormal.safeNormalized();
|
||||
}
|
||||
|
||||
// Return the largest depth of all the contact points
|
||||
inline float ContactManifold::getLargestContactDepth() const {
|
||||
float ContactManifold::getLargestContactDepth() const {
|
||||
float largestDepth = 0.0f;
|
||||
|
||||
for (uint32_t i=0; i<m_nbContactPoints; i++) {
|
||||
float depth = m_contactPoints[i]->getPenetrationDepth();
|
||||
if (depth > largestDepth) {
|
||||
largestDepth = depth;
|
||||
}
|
||||
}
|
||||
|
||||
return largestDepth;
|
||||
}
|
||||
|
||||
|
@ -5,121 +5,84 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/ContactManifold.hpp>
|
||||
|
||||
namespace ephysics {
|
||||
|
||||
// Constants
|
||||
const int32_t MAX_MANIFOLDS_IN_CONTACT_MANIFOLD_SET = 3; // Maximum number of contact manifolds in the set
|
||||
const int32_t CONTACT_CUBEMAP_FACE_NB_SUBDIVISIONS = 3; // N Number for the N x N subdivisions of the cubemap
|
||||
|
||||
// Class ContactManifoldSet
|
||||
/**
|
||||
* This class represents a set of one or several contact manifolds. Typically a
|
||||
const int32_t MAX_MANIFOLDS_IN_CONTACT_MANIFOLD_SET = 3; // Maximum number of contact manifolds in the set
|
||||
const int32_t CONTACT_CUBEMAP_FACE_NB_SUBDIVISIONS = 3; // N Number for the N x N subdivisions of the cubemap
|
||||
/**
|
||||
* @brief This class represents a set of one or several contact manifolds. Typically a
|
||||
* convex/convex collision will have a set with a single manifold and a convex-concave
|
||||
* collision can have more than one manifolds. Note that a contact manifold can
|
||||
* contains several contact points.
|
||||
*/
|
||||
class ContactManifoldSet {
|
||||
|
||||
class ContactManifoldSet {
|
||||
private:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Maximum number of contact manifolds in the set
|
||||
int32_t m_nbMaxManifolds;
|
||||
|
||||
/// Current number of contact manifolds in the set
|
||||
int32_t m_nbManifolds;
|
||||
|
||||
/// Pointer to the first proxy shape of the contact
|
||||
ProxyShape* m_shape1;
|
||||
|
||||
/// Pointer to the second proxy shape of the contact
|
||||
ProxyShape* m_shape2;
|
||||
|
||||
/// Reference to the memory allocator
|
||||
MemoryAllocator& m_memoryAllocator;
|
||||
|
||||
/// Contact manifolds of the set
|
||||
ContactManifold* m_manifolds[MAX_MANIFOLDS_IN_CONTACT_MANIFOLD_SET];
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
int32_t m_nbMaxManifolds; //!< Maximum number of contact manifolds in the set
|
||||
int32_t m_nbManifolds; //!< Current number of contact manifolds in the set
|
||||
ProxyShape* m_shape1; //!< Pointer to the first proxy shape of the contact
|
||||
ProxyShape* m_shape2; //!< Pointer to the second proxy shape of the contact
|
||||
MemoryAllocator& m_memoryAllocator; //!< Reference to the memory allocator
|
||||
ContactManifold* m_manifolds[MAX_MANIFOLDS_IN_CONTACT_MANIFOLD_SET]; //!< Contact manifolds of the set
|
||||
/// Create a new contact manifold and add it to the set
|
||||
void createManifold(short normalDirectionId);
|
||||
|
||||
void createManifold(short _normalDirectionId);
|
||||
/// Remove a contact manifold from the set
|
||||
void removeManifold(int32_t index);
|
||||
|
||||
void removeManifold(int32_t _index);
|
||||
// Return the index of the contact manifold with a similar average normal.
|
||||
int32_t selectManifoldWithSimilarNormal(int16_t normalDirectionId) const;
|
||||
|
||||
int32_t selectManifoldWithSimilarNormal(int16_t _normalDirectionId) const;
|
||||
// Map the normal vector int32_to a cubemap face bucket (a face contains 4x4 buckets)
|
||||
// Each face of the cube is divided int32_to 4x4 buckets. This method maps the
|
||||
// normal vector int32_to of the of the bucket and returns a unique Id for the bucket
|
||||
int16_t computeCubemapNormalId(const vec3& normal) const;
|
||||
|
||||
int16_t computeCubemapNormalId(const vec3& _normal) const;
|
||||
public:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactManifoldSet(ProxyShape* shape1, ProxyShape* shape2,
|
||||
MemoryAllocator& memoryAllocator, int32_t nbMaxManifolds);
|
||||
|
||||
ContactManifoldSet(ProxyShape* _shape1,
|
||||
ProxyShape* _shape2,
|
||||
MemoryAllocator& _memoryAllocator,
|
||||
int32_t _nbMaxManifolds);
|
||||
/// Destructor
|
||||
~ContactManifoldSet();
|
||||
|
||||
/// Return the first proxy shape
|
||||
ProxyShape* getShape1() const;
|
||||
|
||||
/// Return the second proxy shape
|
||||
ProxyShape* getShape2() const;
|
||||
|
||||
/// Add a contact point to the manifold set
|
||||
void addContactPoint(ContactPoint* contact);
|
||||
|
||||
void addContactPoint(ContactPoint* _contact);
|
||||
/// Update the contact manifolds
|
||||
void update();
|
||||
|
||||
/// Clear the contact manifold set
|
||||
void clear();
|
||||
|
||||
/// Return the number of manifolds in the set
|
||||
int32_t getNbContactManifolds() const;
|
||||
|
||||
/// Return a given contact manifold
|
||||
ContactManifold* getContactManifold(int32_t index) const;
|
||||
|
||||
ContactManifold* getContactManifold(int32_t _index) const;
|
||||
/// Return the total number of contact points in the set of manifolds
|
||||
int32_t getTotalNbContactPoints() const;
|
||||
};
|
||||
};
|
||||
|
||||
// Return the first proxy shape
|
||||
inline ProxyShape* ContactManifoldSet::getShape1() const {
|
||||
ProxyShape* ContactManifoldSet::getShape1() const {
|
||||
return m_shape1;
|
||||
}
|
||||
|
||||
// Return the second proxy shape
|
||||
inline ProxyShape* ContactManifoldSet::getShape2() const {
|
||||
ProxyShape* ContactManifoldSet::getShape2() const {
|
||||
return m_shape2;
|
||||
}
|
||||
|
||||
// Return the number of manifolds in the set
|
||||
inline int32_t ContactManifoldSet::getNbContactManifolds() const {
|
||||
int32_t ContactManifoldSet::getNbContactManifolds() const {
|
||||
return m_nbManifolds;
|
||||
}
|
||||
|
||||
// Return a given contact manifold
|
||||
inline ContactManifold* ContactManifoldSet::getContactManifold(int32_t index) const {
|
||||
ContactManifold* ContactManifoldSet::getContactManifold(int32_t index) const {
|
||||
assert(index >= 0 && index < m_nbManifolds);
|
||||
return m_manifolds[index];
|
||||
}
|
||||
|
||||
// Return the total number of contact points in the set of manifolds
|
||||
inline int32_t ContactManifoldSet::getTotalNbContactPoints() const {
|
||||
int32_t ContactManifoldSet::getTotalNbContactPoints() const {
|
||||
int32_t nbPoints = 0;
|
||||
for (int32_t i=0; i<m_nbManifolds; i++) {
|
||||
nbPoints += m_manifolds[i]->getNbContactPoints();
|
||||
|
@ -157,7 +157,7 @@ class ProxyShape {
|
||||
};
|
||||
|
||||
// Return the pointer to the cached collision data
|
||||
inline void** ProxyShape::getCachedCollisionData() {
|
||||
void** ProxyShape::getCachedCollisionData() {
|
||||
return &m_cachedCollisionData;
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ inline void** ProxyShape::getCachedCollisionData() {
|
||||
/**
|
||||
* @return Pointer to the int32_ternal collision shape
|
||||
*/
|
||||
inline const CollisionShape* ProxyShape::getCollisionShape() const {
|
||||
const CollisionShape* ProxyShape::getCollisionShape() const {
|
||||
return m_collisionShape;
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ inline const CollisionShape* ProxyShape::getCollisionShape() const {
|
||||
/**
|
||||
* @return Pointer to the parent body
|
||||
*/
|
||||
inline CollisionBody* ProxyShape::getBody() const {
|
||||
CollisionBody* ProxyShape::getBody() const {
|
||||
return m_body;
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ inline CollisionBody* ProxyShape::getBody() const {
|
||||
/**
|
||||
* @return Mass of the collision shape (in kilograms)
|
||||
*/
|
||||
inline float ProxyShape::getMass() const {
|
||||
float ProxyShape::getMass() const {
|
||||
return m_mass;
|
||||
}
|
||||
|
||||
@ -189,7 +189,7 @@ inline float ProxyShape::getMass() const {
|
||||
/**
|
||||
* @return A pointer to the user data stored int32_to the proxy shape
|
||||
*/
|
||||
inline void* ProxyShape::getUserData() const {
|
||||
void* ProxyShape::getUserData() const {
|
||||
return m_userData;
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ inline void* ProxyShape::getUserData() const {
|
||||
/**
|
||||
* @param userData Pointer to the user data you want to store within the proxy shape
|
||||
*/
|
||||
inline void ProxyShape::setUserData(void* userData) {
|
||||
void ProxyShape::setUserData(void* userData) {
|
||||
m_userData = userData;
|
||||
}
|
||||
|
||||
@ -206,12 +206,12 @@ inline void ProxyShape::setUserData(void* userData) {
|
||||
* @return The transformation that transforms the local-space of the collision shape
|
||||
* to the local-space of the parent body
|
||||
*/
|
||||
inline const etk::Transform3D& ProxyShape::getLocalToBodyTransform() const {
|
||||
const etk::Transform3D& ProxyShape::getLocalToBodyTransform() const {
|
||||
return m_localToBodyTransform;
|
||||
}
|
||||
|
||||
// Set the local to parent body transform
|
||||
inline void ProxyShape::setLocalToBodyTransform(const etk::Transform3D& transform) {
|
||||
void ProxyShape::setLocalToBodyTransform(const etk::Transform3D& transform) {
|
||||
|
||||
m_localToBodyTransform = transform;
|
||||
|
||||
@ -226,7 +226,7 @@ inline void ProxyShape::setLocalToBodyTransform(const etk::Transform3D& transfor
|
||||
* @return The transformation that transforms the local-space of the collision
|
||||
* shape to the world-space
|
||||
*/
|
||||
inline const etk::Transform3D ProxyShape::getLocalToWorldTransform() const {
|
||||
const etk::Transform3D ProxyShape::getLocalToWorldTransform() const {
|
||||
return m_body->m_transform * m_localToBodyTransform;
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ inline const etk::Transform3D ProxyShape::getLocalToWorldTransform() const {
|
||||
/**
|
||||
* @return Pointer to the next proxy shape in the linked list of proxy shapes
|
||||
*/
|
||||
inline ProxyShape* ProxyShape::getNext() {
|
||||
ProxyShape* ProxyShape::getNext() {
|
||||
return m_next;
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ inline ProxyShape* ProxyShape::getNext() {
|
||||
/**
|
||||
* @return Pointer to the next proxy shape in the linked list of proxy shapes
|
||||
*/
|
||||
inline const ProxyShape* ProxyShape::getNext() const {
|
||||
const ProxyShape* ProxyShape::getNext() const {
|
||||
return m_next;
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ inline const ProxyShape* ProxyShape::getNext() const {
|
||||
/**
|
||||
* @return The collision category bits mask of the proxy shape
|
||||
*/
|
||||
inline unsigned short ProxyShape::getCollisionCategoryBits() const {
|
||||
unsigned short ProxyShape::getCollisionCategoryBits() const {
|
||||
return m_collisionCategoryBits;
|
||||
}
|
||||
|
||||
@ -258,7 +258,7 @@ inline unsigned short ProxyShape::getCollisionCategoryBits() const {
|
||||
/**
|
||||
* @param collisionCategoryBits The collision category bits mask of the proxy shape
|
||||
*/
|
||||
inline void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits) {
|
||||
void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits) {
|
||||
m_collisionCategoryBits = collisionCategoryBits;
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ inline void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategor
|
||||
/**
|
||||
* @return The bits mask that specifies with which collision category this shape will collide
|
||||
*/
|
||||
inline unsigned short ProxyShape::getCollideWithMaskBits() const {
|
||||
unsigned short ProxyShape::getCollideWithMaskBits() const {
|
||||
return m_collideWithMaskBits;
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ inline unsigned short ProxyShape::getCollideWithMaskBits() const {
|
||||
/**
|
||||
* @param collideWithMaskBits The bits mask that specifies with which collision category this shape will collide
|
||||
*/
|
||||
inline void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
|
||||
void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
|
||||
m_collideWithMaskBits = collideWithMaskBits;
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ inline void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBit
|
||||
/**
|
||||
* @return The local scaling vector
|
||||
*/
|
||||
inline vec3 ProxyShape::getLocalScaling() const {
|
||||
vec3 ProxyShape::getLocalScaling() const {
|
||||
return m_collisionShape->getScaling();
|
||||
}
|
||||
|
||||
@ -290,7 +290,7 @@ inline vec3 ProxyShape::getLocalScaling() const {
|
||||
/**
|
||||
* @param scaling The new local scaling vector
|
||||
*/
|
||||
inline void ProxyShape::setLocalScaling(const vec3& scaling) {
|
||||
void ProxyShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
// Set the local scaling of the collision shape
|
||||
m_collisionShape->setLocalScaling(scaling);
|
||||
|
@ -4,17 +4,9 @@
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/TriangleMesh.hpp>
|
||||
|
||||
using namespace ephysics;
|
||||
|
||||
// Constructor
|
||||
TriangleMesh::TriangleMesh() {
|
||||
ephysics::TriangleMesh::TriangleMesh() {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
TriangleMesh::~TriangleMesh() {
|
||||
|
||||
}
|
||||
|
@ -4,63 +4,50 @@
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <ephysics/collision/TriangleVertexArray.hpp>
|
||||
|
||||
namespace ephysics {
|
||||
|
||||
// Class TriangleMesh
|
||||
/**
|
||||
* This class represents a mesh made of triangles. A TriangleMesh contains
|
||||
/**
|
||||
* @brief Represents a mesh made of triangles. A TriangleMesh contains
|
||||
* one or several parts. Each part is a set of triangles represented in a
|
||||
* TriangleVertexArray object describing all the triangles vertices of the part.
|
||||
* A TriangleMesh object is used to create a ConcaveMeshShape from a triangle
|
||||
* mesh for instance.
|
||||
*/
|
||||
class TriangleMesh {
|
||||
|
||||
class TriangleMesh {
|
||||
protected:
|
||||
|
||||
/// All the triangle arrays of the mesh (one triangle array per part)
|
||||
std::vector<TriangleVertexArray*> m_triangleArrays;
|
||||
|
||||
std::vector<TriangleVertexArray*> m_triangleArrays; //!< All the triangle arrays of the mesh (one triangle array per part)
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
TriangleMesh();
|
||||
|
||||
/// Destructor
|
||||
virtual ~TriangleMesh();
|
||||
|
||||
/// Add a subpart of the mesh
|
||||
void addSubpart(TriangleVertexArray* triangleVertexArray);
|
||||
|
||||
/// Return a pointer to a given subpart (triangle vertex array) of the mesh
|
||||
TriangleVertexArray* getSubpart(uint32_t indexSubpart) const;
|
||||
|
||||
/// Return the number of subparts of the mesh
|
||||
uint32_t getNbSubparts() const;
|
||||
};
|
||||
|
||||
// Add a subpart of the mesh
|
||||
inline void TriangleMesh::addSubpart(TriangleVertexArray* triangleVertexArray) {
|
||||
m_triangleArrays.push_back(triangleVertexArray );
|
||||
}
|
||||
|
||||
// Return a pointer to a given subpart (triangle vertex array) of the mesh
|
||||
inline TriangleVertexArray* TriangleMesh::getSubpart(uint32_t indexSubpart) const {
|
||||
assert(indexSubpart < m_triangleArrays.size());
|
||||
return m_triangleArrays[indexSubpart];
|
||||
}
|
||||
|
||||
// Return the number of subparts of the mesh
|
||||
inline uint32_t TriangleMesh::getNbSubparts() const {
|
||||
/**
|
||||
* @brief Virtualisation of Destructor
|
||||
*/
|
||||
virtual ~TriangleMesh() = default;
|
||||
/**
|
||||
* @brief Add a subpart of the mesh
|
||||
*/
|
||||
void addSubpart(TriangleVertexArray* _triangleVertexArray) {
|
||||
m_triangleArrays.push_back(_triangleVertexArray );
|
||||
}
|
||||
/**
|
||||
* @brief Get a pointer to a given subpart (triangle vertex array) of the mesh
|
||||
*/
|
||||
TriangleVertexArray* getSubpart(uint32_t _indexSubpart) const {
|
||||
assert(_indexSubpart < m_triangleArrays.size());
|
||||
return m_triangleArrays[_indexSubpart];
|
||||
}
|
||||
/**
|
||||
* @brief Get the number of subparts of the mesh
|
||||
*/
|
||||
uint32_t getNbSubparts() const {
|
||||
return m_triangleArrays.size();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,12 +5,9 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/configuration.hpp>
|
||||
|
||||
namespace ephysics {
|
||||
|
||||
// Class TriangleVertexArray
|
||||
/**
|
||||
* This class is used to describe the vertices and faces of a triangular mesh.
|
||||
* A TriangleVertexArray represents a continuous array of vertices and indexes
|
||||
@ -21,9 +18,7 @@ namespace ephysics {
|
||||
* remains valid during the TriangleVertexArray life.
|
||||
*/
|
||||
class TriangleVertexArray {
|
||||
|
||||
public:
|
||||
|
||||
/// Data type for the vertices in the array
|
||||
enum VertexDataType {VERTEX_FLOAT_TYPE, VERTEX_DOUBLE_TYPE};
|
||||
|
||||
@ -31,35 +26,15 @@ class TriangleVertexArray {
|
||||
enum IndexDataType {INDEX_INTEGER_TYPE, INDEX_SHORT_TYPE};
|
||||
|
||||
protected:
|
||||
|
||||
/// Number of vertices in the array
|
||||
uint32_t m_numberVertices;
|
||||
|
||||
/// Pointer to the first vertex value in the array
|
||||
unsigned char* m_verticesStart;
|
||||
|
||||
/// Stride (number of bytes) between the beginning of two vertices
|
||||
/// values in the array
|
||||
int32_t m_verticesStride;
|
||||
|
||||
/// Number of triangles in the array
|
||||
uint32_t m_numberTriangles;
|
||||
|
||||
/// Pointer to the first vertex index of the array
|
||||
unsigned char* m_indicesStart;
|
||||
|
||||
/// Stride (number of bytes) between the beginning of two indices in
|
||||
/// the array
|
||||
int32_t m_indicesStride;
|
||||
|
||||
/// Data type of the vertices in the array
|
||||
VertexDataType m_vertexDataType;
|
||||
|
||||
/// Data type of the indices in the array
|
||||
IndexDataType m_indexDataType;
|
||||
|
||||
uint32_t m_numberVertices; //!< Number of vertices in the array
|
||||
unsigned char* m_verticesStart; //!< Pointer to the first vertex value in the array
|
||||
int32_t m_verticesStride; //!< Stride (number of bytes) between the beginning of two vertices values in the array
|
||||
uint32_t m_numberTriangles; //!< Number of triangles in the array
|
||||
unsigned char* m_indicesStart; //!< Pointer to the first vertex index of the array
|
||||
int32_t m_indicesStride; //!< Stride (number of bytes) between the beginning of two indices in the array
|
||||
VertexDataType m_vertexDataType; //!< Data type of the vertices in the array
|
||||
IndexDataType m_indexDataType; //!< Data type of the indices in the array
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
TriangleVertexArray(uint32_t nbVertices, void* verticesStart, int32_t verticesStride,
|
||||
uint32_t nbTriangles, void* indexesStart, int32_t indexesStride,
|
||||
|
@ -9,10 +9,8 @@
|
||||
#include <ephysics/collision/CollisionDetection.hpp>
|
||||
#include <ephysics/engine/Profiler.hpp>
|
||||
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace ephysics;
|
||||
|
||||
// Constructor
|
||||
BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection)
|
||||
:m_dynamicAABBTree(DYNAMIC_TREE_AABB_GAP), m_numberMovedShapes(0), m_numberAllocatedMovedShapes(8),
|
||||
m_numberNonUsedMovedShapes(0), m_numberPotentialPairs(0), m_numberAllocatedPotentialPairs(8),
|
||||
@ -27,7 +25,6 @@ BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection)
|
||||
assert(m_potentialPairs != NULL);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
BroadPhaseAlgorithm::~BroadPhaseAlgorithm() {
|
||||
|
||||
// Release the memory for the array of non-static proxy shapes IDs
|
||||
@ -37,8 +34,6 @@ BroadPhaseAlgorithm::~BroadPhaseAlgorithm() {
|
||||
free(m_potentialPairs);
|
||||
}
|
||||
|
||||
// Add a collision shape in the array of shapes that have moved in the last simulation step
|
||||
// and that need to be tested again for broad-phase overlapping.
|
||||
void BroadPhaseAlgorithm::addMovedCollisionShape(int32_t broadPhaseID) {
|
||||
|
||||
// Allocate more elements in the array of shapes that have moved if necessary
|
||||
@ -58,8 +53,6 @@ void BroadPhaseAlgorithm::addMovedCollisionShape(int32_t broadPhaseID) {
|
||||
m_numberMovedShapes++;
|
||||
}
|
||||
|
||||
// Remove a collision shape from the array of shapes that have moved in the last simulation step
|
||||
// and that need to be tested again for broad-phase overlapping.
|
||||
void BroadPhaseAlgorithm::removeMovedCollisionShape(int32_t broadPhaseID) {
|
||||
|
||||
assert(m_numberNonUsedMovedShapes <= m_numberMovedShapes);
|
||||
@ -95,7 +88,6 @@ void BroadPhaseAlgorithm::removeMovedCollisionShape(int32_t broadPhaseID) {
|
||||
}
|
||||
}
|
||||
|
||||
// Add a proxy collision shape int32_to the broad-phase collision detection
|
||||
void BroadPhaseAlgorithm::addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb) {
|
||||
|
||||
// Add the collision shape int32_to the dynamic AABB tree and get its broad-phase ID
|
||||
@ -109,7 +101,6 @@ void BroadPhaseAlgorithm::addProxyCollisionShape(ProxyShape* proxyShape, const A
|
||||
addMovedCollisionShape(proxyShape->m_broadPhaseID);
|
||||
}
|
||||
|
||||
// Remove a proxy collision shape from the broad-phase collision detection
|
||||
void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
||||
|
||||
int32_t broadPhaseID = proxyShape->m_broadPhaseID;
|
||||
@ -122,7 +113,6 @@ void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
||||
removeMovedCollisionShape(broadPhaseID);
|
||||
}
|
||||
|
||||
// Notify the broad-phase that a collision shape has moved and need to be updated
|
||||
void BroadPhaseAlgorithm::updateProxyCollisionShape(ProxyShape* _proxyShape,
|
||||
const AABB& _aabb,
|
||||
const vec3& _displacement,
|
||||
@ -140,7 +130,6 @@ void BroadPhaseAlgorithm::updateProxyCollisionShape(ProxyShape* _proxyShape,
|
||||
}
|
||||
}
|
||||
|
||||
// Compute all the overlapping pairs of collision shapes
|
||||
void BroadPhaseAlgorithm::computeOverlappingPairs() {
|
||||
|
||||
// Reset the potential overlapping pairs
|
||||
@ -218,7 +207,6 @@ void BroadPhaseAlgorithm::computeOverlappingPairs() {
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree
|
||||
void BroadPhaseAlgorithm::notifyOverlappingNodes(int32_t node1ID, int32_t node2ID) {
|
||||
|
||||
// If both the nodes are the same, we do not create store the overlapping pair
|
||||
@ -242,14 +230,11 @@ void BroadPhaseAlgorithm::notifyOverlappingNodes(int32_t node1ID, int32_t node2I
|
||||
m_numberPotentialPairs++;
|
||||
}
|
||||
|
||||
// Called when a overlapping node has been found during the call to
|
||||
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
||||
void AABBOverlapCallback::notifyOverlappingNode(int32_t nodeId) {
|
||||
|
||||
m_broadPhaseAlgorithm.notifyOverlappingNodes(m_referenceNodeId, nodeId);
|
||||
}
|
||||
|
||||
// Called for a broad-phase shape that has to be tested for raycast
|
||||
float BroadPhaseRaycastCallback::raycastBroadPhaseShape(int32_t nodeId, const Ray& ray) {
|
||||
|
||||
float hitFraction = float(-1.0);
|
||||
@ -268,3 +253,22 @@ float BroadPhaseRaycastCallback::raycastBroadPhaseShape(int32_t nodeId, const Ra
|
||||
|
||||
return hitFraction;
|
||||
}
|
||||
|
||||
bool BroadPhaseAlgorithm::testOverlappingShapes(const _ProxyShape* shape1,
|
||||
const ProxyShape* _shape2) const {
|
||||
// Get the two AABBs of the collision shapes
|
||||
const AABB& aabb1 = m_dynamicAABBTree.getFatAABB(_shape1->m_broadPhaseID);
|
||||
const AABB& aabb2 = m_dynamicAABBTree.getFatAABB(_shape2->m_broadPhaseID);
|
||||
|
||||
// Check if the two AABBs are overlapping
|
||||
return aabb1.testCollision(aabb2);
|
||||
}
|
||||
|
||||
void BroadPhaseAlgorithm::raycast(const Ray& _ray,
|
||||
RaycastTest& _raycastTest,
|
||||
unsigned short _raycastWithCategoryMaskBits) const {
|
||||
PROFILE("BroadPhaseAlgorithm::raycast()");
|
||||
BroadPhaseRaycastCallback broadPhaseRaycastCallback(m_dynamicAABBTree, _raycastWithCategoryMaskBits, _raycastTest);
|
||||
m_dynamicAABBTree.raycast(_ray, broadPhaseRaycastCallback);
|
||||
}
|
||||
|
||||
|
@ -5,223 +5,131 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <vector>
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/collision/ProxyShape.hpp>
|
||||
#include <ephysics/collision/broadphase/DynamicAABBTree.hpp>
|
||||
#include <ephysics/engine/Profiler.hpp>
|
||||
|
||||
/// Namespace ReactPhysics3D
|
||||
namespace ephysics {
|
||||
|
||||
// Declarations
|
||||
class CollisionDetection;
|
||||
class BroadPhaseAlgorithm;
|
||||
class CollisionDetection;
|
||||
class BroadPhaseAlgorithm;
|
||||
|
||||
// Structure BroadPhasePair
|
||||
/**
|
||||
* This structure represent a potential overlapping pair during the
|
||||
/**
|
||||
* @brief It represent a potential overlapping pair during the
|
||||
* broad-phase collision detection.
|
||||
*/
|
||||
struct BroadPhasePair {
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Broad-phase ID of the first collision shape
|
||||
int32_t collisionShape1ID;
|
||||
|
||||
/// Broad-phase ID of the second collision shape
|
||||
int32_t collisionShape2ID;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Method used to compare two pairs for sorting algorithm
|
||||
static bool smallerThan(const BroadPhasePair& pair1, const BroadPhasePair& pair2);
|
||||
};
|
||||
|
||||
// class AABBOverlapCallback
|
||||
class AABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
|
||||
struct BroadPhasePair {
|
||||
int32_t collisionShape1ID; //!< Broad-phase ID of the first collision shape
|
||||
int32_t collisionShape2ID; //!< Broad-phase ID of the second collision shape
|
||||
/**
|
||||
* @brief Method used to compare two pairs for sorting algorithm
|
||||
* @param[in] _pair1 first pair of element
|
||||
* @param[in] _pair2 Second pair of element
|
||||
* @return _pair1 is smaller than _pair2
|
||||
*/
|
||||
static bool smallerThan(const BroadPhasePair& _pair1, const BroadPhasePair& _pair2) {
|
||||
if (_pair1.collisionShape1ID < _pair2.collisionShape1ID) return true;
|
||||
if (_pair1.collisionShape1ID == _pair2.collisionShape1ID) {
|
||||
return _pair1.collisionShape2ID < _pair2.collisionShape2ID;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class AABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
|
||||
private:
|
||||
|
||||
BroadPhaseAlgorithm& m_broadPhaseAlgorithm;
|
||||
|
||||
int32_t m_referenceNodeId;
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
AABBOverlapCallback(BroadPhaseAlgorithm& broadPhaseAlgo, int32_t referenceNodeId)
|
||||
: m_broadPhaseAlgorithm(broadPhaseAlgo), m_referenceNodeId(referenceNodeId) {
|
||||
AABBOverlapCallback(BroadPhaseAlgorithm& _broadPhaseAlgo, int32_t _referenceNodeId):
|
||||
m_broadPhaseAlgorithm(_broadPhaseAlgo),
|
||||
m_referenceNodeId(_referenceNodeId) {
|
||||
|
||||
}
|
||||
|
||||
// Called when a overlapping node has been found during the call to
|
||||
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
||||
virtual void notifyOverlappingNode(int32_t nodeId);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Class BroadPhaseRaycastCallback
|
||||
/**
|
||||
/**
|
||||
* Callback called when the AABB of a leaf node is hit by a ray the
|
||||
* broad-phase Dynamic AABB Tree.
|
||||
*/
|
||||
class BroadPhaseRaycastCallback : public DynamicAABBTreeRaycastCallback {
|
||||
|
||||
class BroadPhaseRaycastCallback : public DynamicAABBTreeRaycastCallback {
|
||||
private :
|
||||
|
||||
const DynamicAABBTree& m_dynamicAABBTree;
|
||||
|
||||
unsigned short m_raycastWithCategoryMaskBits;
|
||||
|
||||
RaycastTest& m_raycastTest;
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
BroadPhaseRaycastCallback(const DynamicAABBTree& dynamicAABBTree, unsigned short raycastWithCategoryMaskBits,
|
||||
RaycastTest& raycastTest)
|
||||
: m_dynamicAABBTree(dynamicAABBTree), m_raycastWithCategoryMaskBits(raycastWithCategoryMaskBits),
|
||||
m_raycastTest(raycastTest) {
|
||||
BroadPhaseRaycastCallback(const DynamicAABBTree& _dynamicAABBTree,
|
||||
unsigned short _raycastWithCategoryMaskBits,
|
||||
RaycastTest& _raycastTest):
|
||||
m_dynamicAABBTree(_dynamicAABBTree),
|
||||
m_raycastWithCategoryMaskBits(_raycastWithCategoryMaskBits),
|
||||
m_raycastTest(_raycastTest) {
|
||||
|
||||
}
|
||||
|
||||
// Called for a broad-phase shape that has to be tested for raycast
|
||||
virtual float raycastBroadPhaseShape(int32_t nodeId, const Ray& ray);
|
||||
virtual float raycastBroadPhaseShape(int32_t _nodeId, const Ray& _ray);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Class BroadPhaseAlgorithm
|
||||
/**
|
||||
* This class represents the broad-phase collision detection. The
|
||||
/**
|
||||
* @brief It represents the broad-phase collision detection. The
|
||||
* goal of the broad-phase collision detection is to compute the pairs of proxy shapes
|
||||
* that have their AABBs overlapping. Only those pairs of bodies will be tested
|
||||
* later for collision during the narrow-phase collision detection. A dynamic AABB
|
||||
* tree data structure is used for fast broad-phase collision detection.
|
||||
*/
|
||||
class BroadPhaseAlgorithm {
|
||||
|
||||
class BroadPhaseAlgorithm {
|
||||
protected :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Dynamic AABB tree
|
||||
DynamicAABBTree m_dynamicAABBTree;
|
||||
|
||||
/// Array with the broad-phase IDs of all collision shapes that have moved (or have been
|
||||
/// created) during the last simulation step. Those are the shapes that need to be tested
|
||||
/// for overlapping in the next simulation step.
|
||||
int32_t* m_movedShapes;
|
||||
|
||||
/// Number of collision shapes in the array of shapes that have moved during the last
|
||||
/// simulation step.
|
||||
uint32_t m_numberMovedShapes;
|
||||
|
||||
/// Number of allocated elements for the array of shapes that have moved during the last
|
||||
/// simulation step.
|
||||
uint32_t m_numberAllocatedMovedShapes;
|
||||
|
||||
/// Number of non-used elements in the array of shapes that have moved during the last
|
||||
/// simulation step.
|
||||
uint32_t m_numberNonUsedMovedShapes;
|
||||
|
||||
/// Temporary array of potential overlapping pairs (with potential duplicates)
|
||||
BroadPhasePair* m_potentialPairs;
|
||||
|
||||
/// Number of potential overlapping pairs
|
||||
uint32_t m_numberPotentialPairs;
|
||||
|
||||
/// Number of allocated elements for the array of potential overlapping pairs
|
||||
uint32_t m_numberAllocatedPotentialPairs;
|
||||
|
||||
/// Reference to the collision detection object
|
||||
CollisionDetection& m_collisionDetection;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
DynamicAABBTree m_dynamicAABBTree; //!< Dynamic AABB tree
|
||||
int32_t* m_movedShapes; //!< Array with the broad-phase IDs of all collision shapes that have moved (or have been created) during the last simulation step. Those are the shapes that need to be tested for overlapping in the next simulation step.
|
||||
uint32_t m_numberMovedShapes; //!< Number of collision shapes in the array of shapes that have moved during the last simulation step.
|
||||
uint32_t m_numberAllocatedMovedShapes; //!< Number of allocated elements for the array of shapes that have moved during the last simulation step.
|
||||
uint32_t m_numberNonUsedMovedShapes; //!< Number of non-used elements in the array of shapes that have moved during the last simulation step.
|
||||
BroadPhasePair* m_potentialPairs; //!< Temporary array of potential overlapping pairs (with potential duplicates)
|
||||
uint32_t m_numberPotentialPairs; //!< Number of potential overlapping pairs
|
||||
uint32_t m_numberAllocatedPotentialPairs; //!< Number of allocated elements for the array of potential overlapping pairs
|
||||
CollisionDetection& m_collisionDetection; //!< Reference to the collision detection object
|
||||
/// Private copy-constructor
|
||||
BroadPhaseAlgorithm(const BroadPhaseAlgorithm& algorithm);
|
||||
|
||||
/// Private assignment operator
|
||||
BroadPhaseAlgorithm& operator=(const BroadPhaseAlgorithm& algorithm);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
BroadPhaseAlgorithm(CollisionDetection& collisionDetection);
|
||||
|
||||
BroadPhaseAlgorithm(CollisionDetection& _collisionDetection);
|
||||
/// Destructor
|
||||
virtual ~BroadPhaseAlgorithm();
|
||||
|
||||
/// Add a proxy collision shape int32_to the broad-phase collision detection
|
||||
void addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb);
|
||||
|
||||
void addProxyCollisionShape(ProxyShape* _proxyShape, const AABB& _aabb);
|
||||
/// Remove a proxy collision shape from the broad-phase collision detection
|
||||
void removeProxyCollisionShape(ProxyShape* proxyShape);
|
||||
|
||||
void removeProxyCollisionShape(ProxyShape* _proxyShape);
|
||||
/// Notify the broad-phase that a collision shape has moved and need to be updated
|
||||
void updateProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb,
|
||||
const vec3& displacement, bool forceReinsert = false);
|
||||
|
||||
void updateProxyCollisionShape(ProxyShape* _proxyShape,
|
||||
const AABB& _aabb,
|
||||
const vec3& _displacement,
|
||||
bool _forceReinsert = false);
|
||||
/// Add a collision shape in the array of shapes that have moved in the last simulation step
|
||||
/// and that need to be tested again for broad-phase overlapping.
|
||||
void addMovedCollisionShape(int32_t broadPhaseID);
|
||||
|
||||
void addMovedCollisionShape(int32_t _broadPhaseID);
|
||||
/// Remove a collision shape from the array of shapes that have moved in the last simulation
|
||||
/// step and that need to be tested again for broad-phase overlapping.
|
||||
void removeMovedCollisionShape(int32_t broadPhaseID);
|
||||
|
||||
void removeMovedCollisionShape(int32_t _broadPhaseID);
|
||||
/// Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree
|
||||
void notifyOverlappingNodes(int32_t broadPhaseId1, int32_t broadPhaseId2);
|
||||
|
||||
void notifyOverlappingNodes(int32_t _broadPhaseId1, int32_t _broadPhaseId2);
|
||||
/// Compute all the overlapping pairs of collision shapes
|
||||
void computeOverlappingPairs();
|
||||
|
||||
/// Return true if the two broad-phase collision shapes are overlapping
|
||||
bool testOverlappingShapes(const ProxyShape* shape1, const ProxyShape* shape2) const;
|
||||
|
||||
bool testOverlappingShapes(const ProxyShape* _shape1, const ProxyShape* _shape2) const;
|
||||
/// Ray casting method
|
||||
void raycast(const Ray& ray, RaycastTest& raycastTest,
|
||||
unsigned short raycastWithCategoryMaskBits) const;
|
||||
};
|
||||
|
||||
// Method used to compare two pairs for sorting algorithm
|
||||
inline bool BroadPhasePair::smallerThan(const BroadPhasePair& pair1, const BroadPhasePair& pair2) {
|
||||
|
||||
if (pair1.collisionShape1ID < pair2.collisionShape1ID) return true;
|
||||
if (pair1.collisionShape1ID == pair2.collisionShape1ID) {
|
||||
return pair1.collisionShape2ID < pair2.collisionShape2ID;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if the two broad-phase collision shapes are overlapping
|
||||
inline bool BroadPhaseAlgorithm::testOverlappingShapes(const ProxyShape* shape1,
|
||||
const ProxyShape* shape2) const {
|
||||
// Get the two AABBs of the collision shapes
|
||||
const AABB& aabb1 = m_dynamicAABBTree.getFatAABB(shape1->m_broadPhaseID);
|
||||
const AABB& aabb2 = m_dynamicAABBTree.getFatAABB(shape2->m_broadPhaseID);
|
||||
|
||||
// Check if the two AABBs are overlapping
|
||||
return aabb1.testCollision(aabb2);
|
||||
}
|
||||
|
||||
// Ray casting method
|
||||
inline void BroadPhaseAlgorithm::raycast(const Ray& ray, RaycastTest& raycastTest,
|
||||
unsigned short raycastWithCategoryMaskBits) const {
|
||||
|
||||
PROFILE("BroadPhaseAlgorithm::raycast()");
|
||||
|
||||
BroadPhaseRaycastCallback broadPhaseRaycastCallback(m_dynamicAABBTree, raycastWithCategoryMaskBits, raycastTest);
|
||||
|
||||
m_dynamicAABBTree.raycast(ray, broadPhaseRaycastCallback);
|
||||
}
|
||||
void raycast(const Ray& _ray,
|
||||
RaycastTest& _raycastTest,
|
||||
unsigned short _raycastWithCategoryMaskBits) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -216,38 +216,38 @@ class DynamicAABBTree {
|
||||
};
|
||||
|
||||
// Return true if the node is a leaf of the tree
|
||||
inline bool TreeNode::isLeaf() const {
|
||||
bool TreeNode::isLeaf() const {
|
||||
return (height == 0);
|
||||
}
|
||||
|
||||
// Return the fat AABB corresponding to a given node ID
|
||||
inline const AABB& DynamicAABBTree::getFatAABB(int32_t nodeID) const {
|
||||
const AABB& DynamicAABBTree::getFatAABB(int32_t nodeID) const {
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
return m_nodes[nodeID].aabb;
|
||||
}
|
||||
|
||||
// Return the pointer to the data array of a given leaf node of the tree
|
||||
inline int32_t* DynamicAABBTree::getNodeDataInt(int32_t nodeID) const {
|
||||
int32_t* DynamicAABBTree::getNodeDataInt(int32_t nodeID) const {
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
return m_nodes[nodeID].dataInt;
|
||||
}
|
||||
|
||||
// Return the pointer to the data pointer of a given leaf node of the tree
|
||||
inline void* DynamicAABBTree::getNodeDataPointer(int32_t nodeID) const {
|
||||
void* DynamicAABBTree::getNodeDataPointer(int32_t nodeID) const {
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
return m_nodes[nodeID].dataPointer;
|
||||
}
|
||||
|
||||
// Return the root AABB of the tree
|
||||
inline AABB DynamicAABBTree::getRootAABB() const {
|
||||
AABB DynamicAABBTree::getRootAABB() const {
|
||||
return getFatAABB(m_rootNodeID);
|
||||
}
|
||||
|
||||
// Add an object int32_to the tree. This method creates a new leaf node in the tree and
|
||||
// returns the ID of the corresponding node.
|
||||
inline int32_t DynamicAABBTree::addObject(const AABB& aabb, int32_t data1, int32_t data2) {
|
||||
int32_t DynamicAABBTree::addObject(const AABB& aabb, int32_t data1, int32_t data2) {
|
||||
|
||||
int32_t nodeId = addObjectInternal(aabb);
|
||||
|
||||
@ -259,7 +259,7 @@ inline int32_t DynamicAABBTree::addObject(const AABB& aabb, int32_t data1, int32
|
||||
|
||||
// Add an object int32_to the tree. This method creates a new leaf node in the tree and
|
||||
// returns the ID of the corresponding node.
|
||||
inline int32_t DynamicAABBTree::addObject(const AABB& aabb, void* data) {
|
||||
int32_t DynamicAABBTree::addObject(const AABB& aabb, void* data) {
|
||||
|
||||
int32_t nodeId = addObjectInternal(aabb);
|
||||
|
||||
|
@ -5,39 +5,29 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp>
|
||||
|
||||
namespace ephysics {
|
||||
|
||||
// Class CollisionDispatch
|
||||
/**
|
||||
* This is the abstract base class for dispatching the narrow-phase
|
||||
/**
|
||||
* @biref Abstract base class for dispatching the narrow-phase
|
||||
* collision detection algorithm. Collision dispatching decides which collision
|
||||
* algorithm to use given two types of proxy collision shapes.
|
||||
*/
|
||||
class CollisionDispatch {
|
||||
|
||||
protected:
|
||||
|
||||
class CollisionDispatch {
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
CollisionDispatch() {}
|
||||
|
||||
/// Destructor
|
||||
virtual ~CollisionDispatch() {}
|
||||
|
||||
virtual ~CollisionDispatch() = default;
|
||||
/// Initialize the collision dispatch configuration
|
||||
virtual void init(CollisionDetection* collisionDetection,
|
||||
MemoryAllocator* memoryAllocator) {
|
||||
virtual void init(CollisionDetection* _collisionDetection,
|
||||
MemoryAllocator* _memoryAllocator) {
|
||||
}
|
||||
|
||||
/// Select and return the narrow-phase collision detection algorithm to
|
||||
/// use between two types of collision shapes.
|
||||
virtual NarrowPhaseAlgorithm* selectAlgorithm(int32_t shape1Type,
|
||||
int32_t shape2Type)=0;
|
||||
};
|
||||
virtual NarrowPhaseAlgorithm* selectAlgorithm(int32_t _shape1Type,
|
||||
int32_t _shape2Type) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -88,28 +88,28 @@ void ConcaveVsConvexAlgorithm::testCollision(const CollisionShapeInfo& shape1Inf
|
||||
void ConvexVsTriangleCallback::testTriangle(const vec3* trianglePoints) {
|
||||
|
||||
// Create a triangle collision shape
|
||||
float margin = mConcaveShape->getTriangleMargin();
|
||||
float margin = m_concaveShape->getTriangleMargin();
|
||||
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2], margin);
|
||||
|
||||
// Select the collision algorithm to use between the triangle and the convex shape
|
||||
NarrowPhaseAlgorithm* algo = m_collisionDetection->getCollisionAlgorithm(triangleShape.getType(),
|
||||
mConvexShape->getType());
|
||||
m_convexShape->getType());
|
||||
|
||||
// If there is no collision algorithm between those two kinds of shapes
|
||||
if (algo == NULL) return;
|
||||
|
||||
// Notify the narrow-phase algorithm about the overlapping pair we are going to test
|
||||
algo->setCurrentOverlappingPair(mOverlappingPair);
|
||||
algo->setCurrentOverlappingPair(m_overlappingPair);
|
||||
|
||||
// Create the CollisionShapeInfo objects
|
||||
CollisionShapeInfo shapeConvexInfo(mConvexProxyShape, mConvexShape, mConvexProxyShape->getLocalToWorldTransform(),
|
||||
mOverlappingPair, mConvexProxyShape->getCachedCollisionData());
|
||||
CollisionShapeInfo shapeConcaveInfo(mConcaveProxyShape, &triangleShape,
|
||||
mConcaveProxyShape->getLocalToWorldTransform(),
|
||||
mOverlappingPair, mConcaveProxyShape->getCachedCollisionData());
|
||||
CollisionShapeInfo shapeConvexInfo(m_convexProxyShape, m_convexShape, m_convexProxyShape->getLocalToWorldTransform(),
|
||||
m_overlappingPair, m_convexProxyShape->getCachedCollisionData());
|
||||
CollisionShapeInfo shapeConcaveInfo(m_concaveProxyShape, &triangleShape,
|
||||
m_concaveProxyShape->getLocalToWorldTransform(),
|
||||
m_overlappingPair, m_concaveProxyShape->getCachedCollisionData());
|
||||
|
||||
// Use the collision algorithm to test collision between the triangle and the other convex shape
|
||||
algo->testCollision(shapeConvexInfo, shapeConcaveInfo, mNarrowPhaseCallback);
|
||||
algo->testCollision(shapeConvexInfo, shapeConcaveInfo, m_narrowPhaseCallback);
|
||||
}
|
||||
|
||||
// Process the concave triangle mesh collision using the smooth mesh collision algorithm described
|
||||
|
@ -5,207 +5,140 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp>
|
||||
#include <ephysics/collision/shapes/ConvexShape.hpp>
|
||||
#include <ephysics/collision/shapes/ConcaveShape.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
/// Namespace ReactPhysics3D
|
||||
namespace ephysics {
|
||||
|
||||
// Class ConvexVsTriangleCallback
|
||||
/**
|
||||
* This class is used to encapsulate a callback method for
|
||||
/**
|
||||
* @brief This class is used to encapsulate a callback method for
|
||||
* collision detection between the triangle of a concave mesh shape
|
||||
* and a convex shape.
|
||||
*/
|
||||
class ConvexVsTriangleCallback : public TriangleCallback {
|
||||
|
||||
class ConvexVsTriangleCallback : public TriangleCallback {
|
||||
protected:
|
||||
|
||||
/// Pointer to the collision detection object
|
||||
CollisionDetection* m_collisionDetection;
|
||||
|
||||
/// Narrow-phase collision callback
|
||||
NarrowPhaseCallback* mNarrowPhaseCallback;
|
||||
|
||||
/// Convex collision shape to test collision with
|
||||
const ConvexShape* mConvexShape;
|
||||
|
||||
/// Concave collision shape
|
||||
const ConcaveShape* mConcaveShape;
|
||||
|
||||
/// Proxy shape of the convex collision shape
|
||||
ProxyShape* mConvexProxyShape;
|
||||
|
||||
/// Proxy shape of the concave collision shape
|
||||
ProxyShape* mConcaveProxyShape;
|
||||
|
||||
/// Broadphase overlapping pair
|
||||
OverlappingPair* mOverlappingPair;
|
||||
|
||||
/// Used to sort ContactPointInfos according to their penetration depth
|
||||
static bool contactsDepthCompare(const ContactPointInfo& contact1,
|
||||
const ContactPointInfo& contact2);
|
||||
|
||||
CollisionDetection* m_collisionDetection; //!< Pointer to the collision detection object
|
||||
NarrowPhaseCallback* m_narrowPhaseCallback; //!< Narrow-phase collision callback
|
||||
const ConvexShape* m_convexShape; //!< Convex collision shape to test collision with
|
||||
const ConcaveShape* m_concaveShape; //!< Concave collision shape
|
||||
ProxyShape* m_convexProxyShape; //!< Proxy shape of the convex collision shape
|
||||
ProxyShape* m_concaveProxyShape; //!< Proxy shape of the concave collision shape
|
||||
OverlappingPair* m_overlappingPair; //!< Broadphase overlapping pair
|
||||
static bool contactsDepthCompare(const ContactPointInfo& _contact1,
|
||||
const ContactPointInfo& _contact2);
|
||||
public:
|
||||
|
||||
/// Set the collision detection pointer
|
||||
void setCollisionDetection(CollisionDetection* collisionDetection) {
|
||||
m_collisionDetection = collisionDetection;
|
||||
void setCollisionDetection(CollisionDetection* _collisionDetection) {
|
||||
m_collisionDetection = _collisionDetection;
|
||||
}
|
||||
|
||||
/// Set the narrow-phase collision callback
|
||||
void setNarrowPhaseCallback(NarrowPhaseCallback* callback) {
|
||||
mNarrowPhaseCallback = callback;
|
||||
void setNarrowPhaseCallback(NarrowPhaseCallback* _callback) {
|
||||
m_narrowPhaseCallback = _callback;
|
||||
}
|
||||
|
||||
/// Set the convex collision shape to test collision with
|
||||
void setConvexShape(const ConvexShape* convexShape) {
|
||||
mConvexShape = convexShape;
|
||||
void setConvexShape(const ConvexShape* _convexShape) {
|
||||
m_convexShape = _convexShape;
|
||||
}
|
||||
|
||||
/// Set the concave collision shape
|
||||
void setConcaveShape(const ConcaveShape* concaveShape) {
|
||||
mConcaveShape = concaveShape;
|
||||
void setConcaveShape(const ConcaveShape* _concaveShape) {
|
||||
m_concaveShape = _concaveShape;
|
||||
}
|
||||
|
||||
/// Set the broadphase overlapping pair
|
||||
void setOverlappingPair(OverlappingPair* overlappingPair) {
|
||||
mOverlappingPair = overlappingPair;
|
||||
void setOverlappingPair(OverlappingPair* _overlappingPair) {
|
||||
m_overlappingPair = _overlappingPair;
|
||||
}
|
||||
|
||||
/// Set the proxy shapes of the two collision shapes
|
||||
void setProxyShapes(ProxyShape* convexProxyShape, ProxyShape* concaveProxyShape) {
|
||||
mConvexProxyShape = convexProxyShape;
|
||||
mConcaveProxyShape = concaveProxyShape;
|
||||
void setProxyShapes(ProxyShape* _convexProxyShape, ProxyShape* _concaveProxyShape) {
|
||||
m_convexProxyShape = _convexProxyShape;
|
||||
m_concaveProxyShape = _concaveProxyShape;
|
||||
}
|
||||
|
||||
/// Test collision between a triangle and the convex mesh shape
|
||||
virtual void testTriangle(const vec3* trianglePoints);
|
||||
};
|
||||
virtual void testTriangle(const vec3* _trianglePoints);
|
||||
};
|
||||
|
||||
// Class SmoothMeshContactInfo
|
||||
/**
|
||||
* This class is used to store data about a contact with a triangle for the smooth
|
||||
/**
|
||||
* @brief This class is used to store data about a contact with a triangle for the smooth
|
||||
* mesh algorithm.
|
||||
*/
|
||||
class SmoothMeshContactInfo {
|
||||
|
||||
class SmoothMeshContactInfo {
|
||||
public:
|
||||
|
||||
ContactPointInfo contactInfo;
|
||||
bool isFirstShapeTriangle;
|
||||
vec3 triangleVertices[3];
|
||||
|
||||
/// Constructor
|
||||
SmoothMeshContactInfo(const ContactPointInfo& contact, bool firstShapeTriangle, const vec3& trianglePoint1,
|
||||
const vec3& trianglePoint2, const vec3& trianglePoint3)
|
||||
: contactInfo(contact) {
|
||||
isFirstShapeTriangle = firstShapeTriangle;
|
||||
triangleVertices[0] = trianglePoint1;
|
||||
triangleVertices[1] = trianglePoint2;
|
||||
triangleVertices[2] = trianglePoint3;
|
||||
SmoothMeshContactInfo(const ContactPointInfo& _contact,
|
||||
bool _firstShapeTriangle,
|
||||
const vec3& _trianglePoint1,
|
||||
const vec3& _trianglePoint2,
|
||||
const vec3& _trianglePoint3):
|
||||
contactInfo(_contact) {
|
||||
isFirstShapeTriangle = _firstShapeTriangle;
|
||||
triangleVertices[0] = _trianglePoint1;
|
||||
triangleVertices[1] = _trianglePoint2;
|
||||
triangleVertices[2] = _trianglePoint3;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
struct ContactsDepthCompare {
|
||||
bool operator()(const SmoothMeshContactInfo& contact1, const SmoothMeshContactInfo& contact2)
|
||||
{
|
||||
return contact1.contactInfo.penetrationDepth < contact2.contactInfo.penetrationDepth;
|
||||
struct ContactsDepthCompare {
|
||||
bool operator()(const SmoothMeshContactInfo& _contact1, const SmoothMeshContactInfo& _contact2) {
|
||||
return _contact1.contactInfo.penetrationDepth < _contact2.contactInfo.penetrationDepth;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/// Method used to compare two smooth mesh contact info to sort them
|
||||
//inline static bool contactsDepthCompare(const SmoothMeshContactInfo& contact1,
|
||||
// const SmoothMeshContactInfo& contact2) {
|
||||
// return contact1.contactInfo.penetrationDepth < contact2.contactInfo.penetrationDepth;
|
||||
//}
|
||||
|
||||
// Class SmoothCollisionNarrowPhaseCallback
|
||||
/**
|
||||
* This class is used as a narrow-phase callback to get narrow-phase contacts
|
||||
/**
|
||||
* @brief This class is used as a narrow-phase callback to get narrow-phase contacts
|
||||
* of the concave triangle mesh to temporary store them in order to be used in
|
||||
* the smooth mesh collision algorithm if this one is enabled.
|
||||
*/
|
||||
class SmoothCollisionNarrowPhaseCallback : public NarrowPhaseCallback {
|
||||
|
||||
class SmoothCollisionNarrowPhaseCallback : public NarrowPhaseCallback {
|
||||
private:
|
||||
|
||||
std::vector<SmoothMeshContactInfo>& m_contactPoints;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
SmoothCollisionNarrowPhaseCallback(std::vector<SmoothMeshContactInfo>& contactPoints)
|
||||
: m_contactPoints(contactPoints) {
|
||||
SmoothCollisionNarrowPhaseCallback(std::vector<SmoothMeshContactInfo>& _contactPoints):
|
||||
m_contactPoints(_contactPoints) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Called by a narrow-phase collision algorithm when a new contact has been found
|
||||
virtual void notifyContact(OverlappingPair* overlappingPair,
|
||||
const ContactPointInfo& contactInfo);
|
||||
virtual void notifyContact(OverlappingPair* _overlappingPair, const ContactPointInfo& _contactInfo);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Class ConcaveVsConvexAlgorithm
|
||||
/**
|
||||
* This class is used to compute the narrow-phase collision detection
|
||||
/**
|
||||
* @brief This class is used to compute the narrow-phase collision detection
|
||||
* between a concave collision shape and a convex collision shape. The idea is
|
||||
* to use the GJK collision detection algorithm to compute the collision between
|
||||
* the convex shape and each of the triangles in the concave shape.
|
||||
*/
|
||||
class ConcaveVsConvexAlgorithm : public NarrowPhaseAlgorithm {
|
||||
|
||||
class ConcaveVsConvexAlgorithm : public NarrowPhaseAlgorithm {
|
||||
protected :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private copy-constructor
|
||||
ConcaveVsConvexAlgorithm(const ConcaveVsConvexAlgorithm& algorithm);
|
||||
|
||||
ConcaveVsConvexAlgorithm(const ConcaveVsConvexAlgorithm& _algorithm);
|
||||
/// Private assignment operator
|
||||
ConcaveVsConvexAlgorithm& operator=(const ConcaveVsConvexAlgorithm& algorithm);
|
||||
|
||||
ConcaveVsConvexAlgorithm& operator=(const ConcaveVsConvexAlgorithm& _algorithm);
|
||||
/// Process the concave triangle mesh collision using the smooth mesh collision algorithm
|
||||
void processSmoothMeshCollision(OverlappingPair* overlappingPair,
|
||||
std::vector<SmoothMeshContactInfo> contactPoints,
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
|
||||
void processSmoothMeshCollision(OverlappingPair* _overlappingPair,
|
||||
std::vector<SmoothMeshContactInfo> _contactPoints,
|
||||
NarrowPhaseCallback* _narrowPhaseCallback);
|
||||
/// Add a triangle vertex int32_to the set of processed triangles
|
||||
void addProcessedVertex(std::unordered_multimap<int32_t, vec3>& processTriangleVertices,
|
||||
const vec3& vertex);
|
||||
|
||||
void addProcessedVertex(std::unordered_multimap<int32_t, vec3>& _processTriangleVertices,
|
||||
const vec3& _vertex) {
|
||||
processTriangleVertices.insert(std::make_pair(int32_t(vertex.x() * vertex.y() * vertex.z()), vertex));
|
||||
}
|
||||
/// Return true if the vertex is in the set of already processed vertices
|
||||
bool hasVertexBeenProcessed(const std::unordered_multimap<int32_t, vec3>& processTriangleVertices,
|
||||
const vec3& vertex) const;
|
||||
|
||||
bool hasVertexBeenProcessed(const std::unordered_multimap<int32_t, vec3>& _processTriangleVertices,
|
||||
const vec3& _vertex) const;
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ConcaveVsConvexAlgorithm();
|
||||
|
||||
/// Destructor
|
||||
virtual ~ConcaveVsConvexAlgorithm();
|
||||
|
||||
/// Compute a contact info if the two bounding volume collide
|
||||
virtual void testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
};
|
||||
|
||||
// Add a triangle vertex int32_to the set of processed triangles
|
||||
inline void ConcaveVsConvexAlgorithm::addProcessedVertex(std::unordered_multimap<int32_t, vec3>& processTriangleVertices, const vec3& vertex) {
|
||||
processTriangleVertices.insert(std::make_pair(int32_t(vertex.x() * vertex.y() * vertex.z()), vertex));
|
||||
}
|
||||
virtual void testCollision(const CollisionShapeInfo& _shape1Info,
|
||||
const CollisionShapeInfo& _shape2Info,
|
||||
NarrowPhaseCallback* _narrowPhaseCallback);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ class NarrowPhaseAlgorithm {
|
||||
};
|
||||
|
||||
// Set the current overlapping pair of bodies
|
||||
inline void NarrowPhaseAlgorithm::setCurrentOverlappingPair(OverlappingPair* overlappingPair) {
|
||||
void NarrowPhaseAlgorithm::setCurrentOverlappingPair(OverlappingPair* overlappingPair) {
|
||||
mCurrentOverlappingPair = overlappingPair;
|
||||
}
|
||||
|
||||
|
@ -4,53 +4,46 @@
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/narrowphase/SphereVsSphereAlgorithm.hpp>
|
||||
#include <ephysics/collision/shapes/SphereShape.hpp>
|
||||
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace ephysics;
|
||||
|
||||
// Constructor
|
||||
SphereVsSphereAlgorithm::SphereVsSphereAlgorithm() :
|
||||
ephysics::SphereVsSphereAlgorithm::SphereVsSphereAlgorithm() :
|
||||
NarrowPhaseAlgorithm() {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
SphereVsSphereAlgorithm::~SphereVsSphereAlgorithm() {
|
||||
|
||||
}
|
||||
|
||||
void SphereVsSphereAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
NarrowPhaseCallback* narrowPhaseCallback) {
|
||||
void ephysics::SphereVsSphereAlgorithm::testCollision(const ephysics::CollisionShapeInfo& _shape1Info,
|
||||
const ephysics::CollisionShapeInfo& _shape2Info,
|
||||
ephysics::NarrowPhaseCallback* _narrowPhaseCallback) {
|
||||
// Get the sphere collision shapes
|
||||
const SphereShape* sphereShape1 = static_cast<const SphereShape*>(shape1Info.collisionShape);
|
||||
const SphereShape* sphereShape2 = static_cast<const SphereShape*>(shape2Info.collisionShape);
|
||||
const ephysics::SphereShape* sphereShape1 = static_cast<const ephysics::SphereShape*>(_shape1Info.collisionShape);
|
||||
const ephysics::SphereShape* sphereShape2 = static_cast<const ephysics::SphereShape*>(_shape2Info.collisionShape);
|
||||
// Get the local-space to world-space transforms
|
||||
const etk::Transform3D& transform1 = shape1Info.shapeToWorldTransform;
|
||||
const etk::Transform3D& transform2 = shape2Info.shapeToWorldTransform;
|
||||
const etk::Transform3D& transform1 = _shape1Info.shapeToWorldTransform;
|
||||
const etk::Transform3D& transform2 = _shape2Info.shapeToWorldTransform;
|
||||
// Compute the distance between the centers
|
||||
vec3 vectorBetweenCenters = transform2.getPosition() - transform1.getPosition();
|
||||
float squaredDistanceBetweenCenters = vectorBetweenCenters.length2();
|
||||
// Compute the sum of the radius
|
||||
float sumRadius = sphereShape1->getRadius() + sphereShape2->getRadius();
|
||||
// If the sphere collision shapes int32_tersect
|
||||
float sumRadius = _sphereShape1->getRadius() + sphereShape2->getRadius();
|
||||
// If the sphere collision shapes intersect
|
||||
if (squaredDistanceBetweenCenters <= sumRadius * sumRadius) {
|
||||
vec3 centerSphere2InBody1LocalSpace = transform1.getInverse() * transform2.getPosition();
|
||||
vec3 centerSphere1InBody2LocalSpace = transform2.getInverse() * transform1.getPosition();
|
||||
vec3 int32_tersectionOnBody1 = sphereShape1->getRadius() *
|
||||
centerSphere2InBody1LocalSpace.safeNormalized();
|
||||
vec3 int32_tersectionOnBody2 = sphereShape2->getRadius() *
|
||||
centerSphere1InBody2LocalSpace.safeNormalized();
|
||||
vec3 intersectionOnBody1 = sphereShape1->getRadius() * centerSphere2InBody1LocalSpace.safeNormalized();
|
||||
vec3 intersectionOnBody2 = sphereShape2->getRadius() * centerSphere1InBody2LocalSpace.safeNormalized();
|
||||
float penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters);
|
||||
|
||||
// Create the contact info object
|
||||
ContactPointInfo contactInfo(shape1Info.proxyShape, shape2Info.proxyShape, shape1Info.collisionShape,
|
||||
shape2Info.collisionShape, vectorBetweenCenters.safeNormalized(), penetrationDepth,
|
||||
int32_tersectionOnBody1, int32_tersectionOnBody2);
|
||||
ephysics::ContactPointInfo contactInfo(_shape1Info.proxyShape,
|
||||
_shape2Info.proxyShape,
|
||||
_shape1Info.collisionShape,
|
||||
_shape2Info.collisionShape,
|
||||
vectorBetweenCenters.safeNormalized(),
|
||||
penetrationDepth,
|
||||
intersectionOnBody1,
|
||||
intersectionOnBody2);
|
||||
// Notify about the new contact
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
_narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
}
|
||||
}
|
||||
|
@ -5,46 +5,34 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/body/Body.hpp>
|
||||
#include <ephysics/constraint/ContactPoint.hpp>
|
||||
#include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp>
|
||||
|
||||
|
||||
/// Namespace ReactPhysics3D
|
||||
namespace ephysics {
|
||||
|
||||
// Class SphereVsSphereAlgorithm
|
||||
/**
|
||||
* This class is used to compute the narrow-phase collision detection
|
||||
* @brief It is used to compute the narrow-phase collision detection
|
||||
* between two sphere collision shapes.
|
||||
*/
|
||||
class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
|
||||
|
||||
protected :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private copy-constructor
|
||||
SphereVsSphereAlgorithm(const SphereVsSphereAlgorithm& algorithm);
|
||||
|
||||
/// Private assignment operator
|
||||
SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm);
|
||||
|
||||
SphereVsSphereAlgorithm(const SphereVsSphereAlgorithm& algorithm) = delete;
|
||||
SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm) = delete;
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
SphereVsSphereAlgorithm();
|
||||
|
||||
/// Destructor
|
||||
virtual ~SphereVsSphereAlgorithm();
|
||||
|
||||
/// Compute a contact info if the two bounding volume collide
|
||||
virtual void testCollision(const CollisionShapeInfo& shape1Info,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~SphereVsSphereAlgorithm() = default;
|
||||
/**
|
||||
* @brief Compute a contact info if the two bounding volume collide
|
||||
*/
|
||||
virtual void testCollision(const CollisionShapeInfo& _shape1Info,
|
||||
const CollisionShapeInfo& _shape2Info,
|
||||
NarrowPhaseCallback* _narrowPhaseCallback);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -25,95 +25,88 @@ AABB::AABB(const vec3& minCoordinates, const vec3& maxCoordinates):
|
||||
|
||||
}
|
||||
|
||||
AABB::AABB(const AABB& aabb):
|
||||
m_minCoordinates(aabb.m_minCoordinates),
|
||||
m_maxCoordinates(aabb.m_maxCoordinates) {
|
||||
AABB::AABB(const AABB& _aabb):
|
||||
m_minCoordinates(_aabb.m_minCoordinates),
|
||||
m_maxCoordinates(_aabb.m_maxCoordinates) {
|
||||
|
||||
}
|
||||
|
||||
// Merge the AABB in parameter with the current one
|
||||
void AABB::mergeWithAABB(const AABB& aabb) {
|
||||
m_minCoordinates.setX(std::min(m_minCoordinates.x(), aabb.m_minCoordinates.x()));
|
||||
m_minCoordinates.setY(std::min(m_minCoordinates.y(), aabb.m_minCoordinates.y()));
|
||||
m_minCoordinates.setZ(std::min(m_minCoordinates.z(), aabb.m_minCoordinates.z()));
|
||||
m_maxCoordinates.setX(std::max(m_maxCoordinates.x(), aabb.m_maxCoordinates.x()));
|
||||
m_maxCoordinates.setY(std::max(m_maxCoordinates.y(), aabb.m_maxCoordinates.y()));
|
||||
m_maxCoordinates.setZ(std::max(m_maxCoordinates.z(), aabb.m_maxCoordinates.z()));
|
||||
void AABB::mergeWithAABB(const AABB& _aabb) {
|
||||
m_minCoordinates.setX(std::min(m_minCoordinates.x(), _aabb.m_minCoordinates.x()));
|
||||
m_minCoordinates.setY(std::min(m_minCoordinates.y(), _aabb.m_minCoordinates.y()));
|
||||
m_minCoordinates.setZ(std::min(m_minCoordinates.z(), _aabb.m_minCoordinates.z()));
|
||||
m_maxCoordinates.setX(std::max(m_maxCoordinates.x(), _aabb.m_maxCoordinates.x()));
|
||||
m_maxCoordinates.setY(std::max(m_maxCoordinates.y(), _aabb.m_maxCoordinates.y()));
|
||||
m_maxCoordinates.setZ(std::max(m_maxCoordinates.z(), _aabb.m_maxCoordinates.z()));
|
||||
}
|
||||
|
||||
// Replace the current AABB with a new AABB that is the union of two AABBs in parameters
|
||||
void AABB::mergeTwoAABBs(const AABB& aabb1, const AABB& aabb2) {
|
||||
m_minCoordinates.setX(std::min(aabb1.m_minCoordinates.x(), aabb2.m_minCoordinates.x()));
|
||||
m_minCoordinates.setY(std::min(aabb1.m_minCoordinates.y(), aabb2.m_minCoordinates.y()));
|
||||
m_minCoordinates.setZ(std::min(aabb1.m_minCoordinates.z(), aabb2.m_minCoordinates.z()));
|
||||
m_maxCoordinates.setX(std::max(aabb1.m_maxCoordinates.x(), aabb2.m_maxCoordinates.x()));
|
||||
m_maxCoordinates.setY(std::max(aabb1.m_maxCoordinates.y(), aabb2.m_maxCoordinates.y()));
|
||||
m_maxCoordinates.setZ(std::max(aabb1.m_maxCoordinates.z(), aabb2.m_maxCoordinates.z()));
|
||||
void AABB::mergeTwoAABBs(const AABB& _aabb1, const AABB& _aabb2) {
|
||||
m_minCoordinates.setX(std::min(_aabb1.m_minCoordinates.x(), _aabb2.m_minCoordinates.x()));
|
||||
m_minCoordinates.setY(std::min(_aabb1.m_minCoordinates.y(), _aabb2.m_minCoordinates.y()));
|
||||
m_minCoordinates.setZ(std::min(_aabb1.m_minCoordinates.z(), _aabb2.m_minCoordinates.z()));
|
||||
m_maxCoordinates.setX(std::max(_aabb1.m_maxCoordinates.x(), _aabb2.m_maxCoordinates.x()));
|
||||
m_maxCoordinates.setY(std::max(_aabb1.m_maxCoordinates.y(), _aabb2.m_maxCoordinates.y()));
|
||||
m_maxCoordinates.setZ(std::max(_aabb1.m_maxCoordinates.z(), _aabb2.m_maxCoordinates.z()));
|
||||
}
|
||||
|
||||
// Return true if the current AABB contains the AABB given in parameter
|
||||
bool AABB::contains(const AABB& aabb) const {
|
||||
bool AABB::contains(const AABB& _aabb) const {
|
||||
bool isInside = true;
|
||||
isInside = isInside && m_minCoordinates.x() <= aabb.m_minCoordinates.x();
|
||||
isInside = isInside && m_minCoordinates.y() <= aabb.m_minCoordinates.y();
|
||||
isInside = isInside && m_minCoordinates.z() <= aabb.m_minCoordinates.z();
|
||||
isInside = isInside && m_maxCoordinates.x() >= aabb.m_maxCoordinates.x();
|
||||
isInside = isInside && m_maxCoordinates.y() >= aabb.m_maxCoordinates.y();
|
||||
isInside = isInside && m_maxCoordinates.z() >= aabb.m_maxCoordinates.z();
|
||||
isInside = isInside && m_minCoordinates.x() <= _aabb.m_minCoordinates.x();
|
||||
isInside = isInside && m_minCoordinates.y() <= _aabb.m_minCoordinates.y();
|
||||
isInside = isInside && m_minCoordinates.z() <= _aabb.m_minCoordinates.z();
|
||||
isInside = isInside && m_maxCoordinates.x() >= _aabb.m_maxCoordinates.x();
|
||||
isInside = isInside && m_maxCoordinates.y() >= _aabb.m_maxCoordinates.y();
|
||||
isInside = isInside && m_maxCoordinates.z() >= _aabb.m_maxCoordinates.z();
|
||||
return isInside;
|
||||
}
|
||||
|
||||
// Create and return an AABB for a triangle
|
||||
AABB AABB::createAABBForTriangle(const vec3* trianglePoints) {
|
||||
vec3 minCoords(trianglePoints[0].x(), trianglePoints[0].y(), trianglePoints[0].z());
|
||||
vec3 maxCoords(trianglePoints[0].x(), trianglePoints[0].y(), trianglePoints[0].z());
|
||||
if (trianglePoints[1].x() < minCoords.x()) {
|
||||
minCoords.setX(trianglePoints[1].x());
|
||||
AABB AABB::createAABBForTriangle(const vec3* _trianglePoints) {
|
||||
vec3 minCoords(_trianglePoints[0].x(), _trianglePoints[0].y(), _trianglePoints[0].z());
|
||||
vec3 maxCoords(_trianglePoints[0].x(), _trianglePoints[0].y(), _trianglePoints[0].z());
|
||||
if (_trianglePoints[1].x() < minCoords.x()) {
|
||||
minCoords.setX(_trianglePoints[1].x());
|
||||
}
|
||||
if (trianglePoints[1].y() < minCoords.y()) {
|
||||
minCoords.setY(trianglePoints[1].y());
|
||||
if (_trianglePoints[1].y() < minCoords.y()) {
|
||||
minCoords.setY(_trianglePoints[1].y());
|
||||
}
|
||||
if (trianglePoints[1].z() < minCoords.z()) {
|
||||
minCoords.setZ(trianglePoints[1].z());
|
||||
if (_trianglePoints[1].z() < minCoords.z()) {
|
||||
minCoords.setZ(_trianglePoints[1].z());
|
||||
}
|
||||
if (trianglePoints[2].x() < minCoords.x()) {
|
||||
minCoords.setX(trianglePoints[2].x());
|
||||
if (_trianglePoints[2].x() < minCoords.x()) {
|
||||
minCoords.setX(_trianglePoints[2].x());
|
||||
}
|
||||
if (trianglePoints[2].y() < minCoords.y()) {
|
||||
minCoords.setY(trianglePoints[2].y());
|
||||
if (_trianglePoints[2].y() < minCoords.y()) {
|
||||
minCoords.setY(_trianglePoints[2].y());
|
||||
}
|
||||
if (trianglePoints[2].z() < minCoords.z()) {
|
||||
minCoords.setZ(trianglePoints[2].z());
|
||||
if (_trianglePoints[2].z() < minCoords.z()) {
|
||||
minCoords.setZ(_trianglePoints[2].z());
|
||||
}
|
||||
if (trianglePoints[1].x() > maxCoords.x()) {
|
||||
maxCoords.setX(trianglePoints[1].x());
|
||||
if (_trianglePoints[1].x() > maxCoords.x()) {
|
||||
maxCoords.setX(_trianglePoints[1].x());
|
||||
}
|
||||
if (trianglePoints[1].y() > maxCoords.y()) {
|
||||
maxCoords.setY(trianglePoints[1].y());
|
||||
if (_trianglePoints[1].y() > maxCoords.y()) {
|
||||
maxCoords.setY(_trianglePoints[1].y());
|
||||
}
|
||||
if (trianglePoints[1].z() > maxCoords.z()) {
|
||||
maxCoords.setZ(trianglePoints[1].z());
|
||||
if (_trianglePoints[1].z() > maxCoords.z()) {
|
||||
maxCoords.setZ(_trianglePoints[1].z());
|
||||
}
|
||||
if (trianglePoints[2].x() > maxCoords.x()) {
|
||||
maxCoords.setX(trianglePoints[2].x());
|
||||
if (_trianglePoints[2].x() > maxCoords.x()) {
|
||||
maxCoords.setX(_trianglePoints[2].x());
|
||||
}
|
||||
if (trianglePoints[2].y() > maxCoords.y()) {
|
||||
maxCoords.setY(trianglePoints[2].y());
|
||||
if (_trianglePoints[2].y() > maxCoords.y()) {
|
||||
maxCoords.setY(_trianglePoints[2].y());
|
||||
}
|
||||
if (trianglePoints[2].z() > maxCoords.z()) {
|
||||
maxCoords.setZ(trianglePoints[2].z());
|
||||
if (_trianglePoints[2].z() > maxCoords.z()) {
|
||||
maxCoords.setZ(_trianglePoints[2].z());
|
||||
}
|
||||
return AABB(minCoords, maxCoords);
|
||||
}
|
||||
|
||||
// Return true if the ray int32_tersects the AABB
|
||||
/// This method use the line vs AABB raycasting technique described in
|
||||
/// Real-time Collision Detection by Christer Ericson.
|
||||
bool AABB::testRayIntersect(const Ray& ray) const {
|
||||
const vec3 point2 = ray.point1 + ray.maxFraction * (ray.point2 - ray.point1);
|
||||
bool AABB::testRayIntersect(const Ray& _ray) const {
|
||||
const vec3 point2 = _ray.point1 + _ray.maxFraction * (_ray.point2 - _ray.point1);
|
||||
const vec3 e = m_maxCoordinates - m_minCoordinates;
|
||||
const vec3 d = point2 - ray.point1;
|
||||
const vec3 m = ray.point1 + point2 - m_minCoordinates - m_maxCoordinates;
|
||||
const vec3 d = point2 - _ray.point1;
|
||||
const vec3 m = _ray.point1 + point2 - m_minCoordinates - m_maxCoordinates;
|
||||
// Test if the AABB face normals are separating axis
|
||||
float adx = std::abs(d.x());
|
||||
if (std::abs(m.x()) > e.x() + adx) {
|
||||
@ -147,3 +140,64 @@ bool AABB::testRayIntersect(const Ray& ray) const {
|
||||
// No separating axis has been found
|
||||
return true;
|
||||
}
|
||||
|
||||
vec3 AABB::getExtent() const {
|
||||
return m_maxCoordinates - m_minCoordinates;
|
||||
}
|
||||
|
||||
void AABB::inflate(float _dx, float _dy, float _dz) {
|
||||
m_maxCoordinates += vec3(_dx, _dy, _dz);
|
||||
m_minCoordinates -= vec3(_dx, _dy, _dz);
|
||||
}
|
||||
|
||||
bool AABB::testCollision(const AABB& aabb) const {
|
||||
if (m_maxCoordinates.x() < aabb.m_minCoordinates.x() ||
|
||||
aabb.m_maxCoordinates.x() < m_minCoordinates.x()) return false;
|
||||
if (m_maxCoordinates.y() < aabb.m_minCoordinates.y() ||
|
||||
aabb.m_maxCoordinates.y() < m_minCoordinates.y()) return false;
|
||||
if (m_maxCoordinates.z() < aabb.m_minCoordinates.z()||
|
||||
aabb.m_maxCoordinates.z() < m_minCoordinates.z()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
float AABB::getVolume() const {
|
||||
const vec3 diff = m_maxCoordinates - m_minCoordinates;
|
||||
return (diff.x() * diff.y() * diff.z());
|
||||
}
|
||||
|
||||
bool AABB::testCollisionTriangleAABB(const vec3* _trianglePoints) const {
|
||||
if (min3(_trianglePoints[0].x(), _trianglePoints[1].x(), _trianglePoints[2].x()) > m_maxCoordinates.x()) {
|
||||
return false;
|
||||
}
|
||||
if (min3(_trianglePoints[0].y(), _trianglePoints[1].y(), _trianglePoints[2].y()) > m_maxCoordinates.y()) {
|
||||
return false;
|
||||
}
|
||||
if (min3(_trianglePoints[0].z(), _trianglePoints[1].z(), _trianglePoints[2].z()) > m_maxCoordinates.z()) {
|
||||
return false;
|
||||
}
|
||||
if (max3(_trianglePoints[0].x(), _trianglePoints[1].x(), _trianglePoints[2].x()) < m_minCoordinates.x()) {
|
||||
return false;
|
||||
}
|
||||
if (max3(_trianglePoints[0].y(), _trianglePoints[1].y(), _trianglePoints[2].y()) < m_minCoordinates.y()) {
|
||||
return false;
|
||||
}
|
||||
if (max3(_trianglePoints[0].z(), _trianglePoints[1].z(), _trianglePoints[2].z()) < m_minCoordinates.z()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AABB::contains(const vec3& _point) const {
|
||||
return _point.x() >= m_minCoordinates.x() - MACHINE_EPSILON && _point.x() <= m_maxCoordinates.x() + MACHINE_EPSILON
|
||||
&& _point.y() >= m_minCoordinates.y() - MACHINE_EPSILON && _point.y() <= m_maxCoordinates.y() + MACHINE_EPSILON
|
||||
&& _point.z() >= m_minCoordinates.z() - MACHINE_EPSILON && _point.z() <= m_maxCoordinates.z() + MACHINE_EPSILON);
|
||||
}
|
||||
|
||||
AABB& AABB::operator=(const AABB& _aabb) {
|
||||
if (this != &_aabb) {
|
||||
m_minCoordinates = _aabb.m_minCoordinates;
|
||||
m_maxCoordinates = _aabb.m_maxCoordinates;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -4,184 +4,147 @@
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Class AABB
|
||||
/**
|
||||
* This class represents a bounding volume of type "Axis Aligned
|
||||
/**
|
||||
* @brief Represents a bounding volume of type "Axis Aligned
|
||||
* Bounding Box". It's a box where all the edges are always aligned
|
||||
* with the world coordinate system. The AABB is defined by the
|
||||
* minimum and maximum world coordinates of the three axis.
|
||||
*/
|
||||
class AABB {
|
||||
|
||||
class AABB {
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Minimum world coordinates of the AABB on the x,y and z axis
|
||||
vec3 m_minCoordinates;
|
||||
|
||||
/// Maximum world coordinates of the AABB on the x,y and z axis
|
||||
vec3 m_maxCoordinates;
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* @brief default contructor
|
||||
*/
|
||||
AABB();
|
||||
|
||||
/// Constructor
|
||||
AABB(const vec3& minCoordinates, const vec3& maxCoordinates);
|
||||
|
||||
/// Copy-constructor
|
||||
AABB(const AABB& aabb);
|
||||
|
||||
/// Return the center point
|
||||
vec3 getCenter() const;
|
||||
|
||||
/// Return the minimum coordinates of the AABB
|
||||
const vec3& getMin() const;
|
||||
|
||||
/// Set the minimum coordinates of the AABB
|
||||
void setMin(const vec3& min);
|
||||
|
||||
/// Return the maximum coordinates of the AABB
|
||||
const vec3& getMax() const;
|
||||
|
||||
/// Set the maximum coordinates of the AABB
|
||||
void setMax(const vec3& max);
|
||||
|
||||
/// Return the size of the AABB in the three dimension x, y and z
|
||||
vec3 getExtent() const;
|
||||
|
||||
/// Inflate each side of the AABB by a given size
|
||||
void inflate(float dx, float dy, float dz);
|
||||
|
||||
/// Return true if the current AABB is overlapping with the AABB in argument
|
||||
bool testCollision(const AABB& aabb) const;
|
||||
|
||||
/// Return the volume of the AABB
|
||||
float getVolume() const;
|
||||
|
||||
/// Merge the AABB in parameter with the current one
|
||||
void mergeWithAABB(const AABB& aabb);
|
||||
|
||||
/// Replace the current AABB with a new AABB that is the union of two AABBs in parameters
|
||||
void mergeTwoAABBs(const AABB& aabb1, const AABB& aabb2);
|
||||
|
||||
/// Return true if the current AABB contains the AABB given in parameter
|
||||
bool contains(const AABB& aabb) const;
|
||||
|
||||
/// Return true if a point is inside the AABB
|
||||
bool contains(const vec3& point) const;
|
||||
|
||||
/// Return true if the AABB of a triangle int32_tersects the AABB
|
||||
bool testCollisionTriangleAABB(const vec3* trianglePoints) const;
|
||||
|
||||
/// Return true if the ray int32_tersects the AABB
|
||||
bool testRayIntersect(const Ray& ray) const;
|
||||
|
||||
/// Create and return an AABB for a triangle
|
||||
static AABB createAABBForTriangle(const vec3* trianglePoints);
|
||||
|
||||
/// Assignment operator
|
||||
AABB& operator=(const AABB& aabb);
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicAABBTree;
|
||||
};
|
||||
|
||||
// Return the center point of the AABB in world coordinates
|
||||
inline vec3 AABB::getCenter() const {
|
||||
/**
|
||||
* @brief contructor Whit sizes
|
||||
* @param[in] _minCoordinates Minimum coordinates
|
||||
* @param[in] _maxCoordinates Maximum coordinates
|
||||
*/
|
||||
AABB(const vec3& _minCoordinates, const vec3& _maxCoordinates);
|
||||
/**
|
||||
* @brief Copy-contructor
|
||||
* @param[in] _aabb the object to copy
|
||||
*/
|
||||
AABB(const AABB& _aabb);
|
||||
/**
|
||||
* @brief Get the center point of the AABB box
|
||||
* @return The 3D position of the center
|
||||
*/
|
||||
vec3 getCenter() const {
|
||||
return (m_minCoordinates + m_maxCoordinates) * 0.5f;
|
||||
}
|
||||
|
||||
// Return the minimum coordinates of the AABB
|
||||
inline const vec3& AABB::getMin() const {
|
||||
return m_minCoordinates;
|
||||
}
|
||||
|
||||
// Set the minimum coordinates of the AABB
|
||||
inline void AABB::setMin(const vec3& min) {
|
||||
m_minCoordinates = min;
|
||||
}
|
||||
|
||||
// Return the maximum coordinates of the AABB
|
||||
inline const vec3& AABB::getMax() const {
|
||||
return m_maxCoordinates;
|
||||
}
|
||||
|
||||
// Set the maximum coordinates of the AABB
|
||||
inline void AABB::setMax(const vec3& max) {
|
||||
m_maxCoordinates = max;
|
||||
}
|
||||
|
||||
// Return the size of the AABB in the three dimension x, y and z
|
||||
inline vec3 AABB::getExtent() const {
|
||||
return m_maxCoordinates - m_minCoordinates;
|
||||
}
|
||||
|
||||
// Inflate each side of the AABB by a given size
|
||||
inline void AABB::inflate(float dx, float dy, float dz) {
|
||||
m_maxCoordinates += vec3(dx, dy, dz);
|
||||
m_minCoordinates -= vec3(dx, dy, dz);
|
||||
}
|
||||
|
||||
// Return true if the current AABB is overlapping with the AABB in argument.
|
||||
/// Two AABBs overlap if they overlap in the three x, y and z axis at the same time
|
||||
inline bool AABB::testCollision(const AABB& aabb) const {
|
||||
if (m_maxCoordinates.x() < aabb.m_minCoordinates.x() ||
|
||||
aabb.m_maxCoordinates.x() < m_minCoordinates.x()) return false;
|
||||
if (m_maxCoordinates.y() < aabb.m_minCoordinates.y() ||
|
||||
aabb.m_maxCoordinates.y() < m_minCoordinates.y()) return false;
|
||||
if (m_maxCoordinates.z() < aabb.m_minCoordinates.z()||
|
||||
aabb.m_maxCoordinates.z() < m_minCoordinates.z()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the volume of the AABB
|
||||
inline float AABB::getVolume() const {
|
||||
const vec3 diff = m_maxCoordinates - m_minCoordinates;
|
||||
return (diff.x() * diff.y() * diff.z());
|
||||
}
|
||||
|
||||
// Return true if the AABB of a triangle int32_tersects the AABB
|
||||
inline bool AABB::testCollisionTriangleAABB(const vec3* trianglePoints) const {
|
||||
|
||||
if (min3(trianglePoints[0].x(), trianglePoints[1].x(), trianglePoints[2].x()) > m_maxCoordinates.x()) return false;
|
||||
if (min3(trianglePoints[0].y(), trianglePoints[1].y(), trianglePoints[2].y()) > m_maxCoordinates.y()) return false;
|
||||
if (min3(trianglePoints[0].z(), trianglePoints[1].z(), trianglePoints[2].z()) > m_maxCoordinates.z()) return false;
|
||||
|
||||
if (max3(trianglePoints[0].x(), trianglePoints[1].x(), trianglePoints[2].x()) < m_minCoordinates.x()) return false;
|
||||
if (max3(trianglePoints[0].y(), trianglePoints[1].y(), trianglePoints[2].y()) < m_minCoordinates.y()) return false;
|
||||
if (max3(trianglePoints[0].z(), trianglePoints[1].z(), trianglePoints[2].z()) < m_minCoordinates.z()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true if a point is inside the AABB
|
||||
inline bool AABB::contains(const vec3& point) const {
|
||||
|
||||
return (point.x() >= m_minCoordinates.x() - MACHINE_EPSILON && point.x() <= m_maxCoordinates.x() + MACHINE_EPSILON &&
|
||||
point.y() >= m_minCoordinates.y() - MACHINE_EPSILON && point.y() <= m_maxCoordinates.y() + MACHINE_EPSILON &&
|
||||
point.z() >= m_minCoordinates.z() - MACHINE_EPSILON && point.z() <= m_maxCoordinates.z() + MACHINE_EPSILON);
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
inline AABB& AABB::operator=(const AABB& aabb) {
|
||||
if (this != &aabb) {
|
||||
m_minCoordinates = aabb.m_minCoordinates;
|
||||
m_maxCoordinates = aabb.m_maxCoordinates;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Get the minimum coordinates of the AABB
|
||||
* @return The 3d minimum coordonates
|
||||
*/
|
||||
const vec3& getMin() const {
|
||||
return m_minCoordinates;
|
||||
}
|
||||
/**
|
||||
* @brief Set the minimum coordinates of the AABB
|
||||
* @param[in] _min The 3d minimum coordonates
|
||||
*/
|
||||
void setMin(const vec3& _min) {
|
||||
m_minCoordinates = _min;
|
||||
}
|
||||
/**
|
||||
* @brief Return the maximum coordinates of the AABB
|
||||
* @return The 3d maximum coordonates
|
||||
*/
|
||||
const vec3& getMax() const {
|
||||
return m_maxCoordinates;
|
||||
}
|
||||
/**
|
||||
* @brief Set the maximum coordinates of the AABB
|
||||
* @param[in] _max The 3d maximum coordonates
|
||||
*/
|
||||
void setMax(const vec3& _max) {
|
||||
m_maxCoordinates = _max;
|
||||
}
|
||||
/**
|
||||
* @brief Get the size of the AABB in the three dimension x, y and z
|
||||
* @return the AABB 3D size
|
||||
*/
|
||||
vec3 getExtent() const;
|
||||
/**
|
||||
* @brief Inflate each side of the AABB by a given size
|
||||
* @param[in] _dx Inflate X size
|
||||
* @param[in] _dy Inflate Y size
|
||||
* @param[in] _dz Inflate Z size
|
||||
*/
|
||||
void inflate(float _dx, float _dy, float _dz);
|
||||
/**
|
||||
* @brief Return true if the current AABB is overlapping with the AABB in argument
|
||||
* Two AABBs overlap if they overlap in the three x, y and z axis at the same time
|
||||
* @param[in] _aabb Other AABB box to check.
|
||||
* @return true Collision detected
|
||||
* @return false Not collide
|
||||
*/
|
||||
bool testCollision(const AABB& _aabb) const;
|
||||
/**
|
||||
* @brief Get the volume of the AABB
|
||||
* @return The 3D volume.
|
||||
*/
|
||||
float getVolume() const;
|
||||
/**
|
||||
* @brief Merge the AABB in parameter with the current one
|
||||
* @param[in] _aabb Other AABB box to merge.
|
||||
*/
|
||||
void mergeWithAABB(const AABB& _aabb);
|
||||
/**
|
||||
* @brief Replace the current AABB with a new AABB that is the union of two AABBs in parameters
|
||||
* @param[in] _aabb1 first AABB box to merge with _aabb2.
|
||||
* @param[in] _aabb2 second AABB box to merge with _aabb1.
|
||||
*/
|
||||
void mergeTwoAABBs(const AABB& _aabb1, const AABB& _aabb2);
|
||||
/**
|
||||
* @brief Return true if the current AABB contains the AABB given in parameter
|
||||
* @param[in] _aabb AABB box that is contains in the current.
|
||||
* @return true The parameter in contained inside
|
||||
*/
|
||||
bool contains(const AABB& _aabb) const;
|
||||
/**
|
||||
* @brief Return true if a point is inside the AABB
|
||||
* @param[in] _point Point to check.
|
||||
* @return true The point in contained inside
|
||||
*/
|
||||
bool contains(const vec3& _point) const;
|
||||
/**
|
||||
* @brief check if the AABB of a triangle intersects the AABB
|
||||
* @param[in] _trianglePoints List of 3 point od a triangle
|
||||
* @return true The triangle is contained in the Box
|
||||
*/
|
||||
bool testCollisionTriangleAABB(const vec3* _trianglePoints) const;
|
||||
/**
|
||||
* @brief check if the ray intersects the AABB
|
||||
* This method use the line vs AABB raycasting technique described in
|
||||
* Real-time Collision Detection by Christer Ericson.
|
||||
* @param[in] _ray Ray to test
|
||||
* @return true The raytest intersect the AABB box
|
||||
*/
|
||||
bool testRayIntersect(const Ray& _ray) const;
|
||||
/**
|
||||
* @brief Create and return an AABB for a triangle
|
||||
* @param[in] _trianglePoints List of 3 point od a triangle
|
||||
* @return An AABB box
|
||||
*/
|
||||
static AABB createAABBForTriangle(const vec3* _trianglePoints);
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
* @param[in] _aabb The other box to compare
|
||||
* @return reference on this
|
||||
*/
|
||||
AABB& operator=(const AABB& _aabb);
|
||||
friend class DynamicAABBTree;
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -5,19 +5,15 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cfloat>
|
||||
#include <ephysics/collision/shapes/ConvexShape.hpp>
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Class BoxShape
|
||||
/**
|
||||
* This class represents a 3D box shape. Those axis are unit length.
|
||||
* @brief It represents a 3D box shape. Those axis are unit length.
|
||||
* The three extents are half-widths of the box along the three
|
||||
* axis x, y, z local axis. The "transform" of the corresponding
|
||||
* rigid body will give an orientation and a position to the box. This
|
||||
@ -30,45 +26,32 @@ namespace ephysics {
|
||||
* default margin distance by not using the "margin" parameter in the constructor.
|
||||
*/
|
||||
class BoxShape : public ConvexShape {
|
||||
|
||||
protected :
|
||||
/// Extent sizes of the box in the x, y and z direction
|
||||
vec3 m_extent;
|
||||
vec3 m_extent; //!< Extent sizes of the box in the x, y and z direction
|
||||
/// Private copy-constructor
|
||||
BoxShape(const BoxShape& shape);
|
||||
|
||||
/// Private assignment operator
|
||||
BoxShape& operator=(const BoxShape& shape);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Return the number of bytes used by the collision shape
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
public :
|
||||
/// Constructor
|
||||
BoxShape(const vec3& extent, float margin = OBJECT_MARGIN);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BoxShape() = default;
|
||||
|
||||
/// Return the extents of the box
|
||||
vec3 getExtent() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(vec3& _min, vec3& _max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
};
|
||||
@ -77,12 +60,12 @@ class BoxShape : public ConvexShape {
|
||||
/**
|
||||
* @return The vector with the three extents of the box shape (in meters)
|
||||
*/
|
||||
inline vec3 BoxShape::getExtent() const {
|
||||
vec3 BoxShape::getExtent() const {
|
||||
return m_extent + vec3(m_margin, m_margin, m_margin);
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void BoxShape::setLocalScaling(const vec3& scaling) {
|
||||
void BoxShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
m_extent = (m_extent / m_scaling) * scaling;
|
||||
|
||||
@ -95,7 +78,7 @@ inline void BoxShape::setLocalScaling(const vec3& scaling) {
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void BoxShape::getLocalBounds(vec3& _min, vec3& _max) const {
|
||||
void BoxShape::getLocalBounds(vec3& _min, vec3& _max) const {
|
||||
|
||||
// Maximum bounds
|
||||
_max = m_extent + vec3(m_margin, m_margin, m_margin);
|
||||
@ -105,12 +88,12 @@ inline void BoxShape::getLocalBounds(vec3& _min, vec3& _max) const {
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t BoxShape::getSizeInBytes() const {
|
||||
size_t BoxShape::getSizeInBytes() const {
|
||||
return sizeof(BoxShape);
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the objec margin
|
||||
inline vec3 BoxShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
vec3 BoxShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
return vec3(direction.x() < 0.0 ? -m_extent.x() : m_extent.x(),
|
||||
@ -119,7 +102,7 @@ inline vec3 BoxShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool BoxShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
bool BoxShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
return (localPoint.x() < m_extent[0] && localPoint.x() > -m_extent[0] &&
|
||||
localPoint.y() < m_extent[1] && localPoint.y() > -m_extent[1] &&
|
||||
localPoint.z() < m_extent[2] && localPoint.z() > -m_extent[2]);
|
||||
|
@ -5,17 +5,14 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/shapes/ConvexShape.hpp>
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
|
||||
// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Class CapsuleShape
|
||||
/**
|
||||
* This class represents a capsule collision shape that is defined around the Y axis.
|
||||
/**
|
||||
* @brief It represents a capsule collision shape that is defined around the Y axis.
|
||||
* A capsule shape can be seen as the convex hull of two spheres.
|
||||
* The capsule shape is defined by its radius (radius of the two spheres of the capsule)
|
||||
* and its height (distance between the centers of the two spheres). This collision shape
|
||||
@ -23,10 +20,9 @@ namespace ephysics {
|
||||
* and height of the shape. Therefore, no need to specify an object margin for a
|
||||
* capsule shape.
|
||||
*/
|
||||
class CapsuleShape : public ConvexShape {
|
||||
class CapsuleShape : public ConvexShape {
|
||||
protected:
|
||||
/// Half height of the capsule (height = distance between the centers of the two spheres)
|
||||
float m_halfHeight;
|
||||
float m_halfHeight; //!< Half height of the capsule (height = distance between the centers of the two spheres)
|
||||
/// Private copy-constructor
|
||||
CapsuleShape(const CapsuleShape& shape);
|
||||
|
||||
@ -72,13 +68,13 @@ class CapsuleShape : public ConvexShape {
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
};
|
||||
};
|
||||
|
||||
// Get the radius of the capsule
|
||||
/**
|
||||
* @return The radius of the capsule shape (in meters)
|
||||
*/
|
||||
inline float CapsuleShape::getRadius() const {
|
||||
float CapsuleShape::getRadius() const {
|
||||
return m_margin;
|
||||
}
|
||||
|
||||
@ -86,12 +82,12 @@ inline float CapsuleShape::getRadius() const {
|
||||
/**
|
||||
* @return The height of the capsule shape (in meters)
|
||||
*/
|
||||
inline float CapsuleShape::getHeight() const {
|
||||
float CapsuleShape::getHeight() const {
|
||||
return m_halfHeight + m_halfHeight;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void CapsuleShape::setLocalScaling(const vec3& scaling) {
|
||||
void CapsuleShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
m_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
|
||||
m_margin = (m_margin / m_scaling.x()) * scaling.x();
|
||||
@ -100,7 +96,7 @@ inline void CapsuleShape::setLocalScaling(const vec3& scaling) {
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t CapsuleShape::getSizeInBytes() const {
|
||||
size_t CapsuleShape::getSizeInBytes() const {
|
||||
return sizeof(CapsuleShape);
|
||||
}
|
||||
|
||||
@ -110,7 +106,7 @@ inline size_t CapsuleShape::getSizeInBytes() const {
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void CapsuleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
void CapsuleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
// Maximum bounds
|
||||
max.setX(m_margin);
|
||||
@ -130,7 +126,7 @@ inline void CapsuleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
/// Therefore, in this method, we compute the support points of both top and bottom spheres of
|
||||
/// the capsule and return the point with the maximum dot product with the direction vector. Note
|
||||
/// that the object margin is implicitly the radius and height of the capsule.
|
||||
inline vec3 CapsuleShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
vec3 CapsuleShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
// Support point top sphere
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cassert>
|
||||
#include <typeinfo>
|
||||
#include <etk/math/Vector3D.hpp>
|
||||
@ -15,19 +14,14 @@
|
||||
#include <ephysics/collision/RaycastInfo.hpp>
|
||||
#include <ephysics/memory/MemoryAllocator.hpp>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
/// Type of the collision shape
|
||||
enum CollisionShapeType {TRIANGLE, BOX, SPHERE, CONE, CYLINDER,
|
||||
CAPSULE, CONVEX_MESH, CONCAVE_MESH, HEIGHTFIELD};
|
||||
const int32_t NB_COLLISION_SHAPE_TYPES = 9;
|
||||
|
||||
// Declarations
|
||||
class ProxyShape;
|
||||
class CollisionBody;
|
||||
|
||||
// Class CollisionShape
|
||||
/**
|
||||
* This abstract class represents the collision shape associated with a
|
||||
* body that is used during the narrow-phase collision detection.
|
||||
@ -37,9 +31,9 @@ class CollisionShape {
|
||||
CollisionShapeType m_type; //!< Type of the collision shape
|
||||
vec3 m_scaling; //!< Scaling vector of the collision shape
|
||||
/// Private copy-constructor
|
||||
CollisionShape(const CollisionShape& shape);
|
||||
CollisionShape(const CollisionShape& shape) = delete;
|
||||
/// Private assignment operator
|
||||
CollisionShape& operator=(const CollisionShape& shape);
|
||||
CollisionShape& operator=(const CollisionShape& shape) = delete;
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const vec3& worldPoint, ProxyShape* proxyShape) const=0;
|
||||
/// Raycast method with feedback information
|
||||
@ -78,28 +72,28 @@ class CollisionShape {
|
||||
/**
|
||||
* @return The type of the collision shape (box, sphere, cylinder, ...)
|
||||
*/
|
||||
inline CollisionShapeType CollisionShape::getType() const {
|
||||
CollisionShapeType CollisionShape::getType() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
// Return true if the collision shape type is a convex shape
|
||||
inline bool CollisionShape::isConvex(CollisionShapeType shapeType) {
|
||||
bool CollisionShape::isConvex(CollisionShapeType shapeType) {
|
||||
return shapeType != CONCAVE_MESH && shapeType != HEIGHTFIELD;
|
||||
}
|
||||
|
||||
// Return the scaling vector of the collision shape
|
||||
inline vec3 CollisionShape::getScaling() const {
|
||||
vec3 CollisionShape::getScaling() const {
|
||||
return m_scaling;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void CollisionShape::setLocalScaling(const vec3& scaling) {
|
||||
void CollisionShape::setLocalScaling(const vec3& scaling) {
|
||||
m_scaling = scaling;
|
||||
}
|
||||
|
||||
// Return the maximum number of contact manifolds allowed in an overlapping
|
||||
// pair wit the given two collision shape types
|
||||
inline int32_t CollisionShape::computeNbMaxContactManifolds(CollisionShapeType shapeType1,
|
||||
int32_t CollisionShape::computeNbMaxContactManifolds(CollisionShapeType shapeType1,
|
||||
CollisionShapeType shapeType2) {
|
||||
// If both shapes are convex
|
||||
if (isConvex(shapeType1) && isConvex(shapeType2)) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/shapes/ConcaveShape.hpp>
|
||||
#include <ephysics/collision/broadphase/DynamicAABBTree.hpp>
|
||||
#include <ephysics/collision/TriangleMesh.hpp>
|
||||
@ -14,9 +13,8 @@
|
||||
|
||||
namespace ephysics {
|
||||
|
||||
class ConcaveMeshShape;
|
||||
|
||||
class ConvexTriangleAABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
|
||||
class ConcaveMeshShape;
|
||||
class ConvexTriangleAABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
|
||||
private:
|
||||
TriangleCallback& m_triangleTestCallback; //!<
|
||||
const ConcaveMeshShape& m_concaveMeshShape; //!< Reference to the concave mesh shape
|
||||
@ -35,13 +33,11 @@ class ConvexTriangleAABBOverlapCallback : public DynamicAABBTreeOverlapCallback
|
||||
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
||||
virtual void notifyOverlappingNode(int32_t _nodeId);
|
||||
|
||||
};
|
||||
|
||||
/// Class ConcaveMeshRaycastCallback
|
||||
class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
|
||||
};
|
||||
|
||||
/// Class ConcaveMeshRaycastCallback
|
||||
class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
|
||||
private :
|
||||
|
||||
std::vector<int32_t> m_hitAABBNodes;
|
||||
const DynamicAABBTree& m_dynamicAABBTree;
|
||||
const ConcaveMeshShape& m_concaveMeshShape;
|
||||
@ -49,97 +45,73 @@ class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
|
||||
RaycastInfo& m_raycastInfo;
|
||||
const Ray& m_ray;
|
||||
bool mIsHit;
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
ConcaveMeshRaycastCallback(const DynamicAABBTree& dynamicAABBTree, const ConcaveMeshShape& concaveMeshShape,
|
||||
ProxyShape* proxyShape, RaycastInfo& raycastInfo, const Ray& ray)
|
||||
: m_dynamicAABBTree(dynamicAABBTree), m_concaveMeshShape(concaveMeshShape), m_proxyShape(proxyShape),
|
||||
m_raycastInfo(raycastInfo), m_ray(ray), mIsHit(false) {
|
||||
ConcaveMeshRaycastCallback(const DynamicAABBTree& _dynamicAABBTree,
|
||||
const ConcaveMeshShape& _concaveMeshShape,
|
||||
ProxyShape* _proxyShape,
|
||||
RaycastInfo& _raycastInfo,
|
||||
const Ray& _ray):
|
||||
m_dynamicAABBTree(_dynamicAABBTree),
|
||||
m_concaveMeshShape(_concaveMeshShape),
|
||||
m_proxyShape(_proxyShape),
|
||||
m_raycastInfo(_raycastInfo),
|
||||
m_ray(_ray),
|
||||
mIsHit(false) {
|
||||
|
||||
}
|
||||
|
||||
/// Collect all the AABB nodes that are hit by the ray in the Dynamic AABB Tree
|
||||
virtual float raycastBroadPhaseShape(int32_t nodeId, const Ray& ray);
|
||||
|
||||
virtual float raycastBroadPhaseShape(int32_t _nodeId, const Ray& _ray);
|
||||
/// Raycast all collision shapes that have been collected
|
||||
void raycastTriangles();
|
||||
|
||||
/// Return true if a raycast hit has been found
|
||||
bool getIsHit() const {
|
||||
return mIsHit;
|
||||
}
|
||||
};
|
||||
|
||||
// Class ConcaveMeshShape
|
||||
/**
|
||||
* This class represents a static concave mesh shape. Note that collision detection
|
||||
};
|
||||
/**
|
||||
* @brief Represents a static concave mesh shape. Note that collision detection
|
||||
* with a concave mesh shape can be very expensive. You should use only use
|
||||
* this shape for a static mesh.
|
||||
*/
|
||||
class ConcaveMeshShape : public ConcaveShape {
|
||||
|
||||
class ConcaveMeshShape : public ConcaveShape {
|
||||
protected:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Triangle mesh
|
||||
TriangleMesh* m_triangleMesh;
|
||||
|
||||
/// Dynamic AABB tree to accelerate collision with the triangles
|
||||
DynamicAABBTree m_dynamicAABBTree;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
TriangleMesh* m_triangleMesh; //!< Triangle mesh
|
||||
DynamicAABBTree m_dynamicAABBTree; //!< Dynamic AABB tree to accelerate collision with the triangles
|
||||
/// Private copy-constructor
|
||||
ConcaveMeshShape(const ConcaveMeshShape& shape);
|
||||
|
||||
ConcaveMeshShape(const ConcaveMeshShape& _shape) = delete;
|
||||
/// Private assignment operator
|
||||
ConcaveMeshShape& operator=(const ConcaveMeshShape& shape);
|
||||
|
||||
ConcaveMeshShape& operator=(const ConcaveMeshShape& _shape) = delete;
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
|
||||
virtual bool raycast(const Ray& _ray, RaycastInfo& _raycastInfo, ProxyShape* _proxyShape) const;
|
||||
/// Return the number of bytes used by the collision shape
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
/// Insert all the triangles int32_to the dynamic AABB tree
|
||||
void initBVHTree();
|
||||
|
||||
/// Return the three vertices coordinates (in the array outTriangleVertices) of a triangle
|
||||
/// given the start vertex index pointer of the triangle.
|
||||
void getTriangleVerticesWithIndexPointer(int32_t subPart, int32_t triangleIndex,
|
||||
vec3* outTriangleVertices) const;
|
||||
|
||||
void getTriangleVerticesWithIndexPointer(int32_t _subPart,
|
||||
int32_t _triangleIndex,
|
||||
vec3* _outTriangleVertices) const;
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
ConcaveMeshShape(TriangleMesh* triangleMesh);
|
||||
|
||||
/// Destructor
|
||||
~ConcaveMeshShape();
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions.
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Set the local scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
|
||||
/// Use a callback method on all triangles of the concave shape inside a given AABB
|
||||
virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const;
|
||||
|
||||
// ---------- Friendship ----------- //
|
||||
|
||||
friend class ConvexTriangleAABBOverlapCallback;
|
||||
friend class ConcaveMeshRaycastCallback;
|
||||
};
|
||||
};
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t ConcaveMeshShape::getSizeInBytes() const {
|
||||
size_t ConcaveMeshShape::getSizeInBytes() const {
|
||||
return sizeof(ConcaveMeshShape);
|
||||
}
|
||||
|
||||
@ -149,7 +121,7 @@ inline size_t ConcaveMeshShape::getSizeInBytes() const {
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void ConcaveMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
void ConcaveMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
// Get the AABB of the whole tree
|
||||
AABB treeAABB = m_dynamicAABBTree.getRootAABB();
|
||||
@ -159,7 +131,7 @@ inline void ConcaveMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
}
|
||||
|
||||
// Set the local scaling vector of the collision shape
|
||||
inline void ConcaveMeshShape::setLocalScaling(const vec3& scaling) {
|
||||
void ConcaveMeshShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
|
||||
@ -176,7 +148,7 @@ inline void ConcaveMeshShape::setLocalScaling(const vec3& scaling) {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void ConcaveMeshShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
void ConcaveMeshShape::computeLocalInertiaTensor(etk::Matrix3x3& _tensor, float _mass) const {
|
||||
|
||||
// Default inertia tensor
|
||||
// Note that this is not very realistic for a concave triangle mesh.
|
||||
@ -189,7 +161,7 @@ inline void ConcaveMeshShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor,
|
||||
|
||||
// Called when a overlapping node has been found during the call to
|
||||
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
||||
inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int32_t nodeId) {
|
||||
void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int32_t _nodeId) {
|
||||
|
||||
// Get the node data (triangle index and mesh subpart index)
|
||||
int32_t* data = m_dynamicAABBTree.getNodeDataInt(nodeId);
|
||||
|
@ -5,109 +5,74 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/shapes/CollisionShape.hpp>
|
||||
#include <ephysics/collision/shapes/TriangleShape.hpp>
|
||||
|
||||
// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Class TriangleCallback
|
||||
/**
|
||||
* This class is used to encapsulate a callback method for
|
||||
/**
|
||||
* @brief It is used to encapsulate a callback method for
|
||||
* a single triangle of a ConcaveMesh.
|
||||
*/
|
||||
class TriangleCallback {
|
||||
|
||||
class TriangleCallback {
|
||||
public:
|
||||
virtual ~TriangleCallback() = default;
|
||||
|
||||
/// Report a triangle
|
||||
virtual void testTriangle(const vec3* trianglePoints)=0;
|
||||
virtual void testTriangle(const vec3* _trianglePoints)=0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Class ConcaveShape
|
||||
/**
|
||||
* This abstract class represents a concave collision shape associated with a
|
||||
/**
|
||||
* @brief This abstract class represents a concave collision shape associated with a
|
||||
* body that is used during the narrow-phase collision detection.
|
||||
*/
|
||||
class ConcaveShape : public CollisionShape {
|
||||
|
||||
class ConcaveShape : public CollisionShape {
|
||||
protected :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// True if the smooth mesh collision algorithm is enabled
|
||||
bool m_isSmoothMeshCollisionEnabled;
|
||||
|
||||
// Margin use for collision detection for each triangle
|
||||
float m_triangleMargin;
|
||||
|
||||
/// Raycast test type for the triangle (front, back, front-back)
|
||||
TriangleRaycastSide m_raycastTestType;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
bool m_isSmoothMeshCollisionEnabled; //!< True if the smooth mesh collision algorithm is enabled
|
||||
float m_triangleMargin; //!< Margin use for collision detection for each triangle
|
||||
TriangleRaycastSide m_raycastTestType; //!< Raycast test type for the triangle (front, back, front-back)
|
||||
/// Private copy-constructor
|
||||
ConcaveShape(const ConcaveShape& shape);
|
||||
|
||||
ConcaveShape(const ConcaveShape& _shape) = delete;
|
||||
/// Private assignment operator
|
||||
ConcaveShape& operator=(const ConcaveShape& shape);
|
||||
|
||||
ConcaveShape& operator=(const ConcaveShape& _shape) = delete;
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
virtual bool testPointInside(const vec3& _localPoint, ProxyShape* _proxyShape) const;
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ConcaveShape(CollisionShapeType type);
|
||||
|
||||
ConcaveShape(CollisionShapeType _type);
|
||||
/// Destructor
|
||||
virtual ~ConcaveShape();
|
||||
|
||||
/// Return the triangle margin
|
||||
float getTriangleMargin() const;
|
||||
|
||||
/// Return the raycast test type (front, back, front-back)
|
||||
TriangleRaycastSide getRaycastTestType() const;
|
||||
|
||||
// Set the raycast test type (front, back, front-back)
|
||||
void setRaycastTestType(TriangleRaycastSide testType);
|
||||
|
||||
void setRaycastTestType(TriangleRaycastSide _testType);
|
||||
/// Return true if the collision shape is convex, false if it is concave
|
||||
virtual bool isConvex() const;
|
||||
|
||||
/// Use a callback method on all triangles of the concave shape inside a given AABB
|
||||
virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const=0;
|
||||
|
||||
virtual void testAllTriangles(TriangleCallback& _callback, const AABB& _localAABB) const=0;
|
||||
/// Return true if the smooth mesh collision is enabled
|
||||
bool getIsSmoothMeshCollisionEnabled() const;
|
||||
|
||||
/// Enable/disable the smooth mesh collision algorithm
|
||||
void setIsSmoothMeshCollisionEnabled(bool isEnabled);
|
||||
};
|
||||
void setIsSmoothMeshCollisionEnabled(bool _isEnabled);
|
||||
};
|
||||
|
||||
// Return the triangle margin
|
||||
inline float ConcaveShape::getTriangleMargin() const {
|
||||
float ConcaveShape::getTriangleMargin() const {
|
||||
return m_triangleMargin;
|
||||
}
|
||||
|
||||
/// Return true if the collision shape is convex, false if it is concave
|
||||
inline bool ConcaveShape::isConvex() const {
|
||||
bool ConcaveShape::isConvex() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool ConcaveShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
bool ConcaveShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if the smooth mesh collision is enabled
|
||||
inline bool ConcaveShape::getIsSmoothMeshCollisionEnabled() const {
|
||||
bool ConcaveShape::getIsSmoothMeshCollisionEnabled() const {
|
||||
return m_isSmoothMeshCollisionEnabled;
|
||||
}
|
||||
|
||||
@ -115,12 +80,12 @@ inline bool ConcaveShape::getIsSmoothMeshCollisionEnabled() const {
|
||||
/// Smooth mesh collision is used to avoid collisions against some int32_ternal edges
|
||||
/// of the triangle mesh. If it is enabled, collsions with the mesh will be smoother
|
||||
/// but collisions computation is a bit more expensive.
|
||||
inline void ConcaveShape::setIsSmoothMeshCollisionEnabled(bool isEnabled) {
|
||||
void ConcaveShape::setIsSmoothMeshCollisionEnabled(bool isEnabled) {
|
||||
m_isSmoothMeshCollisionEnabled = isEnabled;
|
||||
}
|
||||
|
||||
// Return the raycast test type (front, back, front-back)
|
||||
inline TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
|
||||
TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
|
||||
return m_raycastTestType;
|
||||
}
|
||||
|
||||
@ -128,7 +93,7 @@ inline TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
|
||||
/**
|
||||
* @param testType Raycast test type for the triangle (front, back, front-back)
|
||||
*/
|
||||
inline void ConcaveShape::setRaycastTestType(TriangleRaycastSide testType) {
|
||||
void ConcaveShape::setRaycastTestType(TriangleRaycastSide testType) {
|
||||
m_raycastTestType = testType;
|
||||
}
|
||||
|
||||
|
@ -5,17 +5,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/shapes/ConvexShape.hpp>
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Class ConeShape
|
||||
/**
|
||||
* This class represents a cone collision shape centered at the
|
||||
/**
|
||||
* @brief This class represents a cone collision shape centered at the
|
||||
* origin and alligned with the Y axis. The cone is defined
|
||||
* by its height and by the radius of its base. The center of the
|
||||
* cone is at the half of the height. The "transform" of the
|
||||
@ -28,61 +24,44 @@ namespace ephysics {
|
||||
* constructor of the cone shape. Otherwise, it is recommended to use the
|
||||
* default margin distance by not using the "margin" parameter in the constructor.
|
||||
*/
|
||||
class ConeShape : public ConvexShape {
|
||||
class ConeShape : public ConvexShape {
|
||||
protected :
|
||||
/// Radius of the base
|
||||
float m_radius;
|
||||
/// Half height of the cone
|
||||
float m_halfHeight;
|
||||
/// sine of the semi angle at the apex point
|
||||
float m_sinTheta;
|
||||
float m_radius; //!< Radius of the base
|
||||
float m_halfHeight; //!< Half height of the cone
|
||||
float m_sinTheta; //!< sine of the semi angle at the apex point
|
||||
/// Private copy-constructor
|
||||
ConeShape(const ConeShape& shape);
|
||||
|
||||
ConeShape(const ConeShape& _shape) = delete;
|
||||
/// Private assignment operator
|
||||
ConeShape& operator=(const ConeShape& shape);
|
||||
|
||||
ConeShape& operator=(const ConeShape& _shape) = delete;
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& _direction,
|
||||
void** _cachedCollisionData) const;
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
virtual bool testPointInside(const vec3& _localPoint, ProxyShape* _proxyShape) const;
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
|
||||
virtual bool raycast(const Ray& _ray, RaycastInfo& _raycastInfo, ProxyShape* _proxyShape) const;
|
||||
/// Return the number of bytes used by the collision shape
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ConeShape(float m_radius, float height, float margin = OBJECT_MARGIN);
|
||||
|
||||
ConeShape(float _radius, float _height, float _margin = OBJECT_MARGIN);
|
||||
/// Return the radius
|
||||
float getRadius() const;
|
||||
|
||||
/// Return the height
|
||||
float getHeight() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
virtual void setLocalScaling(const vec3& _scaling);
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
virtual void getLocalBounds(vec3& _min, vec3& _max) const;
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
};
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& _tensor, float _mass) const;
|
||||
};
|
||||
|
||||
// Return the radius
|
||||
/**
|
||||
* @return Radius of the cone (in meters)
|
||||
*/
|
||||
inline float ConeShape::getRadius() const {
|
||||
float ConeShape::getRadius() const {
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
@ -90,12 +69,12 @@ inline float ConeShape::getRadius() const {
|
||||
/**
|
||||
* @return Height of the cone (in meters)
|
||||
*/
|
||||
inline float ConeShape::getHeight() const {
|
||||
float ConeShape::getHeight() const {
|
||||
return float(2.0) * m_halfHeight;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void ConeShape::setLocalScaling(const vec3& scaling) {
|
||||
void ConeShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
m_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
|
||||
m_radius = (m_radius / m_scaling.x()) * scaling.x();
|
||||
@ -104,7 +83,7 @@ inline void ConeShape::setLocalScaling(const vec3& scaling) {
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t ConeShape::getSizeInBytes() const {
|
||||
size_t ConeShape::getSizeInBytes() const {
|
||||
return sizeof(ConeShape);
|
||||
}
|
||||
|
||||
@ -113,7 +92,7 @@ inline size_t ConeShape::getSizeInBytes() const {
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void ConeShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
void ConeShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
// Maximum bounds
|
||||
max.setX(m_radius + m_margin);
|
||||
@ -132,7 +111,7 @@ inline void ConeShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void ConeShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
void ConeShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
float rSquare = m_radius * m_radius;
|
||||
float diagXZ = float(0.15) * mass * (rSquare + m_halfHeight);
|
||||
tensor.setValue(diagXZ, 0.0, 0.0,
|
||||
@ -141,7 +120,7 @@ inline void ConeShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float m
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool ConeShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
bool ConeShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
const float radiusHeight = m_radius * (-localPoint.y() + m_halfHeight) /
|
||||
(m_halfHeight * float(2.0));
|
||||
return (localPoint.y() < m_halfHeight && localPoint.y() > -m_halfHeight) &&
|
||||
|
@ -128,13 +128,13 @@ class ConvexMeshShape : public ConvexShape {
|
||||
};
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
inline void ConvexMeshShape::setLocalScaling(const vec3& scaling) {
|
||||
void ConvexMeshShape::setLocalScaling(const vec3& scaling) {
|
||||
ConvexShape::setLocalScaling(scaling);
|
||||
recalculateBounds();
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t ConvexMeshShape::getSizeInBytes() const {
|
||||
size_t ConvexMeshShape::getSizeInBytes() const {
|
||||
return sizeof(ConvexMeshShape);
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ inline size_t ConvexMeshShape::getSizeInBytes() const {
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void ConvexMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
void ConvexMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
min = m_minBounds;
|
||||
max = m_maxBounds;
|
||||
}
|
||||
@ -156,7 +156,7 @@ inline void ConvexMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void ConvexMeshShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
void ConvexMeshShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
float factor = (1.0f / float(3.0)) * mass;
|
||||
vec3 realExtent = 0.5f * (m_maxBounds - m_minBounds);
|
||||
assert(realExtent.x() > 0 && realExtent.y() > 0 && realExtent.z() > 0);
|
||||
@ -172,7 +172,7 @@ inline void ConvexMeshShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, f
|
||||
/**
|
||||
* @param vertex Vertex to be added
|
||||
*/
|
||||
inline void ConvexMeshShape::addVertex(const vec3& vertex) {
|
||||
void ConvexMeshShape::addVertex(const vec3& vertex) {
|
||||
|
||||
// Add the vertex in to vertices array
|
||||
m_vertices.push_back(vertex);
|
||||
@ -207,7 +207,7 @@ inline void ConvexMeshShape::addVertex(const vec3& vertex) {
|
||||
* @param v1 Index of the first vertex of the edge to add
|
||||
* @param v2 Index of the second vertex of the edge to add
|
||||
*/
|
||||
inline void ConvexMeshShape::addEdge(uint32_t v1, uint32_t v2) {
|
||||
void ConvexMeshShape::addEdge(uint32_t v1, uint32_t v2) {
|
||||
|
||||
// If the entry for vertex v1 does not exist in the adjacency list
|
||||
if (m_edgesAdjacencyList.count(v1) == 0) {
|
||||
@ -228,7 +228,7 @@ inline void ConvexMeshShape::addEdge(uint32_t v1, uint32_t v2) {
|
||||
/**
|
||||
* @return True if the edges information is used and false otherwise
|
||||
*/
|
||||
inline bool ConvexMeshShape::isEdgesInformationUsed() const {
|
||||
bool ConvexMeshShape::isEdgesInformationUsed() const {
|
||||
return m_isEdgesInformationUsed;
|
||||
}
|
||||
|
||||
@ -238,12 +238,12 @@ inline bool ConvexMeshShape::isEdgesInformationUsed() const {
|
||||
* @param isEdgesUsed True if you want to use the edges information to speed up
|
||||
* the collision detection with the convex mesh shape
|
||||
*/
|
||||
inline void ConvexMeshShape::setIsEdgesInformationUsed(bool isEdgesUsed) {
|
||||
void ConvexMeshShape::setIsEdgesInformationUsed(bool isEdgesUsed) {
|
||||
m_isEdgesInformationUsed = isEdgesUsed;
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool ConvexMeshShape::testPointInside(const vec3& localPoint,
|
||||
bool ConvexMeshShape::testPointInside(const vec3& localPoint,
|
||||
ProxyShape* proxyShape) const {
|
||||
|
||||
// Use the GJK algorithm to test if the point is inside the convex mesh
|
||||
|
@ -67,7 +67,7 @@ class ConvexShape : public CollisionShape {
|
||||
};
|
||||
|
||||
/// Return true if the collision shape is convex, false if it is concave
|
||||
inline bool ConvexShape::isConvex() const {
|
||||
bool ConvexShape::isConvex() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ inline bool ConvexShape::isConvex() const {
|
||||
/**
|
||||
* @return The margin (in meters) around the collision shape
|
||||
*/
|
||||
inline float ConvexShape::getMargin() const {
|
||||
float ConvexShape::getMargin() const {
|
||||
return m_margin;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ class CylinderShape : public ConvexShape {
|
||||
/**
|
||||
* @return Radius of the cylinder (in meters)
|
||||
*/
|
||||
inline float CylinderShape::getRadius() const {
|
||||
float CylinderShape::getRadius() const {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
@ -99,12 +99,12 @@ inline float CylinderShape::getRadius() const {
|
||||
/**
|
||||
* @return Height of the cylinder (in meters)
|
||||
*/
|
||||
inline float CylinderShape::getHeight() const {
|
||||
float CylinderShape::getHeight() const {
|
||||
return m_halfHeight + m_halfHeight;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void CylinderShape::setLocalScaling(const vec3& scaling) {
|
||||
void CylinderShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
m_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
|
||||
mRadius = (mRadius / m_scaling.x()) * scaling.x();
|
||||
@ -113,7 +113,7 @@ inline void CylinderShape::setLocalScaling(const vec3& scaling) {
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t CylinderShape::getSizeInBytes() const {
|
||||
size_t CylinderShape::getSizeInBytes() const {
|
||||
return sizeof(CylinderShape);
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ inline size_t CylinderShape::getSizeInBytes() const {
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void CylinderShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
void CylinderShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
// Maximum bounds
|
||||
max.setX(mRadius + m_margin);
|
||||
max.setY(m_halfHeight + m_margin);
|
||||
@ -139,7 +139,7 @@ inline void CylinderShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void CylinderShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
void CylinderShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
float height = float(2.0) * m_halfHeight;
|
||||
float diag = (1.0f / float(12.0)) * mass * (3 * mRadius * mRadius + height * height);
|
||||
tensor.setValue(diag, 0.0, 0.0, 0.0,
|
||||
@ -148,7 +148,7 @@ inline void CylinderShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, flo
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool CylinderShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const{
|
||||
bool CylinderShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const{
|
||||
return ( (localPoint.x() * localPoint.x() + localPoint.z() * localPoint.z()) < mRadius * mRadius
|
||||
&& localPoint.y() < m_halfHeight
|
||||
&& localPoint.y() > -m_halfHeight);
|
||||
|
@ -169,32 +169,32 @@ class HeightFieldShape : public ConcaveShape {
|
||||
};
|
||||
|
||||
// Return the number of rows in the height field
|
||||
inline int32_t HeightFieldShape::getNbRows() const {
|
||||
int32_t HeightFieldShape::getNbRows() const {
|
||||
return m_numberRows;
|
||||
}
|
||||
|
||||
// Return the number of columns in the height field
|
||||
inline int32_t HeightFieldShape::getNbColumns() const {
|
||||
int32_t HeightFieldShape::getNbColumns() const {
|
||||
return m_numberColumns;
|
||||
}
|
||||
|
||||
// Return the type of height value in the height field
|
||||
inline HeightFieldShape::HeightDataType HeightFieldShape::getHeightDataType() const {
|
||||
HeightFieldShape::HeightDataType HeightFieldShape::getHeightDataType() const {
|
||||
return m_heightDataType;
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t HeightFieldShape::getSizeInBytes() const {
|
||||
size_t HeightFieldShape::getSizeInBytes() const {
|
||||
return sizeof(HeightFieldShape);
|
||||
}
|
||||
|
||||
// Set the local scaling vector of the collision shape
|
||||
inline void HeightFieldShape::setLocalScaling(const vec3& scaling) {
|
||||
void HeightFieldShape::setLocalScaling(const vec3& scaling) {
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
|
||||
// Return the height of a given (x,y) point in the height field
|
||||
inline float HeightFieldShape::getHeightAt(int32_t x, int32_t y) const {
|
||||
float HeightFieldShape::getHeightAt(int32_t x, int32_t y) const {
|
||||
|
||||
switch(m_heightDataType) {
|
||||
case HEIGHT_FLOAT_TYPE : return ((float*)m_heightFieldData)[y * m_numberColumns + x];
|
||||
@ -205,7 +205,7 @@ inline float HeightFieldShape::getHeightAt(int32_t x, int32_t y) const {
|
||||
}
|
||||
|
||||
// Return the closest inside int32_teger grid value of a given floating grid value
|
||||
inline int32_t HeightFieldShape::computeIntegerGridValue(float value) const {
|
||||
int32_t HeightFieldShape::computeIntegerGridValue(float value) const {
|
||||
return (value < 0.0f) ? value - 0.5f : value + float(0.5);
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ inline int32_t HeightFieldShape::computeIntegerGridValue(float value) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void HeightFieldShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
void HeightFieldShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
|
||||
// Default inertia tensor
|
||||
// Note that this is not very realistic for a concave triangle mesh.
|
||||
|
@ -5,154 +5,133 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/collision/shapes/ConvexShape.hpp>
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
|
||||
// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Class SphereShape
|
||||
/**
|
||||
* This class represents a sphere collision shape that is centered
|
||||
* @brief Represents a sphere collision shape that is centered
|
||||
* at the origin and defined by its radius. This collision shape does not
|
||||
* have an explicit object margin distance. The margin is implicitly the
|
||||
* radius of the sphere. Therefore, no need to specify an object margin
|
||||
* for a sphere shape.
|
||||
*/
|
||||
class SphereShape : public ConvexShape {
|
||||
|
||||
protected :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Private copy-constructor
|
||||
SphereShape(const SphereShape& shape);
|
||||
|
||||
/// Private assignment operator
|
||||
SphereShape& operator=(const SphereShape& shape);
|
||||
|
||||
SphereShape& operator=(const SphereShape& shape) = delete;
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Return the number of bytes used by the collision shape
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
SphereShape(float radius);
|
||||
|
||||
/// Destructor
|
||||
virtual ~SphereShape();
|
||||
|
||||
/// Return the radius of the sphere
|
||||
float getRadius() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions.
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
|
||||
/// Update the AABB of a body using its collision shape
|
||||
virtual void computeAABB(AABB& aabb, const etk::Transform3D& transform) const;
|
||||
};
|
||||
|
||||
// Get the radius of the sphere
|
||||
/**
|
||||
* @brief
|
||||
* @return Radius of the sphere (in meters)
|
||||
*/
|
||||
inline float SphereShape::getRadius() const {
|
||||
float SphereShape::getRadius() const {
|
||||
return m_margin;
|
||||
}
|
||||
|
||||
* @brief
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void SphereShape::setLocalScaling(const vec3& scaling) {
|
||||
void SphereShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
m_margin = (m_margin / m_scaling.x()) * scaling.x();
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
|
||||
* @brief
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t SphereShape::getSizeInBytes() const {
|
||||
size_t SphereShape::getSizeInBytes() const {
|
||||
return sizeof(SphereShape);
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the object margin
|
||||
inline vec3 SphereShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
// Return the center of the sphere (the radius is taken int32_to account in the object margin)
|
||||
/**
|
||||
* @brief Get a local support point in a given direction without the object margin
|
||||
* @param[in] _direction
|
||||
* @param[in] _cachedCollisionData
|
||||
* @return the center of the sphere (the radius is taken int32_to account in the object margin)
|
||||
*/
|
||||
vec3 SphereShape::getLocalSupportPointWithoutMargin(const vec3& _direction, void** _cachedCollisionData) const {
|
||||
return vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// Return the local bounds of the shape in x, y and z directions.
|
||||
// This method is used to compute the AABB of the box
|
||||
/**
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
* @brief Get the local bounds of the shape in x, y and z directions.
|
||||
* This method is used to compute the AABB of the box
|
||||
* @param _min The minimum bounds of the shape in local-space coordinates
|
||||
* @param _max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void SphereShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
void SphereShape::getLocalBounds(vec3& _min, vec3& _max) const {
|
||||
// Maximum bounds
|
||||
max.setX(m_margin);
|
||||
max.setY(m_margin);
|
||||
max.setZ(m_margin);
|
||||
_max.setX(m_margin);
|
||||
_max.setY(m_margin);
|
||||
_max.setZ(m_margin);
|
||||
// Minimum bounds
|
||||
min.setX(-m_margin);
|
||||
min.setY(min.x());
|
||||
min.setZ(min.x());
|
||||
_min.setX(-m_margin);
|
||||
_min.setY(_min.x());
|
||||
_min.setZ(_min.x());
|
||||
}
|
||||
|
||||
// Return the local inertia tensor of the sphere
|
||||
/**
|
||||
* @param[out] tensor The 3x3 inertia tensor matrix of the shape in local-space
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
* @brief Compute the local inertia tensor of the sphere
|
||||
* @param[out] _tensor The 3x3 inertia tensor matrix of the shape in local-space coordinates
|
||||
* @param[in] _mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void SphereShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
float diag = float(0.4) * mass * m_margin * m_margin;
|
||||
tensor.setValue(diag, 0.0, 0.0,
|
||||
0.0, diag, 0.0,
|
||||
0.0, 0.0, diag);
|
||||
void SphereShape::computeLocalInertiaTensor(etk::Matrix3x3& _tensor, float _mass) const {
|
||||
float _diag = 0.4f * _mass * m_margin * m_margin;
|
||||
tensor.setValue(_diag, 0.0f, 0.0f,
|
||||
0.0f, _diag, 0.0f,
|
||||
0.0f, 0.0f, _diag);
|
||||
}
|
||||
|
||||
// Update the AABB of a body using its collision shape
|
||||
/**
|
||||
* @param[out] aabb The axis-aligned bounding box (AABB) of the collision shape
|
||||
* computed in world-space coordinates
|
||||
* @param transform etk::Transform3D used to compute the AABB of the collision shape
|
||||
* @brief Update the AABB of a body using its collision shape
|
||||
* @param[out] _aabb The axis-aligned bounding box (AABB) of the collision shape computed in world-space coordinates
|
||||
* @param[in] _transform etk::Transform3D used to compute the AABB of the collision shape
|
||||
*/
|
||||
inline void SphereShape::computeAABB(AABB& aabb, const etk::Transform3D& transform) const {
|
||||
|
||||
void SphereShape::computeAABB(AABB& _aabb, const etk::Transform3D& _transform) const {
|
||||
// Get the local extents in x,y and z direction
|
||||
vec3 extents(m_margin, m_margin, m_margin);
|
||||
|
||||
// Update the AABB with the new minimum and maximum coordinates
|
||||
aabb.setMin(transform.getPosition() - extents);
|
||||
aabb.setMax(transform.getPosition() + extents);
|
||||
_aabb.setMin(_transform.getPosition() - extents);
|
||||
_aabb.setMax(_transform.getPosition() + extents);
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool SphereShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
return (localPoint.length2() < m_margin * m_margin);
|
||||
/**
|
||||
* @brief Test if a point is inside a shape
|
||||
* @param[in] _localPoint Point to check
|
||||
* @param[in] _proxyShape Shape to check
|
||||
* @return true if a point is inside the collision shape
|
||||
*/
|
||||
bool SphereShape::testPointInside(const vec3& _localPoint, ProxyShape* _proxyShape) const {
|
||||
return (_localPoint.length2() < m_margin * m_margin);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ using namespace ephysics;
|
||||
*/
|
||||
TriangleShape::TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3, float margin)
|
||||
: ConvexShape(TRIANGLE, margin) {
|
||||
mPoints[0] = point1;
|
||||
mPoints[1] = point2;
|
||||
mPoints[2] = point3;
|
||||
m_points[0] = point1;
|
||||
m_points[1] = point2;
|
||||
m_points[2] = point3;
|
||||
m_raycastTestType = FRONT;
|
||||
}
|
||||
|
||||
@ -41,9 +41,9 @@ bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
PROFILE("TriangleShape::raycast()");
|
||||
|
||||
const vec3 pq = ray.point2 - ray.point1;
|
||||
const vec3 pa = mPoints[0] - ray.point1;
|
||||
const vec3 pb = mPoints[1] - ray.point1;
|
||||
const vec3 pc = mPoints[2] - ray.point1;
|
||||
const vec3 pa = m_points[0] - ray.point1;
|
||||
const vec3 pb = m_points[1] - ray.point1;
|
||||
const vec3 pc = m_points[2] - ray.point1;
|
||||
|
||||
// Test if the line PQ is inside the eges BC, CA and AB. We use the triple
|
||||
// product for this test.
|
||||
@ -89,12 +89,12 @@ bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
w *= denom;
|
||||
|
||||
// Compute the local hit point using the barycentric coordinates
|
||||
const vec3 localHitPoint = u * mPoints[0] + v * mPoints[1] + w * mPoints[2];
|
||||
const vec3 localHitPoint = u * m_points[0] + v * m_points[1] + w * m_points[2];
|
||||
const float hitFraction = (localHitPoint - ray.point1).length() / pq.length();
|
||||
|
||||
if (hitFraction < 0.0f || hitFraction > ray.maxFraction) return false;
|
||||
|
||||
vec3 localHitNormal = (mPoints[1] - mPoints[0]).cross(mPoints[2] - mPoints[0]);
|
||||
vec3 localHitNormal = (m_points[1] - m_points[0]).cross(m_points[2] - m_points[0]);
|
||||
if (localHitNormal.dot(pq) > 0.0f) localHitNormal = -localHitNormal;
|
||||
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
|
@ -5,45 +5,28 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
#include <ephysics/collision/shapes/ConvexShape.hpp>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
/// Raycast test side for the triangle
|
||||
/**
|
||||
* @brief Raycast test side for the triangle
|
||||
*/
|
||||
enum TriangleRaycastSide {
|
||||
|
||||
/// Raycast against front triangle
|
||||
FRONT,
|
||||
|
||||
/// Raycast against back triangle
|
||||
BACK,
|
||||
|
||||
/// Raycast against front and back triangle
|
||||
FRONT_AND_BACK
|
||||
FRONT, //!< Raycast against front triangle
|
||||
BACK, //!< Raycast against back triangle
|
||||
FRONT_AND_BACK //!< Raycast against front and back triangle
|
||||
};
|
||||
|
||||
// Class TriangleShape
|
||||
/**
|
||||
* This class represents a triangle collision shape that is centered
|
||||
* at the origin and defined three points.
|
||||
*/
|
||||
class TriangleShape : public ConvexShape {
|
||||
|
||||
protected:
|
||||
|
||||
// -------------------- Attribute -------------------- //
|
||||
|
||||
/// Three points of the triangle
|
||||
vec3 mPoints[3];
|
||||
|
||||
/// Raycast test type for the triangle (front, back, front-back)
|
||||
TriangleRaycastSide m_raycastTestType;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
vec3 m_points[3]; //!< Three points of the triangle
|
||||
TriangleRaycastSide m_raycastTestType; //!< Raycast test type for the triangle (front, back, front-back)
|
||||
/// Private copy-constructor
|
||||
TriangleShape(const TriangleShape& shape);
|
||||
|
||||
@ -64,9 +47,6 @@ class TriangleShape : public ConvexShape {
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3,
|
||||
float margin = OBJECT_MARGIN);
|
||||
@ -94,23 +74,20 @@ class TriangleShape : public ConvexShape {
|
||||
|
||||
/// Return the coordinates of a given vertex of the triangle
|
||||
vec3 getVertex(int32_t index) const;
|
||||
|
||||
// ---------- Friendship ---------- //
|
||||
|
||||
friend class ConcaveMeshRaycastCallback;
|
||||
friend class TriangleOverlapCallback;
|
||||
};
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
inline size_t TriangleShape::getSizeInBytes() const {
|
||||
size_t TriangleShape::getSizeInBytes() const {
|
||||
return sizeof(TriangleShape);
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the object margin
|
||||
inline vec3 TriangleShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
vec3 TriangleShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
vec3 dotProducts(direction.dot(mPoints[0]), direction.dot(mPoints[1]), direction.dot(mPoints[2]));
|
||||
return mPoints[dotProducts.getMaxAxis()];
|
||||
vec3 dotProducts(direction.dot(m_points[0]), direction.dot(m_points[1]), direction.dot(m_points[2]));
|
||||
return m_points[dotProducts.getMaxAxis()];
|
||||
}
|
||||
|
||||
// Return the local bounds of the shape in x, y and z directions.
|
||||
@ -119,11 +96,11 @@ inline vec3 TriangleShape::getLocalSupportPointWithoutMargin(const vec3& directi
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
inline void TriangleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
void TriangleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
const vec3 xAxis(mPoints[0].x(), mPoints[1].x(), mPoints[2].x());
|
||||
const vec3 yAxis(mPoints[0].y(), mPoints[1].y(), mPoints[2].y());
|
||||
const vec3 zAxis(mPoints[0].z(), mPoints[1].z(), mPoints[2].z());
|
||||
const vec3 xAxis(m_points[0].x(), m_points[1].x(), m_points[2].x());
|
||||
const vec3 yAxis(m_points[0].y(), m_points[1].y(), m_points[2].y());
|
||||
const vec3 zAxis(m_points[0].z(), m_points[1].z(), m_points[2].z());
|
||||
min.setValue(xAxis.getMin(), yAxis.getMin(), zAxis.getMin());
|
||||
max.setValue(xAxis.getMax(), yAxis.getMax(), zAxis.getMax());
|
||||
|
||||
@ -132,11 +109,11 @@ inline void TriangleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
}
|
||||
|
||||
// Set the local scaling vector of the collision shape
|
||||
inline void TriangleShape::setLocalScaling(const vec3& scaling) {
|
||||
void TriangleShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
mPoints[0] = (mPoints[0] / m_scaling) * scaling;
|
||||
mPoints[1] = (mPoints[1] / m_scaling) * scaling;
|
||||
mPoints[2] = (mPoints[2] / m_scaling) * scaling;
|
||||
m_points[0] = (m_points[0] / m_scaling) * scaling;
|
||||
m_points[1] = (m_points[1] / m_scaling) * scaling;
|
||||
m_points[2] = (m_points[2] / m_scaling) * scaling;
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
@ -147,7 +124,7 @@ inline void TriangleShape::setLocalScaling(const vec3& scaling) {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void TriangleShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
void TriangleShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
tensor.setZero();
|
||||
}
|
||||
|
||||
@ -157,11 +134,11 @@ inline void TriangleShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, flo
|
||||
* computed in world-space coordinates
|
||||
* @param transform etk::Transform3D used to compute the AABB of the collision shape
|
||||
*/
|
||||
inline void TriangleShape::computeAABB(AABB& aabb, const etk::Transform3D& transform) const {
|
||||
void TriangleShape::computeAABB(AABB& aabb, const etk::Transform3D& transform) const {
|
||||
|
||||
const vec3 worldPoint1 = transform * mPoints[0];
|
||||
const vec3 worldPoint2 = transform * mPoints[1];
|
||||
const vec3 worldPoint3 = transform * mPoints[2];
|
||||
const vec3 worldPoint1 = transform * m_points[0];
|
||||
const vec3 worldPoint2 = transform * m_points[1];
|
||||
const vec3 worldPoint3 = transform * m_points[2];
|
||||
|
||||
const vec3 xAxis(worldPoint1.x(), worldPoint2.x(), worldPoint3.x());
|
||||
const vec3 yAxis(worldPoint1.y(), worldPoint2.y(), worldPoint3.y());
|
||||
@ -171,12 +148,12 @@ inline void TriangleShape::computeAABB(AABB& aabb, const etk::Transform3D& trans
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool TriangleShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
bool TriangleShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return the raycast test type (front, back, front-back)
|
||||
inline TriangleRaycastSide TriangleShape::getRaycastTestType() const {
|
||||
TriangleRaycastSide TriangleShape::getRaycastTestType() const {
|
||||
return m_raycastTestType;
|
||||
}
|
||||
|
||||
@ -184,7 +161,7 @@ inline TriangleRaycastSide TriangleShape::getRaycastTestType() const {
|
||||
/**
|
||||
* @param testType Raycast test type for the triangle (front, back, front-back)
|
||||
*/
|
||||
inline void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
|
||||
void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
|
||||
m_raycastTestType = testType;
|
||||
}
|
||||
|
||||
@ -192,9 +169,9 @@ inline void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
|
||||
/**
|
||||
* @param index Index (0 to 2) of a vertex of the triangle
|
||||
*/
|
||||
inline vec3 TriangleShape::getVertex(int32_t index) const {
|
||||
vec3 TriangleShape::getVertex(int32_t index) const {
|
||||
assert(index >= 0 && index < 3);
|
||||
return mPoints[index];
|
||||
return m_points[index];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,120 +5,68 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/constraint/Joint.hpp>
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
|
||||
namespace ephysics {
|
||||
|
||||
// Structure BallAndSocketJointInfo
|
||||
/**
|
||||
* This structure is used to gather the information needed to create a ball-and-socket
|
||||
/**
|
||||
* @brief It is used to gather the information needed to create a ball-and-socket
|
||||
* joint. This structure will be used to create the actual ball-and-socket joint.
|
||||
*/
|
||||
struct BallAndSocketJointInfo : public JointInfo {
|
||||
|
||||
struct BallAndSocketJointInfo : public JointInfo {
|
||||
public :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point (in world-space coordinates)
|
||||
vec3 m_anchorPointWorldSpace;
|
||||
|
||||
/// Constructor
|
||||
vec3 m_anchorPointWorldSpace; //!< Anchor point (in world-space coordinates)
|
||||
/**
|
||||
* @param rigidBody1 Pointer to the first body of the joint
|
||||
* @param rigidBody2 Pointer to the second body of the joint
|
||||
* @param initAnchorPointWorldSpace The anchor point in world-space
|
||||
* coordinates
|
||||
* @brief Constructor
|
||||
* @param _rigidBody1 Pointer to the first body of the joint
|
||||
* @param _rigidBody2 Pointer to the second body of the joint
|
||||
* @param _initAnchorPointWorldSpace The anchor point in world-space coordinates
|
||||
*/
|
||||
BallAndSocketJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const vec3& initAnchorPointWorldSpace)
|
||||
: JointInfo(rigidBody1, rigidBody2, BALLSOCKETJOINT),
|
||||
m_anchorPointWorldSpace(initAnchorPointWorldSpace) {}
|
||||
};
|
||||
BallAndSocketJointInfo(RigidBody* _rigidBody1,
|
||||
RigidBody* _rigidBody2,
|
||||
const vec3& _initAnchorPointWorldSpace):
|
||||
JointInfo(_rigidBody1, _rigidBody2, BALLSOCKETJOINT),
|
||||
m_anchorPointWorldSpace(_initAnchorPointWorldSpace) {
|
||||
|
||||
// Class BallAndSocketJoint
|
||||
/**
|
||||
* This class represents a ball-and-socket joint that allows arbitrary rotation
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @brief Represents a ball-and-socket joint that allows arbitrary rotation
|
||||
* between two bodies. This joint has three degrees of freedom. It can be used to
|
||||
* create a chain of bodies for instance.
|
||||
*/
|
||||
class BallAndSocketJoint : public Joint {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Constants -------------------- //
|
||||
|
||||
// Beta value for the bias factor of position correction
|
||||
static const float BETA;
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point of body 1 (in local-space coordinates of body 1)
|
||||
vec3 m_localAnchorPointBody1;
|
||||
|
||||
/// Anchor point of body 2 (in local-space coordinates of body 2)
|
||||
vec3 m_localAnchorPointBody2;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
vec3 m_r1World;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
vec3 m_r2World;
|
||||
|
||||
/// Inertia tensor of body 1 (in world-space coordinates)
|
||||
etk::Matrix3x3 m_i1;
|
||||
|
||||
/// Inertia tensor of body 2 (in world-space coordinates)
|
||||
etk::Matrix3x3 m_i2;
|
||||
|
||||
/// Bias vector for the constraint
|
||||
vec3 m_biasVector;
|
||||
|
||||
/// Inverse mass matrix K=JM^-1J^-t of the constraint
|
||||
etk::Matrix3x3 m_inverseMassMatrix;
|
||||
|
||||
/// Accumulated impulse
|
||||
vec3 m_impulse;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
class BallAndSocketJoint : public Joint {
|
||||
private:
|
||||
static const float BETA; //!< Beta value for the bias factor of position correction
|
||||
vec3 m_localAnchorPointBody1; //!< Anchor point of body 1 (in local-space coordinates of body 1)
|
||||
vec3 m_localAnchorPointBody2; //!< Anchor point of body 2 (in local-space coordinates of body 2)
|
||||
vec3 m_r1World; //!< Vector from center of body 2 to anchor point in world-space
|
||||
vec3 m_r2World; //!< Vector from center of body 2 to anchor point in world-space
|
||||
etk::Matrix3x3 m_i1; //!< Inertia tensor of body 1 (in world-space coordinates)
|
||||
etk::Matrix3x3 m_i2; //!< Inertia tensor of body 2 (in world-space coordinates)
|
||||
vec3 m_biasVector; //!< Bias vector for the constraint
|
||||
etk::Matrix3x3 m_inverseMassMatrix; //!< Inverse mass matrix K=JM^-1J^-t of the constraint
|
||||
vec3 m_impulse; //!< Accumulated impulse
|
||||
/// Private copy-constructor
|
||||
BallAndSocketJoint(const BallAndSocketJoint& constraint);
|
||||
|
||||
/// Private assignment operator
|
||||
BallAndSocketJoint& operator=(const BallAndSocketJoint& constraint);
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
||||
virtual size_t getSizeInBytes() const {
|
||||
return sizeof(BallAndSocketJoint);
|
||||
}
|
||||
/// Initialize before solving the constraint
|
||||
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Warm start the constraint (apply the previous impulse at the beginning of the step)
|
||||
virtual void warmstart(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the velocity constraint
|
||||
virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
/// Solve the position constraint (for position error correction)
|
||||
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BallAndSocketJoint();
|
||||
};
|
||||
|
||||
// Return the number of bytes used by the joint
|
||||
inline size_t BallAndSocketJoint::getSizeInBytes() const {
|
||||
return sizeof(BallAndSocketJoint);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -14,22 +14,22 @@ using namespace std;
|
||||
// Constructor
|
||||
ContactPoint::ContactPoint(const ContactPointInfo& contactInfo)
|
||||
: m_body1(contactInfo.shape1->getBody()), m_body2(contactInfo.shape2->getBody()),
|
||||
mNormal(contactInfo.normal),
|
||||
mPenetrationDepth(contactInfo.penetrationDepth),
|
||||
mLocalPointOnBody1(contactInfo.localPoint1),
|
||||
mLocalPointOnBody2(contactInfo.localPoint2),
|
||||
m_normal(contactInfo.normal),
|
||||
m_penetrationDepth(contactInfo.penetrationDepth),
|
||||
m_localPointOnBody1(contactInfo.localPoint1),
|
||||
m_localPointOnBody2(contactInfo.localPoint2),
|
||||
m_worldPointOnBody1(contactInfo.shape1->getBody()->getTransform() *
|
||||
contactInfo.shape1->getLocalToBodyTransform() *
|
||||
contactInfo.localPoint1),
|
||||
m_worldPointOnBody2(contactInfo.shape2->getBody()->getTransform() *
|
||||
contactInfo.shape2->getLocalToBodyTransform() *
|
||||
contactInfo.localPoint2),
|
||||
mIsRestingContact(false) {
|
||||
m_isRestingContact(false) {
|
||||
|
||||
m_frictionVectors[0] = vec3(0, 0, 0);
|
||||
m_frictionVectors[1] = vec3(0, 0, 0);
|
||||
|
||||
assert(mPenetrationDepth > 0.0);
|
||||
assert(m_penetrationDepth > 0.0);
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,347 +5,269 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/body/CollisionBody.hpp>
|
||||
#include <ephysics/collision/CollisionShapeInfo.hpp>
|
||||
#include <ephysics/configuration.hpp>
|
||||
#include <ephysics/mathematics/mathematics.hpp>
|
||||
#include <ephysics/configuration.hpp>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace ephysics {
|
||||
|
||||
// Structure ContactPointInfo
|
||||
/**
|
||||
* This structure contains informations about a collision contact
|
||||
/**
|
||||
* @brief This structure contains informations about a collision contact
|
||||
* computed during the narrow-phase collision detection. Those
|
||||
* informations are used to compute the contact set for a contact
|
||||
* between two bodies.
|
||||
*/
|
||||
struct ContactPointInfo {
|
||||
|
||||
private:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
struct ContactPointInfo {
|
||||
public:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// First proxy shape of the contact
|
||||
ProxyShape* shape1;
|
||||
|
||||
/// Second proxy shape of the contact
|
||||
ProxyShape* shape2;
|
||||
|
||||
/// First collision shape
|
||||
const CollisionShape* collisionShape1;
|
||||
|
||||
/// Second collision shape
|
||||
const CollisionShape* collisionShape2;
|
||||
|
||||
/// Normalized normal vector of the collision contact in world space
|
||||
vec3 normal;
|
||||
|
||||
/// Penetration depth of the contact
|
||||
float penetrationDepth;
|
||||
|
||||
/// Contact point of body 1 in local space of body 1
|
||||
vec3 localPoint1;
|
||||
|
||||
/// Contact point of body 2 in local space of body 2
|
||||
vec3 localPoint2;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactPointInfo(ProxyShape* proxyShape1, ProxyShape* proxyShape2, const CollisionShape* collShape1,
|
||||
const CollisionShape* collShape2, const vec3& normal, float penetrationDepth,
|
||||
const vec3& localPoint1, const vec3& localPoint2)
|
||||
: shape1(proxyShape1), shape2(proxyShape2), collisionShape1(collShape1), collisionShape2(collShape2),
|
||||
normal(normal), penetrationDepth(penetrationDepth), localPoint1(localPoint1),
|
||||
localPoint2(localPoint2) {
|
||||
ContactPointInfo(ProxyShape* _proxyShape1,
|
||||
ProxyShape* _proxyShape2,
|
||||
const CollisionShape* _collShape1,
|
||||
const CollisionShape* _collShape2,
|
||||
const vec3& _normal,
|
||||
float _penetrationDepth,
|
||||
const vec3& _localPoint1,
|
||||
const vec3& _localPoint2):
|
||||
shape1(_proxyShape1),
|
||||
shape2(_proxyShape2),
|
||||
collisionShape1(_collShape1),
|
||||
collisionShape2(_collShape2),
|
||||
normal(_normal),
|
||||
penetrationDepth(_penetrationDepth),
|
||||
localPoint1(_localPoint1),
|
||||
localPoint2(_localPoint2) {
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Class ContactPoint
|
||||
/**
|
||||
* This class represents a collision contact point between two
|
||||
/**
|
||||
* @brief This class represents a collision contact point between two
|
||||
* bodies in the physics engine.
|
||||
*/
|
||||
class ContactPoint {
|
||||
|
||||
class ContactPoint {
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// First rigid body of the contact
|
||||
CollisionBody* m_body1;
|
||||
|
||||
/// Second rigid body of the contact
|
||||
CollisionBody* m_body2;
|
||||
|
||||
/// Normalized normal vector of the contact (from body1 toward body2) in world space
|
||||
const vec3 mNormal;
|
||||
|
||||
/// Penetration depth
|
||||
float mPenetrationDepth;
|
||||
|
||||
/// Contact point on body 1 in local space of body 1
|
||||
const vec3 mLocalPointOnBody1;
|
||||
|
||||
/// Contact point on body 2 in local space of body 2
|
||||
const vec3 mLocalPointOnBody2;
|
||||
|
||||
/// Contact point on body 1 in world space
|
||||
vec3 m_worldPointOnBody1;
|
||||
|
||||
/// Contact point on body 2 in world space
|
||||
vec3 m_worldPointOnBody2;
|
||||
|
||||
/// True if the contact is a resting contact (exists for more than one time step)
|
||||
bool mIsRestingContact;
|
||||
|
||||
/// Two orthogonal vectors that span the tangential friction plane
|
||||
vec3 m_frictionVectors[2];
|
||||
|
||||
/// Cached penetration impulse
|
||||
float mPenetrationImpulse;
|
||||
|
||||
/// Cached first friction impulse
|
||||
float m_frictionImpulse1;
|
||||
|
||||
/// Cached second friction impulse
|
||||
float m_frictionImpulse2;
|
||||
|
||||
/// Cached rolling resistance impulse
|
||||
vec3 m_rollingResistanceImpulse;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
CollisionBody* m_body1; //!< First rigid body of the contact
|
||||
CollisionBody* m_body2; //!< Second rigid body of the contact
|
||||
const vec3 m_normal; //!< Normalized normal vector of the contact (from body1 toward body2) in world space
|
||||
float m_penetrationDepth; //!< Penetration depth
|
||||
const vec3 m_localPointOnBody1; //!< Contact point on body 1 in local space of body 1
|
||||
const vec3 m_localPointOnBody2; //!< Contact point on body 2 in local space of body 2
|
||||
vec3 m_worldPointOnBody1; //!< Contact point on body 1 in world space
|
||||
vec3 m_worldPointOnBody2; //!< Contact point on body 2 in world space
|
||||
bool m_isRestingContact; //!< True if the contact is a resting contact (exists for more than one time step)
|
||||
vec3 m_frictionVectors[2]; //!< Two orthogonal vectors that span the tangential friction plane
|
||||
float m_penetrationImpulse; //!< Cached penetration impulse
|
||||
float m_frictionImpulse1; //!< Cached first friction impulse
|
||||
float m_frictionImpulse2; //!< Cached second friction impulse
|
||||
vec3 m_rollingResistanceImpulse; //!< Cached rolling resistance impulse
|
||||
/// Private copy-constructor
|
||||
ContactPoint(const ContactPoint& contact);
|
||||
|
||||
ContactPoint(const ContactPoint& contact) = delete;
|
||||
/// Private assignment operator
|
||||
ContactPoint& operator=(const ContactPoint& contact);
|
||||
|
||||
ContactPoint& operator=(const ContactPoint& contact) = delete;
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactPoint(const ContactPointInfo& contactInfo);
|
||||
|
||||
/// Destructor
|
||||
~ContactPoint();
|
||||
|
||||
/// Return the reference to the body 1
|
||||
CollisionBody* getBody1() const;
|
||||
|
||||
/// Return the reference to the body 2
|
||||
CollisionBody* getBody2() const;
|
||||
|
||||
/// Return the normal vector of the contact
|
||||
vec3 getNormal() const;
|
||||
|
||||
/// Set the penetration depth of the contact
|
||||
void setPenetrationDepth(float penetrationDepth);
|
||||
|
||||
void setPenetrationDepth(float _penetrationDepth);
|
||||
/// Return the contact local point on body 1
|
||||
vec3 getLocalPointOnBody1() const;
|
||||
|
||||
/// Return the contact local point on body 2
|
||||
vec3 getLocalPointOnBody2() const;
|
||||
|
||||
/// Return the contact world point on body 1
|
||||
vec3 getWorldPointOnBody1() const;
|
||||
|
||||
/// Return the contact world point on body 2
|
||||
vec3 getWorldPointOnBody2() const;
|
||||
|
||||
/// Return the cached penetration impulse
|
||||
float getPenetrationImpulse() const;
|
||||
|
||||
/// Return the cached first friction impulse
|
||||
float getFrictionImpulse1() const;
|
||||
|
||||
/// Return the cached second friction impulse
|
||||
float getFrictionImpulse2() const;
|
||||
|
||||
/// Return the cached rolling resistance impulse
|
||||
vec3 getRollingResistanceImpulse() const;
|
||||
|
||||
/// Set the cached penetration impulse
|
||||
void setPenetrationImpulse(float impulse);
|
||||
|
||||
void setPenetrationImpulse(float _impulse);
|
||||
/// Set the first cached friction impulse
|
||||
void setFrictionImpulse1(float impulse);
|
||||
|
||||
void setFrictionImpulse1(float _impulse);
|
||||
/// Set the second cached friction impulse
|
||||
void setFrictionImpulse2(float impulse);
|
||||
|
||||
void setFrictionImpulse2(float _impulse);
|
||||
/// Set the cached rolling resistance impulse
|
||||
void setRollingResistanceImpulse(const vec3& impulse);
|
||||
|
||||
void setRollingResistanceImpulse(const vec3& _impulse);
|
||||
/// Set the contact world point on body 1
|
||||
void setWorldPointOnBody1(const vec3& worldPoint);
|
||||
|
||||
void setWorldPointOnBody1(const vec3& _worldPoint);
|
||||
/// Set the contact world point on body 2
|
||||
void setWorldPointOnBody2(const vec3& worldPoint);
|
||||
|
||||
void setWorldPointOnBody2(const vec3& _worldPoint);
|
||||
/// Return true if the contact is a resting contact
|
||||
bool getIsRestingContact() const;
|
||||
|
||||
/// Set the mIsRestingContact variable
|
||||
void setIsRestingContact(bool isRestingContact);
|
||||
|
||||
/// Set the m_isRestingContact variable
|
||||
void setIsRestingContact(bool _isRestingContact);
|
||||
/// Get the first friction vector
|
||||
vec3 getFrictionVector1() const;
|
||||
|
||||
/// Set the first friction vector
|
||||
void setFrictionVector1(const vec3& frictionVector1);
|
||||
|
||||
void setFrictionVector1(const vec3& _frictionVector1);
|
||||
/// Get the second friction vector
|
||||
vec3 getFrictionvec2() const;
|
||||
|
||||
/// Set the second friction vector
|
||||
void setFrictionvec2(const vec3& frictionvec2);
|
||||
|
||||
void setFrictionvec2(const vec3& _frictionvec2);
|
||||
/// Return the penetration depth
|
||||
float getPenetrationDepth() const;
|
||||
|
||||
/// Return the number of bytes used by the contact point
|
||||
size_t getSizeInBytes() const;
|
||||
};
|
||||
};
|
||||
|
||||
// Return the reference to the body 1
|
||||
inline CollisionBody* ContactPoint::getBody1() const {
|
||||
CollisionBody* ContactPoint::getBody1() const {
|
||||
return m_body1;
|
||||
}
|
||||
|
||||
// Return the reference to the body 2
|
||||
inline CollisionBody* ContactPoint::getBody2() const {
|
||||
CollisionBody* ContactPoint::getBody2() const {
|
||||
return m_body2;
|
||||
}
|
||||
|
||||
// Return the normal vector of the contact
|
||||
inline vec3 ContactPoint::getNormal() const {
|
||||
return mNormal;
|
||||
vec3 ContactPoint::getNormal() const {
|
||||
return m_normal;
|
||||
}
|
||||
|
||||
// Set the penetration depth of the contact
|
||||
inline void ContactPoint::setPenetrationDepth(float penetrationDepth) {
|
||||
this->mPenetrationDepth = penetrationDepth;
|
||||
void ContactPoint::setPenetrationDepth(float penetrationDepth) {
|
||||
this->m_penetrationDepth = penetrationDepth;
|
||||
}
|
||||
|
||||
// Return the contact point on body 1
|
||||
inline vec3 ContactPoint::getLocalPointOnBody1() const {
|
||||
return mLocalPointOnBody1;
|
||||
vec3 ContactPoint::getLocalPointOnBody1() const {
|
||||
return m_localPointOnBody1;
|
||||
}
|
||||
|
||||
// Return the contact point on body 2
|
||||
inline vec3 ContactPoint::getLocalPointOnBody2() const {
|
||||
return mLocalPointOnBody2;
|
||||
vec3 ContactPoint::getLocalPointOnBody2() const {
|
||||
return m_localPointOnBody2;
|
||||
}
|
||||
|
||||
// Return the contact world point on body 1
|
||||
inline vec3 ContactPoint::getWorldPointOnBody1() const {
|
||||
vec3 ContactPoint::getWorldPointOnBody1() const {
|
||||
return m_worldPointOnBody1;
|
||||
}
|
||||
|
||||
// Return the contact world point on body 2
|
||||
inline vec3 ContactPoint::getWorldPointOnBody2() const {
|
||||
vec3 ContactPoint::getWorldPointOnBody2() const {
|
||||
return m_worldPointOnBody2;
|
||||
}
|
||||
|
||||
// Return the cached penetration impulse
|
||||
inline float ContactPoint::getPenetrationImpulse() const {
|
||||
return mPenetrationImpulse;
|
||||
float ContactPoint::getPenetrationImpulse() const {
|
||||
return m_penetrationImpulse;
|
||||
}
|
||||
|
||||
// Return the cached first friction impulse
|
||||
inline float ContactPoint::getFrictionImpulse1() const {
|
||||
float ContactPoint::getFrictionImpulse1() const {
|
||||
return m_frictionImpulse1;
|
||||
}
|
||||
|
||||
// Return the cached second friction impulse
|
||||
inline float ContactPoint::getFrictionImpulse2() const {
|
||||
float ContactPoint::getFrictionImpulse2() const {
|
||||
return m_frictionImpulse2;
|
||||
}
|
||||
|
||||
// Return the cached rolling resistance impulse
|
||||
inline vec3 ContactPoint::getRollingResistanceImpulse() const {
|
||||
vec3 ContactPoint::getRollingResistanceImpulse() const {
|
||||
return m_rollingResistanceImpulse;
|
||||
}
|
||||
|
||||
// Set the cached penetration impulse
|
||||
inline void ContactPoint::setPenetrationImpulse(float impulse) {
|
||||
mPenetrationImpulse = impulse;
|
||||
void ContactPoint::setPenetrationImpulse(float impulse) {
|
||||
m_penetrationImpulse = impulse;
|
||||
}
|
||||
|
||||
// Set the first cached friction impulse
|
||||
inline void ContactPoint::setFrictionImpulse1(float impulse) {
|
||||
void ContactPoint::setFrictionImpulse1(float impulse) {
|
||||
m_frictionImpulse1 = impulse;
|
||||
}
|
||||
|
||||
// Set the second cached friction impulse
|
||||
inline void ContactPoint::setFrictionImpulse2(float impulse) {
|
||||
void ContactPoint::setFrictionImpulse2(float impulse) {
|
||||
m_frictionImpulse2 = impulse;
|
||||
}
|
||||
|
||||
// Set the cached rolling resistance impulse
|
||||
inline void ContactPoint::setRollingResistanceImpulse(const vec3& impulse) {
|
||||
void ContactPoint::setRollingResistanceImpulse(const vec3& impulse) {
|
||||
m_rollingResistanceImpulse = impulse;
|
||||
}
|
||||
|
||||
// Set the contact world point on body 1
|
||||
inline void ContactPoint::setWorldPointOnBody1(const vec3& worldPoint) {
|
||||
void ContactPoint::setWorldPointOnBody1(const vec3& worldPoint) {
|
||||
m_worldPointOnBody1 = worldPoint;
|
||||
}
|
||||
|
||||
// Set the contact world point on body 2
|
||||
inline void ContactPoint::setWorldPointOnBody2(const vec3& worldPoint) {
|
||||
void ContactPoint::setWorldPointOnBody2(const vec3& worldPoint) {
|
||||
m_worldPointOnBody2 = worldPoint;
|
||||
}
|
||||
|
||||
// Return true if the contact is a resting contact
|
||||
inline bool ContactPoint::getIsRestingContact() const {
|
||||
return mIsRestingContact;
|
||||
bool ContactPoint::getIsRestingContact() const {
|
||||
return m_isRestingContact;
|
||||
}
|
||||
|
||||
// Set the mIsRestingContact variable
|
||||
inline void ContactPoint::setIsRestingContact(bool isRestingContact) {
|
||||
mIsRestingContact = isRestingContact;
|
||||
// Set the m_isRestingContact variable
|
||||
void ContactPoint::setIsRestingContact(bool isRestingContact) {
|
||||
m_isRestingContact = isRestingContact;
|
||||
}
|
||||
|
||||
// Get the first friction vector
|
||||
inline vec3 ContactPoint::getFrictionVector1() const {
|
||||
vec3 ContactPoint::getFrictionVector1() const {
|
||||
return m_frictionVectors[0];
|
||||
}
|
||||
|
||||
// Set the first friction vector
|
||||
inline void ContactPoint::setFrictionVector1(const vec3& frictionVector1) {
|
||||
void ContactPoint::setFrictionVector1(const vec3& frictionVector1) {
|
||||
m_frictionVectors[0] = frictionVector1;
|
||||
}
|
||||
|
||||
// Get the second friction vector
|
||||
inline vec3 ContactPoint::getFrictionvec2() const {
|
||||
vec3 ContactPoint::getFrictionvec2() const {
|
||||
return m_frictionVectors[1];
|
||||
}
|
||||
|
||||
// Set the second friction vector
|
||||
inline void ContactPoint::setFrictionvec2(const vec3& frictionvec2) {
|
||||
void ContactPoint::setFrictionvec2(const vec3& frictionvec2) {
|
||||
m_frictionVectors[1] = frictionvec2;
|
||||
}
|
||||
|
||||
// Return the penetration depth of the contact
|
||||
inline float ContactPoint::getPenetrationDepth() const {
|
||||
return mPenetrationDepth;
|
||||
float ContactPoint::getPenetrationDepth() const {
|
||||
return m_penetrationDepth;
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the contact point
|
||||
inline size_t ContactPoint::getSizeInBytes() const {
|
||||
size_t ContactPoint::getSizeInBytes() const {
|
||||
return sizeof(ContactPoint);
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ class FixedJoint : public Joint {
|
||||
};
|
||||
|
||||
// Return the number of bytes used by the joint
|
||||
inline size_t FixedJoint::getSizeInBytes() const {
|
||||
size_t FixedJoint::getSizeInBytes() const {
|
||||
return sizeof(FixedJoint);
|
||||
}
|
||||
|
||||
|
@ -321,7 +321,7 @@ class HingeJoint : public Joint {
|
||||
/**
|
||||
* @return True if the limits of the joint are enabled and false otherwise
|
||||
*/
|
||||
inline bool HingeJoint::isLimitEnabled() const {
|
||||
bool HingeJoint::isLimitEnabled() const {
|
||||
return mIsLimitEnabled;
|
||||
}
|
||||
|
||||
@ -329,7 +329,7 @@ inline bool HingeJoint::isLimitEnabled() const {
|
||||
/**
|
||||
* @return True if the motor of joint is enabled and false otherwise
|
||||
*/
|
||||
inline bool HingeJoint::isMotorEnabled() const {
|
||||
bool HingeJoint::isMotorEnabled() const {
|
||||
return mIsMotorEnabled;
|
||||
}
|
||||
|
||||
@ -337,7 +337,7 @@ inline bool HingeJoint::isMotorEnabled() const {
|
||||
/**
|
||||
* @return The minimum limit angle of the joint (in radian)
|
||||
*/
|
||||
inline float HingeJoint::getMinAngleLimit() const {
|
||||
float HingeJoint::getMinAngleLimit() const {
|
||||
return mLowerLimit;
|
||||
}
|
||||
|
||||
@ -345,7 +345,7 @@ inline float HingeJoint::getMinAngleLimit() const {
|
||||
/**
|
||||
* @return The maximum limit angle of the joint (in radian)
|
||||
*/
|
||||
inline float HingeJoint::getMaxAngleLimit() const {
|
||||
float HingeJoint::getMaxAngleLimit() const {
|
||||
return mUpperLimit;
|
||||
}
|
||||
|
||||
@ -353,7 +353,7 @@ inline float HingeJoint::getMaxAngleLimit() const {
|
||||
/**
|
||||
* @return The current speed of the joint motor (in radian per second)
|
||||
*/
|
||||
inline float HingeJoint::getMotorSpeed() const {
|
||||
float HingeJoint::getMotorSpeed() const {
|
||||
return mMotorSpeed;
|
||||
}
|
||||
|
||||
@ -361,7 +361,7 @@ inline float HingeJoint::getMotorSpeed() const {
|
||||
/**
|
||||
* @return The maximum torque of the joint motor (in Newtons)
|
||||
*/
|
||||
inline float HingeJoint::getMaxMotorTorque() const {
|
||||
float HingeJoint::getMaxMotorTorque() const {
|
||||
return mMaxMotorTorque;
|
||||
}
|
||||
|
||||
@ -370,12 +370,12 @@ inline float HingeJoint::getMaxMotorTorque() const {
|
||||
* @param timeStep The current time step (in seconds)
|
||||
* @return The int32_tensity of the current torque (in Newtons) of the joint motor
|
||||
*/
|
||||
inline float HingeJoint::getMotorTorque(float timeStep) const {
|
||||
float HingeJoint::getMotorTorque(float timeStep) const {
|
||||
return m_impulseMotor / timeStep;
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the joint
|
||||
inline size_t HingeJoint::getSizeInBytes() const {
|
||||
size_t HingeJoint::getSizeInBytes() const {
|
||||
return sizeof(HingeJoint);
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ class Joint {
|
||||
/**
|
||||
* @return The first body involved in the joint
|
||||
*/
|
||||
inline RigidBody* Joint::getBody1() const {
|
||||
RigidBody* Joint::getBody1() const {
|
||||
return m_body1;
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ inline RigidBody* Joint::getBody1() const {
|
||||
/**
|
||||
* @return The second body involved in the joint
|
||||
*/
|
||||
inline RigidBody* Joint::getBody2() const {
|
||||
RigidBody* Joint::getBody2() const {
|
||||
return m_body2;
|
||||
}
|
||||
|
||||
@ -201,7 +201,7 @@ inline RigidBody* Joint::getBody2() const {
|
||||
/**
|
||||
* @return True if the joint is active
|
||||
*/
|
||||
inline bool Joint::isActive() const {
|
||||
bool Joint::isActive() const {
|
||||
return (m_body1->isActive() && m_body2->isActive());
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ inline bool Joint::isActive() const {
|
||||
/**
|
||||
* @return The type of the joint
|
||||
*/
|
||||
inline JointType Joint::getType() const {
|
||||
JointType Joint::getType() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
@ -218,12 +218,12 @@ inline JointType Joint::getType() const {
|
||||
* @return True if the collision is enabled between the two bodies of the joint
|
||||
* is enabled and false otherwise
|
||||
*/
|
||||
inline bool Joint::isCollisionEnabled() const {
|
||||
bool Joint::isCollisionEnabled() const {
|
||||
return m_isCollisionEnabled;
|
||||
}
|
||||
|
||||
// Return true if the joint has already been added int32_to an island
|
||||
inline bool Joint::isAlreadyInIsland() const {
|
||||
bool Joint::isAlreadyInIsland() const {
|
||||
return m_isAlreadyInIsland;
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,7 @@ class SliderJoint : public Joint {
|
||||
/**
|
||||
* @return True if the joint limits are enabled
|
||||
*/
|
||||
inline bool SliderJoint::isLimitEnabled() const {
|
||||
bool SliderJoint::isLimitEnabled() const {
|
||||
return mIsLimitEnabled;
|
||||
}
|
||||
|
||||
@ -330,7 +330,7 @@ inline bool SliderJoint::isLimitEnabled() const {
|
||||
/**
|
||||
* @return True if the joint motor is enabled
|
||||
*/
|
||||
inline bool SliderJoint::isMotorEnabled() const {
|
||||
bool SliderJoint::isMotorEnabled() const {
|
||||
return mIsMotorEnabled;
|
||||
}
|
||||
|
||||
@ -338,7 +338,7 @@ inline bool SliderJoint::isMotorEnabled() const {
|
||||
/**
|
||||
* @return The minimum translation limit of the joint (in meters)
|
||||
*/
|
||||
inline float SliderJoint::getMinTranslationLimit() const {
|
||||
float SliderJoint::getMinTranslationLimit() const {
|
||||
return mLowerLimit;
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@ inline float SliderJoint::getMinTranslationLimit() const {
|
||||
/**
|
||||
* @return The maximum translation limit of the joint (in meters)
|
||||
*/
|
||||
inline float SliderJoint::getMaxTranslationLimit() const {
|
||||
float SliderJoint::getMaxTranslationLimit() const {
|
||||
return mUpperLimit;
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ inline float SliderJoint::getMaxTranslationLimit() const {
|
||||
/**
|
||||
* @return The current motor speed of the joint (in meters per second)
|
||||
*/
|
||||
inline float SliderJoint::getMotorSpeed() const {
|
||||
float SliderJoint::getMotorSpeed() const {
|
||||
return mMotorSpeed;
|
||||
}
|
||||
|
||||
@ -362,7 +362,7 @@ inline float SliderJoint::getMotorSpeed() const {
|
||||
/**
|
||||
* @return The maximum force of the joint motor (in Newton x meters)
|
||||
*/
|
||||
inline float SliderJoint::getMaxMotorForce() const {
|
||||
float SliderJoint::getMaxMotorForce() const {
|
||||
return mMaxMotorForce;
|
||||
}
|
||||
|
||||
@ -371,12 +371,12 @@ inline float SliderJoint::getMaxMotorForce() const {
|
||||
* @param timeStep Time step (in seconds)
|
||||
* @return The current force of the joint motor (in Newton x meters)
|
||||
*/
|
||||
inline float SliderJoint::getMotorForce(float timeStep) const {
|
||||
float SliderJoint::getMotorForce(float timeStep) const {
|
||||
return m_impulseMotor / timeStep;
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the joint
|
||||
inline size_t SliderJoint::getSizeInBytes() const {
|
||||
size_t SliderJoint::getSizeInBytes() const {
|
||||
return sizeof(SliderJoint);
|
||||
}
|
||||
|
||||
|
@ -84,12 +84,12 @@ namespace ephysics {
|
||||
*/
|
||||
void raycast(const Ray& _ray,
|
||||
RaycastCallback* _raycastCallback,
|
||||
unsigned short _raycastWithCategoryMaskBitss = 0xFFFF) const {
|
||||
unsigned short _raycastWithCategoryMaskBits = 0xFFFF) const {
|
||||
m_collisionDetection.raycast(_raycastCallback, _ray, _raycastWithCategoryMaskBits);
|
||||
}
|
||||
/// Test if the AABBs of two bodies overlap
|
||||
bool testAABBOverlap(const CollisionBody* body1,
|
||||
const CollisionBody* body2) const;
|
||||
bool testAABBOverlap(const CollisionBody* _body1,
|
||||
const CollisionBody* _body2) const;
|
||||
/**
|
||||
* @brief Test if the AABBs of two proxy shapes overlap
|
||||
* @param _shape1 Pointer to the first proxy shape to test
|
||||
@ -97,26 +97,26 @@ namespace ephysics {
|
||||
*/
|
||||
bool testAABBOverlap(const ProxyShape* _shape1,
|
||||
const ProxyShape* _shape2) const {
|
||||
return m_collisionDetection.testAABBOverlap(shape1, shape2);
|
||||
return m_collisionDetection.testAABBOverlap(_shape1, _shape2);
|
||||
}
|
||||
/// Test and report collisions between a given shape and all the others
|
||||
/// shapes of the world
|
||||
virtual void testCollision(const ProxyShape* shape,
|
||||
CollisionCallback* callback);
|
||||
virtual void testCollision(const ProxyShape* _shape,
|
||||
CollisionCallback* _callback);
|
||||
/// Test and report collisions between two given shapes
|
||||
virtual void testCollision(const ProxyShape* shape1,
|
||||
const ProxyShape* shape2,
|
||||
CollisionCallback* callback);
|
||||
virtual void testCollision(const ProxyShape* _shape1,
|
||||
const ProxyShape* _shape2,
|
||||
CollisionCallback* _callback);
|
||||
/// Test and report collisions between a body and all the others bodies of the
|
||||
/// world
|
||||
virtual void testCollision(const CollisionBody* body,
|
||||
CollisionCallback* callback);
|
||||
virtual void testCollision(const CollisionBody* _body,
|
||||
CollisionCallback* _callback);
|
||||
/// Test and report collisions between two bodies
|
||||
virtual void testCollision(const CollisionBody* body1,
|
||||
const CollisionBody* body2,
|
||||
CollisionCallback* callback);
|
||||
virtual void testCollision(const CollisionBody* _body1,
|
||||
const CollisionBody* _body2,
|
||||
CollisionCallback* _callback);
|
||||
/// Test and report collisions between all shapes of the world
|
||||
virtual void testCollision(CollisionCallback* callback);
|
||||
virtual void testCollision(CollisionCallback* _callback);
|
||||
friend class CollisionDetection;
|
||||
friend class CollisionBody;
|
||||
friend class RigidBody;
|
||||
|
@ -131,7 +131,7 @@ namespace ephysics {
|
||||
};
|
||||
|
||||
// Set the constrained velocities arrays
|
||||
inline void ConstraintSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
void ConstraintSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
vec3* constrainedAngularVelocities) {
|
||||
assert(constrainedLinearVelocities != NULL);
|
||||
assert(constrainedAngularVelocities != NULL);
|
||||
@ -140,7 +140,7 @@ inline void ConstraintSolver::setConstrainedVelocitiesArrays(vec3* constrainedLi
|
||||
}
|
||||
|
||||
// Set the constrained positions/orientations arrays
|
||||
inline void ConstraintSolver::setConstrainedPositionsArrays(vec3* constrainedPositions,
|
||||
void ConstraintSolver::setConstrainedPositionsArrays(vec3* constrainedPositions,
|
||||
etk::Quaternion* constrainedOrientations) {
|
||||
assert(constrainedPositions != NULL);
|
||||
assert(constrainedOrientations != NULL);
|
||||
|
@ -499,7 +499,7 @@ void ContactSolver::solve() {
|
||||
|
||||
ContactManifoldSolver& contactManifold = m_contactConstraints[c];
|
||||
|
||||
float sumPenetrationImpulse = 0.0;
|
||||
float sum_penetrationImpulse = 0.0;
|
||||
|
||||
// Get the constrained velocities
|
||||
const vec3& v1 = m_linearVelocities[contactManifold.indexBody1];
|
||||
@ -545,7 +545,7 @@ void ContactSolver::solve() {
|
||||
// Apply the impulse to the bodies of the constraint
|
||||
applyImpulse(impulsePenetration, contactManifold);
|
||||
|
||||
sumPenetrationImpulse += contactPoint.penetrationImpulse;
|
||||
sum_penetrationImpulse += contactPoint.penetrationImpulse;
|
||||
|
||||
// If the split impulse position correction is active
|
||||
if (m_isSplitImpulseActive) {
|
||||
@ -661,7 +661,7 @@ void ContactSolver::solve() {
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
float deltaLambda = -Jv * contactManifold.inverseFriction1Mass;
|
||||
float frictionLimit = contactManifold.frictionCoefficient * sumPenetrationImpulse;
|
||||
float frictionLimit = contactManifold.frictionCoefficient * sum_penetrationImpulse;
|
||||
lambdaTemp = contactManifold.friction1Impulse;
|
||||
contactManifold.friction1Impulse = std::max(-frictionLimit,
|
||||
std::min(contactManifold.friction1Impulse +
|
||||
@ -688,7 +688,7 @@ void ContactSolver::solve() {
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
deltaLambda = -Jv * contactManifold.inverseFriction2Mass;
|
||||
frictionLimit = contactManifold.frictionCoefficient * sumPenetrationImpulse;
|
||||
frictionLimit = contactManifold.frictionCoefficient * sum_penetrationImpulse;
|
||||
lambdaTemp = contactManifold.friction2Impulse;
|
||||
contactManifold.friction2Impulse = std::max(-frictionLimit,
|
||||
std::min(contactManifold.friction2Impulse +
|
||||
@ -713,7 +713,7 @@ void ContactSolver::solve() {
|
||||
Jv = deltaV.dot(contactManifold.normal);
|
||||
|
||||
deltaLambda = -Jv * (contactManifold.inverseTwistFrictionMass);
|
||||
frictionLimit = contactManifold.frictionCoefficient * sumPenetrationImpulse;
|
||||
frictionLimit = contactManifold.frictionCoefficient * sum_penetrationImpulse;
|
||||
lambdaTemp = contactManifold.frictionTwistImpulse;
|
||||
contactManifold.frictionTwistImpulse = std::max(-frictionLimit,
|
||||
std::min(contactManifold.frictionTwistImpulse
|
||||
@ -740,7 +740,7 @@ void ContactSolver::solve() {
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
vec3 deltaLambdaRolling = contactManifold.inverseRollingResistance * (-JvRolling);
|
||||
float rollingLimit = contactManifold.rollingResistanceFactor * sumPenetrationImpulse;
|
||||
float rollingLimit = contactManifold.rollingResistanceFactor * sum_penetrationImpulse;
|
||||
vec3 lambdaTempRolling = contactManifold.rollingResistanceImpulse;
|
||||
contactManifold.rollingResistanceImpulse = clamp(contactManifold.rollingResistanceImpulse + deltaLambdaRolling,
|
||||
rollingLimit);
|
||||
|
@ -238,7 +238,7 @@ namespace ephysics {
|
||||
};
|
||||
|
||||
// Set the split velocities arrays
|
||||
inline void ContactSolver::setSplitVelocitiesArrays(vec3* splitLinearVelocities,
|
||||
void ContactSolver::setSplitVelocitiesArrays(vec3* splitLinearVelocities,
|
||||
vec3* splitAngularVelocities) {
|
||||
assert(splitLinearVelocities != NULL);
|
||||
assert(splitAngularVelocities != NULL);
|
||||
@ -247,7 +247,7 @@ inline void ContactSolver::setSplitVelocitiesArrays(vec3* splitLinearVelocities,
|
||||
}
|
||||
|
||||
// Set the constrained velocities arrays
|
||||
inline void ContactSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
void ContactSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
vec3* constrainedAngularVelocities) {
|
||||
assert(constrainedLinearVelocities != NULL);
|
||||
assert(constrainedAngularVelocities != NULL);
|
||||
@ -256,23 +256,23 @@ inline void ContactSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinea
|
||||
}
|
||||
|
||||
// Return true if the split impulses position correction technique is used for contacts
|
||||
inline bool ContactSolver::isSplitImpulseActive() const {
|
||||
bool ContactSolver::isSplitImpulseActive() const {
|
||||
return m_isSplitImpulseActive;
|
||||
}
|
||||
|
||||
// Activate or Deactivate the split impulses for contacts
|
||||
inline void ContactSolver::setIsSplitImpulseActive(bool isActive) {
|
||||
void ContactSolver::setIsSplitImpulseActive(bool isActive) {
|
||||
m_isSplitImpulseActive = isActive;
|
||||
}
|
||||
|
||||
// Activate or deactivate the solving of friction constraints at the center of
|
||||
// the contact manifold instead of solving them at each contact point
|
||||
inline void ContactSolver::setIsSolveFrictionAtContactManifoldCenterActive(bool isActive) {
|
||||
void ContactSolver::setIsSolveFrictionAtContactManifoldCenterActive(bool isActive) {
|
||||
m_isSolveFrictionAtContactManifoldCenterActive = isActive;
|
||||
}
|
||||
|
||||
// Compute the collision restitution factor from the restitution factor of each body
|
||||
inline float ContactSolver::computeMixedRestitutionFactor(RigidBody* body1,
|
||||
float ContactSolver::computeMixedRestitutionFactor(RigidBody* body1,
|
||||
RigidBody* body2) const {
|
||||
float restitution1 = body1->getMaterial().getBounciness();
|
||||
float restitution2 = body2->getMaterial().getBounciness();
|
||||
@ -282,7 +282,7 @@ inline float ContactSolver::computeMixedRestitutionFactor(RigidBody* body1,
|
||||
}
|
||||
|
||||
// Compute the mixed friction coefficient from the friction coefficient of each body
|
||||
inline float ContactSolver::computeMixedFrictionCoefficient(RigidBody *body1,
|
||||
float ContactSolver::computeMixedFrictionCoefficient(RigidBody *body1,
|
||||
RigidBody *body2) const {
|
||||
// Use the geometric mean to compute the mixed friction coefficient
|
||||
return sqrt(body1->getMaterial().getFrictionCoefficient() *
|
||||
@ -290,13 +290,13 @@ inline float ContactSolver::computeMixedFrictionCoefficient(RigidBody *body1,
|
||||
}
|
||||
|
||||
// Compute th mixed rolling resistance factor between two bodies
|
||||
inline float ContactSolver::computeMixedRollingResistance(RigidBody* body1,
|
||||
float ContactSolver::computeMixedRollingResistance(RigidBody* body1,
|
||||
RigidBody* body2) const {
|
||||
return float(0.5f) * (body1->getMaterial().getRollingResistance() + body2->getMaterial().getRollingResistance());
|
||||
}
|
||||
|
||||
// Compute a penetration constraint impulse
|
||||
inline const Impulse ContactSolver::computePenetrationImpulse(float deltaLambda,
|
||||
const Impulse ContactSolver::computePenetrationImpulse(float deltaLambda,
|
||||
const ContactPointSolver& contactPoint)
|
||||
const {
|
||||
return Impulse(-contactPoint.normal * deltaLambda, -contactPoint.r1CrossN * deltaLambda,
|
||||
@ -304,7 +304,7 @@ inline const Impulse ContactSolver::computePenetrationImpulse(float deltaLambda,
|
||||
}
|
||||
|
||||
// Compute the first friction constraint impulse
|
||||
inline const Impulse ContactSolver::computeFriction1Impulse(float deltaLambda,
|
||||
const Impulse ContactSolver::computeFriction1Impulse(float deltaLambda,
|
||||
const ContactPointSolver& contactPoint)
|
||||
const {
|
||||
return Impulse(-contactPoint.frictionVector1 * deltaLambda,
|
||||
@ -314,7 +314,7 @@ inline const Impulse ContactSolver::computeFriction1Impulse(float deltaLambda,
|
||||
}
|
||||
|
||||
// Compute the second friction constraint impulse
|
||||
inline const Impulse ContactSolver::computeFriction2Impulse(float deltaLambda,
|
||||
const Impulse ContactSolver::computeFriction2Impulse(float deltaLambda,
|
||||
const ContactPointSolver& contactPoint)
|
||||
const {
|
||||
return Impulse(-contactPoint.frictionvec2 * deltaLambda,
|
||||
|
@ -166,7 +166,7 @@ namespace ephysics {
|
||||
};
|
||||
|
||||
// Reset the external force and torque applied to the bodies
|
||||
inline void DynamicsWorld::resetBodiesForceAndTorque() {
|
||||
void DynamicsWorld::resetBodiesForceAndTorque() {
|
||||
|
||||
// For each body of the world
|
||||
std::set<RigidBody*>::iterator it;
|
||||
@ -177,7 +177,7 @@ inline void DynamicsWorld::resetBodiesForceAndTorque() {
|
||||
}
|
||||
|
||||
// Get the number of iterations for the velocity constraint solver
|
||||
inline uint32_t DynamicsWorld::getNbIterationsVelocitySolver() const {
|
||||
uint32_t DynamicsWorld::getNbIterationsVelocitySolver() const {
|
||||
return m_nbVelocitySolverIterations;
|
||||
}
|
||||
|
||||
@ -185,12 +185,12 @@ inline uint32_t DynamicsWorld::getNbIterationsVelocitySolver() const {
|
||||
/**
|
||||
* @param nbIterations Number of iterations for the velocity solver
|
||||
*/
|
||||
inline void DynamicsWorld::setNbIterationsVelocitySolver(uint32_t nbIterations) {
|
||||
void DynamicsWorld::setNbIterationsVelocitySolver(uint32_t nbIterations) {
|
||||
m_nbVelocitySolverIterations = nbIterations;
|
||||
}
|
||||
|
||||
// Get the number of iterations for the position constraint solver
|
||||
inline uint32_t DynamicsWorld::getNbIterationsPositionSolver() const {
|
||||
uint32_t DynamicsWorld::getNbIterationsPositionSolver() const {
|
||||
return m_nbPositionSolverIterations;
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ inline uint32_t DynamicsWorld::getNbIterationsPositionSolver() const {
|
||||
/**
|
||||
* @param nbIterations Number of iterations for the position solver
|
||||
*/
|
||||
inline void DynamicsWorld::setNbIterationsPositionSolver(uint32_t nbIterations) {
|
||||
void DynamicsWorld::setNbIterationsPositionSolver(uint32_t nbIterations) {
|
||||
m_nbPositionSolverIterations = nbIterations;
|
||||
}
|
||||
|
||||
@ -206,7 +206,7 @@ inline void DynamicsWorld::setNbIterationsPositionSolver(uint32_t nbIterations)
|
||||
/**
|
||||
* @param technique Technique used for the position correction (Baumgarte or Split Impulses)
|
||||
*/
|
||||
inline void DynamicsWorld::setContactsPositionCorrectionTechnique(
|
||||
void DynamicsWorld::setContactsPositionCorrectionTechnique(
|
||||
ContactsPositionCorrectionTechnique technique) {
|
||||
if (technique == BAUMGARTE_CONTACTS) {
|
||||
m_contactSolver.setIsSplitImpulseActive(false);
|
||||
@ -220,7 +220,7 @@ inline void DynamicsWorld::setContactsPositionCorrectionTechnique(
|
||||
/**
|
||||
* @param technique Technique used for the joins position correction (Baumgarte or Non Linear Gauss Seidel)
|
||||
*/
|
||||
inline void DynamicsWorld::setJointsPositionCorrectionTechnique(
|
||||
void DynamicsWorld::setJointsPositionCorrectionTechnique(
|
||||
JointsPositionCorrectionTechnique technique) {
|
||||
if (technique == BAUMGARTE_JOINTS) {
|
||||
m_constraintSolver.setIsNonLinearGaussSeidelPositionCorrectionActive(false);
|
||||
@ -236,7 +236,7 @@ inline void DynamicsWorld::setJointsPositionCorrectionTechnique(
|
||||
* @param isActive True if you want the friction to be solved at the center of
|
||||
* the contact manifold and false otherwise
|
||||
*/
|
||||
inline void DynamicsWorld::setIsSolveFrictionAtContactManifoldCenterActive(bool isActive) {
|
||||
void DynamicsWorld::setIsSolveFrictionAtContactManifoldCenterActive(bool isActive) {
|
||||
m_contactSolver.setIsSolveFrictionAtContactManifoldCenterActive(isActive);
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ inline void DynamicsWorld::setIsSolveFrictionAtContactManifoldCenterActive(bool
|
||||
/**
|
||||
* @return The current gravity vector (in meter per seconds squared)
|
||||
*/
|
||||
inline vec3 DynamicsWorld::getGravity() const {
|
||||
vec3 DynamicsWorld::getGravity() const {
|
||||
return m_gravity;
|
||||
}
|
||||
|
||||
@ -252,7 +252,7 @@ inline vec3 DynamicsWorld::getGravity() const {
|
||||
/**
|
||||
* @param gravity The gravity vector (in meter per seconds squared)
|
||||
*/
|
||||
inline void DynamicsWorld::setGravity(vec3& gravity) {
|
||||
void DynamicsWorld::setGravity(vec3& gravity) {
|
||||
m_gravity = gravity;
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ inline void DynamicsWorld::setGravity(vec3& gravity) {
|
||||
/**
|
||||
* @return True if the gravity is enabled in the world
|
||||
*/
|
||||
inline bool DynamicsWorld::isGravityEnabled() const {
|
||||
bool DynamicsWorld::isGravityEnabled() const {
|
||||
return m_isGravityEnabled;
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ inline bool DynamicsWorld::isGravityEnabled() const {
|
||||
* @param isGravityEnabled True if you want to enable the gravity in the world
|
||||
* and false otherwise
|
||||
*/
|
||||
inline void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) {
|
||||
void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) {
|
||||
m_isGravityEnabled = isGravityEnabled;
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ inline void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) {
|
||||
/**
|
||||
* @return Number of rigid bodies in the world
|
||||
*/
|
||||
inline uint32_t DynamicsWorld::getNbRigidBodies() const {
|
||||
uint32_t DynamicsWorld::getNbRigidBodies() const {
|
||||
return m_rigidBodies.size();
|
||||
}
|
||||
|
||||
@ -285,7 +285,7 @@ inline uint32_t DynamicsWorld::getNbRigidBodies() const {
|
||||
/**
|
||||
* @return Number of joints in the world
|
||||
*/
|
||||
inline uint32_t DynamicsWorld::getNbJoints() const {
|
||||
uint32_t DynamicsWorld::getNbJoints() const {
|
||||
return m_joints.size();
|
||||
}
|
||||
|
||||
@ -293,7 +293,7 @@ inline uint32_t DynamicsWorld::getNbJoints() const {
|
||||
/**
|
||||
* @return Starting iterator of the set of rigid bodies
|
||||
*/
|
||||
inline std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesBeginIterator() {
|
||||
std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesBeginIterator() {
|
||||
return m_rigidBodies.begin();
|
||||
}
|
||||
|
||||
@ -301,7 +301,7 @@ inline std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesBeginIterator
|
||||
/**
|
||||
* @return Ending iterator of the set of rigid bodies
|
||||
*/
|
||||
inline std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesEndIterator() {
|
||||
std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesEndIterator() {
|
||||
return m_rigidBodies.end();
|
||||
}
|
||||
|
||||
@ -309,7 +309,7 @@ inline std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesEndIterator()
|
||||
/**
|
||||
* @return True if the sleeping technique is enabled and false otherwise
|
||||
*/
|
||||
inline bool DynamicsWorld::isSleepingEnabled() const {
|
||||
bool DynamicsWorld::isSleepingEnabled() const {
|
||||
return m_isSleepingEnabled;
|
||||
}
|
||||
|
||||
@ -317,7 +317,7 @@ inline bool DynamicsWorld::isSleepingEnabled() const {
|
||||
/**
|
||||
* @return The sleep linear velocity (in meters per second)
|
||||
*/
|
||||
inline float DynamicsWorld::getSleepLinearVelocity() const {
|
||||
float DynamicsWorld::getSleepLinearVelocity() const {
|
||||
return m_sleepLinearVelocity;
|
||||
}
|
||||
|
||||
@ -328,7 +328,7 @@ inline float DynamicsWorld::getSleepLinearVelocity() const {
|
||||
/**
|
||||
* @param sleepLinearVelocity The sleep linear velocity (in meters per second)
|
||||
*/
|
||||
inline void DynamicsWorld::setSleepLinearVelocity(float sleepLinearVelocity) {
|
||||
void DynamicsWorld::setSleepLinearVelocity(float sleepLinearVelocity) {
|
||||
assert(sleepLinearVelocity >= 0.0f);
|
||||
m_sleepLinearVelocity = sleepLinearVelocity;
|
||||
}
|
||||
@ -337,7 +337,7 @@ inline void DynamicsWorld::setSleepLinearVelocity(float sleepLinearVelocity) {
|
||||
/**
|
||||
* @return The sleep angular velocity (in radian per second)
|
||||
*/
|
||||
inline float DynamicsWorld::getSleepAngularVelocity() const {
|
||||
float DynamicsWorld::getSleepAngularVelocity() const {
|
||||
return m_sleepAngularVelocity;
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@ inline float DynamicsWorld::getSleepAngularVelocity() const {
|
||||
/**
|
||||
* @param sleepAngularVelocity The sleep angular velocity (in radian per second)
|
||||
*/
|
||||
inline void DynamicsWorld::setSleepAngularVelocity(float sleepAngularVelocity) {
|
||||
void DynamicsWorld::setSleepAngularVelocity(float sleepAngularVelocity) {
|
||||
assert(sleepAngularVelocity >= 0.0f);
|
||||
m_sleepAngularVelocity = sleepAngularVelocity;
|
||||
}
|
||||
@ -357,7 +357,7 @@ inline void DynamicsWorld::setSleepAngularVelocity(float sleepAngularVelocity) {
|
||||
/**
|
||||
* @return Time a body is required to stay still before sleeping (in seconds)
|
||||
*/
|
||||
inline float DynamicsWorld::getTimeBeforeSleep() const {
|
||||
float DynamicsWorld::getTimeBeforeSleep() const {
|
||||
return m_timeBeforeSleep;
|
||||
}
|
||||
|
||||
@ -366,7 +366,7 @@ inline float DynamicsWorld::getTimeBeforeSleep() const {
|
||||
/**
|
||||
* @param timeBeforeSleep Time a body is required to stay still before sleeping (in seconds)
|
||||
*/
|
||||
inline void DynamicsWorld::setTimeBeforeSleep(float timeBeforeSleep) {
|
||||
void DynamicsWorld::setTimeBeforeSleep(float timeBeforeSleep) {
|
||||
assert(timeBeforeSleep >= 0.0f);
|
||||
m_timeBeforeSleep = timeBeforeSleep;
|
||||
}
|
||||
@ -377,7 +377,7 @@ inline void DynamicsWorld::setTimeBeforeSleep(float timeBeforeSleep) {
|
||||
* @param eventListener Pointer to the event listener object that will receive
|
||||
* event callbacks during the simulation
|
||||
*/
|
||||
inline void DynamicsWorld::setEventListener(EventListener* eventListener) {
|
||||
void DynamicsWorld::setEventListener(EventListener* eventListener) {
|
||||
m_eventListener = eventListener;
|
||||
}
|
||||
|
||||
|
@ -59,51 +59,51 @@ namespace ephysics {
|
||||
};
|
||||
|
||||
// Add a body int32_to the island
|
||||
inline void Island::addBody(RigidBody* body) {
|
||||
void Island::addBody(RigidBody* body) {
|
||||
assert(!body->isSleeping());
|
||||
m_bodies[m_numberBodies] = body;
|
||||
m_numberBodies++;
|
||||
}
|
||||
|
||||
// Add a contact manifold int32_to the island
|
||||
inline void Island::addContactManifold(ContactManifold* contactManifold) {
|
||||
void Island::addContactManifold(ContactManifold* contactManifold) {
|
||||
m_contactManifolds[m_numberContactManifolds] = contactManifold;
|
||||
m_numberContactManifolds++;
|
||||
}
|
||||
|
||||
// Add a joint int32_to the island
|
||||
inline void Island::addJoint(Joint* joint) {
|
||||
void Island::addJoint(Joint* joint) {
|
||||
m_joints[m_numberJoints] = joint;
|
||||
m_numberJoints++;
|
||||
}
|
||||
|
||||
// Return the number of bodies in the island
|
||||
inline uint32_t Island::getNbBodies() const {
|
||||
uint32_t Island::getNbBodies() const {
|
||||
return m_numberBodies;
|
||||
}
|
||||
|
||||
// Return the number of contact manifolds in the island
|
||||
inline uint32_t Island::getNbContactManifolds() const {
|
||||
uint32_t Island::getNbContactManifolds() const {
|
||||
return m_numberContactManifolds;
|
||||
}
|
||||
|
||||
// Return the number of joints in the island
|
||||
inline uint32_t Island::getNbJoints() const {
|
||||
uint32_t Island::getNbJoints() const {
|
||||
return m_numberJoints;
|
||||
}
|
||||
|
||||
// Return a pointer to the array of bodies
|
||||
inline RigidBody** Island::getBodies() {
|
||||
RigidBody** Island::getBodies() {
|
||||
return m_bodies;
|
||||
}
|
||||
|
||||
// Return a pointer to the array of contact manifolds
|
||||
inline ContactManifold** Island::getContactManifold() {
|
||||
ContactManifold** Island::getContactManifold() {
|
||||
return m_contactManifolds;
|
||||
}
|
||||
|
||||
// Return a pointer to the array of joints
|
||||
inline Joint** Island::getJoints() {
|
||||
Joint** Island::getJoints() {
|
||||
return m_joints;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ namespace ephysics {
|
||||
/**
|
||||
* @return Bounciness factor (between 0 and 1) where 1 is very bouncy
|
||||
*/
|
||||
inline float Material::getBounciness() const {
|
||||
float Material::getBounciness() const {
|
||||
return m_bounciness;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ inline float Material::getBounciness() const {
|
||||
/**
|
||||
* @param bounciness Bounciness factor (between 0 and 1) where 1 is very bouncy
|
||||
*/
|
||||
inline void Material::setBounciness(float bounciness) {
|
||||
void Material::setBounciness(float bounciness) {
|
||||
assert(bounciness >= 0.0f && bounciness <= 1.0f);
|
||||
m_bounciness = bounciness;
|
||||
}
|
||||
@ -62,7 +62,7 @@ inline void Material::setBounciness(float bounciness) {
|
||||
/**
|
||||
* @return Friction coefficient (positive value)
|
||||
*/
|
||||
inline float Material::getFrictionCoefficient() const {
|
||||
float Material::getFrictionCoefficient() const {
|
||||
return m_frictionCoefficient;
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ inline float Material::getFrictionCoefficient() const {
|
||||
/**
|
||||
* @param frictionCoefficient Friction coefficient (positive value)
|
||||
*/
|
||||
inline void Material::setFrictionCoefficient(float frictionCoefficient) {
|
||||
void Material::setFrictionCoefficient(float frictionCoefficient) {
|
||||
assert(frictionCoefficient >= 0.0f);
|
||||
m_frictionCoefficient = frictionCoefficient;
|
||||
}
|
||||
@ -83,7 +83,7 @@ inline void Material::setFrictionCoefficient(float frictionCoefficient) {
|
||||
/**
|
||||
* @return The rolling resistance factor (positive value)
|
||||
*/
|
||||
inline float Material::getRollingResistance() const {
|
||||
float Material::getRollingResistance() const {
|
||||
return m_rollingResistance;
|
||||
}
|
||||
|
||||
@ -93,13 +93,13 @@ inline float Material::getRollingResistance() const {
|
||||
/**
|
||||
* @param rollingResistance The rolling resistance factor
|
||||
*/
|
||||
inline void Material::setRollingResistance(float rollingResistance) {
|
||||
void Material::setRollingResistance(float rollingResistance) {
|
||||
assert(rollingResistance >= 0);
|
||||
m_rollingResistance = rollingResistance;
|
||||
}
|
||||
|
||||
// Overloaded assignment operator
|
||||
inline Material& Material::operator=(const Material& material) {
|
||||
Material& Material::operator=(const Material& material) {
|
||||
|
||||
// Check for self-assignment
|
||||
if (this != &material) {
|
||||
|
@ -58,48 +58,48 @@ namespace ephysics {
|
||||
};
|
||||
|
||||
// Return the pointer to first body
|
||||
inline ProxyShape* OverlappingPair::getShape1() const {
|
||||
ProxyShape* OverlappingPair::getShape1() const {
|
||||
return m_contactManifoldSet.getShape1();
|
||||
}
|
||||
|
||||
// Return the pointer to second body
|
||||
inline ProxyShape* OverlappingPair::getShape2() const {
|
||||
ProxyShape* OverlappingPair::getShape2() const {
|
||||
return m_contactManifoldSet.getShape2();
|
||||
}
|
||||
|
||||
// Add a contact to the contact manifold
|
||||
inline void OverlappingPair::addContact(ContactPoint* contact) {
|
||||
void OverlappingPair::addContact(ContactPoint* contact) {
|
||||
m_contactManifoldSet.addContactPoint(contact);
|
||||
}
|
||||
|
||||
// Update the contact manifold
|
||||
inline void OverlappingPair::update() {
|
||||
void OverlappingPair::update() {
|
||||
m_contactManifoldSet.update();
|
||||
}
|
||||
|
||||
// Return the cached separating axis
|
||||
inline vec3 OverlappingPair::getCachedSeparatingAxis() const {
|
||||
vec3 OverlappingPair::getCachedSeparatingAxis() const {
|
||||
return m_cachedSeparatingAxis;
|
||||
}
|
||||
|
||||
// Set the cached separating axis
|
||||
inline void OverlappingPair::setCachedSeparatingAxis(const vec3& axis) {
|
||||
void OverlappingPair::setCachedSeparatingAxis(const vec3& axis) {
|
||||
m_cachedSeparatingAxis = axis;
|
||||
}
|
||||
|
||||
|
||||
// Return the number of contact points in the contact manifold
|
||||
inline uint32_t OverlappingPair::getNbContactPoints() const {
|
||||
uint32_t OverlappingPair::getNbContactPoints() const {
|
||||
return m_contactManifoldSet.getTotalNbContactPoints();
|
||||
}
|
||||
|
||||
// Return the contact manifold
|
||||
inline const ContactManifoldSet& OverlappingPair::getContactManifoldSet() {
|
||||
const ContactManifoldSet& OverlappingPair::getContactManifoldSet() {
|
||||
return m_contactManifoldSet;
|
||||
}
|
||||
|
||||
// Return the pair of bodies index
|
||||
inline overlappingpairid OverlappingPair::computeID(ProxyShape* shape1, ProxyShape* shape2) {
|
||||
overlappingpairid OverlappingPair::computeID(ProxyShape* shape1, ProxyShape* shape2) {
|
||||
assert(shape1->m_broadPhaseID >= 0 && shape2->m_broadPhaseID >= 0);
|
||||
|
||||
// Construct the pair of body index
|
||||
@ -111,7 +111,7 @@ inline overlappingpairid OverlappingPair::computeID(ProxyShape* shape1, ProxySha
|
||||
}
|
||||
|
||||
// Return the pair of bodies index
|
||||
inline bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body1,
|
||||
bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body1,
|
||||
CollisionBody* body2) {
|
||||
|
||||
// Construct the pair of body index
|
||||
@ -123,7 +123,7 @@ inline bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body
|
||||
}
|
||||
|
||||
// Clear the contact points of the contact manifold
|
||||
inline void OverlappingPair::clearContactPoints() {
|
||||
void OverlappingPair::clearContactPoints() {
|
||||
m_contactManifoldSet.clear();
|
||||
}
|
||||
|
||||
|
@ -147,113 +147,113 @@ namespace ephysics {
|
||||
#define PROFILE(name) ProfileSample profileSample(name)
|
||||
|
||||
// Return true if we are at the root of the profiler tree
|
||||
inline bool ProfileNodeIterator::isRoot() {
|
||||
bool ProfileNodeIterator::isRoot() {
|
||||
return (m_currentParentNode->getParentNode() == nullptr);
|
||||
}
|
||||
|
||||
// Return true if we are at the end of a branch of the profiler tree
|
||||
inline bool ProfileNodeIterator::isEnd() {
|
||||
bool ProfileNodeIterator::isEnd() {
|
||||
return (m_currentChildNode == nullptr);
|
||||
}
|
||||
|
||||
// Return the name of the current node
|
||||
inline const char* ProfileNodeIterator::getCurrentName() {
|
||||
const char* ProfileNodeIterator::getCurrentName() {
|
||||
return m_currentChildNode->getName();
|
||||
}
|
||||
|
||||
// Return the total time of the current node
|
||||
inline long double ProfileNodeIterator::getCurrentTotalTime() {
|
||||
long double ProfileNodeIterator::getCurrentTotalTime() {
|
||||
return m_currentChildNode->getTotalTime();
|
||||
}
|
||||
|
||||
// Return the total number of calls of the current node
|
||||
inline uint32_t ProfileNodeIterator::getCurrentNbTotalCalls() {
|
||||
uint32_t ProfileNodeIterator::getCurrentNbTotalCalls() {
|
||||
return m_currentChildNode->getNbTotalCalls();
|
||||
}
|
||||
|
||||
// Return the name of the current parent node
|
||||
inline const char* ProfileNodeIterator::getCurrentParentName() {
|
||||
const char* ProfileNodeIterator::getCurrentParentName() {
|
||||
return m_currentParentNode->getName();
|
||||
}
|
||||
|
||||
// Return the total time of the current parent node
|
||||
inline long double ProfileNodeIterator::getCurrentParentTotalTime() {
|
||||
long double ProfileNodeIterator::getCurrentParentTotalTime() {
|
||||
return m_currentParentNode->getTotalTime();
|
||||
}
|
||||
|
||||
// Return the total number of calls of the current parent node
|
||||
inline uint32_t ProfileNodeIterator::getCurrentParentNbTotalCalls() {
|
||||
uint32_t ProfileNodeIterator::getCurrentParentNbTotalCalls() {
|
||||
return m_currentParentNode->getNbTotalCalls();
|
||||
}
|
||||
|
||||
// Go to the first node
|
||||
inline void ProfileNodeIterator::first() {
|
||||
void ProfileNodeIterator::first() {
|
||||
m_currentChildNode = m_currentParentNode->getChildNode();
|
||||
}
|
||||
|
||||
// Go to the next node
|
||||
inline void ProfileNodeIterator::next() {
|
||||
void ProfileNodeIterator::next() {
|
||||
m_currentChildNode = m_currentChildNode->getSiblingNode();
|
||||
}
|
||||
|
||||
// Return a pointer to the parent node
|
||||
inline ProfileNode* ProfileNode::getParentNode() {
|
||||
ProfileNode* ProfileNode::getParentNode() {
|
||||
return m_parentNode;
|
||||
}
|
||||
|
||||
// Return a pointer to a sibling node
|
||||
inline ProfileNode* ProfileNode::getSiblingNode() {
|
||||
ProfileNode* ProfileNode::getSiblingNode() {
|
||||
return m_siblingNode;
|
||||
}
|
||||
|
||||
// Return a pointer to a child node
|
||||
inline ProfileNode* ProfileNode::getChildNode() {
|
||||
ProfileNode* ProfileNode::getChildNode() {
|
||||
return m_childNode;
|
||||
}
|
||||
|
||||
// Return the name of the node
|
||||
inline const char* ProfileNode::getName() {
|
||||
const char* ProfileNode::getName() {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
// Return the total number of call of the corresponding block of code
|
||||
inline uint32_t ProfileNode::getNbTotalCalls() const {
|
||||
uint32_t ProfileNode::getNbTotalCalls() const {
|
||||
return m_numberTotalCalls;
|
||||
}
|
||||
|
||||
// Return the total time spent in the block of code
|
||||
inline long double ProfileNode::getTotalTime() const {
|
||||
long double ProfileNode::getTotalTime() const {
|
||||
return m_totalTime;
|
||||
}
|
||||
|
||||
// Return the number of frames
|
||||
inline uint32_t Profiler::getNbFrames() {
|
||||
uint32_t Profiler::getNbFrames() {
|
||||
return m_frameCounter;
|
||||
}
|
||||
|
||||
// Return the elasped time since the start/reset of the profiling
|
||||
inline long double Profiler::getElapsedTimeSinceStart() {
|
||||
long double Profiler::getElapsedTimeSinceStart() {
|
||||
long double currentTime = Timer::getCurrentSystemTime() * 1000.0;
|
||||
return currentTime - m_profilingStartTime;
|
||||
}
|
||||
|
||||
// Increment the frame counter
|
||||
inline void Profiler::incrementFrameCounter() {
|
||||
void Profiler::incrementFrameCounter() {
|
||||
m_frameCounter++;
|
||||
}
|
||||
|
||||
// Return an iterator over the profiler tree starting at the root
|
||||
inline ProfileNodeIterator* Profiler::getIterator() {
|
||||
ProfileNodeIterator* Profiler::getIterator() {
|
||||
return new ProfileNodeIterator(&m_rootNode);
|
||||
}
|
||||
|
||||
// Destroy a previously allocated iterator
|
||||
inline void Profiler::destroyIterator(ProfileNodeIterator* iterator) {
|
||||
void Profiler::destroyIterator(ProfileNodeIterator* iterator) {
|
||||
delete iterator;
|
||||
}
|
||||
|
||||
// Destroy the profiler (release the memory)
|
||||
inline void Profiler::destroy() {
|
||||
void Profiler::destroy() {
|
||||
m_rootNode.destroy();
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/// Namespace ReactPhysics3D
|
||||
namespace ephysics {
|
||||
/**
|
||||
* @brief This class will take care of the time in the physics engine. It
|
||||
@ -68,50 +67,48 @@ namespace ephysics {
|
||||
};
|
||||
|
||||
// Return the timestep of the physics engine
|
||||
inline double Timer::getTimeStep() const {
|
||||
double Timer::getTimeStep() const {
|
||||
return m_timeStep;
|
||||
}
|
||||
|
||||
// Set the timestep of the physics engine
|
||||
inline void Timer::setTimeStep(double timeStep) {
|
||||
void Timer::setTimeStep(double timeStep) {
|
||||
assert(timeStep > 0.0f);
|
||||
m_timeStep = timeStep;
|
||||
}
|
||||
|
||||
// Return the current time
|
||||
inline long double Timer::getPhysicsTime() const {
|
||||
long double Timer::getPhysicsTime() const {
|
||||
return m_lastUpdateTime;
|
||||
}
|
||||
|
||||
// Return if the timer is running
|
||||
inline bool Timer::getIsRunning() const {
|
||||
bool Timer::getIsRunning() const {
|
||||
return m_isRunning;
|
||||
}
|
||||
|
||||
// Start the timer
|
||||
inline void Timer::start() {
|
||||
void Timer::start() {
|
||||
if (!m_isRunning) {
|
||||
|
||||
// Get the current system time
|
||||
m_lastUpdateTime = getCurrentSystemTime();
|
||||
|
||||
m_accumulator = 0.0;
|
||||
m_isRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the timer
|
||||
inline void Timer::stop() {
|
||||
void Timer::stop() {
|
||||
m_isRunning = false;
|
||||
}
|
||||
|
||||
// True if it's possible to take a new step
|
||||
inline bool Timer::isPossibleToTakeStep() const {
|
||||
bool Timer::isPossibleToTakeStep() const {
|
||||
return (m_accumulator >= m_timeStep);
|
||||
}
|
||||
|
||||
// Take a new step => update the timer by adding the timeStep value to the current time
|
||||
inline void Timer::nextStep() {
|
||||
void Timer::nextStep() {
|
||||
assert(m_isRunning);
|
||||
|
||||
// Update the accumulator value
|
||||
@ -119,23 +116,15 @@ inline void Timer::nextStep() {
|
||||
}
|
||||
|
||||
// Compute the int32_terpolation factor
|
||||
inline float Timer::computeInterpolationFactor() {
|
||||
float Timer::computeInterpolationFactor() {
|
||||
return (float(m_accumulator / m_timeStep));
|
||||
}
|
||||
|
||||
// Compute the time since the last update() call and add it to the accumulator
|
||||
inline void Timer::update() {
|
||||
|
||||
// Get the current system time
|
||||
void Timer::update() {
|
||||
long double currentTime = getCurrentSystemTime();
|
||||
|
||||
// Compute the delta display time between two display frames
|
||||
m_deltaTime = currentTime - m_lastUpdateTime;
|
||||
|
||||
// Update the current display time
|
||||
m_lastUpdateTime = currentTime;
|
||||
|
||||
// Update the accumulator value
|
||||
m_accumulator += m_deltaTime;
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,6 @@
|
||||
|
||||
// Libraries
|
||||
#include <test/TestSuite.hpp>
|
||||
#include <test/tests/mathematics/Testvec2.hpp>
|
||||
#include <test/tests/mathematics/Testvec3.hpp>
|
||||
#include <test/tests/mathematics/Testetk::Transform3D.hpp>
|
||||
#include <test/tests/mathematics/Testetk::Quaternion.hpp>
|
||||
#include <test/tests/mathematics/Testetk::Matrix2x2.hpp>
|
||||
#include <test/tests/mathematics/Testetk::Matrix3x3.hpp>
|
||||
#include <test/tests/mathematics/TestMathematicsFunctions.hpp>
|
||||
#include <test/tests/collision/TestPointInside.hpp>
|
||||
#include <test/tests/collision/TestRaycast.hpp>
|
||||
|
Loading…
x
Reference in New Issue
Block a user