[DEV] continue renaming

This commit is contained in:
Edouard DUPIN 2017-06-20 21:36:05 +02:00
parent 6c3d49de92
commit f9975bc8dc
55 changed files with 2462 additions and 3482 deletions

View File

@ -4,24 +4,17 @@
* @license BSD 3 clauses (see license file) * @license BSD 3 clauses (see license file)
*/ */
// Libraries
#include <ephysics/body/Body.hpp> #include <ephysics/body/Body.hpp>
#include <ephysics/collision/shapes/CollisionShape.hpp> #include <ephysics/collision/shapes/CollisionShape.hpp>
// We want to use the ReactPhysics3D namespace
using namespace ephysics;
// Constructor ephysics::Body::Body(bodyindex _id):
/** m_id(_id),
* @param id ID of the new body m_isAlreadyInIsland(false),
*/ m_isAllowedToSleep(true),
Body::Body(bodyindex id) m_isActive(true),
: m_id(id), m_isAlreadyInIsland(false), m_isAllowedToSleep(true), m_isActive(true), m_isSleeping(false),
m_isSleeping(false), m_sleepTime(0), m_userData(NULL) { m_sleepTime(0),
m_userData(nullptr) {
}
}
// Destructor
Body::~Body() {
}

View File

@ -5,216 +5,159 @@
*/ */
#pragma once #pragma once
// Libraries
#include <stdexcept> #include <stdexcept>
#include <cassert> #include <cassert>
#include <ephysics/configuration.hpp> #include <ephysics/configuration.hpp>
/// Namespace ephysics
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 * instantiante this class but instantiate the CollisionBody or RigidBody
* classes instead. * classes instead.
*/ */
class Body { class Body {
protected : protected :
bodyindex m_id; //!< ID of the body
// -------------------- Attributes -------------------- // 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
/// ID of the body /**
bodyindex m_id; * @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.
/// True if the body has already been added in an island (for sleeping technique) * 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.
bool m_isAlreadyInIsland; * 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.
/// 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.
bool m_isActive; bool m_isActive;
bool m_isSleeping; //!< True if the body is sleeping (for sleeping technique)
/// True if the body is sleeping (for sleeping technique) float m_sleepTime; //!< Elapsed time since the body velocity was bellow the sleep velocity
bool m_isSleeping; void* m_userData; //!< Pointer that can be used to attach user data to the body
/// 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 -------------------- //
/// Private copy-constructor /// Private copy-constructor
Body(const Body& body); Body(const Body& body);
/// Private assignment operator /// Private assignment operator
Body& operator=(const Body& body); Body& operator=(const Body& body);
public : public :
/**
// -------------------- Methods -------------------- // * @brief Constructor
* @param[in] _id ID of the new body
/// Constructor */
Body(bodyindex id); Body(bodyindex _id);
/**
/// Destructor * @brtief Virtualize Destructor
virtual ~Body(); */
virtual ~Body() = default;
/// Return the ID of the body /**
bodyindex getID() const; * @brief Return the id of the body
* @return The ID of the body
/// Return whether or not the body is allowed to sleep */
bool isAllowedToSleep() const; bodyindex getID() const {
return m_id;
/// Set whether or not the body is allowed to go to sleep }
void setIsAllowedToSleep(bool isAllowedToSleep); /**
* @brief Return whether or not the body is allowed to sleep
/// Set the variable to know whether or not the body is sleeping * @return True if the body is allowed to sleep and false otherwise
virtual void setIsSleeping(bool isSleeping); */
bool isAllowedToSleep() const {
/// Return whether or not the body is sleeping return m_isAllowedToSleep;
bool isSleeping() const; }
/**
/// Return true if the body is active * @brief Set whether or not the body is allowed to go to sleep
bool isActive() const; * @param[in] _isAllowedToSleep True if the body is allowed to sleep
*/
/// Set whether or not the body is active void setIsAllowedToSleep(bool _isAllowedToSleep) {
virtual void setIsActive(bool isActive); m_isAllowedToSleep = _isAllowedToSleep;
if (!m_isAllowedToSleep) {
/// Return a pointer to the user data attached to this body setIsSleeping(false);
void* getUserData() const; }
}
/// Attach user data to this body /**
void setUserData(void* userData); * @brief Return whether or not the body is sleeping
* @return True if the body is currently sleeping and false otherwise
/// Smaller than operator */
bool operator<(const Body& body2) const; bool isSleeping() const {
return m_isSleeping;
/// Larger than operator }
bool operator>(const Body& body2) const; /**
* @brief Return true if the body is active
/// Equal operator * @return True if the body currently active and false otherwise
bool operator==(const Body& body2) const; */
bool isActive() const {
/// Not equal operator return m_isActive;
bool operator!=(const Body& body2) const; }
/**
// -------------------- Friendship -------------------- // * @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;
}
/**
* @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
*/
void* getUserData() const {
return m_userData;
}
/**
* @brief Attach user data to this body
* @param[in] _userData A pointer to the user data you want to attach to the body
*/
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; friend class DynamicsWorld;
}; };
// Return the id of the body
/**
* @return The ID of the body
*/
inline bodyindex Body::getID() const {
return m_id;
}
// 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 {
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
*/
inline void Body::setIsAllowedToSleep(bool isAllowedToSleep) {
m_isAllowedToSleep = isAllowedToSleep;
if (!m_isAllowedToSleep) setIsSleeping(false);
}
// Return whether or not the body is sleeping
/**
* @return True if the body is currently sleeping and false otherwise
*/
inline bool Body::isSleeping() const {
return m_isSleeping;
}
// Return true if the body is active
/**
* @return True if the body currently active and false otherwise
*/
inline bool Body::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 {
if (m_isSleeping) {
m_sleepTime = 0.0f;
}
}
m_isSleeping = isSleeping;
}
// 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 {
return m_userData;
}
// Attach user data to this body
/**
* @param userData A pointer to the user data you want to attach to the body
*/
inline void Body::setUserData(void* userData) {
m_userData = userData;
}
// 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);
}
} }

View File

@ -12,21 +12,20 @@
// We want to use the ReactPhysics3D namespace // We want to use the ReactPhysics3D namespace
using namespace ephysics; 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() { CollisionBody::~CollisionBody() {
assert(m_contactManifoldsList == NULL); assert(m_contactManifoldsList == nullptr);
// Remove all the proxy collision shapes of the body // Remove all the proxy collision shapes of the body
removeAllCollisionShapes(); 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 ProxyShape* CollisionBody::addCollisionShape(CollisionShape* _collisionShape,
// shape between several bodies using the same collision shape instance to const etk::Transform3D& _transform) {
// 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) {
// Create a new proxy collision shape to attach the collision shape to the body // Create a new proxy collision shape to attach the collision shape to the body
ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate( ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate(sizeof(ProxyShape))) ProxyShape(this, _collisionShape,_transform, float(1));
sizeof(ProxyShape))) ProxyShape(this, collisionShape,
transform, float(1));
// Add it to the list of proxy collision shapes of the body // Add it to the list of proxy collision shapes of the body
if (m_proxyCollisionShapes == NULL) { if (m_proxyCollisionShapes == nullptr) {
m_proxyCollisionShapes = proxyShape; m_proxyCollisionShapes = proxyShape;
} } else {
else {
proxyShape->m_next = m_proxyCollisionShapes; proxyShape->m_next = m_proxyCollisionShapes;
m_proxyCollisionShapes = proxyShape; m_proxyCollisionShapes = proxyShape;
} }
// Compute the world-space AABB of the new collision shape
AABB aabb; 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_world.m_collisionDetection.addProxyCollisionShape(proxyShape, aabb);
m_numberCollisionShapes++; m_numberCollisionShapes++;
// Return a pointer to the collision shape
return proxyShape; return proxyShape;
} }
// Remove a collision shape from the body void CollisionBody::removeCollisionShape(const ProxyShape* _proxyShape) {
/// 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) {
ProxyShape* current = m_proxyCollisionShapes; ProxyShape* current = m_proxyCollisionShapes;
// If the the first proxy shape is the one to remove // If the the first proxy shape is the one to remove
if (current == proxyShape) { if (current == _proxyShape) {
m_proxyCollisionShapes = current->m_next; m_proxyCollisionShapes = current->m_next;
if (m_isActive) { if (m_isActive) {
m_world.m_collisionDetection.removeProxyCollisionShape(current); m_world.m_collisionDetection.removeProxyCollisionShape(current);
} }
current->~ProxyShape(); current->~ProxyShape();
m_world.m_memoryAllocator.release(current, sizeof(ProxyShape)); m_world.m_memoryAllocator.release(current, sizeof(ProxyShape));
m_numberCollisionShapes--; m_numberCollisionShapes--;
return; return;
} }
// Look for the proxy shape that contains the collision shape in parameter // 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 we have found the collision shape to remove
if (current->m_next == proxyShape) { if (current->m_next == _proxyShape) {
// Remove the proxy collision shape // Remove the proxy collision shape
ProxyShape* elementToRemove = current->m_next; ProxyShape* elementToRemove = current->m_next;
current->m_next = elementToRemove->m_next; current->m_next = elementToRemove->m_next;
if (m_isActive) { if (m_isActive) {
m_world.m_collisionDetection.removeProxyCollisionShape(elementToRemove); m_world.m_collisionDetection.removeProxyCollisionShape(elementToRemove);
} }
elementToRemove->~ProxyShape(); elementToRemove->~ProxyShape();
m_world.m_memoryAllocator.release(elementToRemove, sizeof(ProxyShape)); m_world.m_memoryAllocator.release(elementToRemove, sizeof(ProxyShape));
m_numberCollisionShapes--; m_numberCollisionShapes--;
return; return;
} }
// Get the next element in the list // Get the next element in the list
current = current->m_next; current = current->m_next;
} }
} }
// Remove all the collision shapes
void CollisionBody::removeAllCollisionShapes() { void CollisionBody::removeAllCollisionShapes() {
ProxyShape* current = m_proxyCollisionShapes; ProxyShape* current = m_proxyCollisionShapes;
// Look for the proxy shape that contains the collision shape in parameter // Look for the proxy shape that contains the collision shape in parameter
while(current != NULL) { while(current != nullptr) {
// Remove the proxy collision shape // Remove the proxy collision shape
ProxyShape* nextElement = current->m_next; ProxyShape* nextElement = current->m_next;
if (m_isActive) { if (m_isActive) {
m_world.m_collisionDetection.removeProxyCollisionShape(current); m_world.m_collisionDetection.removeProxyCollisionShape(current);
} }
current->~ProxyShape(); current->~ProxyShape();
m_world.m_memoryAllocator.release(current, sizeof(ProxyShape)); m_world.m_memoryAllocator.release(current, sizeof(ProxyShape));
// Get the next element in the list // Get the next element in the list
current = nextElement; current = nextElement;
} }
m_proxyCollisionShapes = nullptr;
m_proxyCollisionShapes = NULL;
} }
// Reset the contact manifold lists
void CollisionBody::resetContactManifoldsList() {
void CollisionBody::resetContactManifoldsList() {
// Delete the linked list of contact manifolds of that body // Delete the linked list of contact manifolds of that body
ContactManifoldListElement* currentElement = m_contactManifoldsList; ContactManifoldListElement* currentElement = m_contactManifoldsList;
while (currentElement != NULL) { while (currentElement != nullptr) {
ContactManifoldListElement* nextElement = currentElement->next; ContactManifoldListElement* nextElement = currentElement->next;
// Delete the current element // Delete the current element
currentElement->~ContactManifoldListElement(); currentElement->~ContactManifoldListElement();
m_world.m_memoryAllocator.release(currentElement, sizeof(ContactManifoldListElement)); m_world.m_memoryAllocator.release(currentElement, sizeof(ContactManifoldListElement));
currentElement = nextElement; 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 { void CollisionBody::updateBroadPhaseState() const {
// For all the proxy collision shapes of the body // 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 // Update the proxy
updateProxyShapeInBroadPhase(shape); 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; AABB aabb;
proxyShape->getCollisionShape()->computeAABB(aabb, m_transform * proxyShape->getLocalToBodyTransform()); _proxyShape->getCollisionShape()->computeAABB(aabb, m_transform * _proxyShape->getLocalToBodyTransform());
m_world.m_collisionDetection.updateProxyCollisionShape(_proxyShape, aabb, vec3(0, 0, 0), _forceReinsert);
// Update the broad-phase state for the proxy collision shape
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 the state does not change
if (m_isActive == isActive) return; if (m_isActive == _isActive) {
return;
Body::setIsActive(isActive); }
Body::setIsActive(_isActive);
// If we have to activate the body // If we have to activate the body
if (isActive) { if (_isActive == true) {
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
// 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
AABB aabb; AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, m_transform * shape->m_localToBodyTransform); shape->getCollisionShape()->computeAABB(aabb, m_transform * shape->m_localToBodyTransform);
// Add the proxy shape to the collision detection
m_world.m_collisionDetection.addProxyCollisionShape(shape, aabb); m_world.m_collisionDetection.addProxyCollisionShape(shape, aabb);
} }
} } else {
else { // If we have to deactivate the body for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
// 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
m_world.m_collisionDetection.removeProxyCollisionShape(shape); m_world.m_collisionDetection.removeProxyCollisionShape(shape);
} }
// Reset the contact manifold list of the body
resetContactManifoldsList(); 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 { void CollisionBody::askForBroadPhaseCollisionCheck() const {
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
// For all the proxy collision shapes of the body
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
m_world.m_collisionDetection.askForBroadPhaseCollisionCheck(shape); 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() { int32_t CollisionBody::resetIsAlreadyInIslandAndCountManifolds() {
m_isAlreadyInIsland = false; m_isAlreadyInIsland = false;
int32_t nbManifolds = 0; 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; ContactManifoldListElement* currentElement = m_contactManifoldsList;
while (currentElement != NULL) { while (currentElement != nullptr) {
currentElement->contactManifold->m_isAlreadyInIsland = false; currentElement->contactManifold->m_isAlreadyInIsland = false;
currentElement = currentElement->next; currentElement = currentElement->next;
nbManifolds++; nbManifolds++;
} }
return nbManifolds; return nbManifolds;
} }
// Return true if a point is inside the collision body bool CollisionBody::testPointInside(const vec3& _worldPoint) const {
/// This method returns true if a point is inside any collision shape of the body for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
/** if (shape->testPointInside(_worldPoint)) return true;
* @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;
} }
return false; return false;
} }
// Raycast method with feedback information bool CollisionBody::raycast(const Ray& _ray, RaycastInfo& _raycastInfo) {
/// The method returns the closest hit among all the collision shapes of the body if (m_isActive == false) {
/** return false;
* @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 isHit = false; bool isHit = false;
Ray rayTemp(ray); Ray rayTemp(_ray);
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
// For each collision shape of the body
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
// Test if the ray hits the collision shape // Test if the ray hits the collision shape
if (shape->raycast(rayTemp, raycastInfo)) { if (shape->raycast(rayTemp, _raycastInfo)) {
rayTemp.maxFraction = raycastInfo.hitFraction; rayTemp.maxFraction = _raycastInfo.hitFraction;
isHit = true; isHit = true;
} }
} }
return isHit; 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 CollisionBody::getAABB() const {
AABB bodyAABB; AABB bodyAABB;
if (m_proxyCollisionShapes == nullptr) {
if (m_proxyCollisionShapes == NULL) return bodyAABB; return bodyAABB;
}
m_proxyCollisionShapes->getCollisionShape()->computeAABB(bodyAABB, m_transform * m_proxyCollisionShapes->getLocalToBodyTransform()); m_proxyCollisionShapes->getCollisionShape()->computeAABB(bodyAABB, m_transform * m_proxyCollisionShapes->getLocalToBodyTransform());
for (ProxyShape* shape = m_proxyCollisionShapes->m_next; shape != nullptr; shape = shape->m_next) {
// 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
AABB aabb; AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, m_transform * shape->getLocalToBodyTransform()); shape->getCollisionShape()->computeAABB(aabb, m_transform * shape->getLocalToBodyTransform());
// Merge the proxy shape AABB with the current body AABB
bodyAABB.mergeWithAABB(aabb); bodyAABB.mergeWithAABB(aabb);
} }
return bodyAABB; return bodyAABB;
} }

View File

@ -16,257 +16,199 @@
#include <ephysics/memory/MemoryAllocator.hpp> #include <ephysics/memory/MemoryAllocator.hpp>
#include <ephysics/configuration.hpp> #include <ephysics/configuration.hpp>
/// Namespace ephysics
namespace ephysics { namespace ephysics {
struct ContactManifoldListElement;
// Class declarations class ProxyShape;
struct ContactManifoldListElement; class CollisionWorld;
class ProxyShape; /**
class CollisionWorld; * @brief Define the type of the body
*/
/// Enumeration for the type of a body enum BodyType {
/// STATIC : A static body has infinite mass, zero velocity but the position can be STATIC, //!< A static body has infinite mass, zero velocity but the position can be changed manually. A static body does not collide with other static or kinematic bodies.
/// 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.
/// KINEMATIC : A kinematic body has infinite mass, the velocity can be changed manually and its 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.
/// 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 * @brief This class represents a body that is able to collide with others bodies. This class inherits from the Body class.
/// position is determined by the physics engine. A dynamic body can collide with other */
/// dynamic, static or kinematic bodies. class CollisionBody : public Body {
enum BodyType {STATIC, KINEMATIC, DYNAMIC}; protected :
BodyType m_type; //!< Type of body (static, kinematic or dynamic)
// Class CollisionBody 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
* This class represents a body that is able to collide with others uint32_t m_numberCollisionShapes; //!< Number of collision shapes
* bodies. This class inherits from the Body class. 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
class CollisionBody : public Body { /// Private copy-constructor
CollisionBody(const CollisionBody& _body) = delete;
protected : /// Private assignment operator
CollisionBody& operator=(const CollisionBody& _body) = delete;
// -------------------- Attributes -------------------- // /**
* @brief Reset the contact manifold lists
/// Type of body (static, kinematic or dynamic) */
BodyType m_type; void resetContactManifoldsList();
/**
/// Position and orientation of the body * @brief Remove all the collision shapes
etk::Transform3D m_transform; */
void removeAllCollisionShapes();
/// First element of the linked list of proxy collision shapes of this body /**
ProxyShape* m_proxyCollisionShapes; * @brief Update the broad-phase state for this body (because it has moved for instance)
*/
/// Number of collision shapes virtual void updateBroadPhaseState() const;
uint32_t m_numberCollisionShapes; /**
* @brief Update the broad-phase state of a proxy collision shape of the body
/// First element of the linked list of contact manifolds involving this body */
ContactManifoldListElement* m_contactManifoldsList; void updateProxyShapeInBroadPhase(ProxyShape* _proxyShape, bool _forceReinsert = false) const;
/**
/// Reference to the world the body belongs to * @brief Ask the broad-phase to test again the collision shapes of the body for collision (as if the body has moved).
CollisionWorld& m_world; */
void askForBroadPhaseCollisionCheck() const;
// -------------------- Methods -------------------- // /**
* @brief Reset the m_isAlreadyInIsland variable of the body and contact manifolds.
/// Private copy-constructor * This method also returns the number of contact manifolds of the body.
CollisionBody(const CollisionBody& body); */
int32_t resetIsAlreadyInIslandAndCountManifolds();
/// Private assignment operator public :
CollisionBody& operator=(const CollisionBody& body); /**
* @brief Constructor
/// Reset the contact manifold lists * @param[in] _transform The transform of the body
void resetContactManifoldsList(); * @param[in] _world The physics world where the body is created
* @param[in] _id ID of the body
/// Remove all the collision shapes */
void removeAllCollisionShapes(); CollisionBody(const etk::Transform3D& _transform, CollisionWorld& _world, bodyindex _id);
/**
/// Update the broad-phase state for this body (because it has moved for instance) * @brief Destructor
virtual void updateBroadPhaseState() const; */
virtual ~CollisionBody();
/// Update the broad-phase state of a proxy collision shape of the body /**
void updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool forceReinsert = false) const; * @brief Return the type of the body
* @return the type of the body (STATIC, KINEMATIC, DYNAMIC)
/// Ask the broad-phase to test again the collision shapes of the body for collision */
/// (as if the body has moved). BodyType getType() const {
void askForBroadPhaseCollisionCheck() const; return m_type;
}
/// Reset the m_isAlreadyInIsland variable of the body and contact manifolds /**
int32_t resetIsAlreadyInIslandAndCountManifolds(); * @brief Set the type of the body
* @param[in] type The type of the body (STATIC, KINEMATIC, DYNAMIC)
public : */
virtual void setType(BodyType _type);
// -------------------- Methods -------------------- // /**
* @brief Set whether or not the body is active
/// Constructor * @param[in] _isActive True if you want to activate the body
CollisionBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id); */
virtual void setIsActive(bool _isActive);
/// Destructor /**
virtual ~CollisionBody(); * @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
/// Return the type of the body */
BodyType getType() const; const etk::Transform3D& getTransform() const {
/** return m_transform;
* @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 * @brief Set the current position and orientation
* changed manually. A static body does not collide with other static or kinematic bodies. * @param transform The transformation of the body that transforms the local-space of the body int32_to world-space
* 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 void setTransform(const etk::Transform3D& _transform) {
* other static or kinematic bodies. m_transform = _transform;
* DYNAMIC : A dynamic body has non-zero mass, non-zero velocity determined by forces and its updateBroadPhaseState();
* 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) * @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.
virtual void setType(BodyType _type); *
* 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
/// Set whether or not the body is active * returned proxy shape to get and set information about the corresponding collision shape for that body.
virtual void setIsActive(bool isActive); * @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 the current position and orientation * @return A pointer to the proxy shape that has been created to link the body to the new collision shape you have added.
const etk::Transform3D& getTransform() const; */
virtual ProxyShape* addCollisionShape(CollisionShape* _collisionShape, const etk::Transform3D& _transform);
/// Set the current position and orientation /**
virtual void setTransform(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
/// Add a collision shape to the body. * @param[in] _proxyShape The pointer of the proxy shape you want to remove
virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape, */
const etk::Transform3D& transform); virtual void removeCollisionShape(const ProxyShape* _proxyShape);
/**
/// Remove a collision shape from the body * @brief Get the first element of the linked list of contact manifolds involving this body
virtual void removeCollisionShape(const ProxyShape* proxyShape); * @return A pointer to the first element of the linked-list with the contact manifolds of this body
*/
/// Return the first element of the linked list of contact manifolds involving this body const ContactManifoldListElement* getContactManifoldsList() const {
const ContactManifoldListElement* getContactManifoldsList() const; return m_contactManifoldsList;
}
/// Return true if a point is inside the collision body /**
bool testPointInside(const vec3& worldPoint) const; * @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
/// Raycast method with feedback information * @param[in] _worldPoint The point to test (in world-space coordinates)
bool raycast(const Ray& ray, RaycastInfo& raycastInfo); * @return True if the point is inside the body
*/
/// Compute and return the AABB of the body by merging all proxy shapes AABBs bool testPointInside(const vec3& _worldPoint) const;
AABB getAABB() const; /**
* @brief Raycast method with feedback information
/// Return the linked list of proxy shapes of that body * The method returns the closest hit among all the collision shapes of the body
ProxyShape* getProxyShapesList(); * @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 the linked list of proxy shapes of that body * @return True if the ray hit the body and false otherwise
const ProxyShape* getProxyShapesList() const; */
bool raycast(const Ray& _ray, RaycastInfo& _raycastInfo);
/// Return the world-space coordinates of a point given the local-space coordinates of the body /**
vec3 getWorldPoint(const vec3& localPoint) const; * @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
/// Return the world-space vector of a vector given in local-space coordinates of the body */
vec3 getWorldVector(const vec3& localVector) const; AABB getAABB() const;
/**
/// Return the body local-space coordinates of a point given in the world-space coordinates * @brief Get the linked list of proxy shapes of that body
vec3 getLocalPoint(const vec3& worldPoint) const; * @return The pointer of the first proxy shape of the linked-list of all the
* proxy shapes of the body
/// Return the body local-space coordinates of a vector given in the world-space coordinates */
vec3 getLocalVector(const vec3& worldVector) const; ProxyShape* getProxyShapesList() {
return m_proxyCollisionShapes;
// -------------------- Friendship -------------------- // }
/**
friend class CollisionWorld; * @brief Get the linked list of proxy shapes of that body
friend class DynamicsWorld; * @return The pointer of the first proxy shape of the linked-list of all the proxy shapes of the body
friend class CollisionDetection; */
friend class BroadPhaseAlgorithm; const ProxyShape* getProxyShapesList() const {
friend class ConvexMeshShape; return m_proxyCollisionShapes;
friend class ProxyShape; }
}; /**
* @brief Get the world-space coordinates of a point given the local-space coordinates of the body
// Return the type of the body * @param[in] _localPoint A point in the local-space coordinates of the body
/** * @return The point in world-space coordinates
* @return the type of the body (STATIC, KINEMATIC, DYNAMIC) */
*/ vec3 getWorldPoint(const vec3& _localPoint) const {
inline BodyType CollisionBody::getType() const { return m_transform * _localPoint;
return m_type; }
/**
* @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 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;
}
}

View File

@ -11,23 +11,24 @@
#include <ephysics/engine/DynamicsWorld.hpp> #include <ephysics/engine/DynamicsWorld.hpp>
#include <ephysics/debug.hpp> #include <ephysics/debug.hpp>
// We want to use the ReactPhysics3D namespace
using namespace ephysics; using namespace ephysics;
RigidBody::RigidBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id) RigidBody::RigidBody(const etk::Transform3D& _transform, CollisionWorld& _world, bodyindex _id):
: CollisionBody(transform, world, id), m_initMass(1.0f), CollisionBody(_transform, _world, _id),
m_centerOfMassLocal(0, 0, 0), m_centerOfMassWorld(transform.getPosition()), m_initMass(1.0f),
m_isGravityEnabled(true), m_linearDamping(0.0f), m_angularDamping(float(0.0)), m_centerOfMassLocal(0, 0, 0),
m_jointsList(NULL) { m_centerOfMassWorld(_transform.getPosition()),
m_isGravityEnabled(true),
m_linearDamping(0.0f),
m_angularDamping(float(0.0)),
m_jointsList(nullptr) {
// Compute the inverse mass // Compute the inverse mass
m_massInverse = 1.0f / m_initMass; m_massInverse = 1.0f / m_initMass;
} }
// Destructor
RigidBody::~RigidBody() { RigidBody::~RigidBody() {
assert(m_jointsList == NULL); assert(m_jointsList == nullptr);
} }
@ -60,37 +61,23 @@ void RigidBody::setType(BodyType _type) {
m_externalTorque.setZero(); 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; void RigidBody::setInertiaTensorLocal(const etk::Matrix3x3& _inertiaTensorLocal) {
if (m_type != DYNAMIC) {
m_inertiaTensorLocal = inertiaTensorLocal; return;
}
// Compute the inverse local inertia tensor m_inertiaTensorLocal = _inertiaTensorLocal;
m_inertiaTensorLocalInverse = m_inertiaTensorLocal.getInverse(); 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; const vec3 oldCenterOfMass = m_centerOfMassWorld;
m_centerOfMassLocal = centerOfMassLocal; m_centerOfMassLocal = _centerOfMassLocal;
// Compute the center of mass in world-space coordinates
m_centerOfMassWorld = m_transform * m_centerOfMassLocal; m_centerOfMassWorld = m_transform * m_centerOfMassLocal;
// Update the linear velocity of the center of mass
m_linearVelocity += m_angularVelocity.cross(m_centerOfMassWorld - oldCenterOfMass); 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) { void RigidBody::removeJointFrom_jointsList(MemoryAllocator& _memoryAllocator, const Joint* _joint) {
assert(joint != nullptr); assert(_joint != nullptr);
assert(m_jointsList != nullptr); assert(m_jointsList != nullptr);
// Remove the joint from the linked list of the joints of the first body // 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; JointListElement* elementToRemove = m_jointsList;
m_jointsList = elementToRemove->next; m_jointsList = elementToRemove->next;
elementToRemove->~JointListElement(); 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 else { // If the element to remove is not the first one in the list
JointListElement* currentElement = m_jointsList; JointListElement* currentElement = m_jointsList;
while (currentElement->next != nullptr) { while (currentElement->next != nullptr) {
if (currentElement->next->joint == joint) { if (currentElement->next->joint == _joint) {
JointListElement* elementToRemove = currentElement->next; JointListElement* elementToRemove = currentElement->next;
currentElement->next = elementToRemove->next; currentElement->next = elementToRemove->next;
elementToRemove->~JointListElement(); elementToRemove->~JointListElement();
memoryAllocator.release(elementToRemove, sizeof(JointListElement)); _memoryAllocator.release(elementToRemove, sizeof(JointListElement));
break; break;
} }
currentElement = currentElement->next; 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 // Create a new proxy collision shape to attach the collision shape to the body
ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate( ProxyShape* proxyShape = new (m_world.m_memoryAllocator.allocate(sizeof(ProxyShape))) ProxyShape(this, _collisionShape, _transform, _mass);
sizeof(ProxyShape))) ProxyShape(this, collisionShape,
transform, mass);
// Add it to the list of proxy collision shapes of the body // Add it to the list of proxy collision shapes of the body
if (m_proxyCollisionShapes == NULL) { if (m_proxyCollisionShapes == nullptr) {
m_proxyCollisionShapes = proxyShape; m_proxyCollisionShapes = proxyShape;
} } else {
else {
proxyShape->m_next = m_proxyCollisionShapes; proxyShape->m_next = m_proxyCollisionShapes;
m_proxyCollisionShapes = proxyShape; m_proxyCollisionShapes = proxyShape;
} }
// Compute the world-space AABB of the new collision shape // Compute the world-space AABB of the new collision shape
AABB aabb; AABB aabb;
collisionShape->computeAABB(aabb, m_transform * transform); _collisionShape->computeAABB(aabb, m_transform * _transform);
// Notify the collision detection about this new collision shape // Notify the collision detection about this new collision shape
m_world.m_collisionDetection.addProxyCollisionShape(proxyShape, aabb); m_world.m_collisionDetection.addProxyCollisionShape(proxyShape, aabb);
m_numberCollisionShapes++; m_numberCollisionShapes++;
// Recompute the center of mass, total mass and inertia tensor of the body with the new
// collision shape
recomputeMassInformation(); recomputeMassInformation();
// Return a pointer to the proxy collision shape
return proxyShape; return proxyShape;
} }
// Remove a collision shape from the body void RigidBody::removeCollisionShape(const ProxyShape* _proxyShape) {
/// To remove a collision shape, you need to specify the pointer to the proxy CollisionBody::removeCollisionShape(_proxyShape);
/// 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);
recomputeMassInformation(); recomputeMassInformation();
} }
@ -241,8 +192,6 @@ void RigidBody::setTransform(const etk::Transform3D& _transform) {
updateBroadPhaseState(); 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() { void RigidBody::recomputeMassInformation() {
m_initMass = 0.0f; m_initMass = 0.0f;
m_massInverse = 0.0f; m_massInverse = 0.0f;
@ -300,21 +249,16 @@ void RigidBody::recomputeMassInformation() {
void RigidBody::updateBroadPhaseState() const { void RigidBody::updateBroadPhaseState() const {
PROFILE("RigidBody::updateBroadPhaseState()"); PROFILE("RigidBody::updateBroadPhaseState()");
DynamicsWorld& world = static_cast<DynamicsWorld&>(m_world); DynamicsWorld& world = static_cast<DynamicsWorld&>(m_world);
const vec3 displacement = world.m_timeStep * m_linearVelocity; const vec3 displacement = world.m_timeStep * m_linearVelocity;
// For all the proxy collision shapes of the body // For all the proxy collision shapes of the body
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) { for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
// Recompute the world-space AABB of the collision shape // Recompute the world-space AABB of the collision shape
AABB aabb; AABB aabb;
EPHY_ERROR(" : " << aabb.getMin() << " " << aabb.getMax()); EPHY_ERROR(" : " << aabb.getMin() << " " << aabb.getMax());
shape->getCollisionShape()->computeAABB(aabb, m_transform *shape->getLocalToBodyTransform()); shape->getCollisionShape()->computeAABB(aabb, m_transform *shape->getLocalToBodyTransform());
EPHY_ERROR(" : " << aabb.getMin() << " " << aabb.getMax()); EPHY_ERROR(" : " << aabb.getMin() << " " << aabb.getMax());
// Update the broad-phase state for the proxy collision shape // Update the broad-phase state for the proxy collision shape
m_world.m_collisionDetection.updateProxyCollisionShape(shape, aabb, displacement); m_world.m_collisionDetection.updateProxyCollisionShape(shape, aabb, displacement);
} }
@ -322,41 +266,32 @@ void RigidBody::updateBroadPhaseState() const {
void RigidBody::applyForceToCenterOfMass(const vec3& _force) { void RigidBody::applyForceToCenterOfMass(const vec3& _force) {
// If it is not a dynamic body, we do nothing
if (m_type != DYNAMIC) { if (m_type != DYNAMIC) {
return; return;
} }
// Awake the body if it was sleeping
if (m_isSleeping) { if (m_isSleeping) {
setIsSleeping(false); setIsSleeping(false);
} }
// Add the force
m_externalForce += _force; m_externalForce += _force;
} }
void RigidBody::applyForce(const vec3& _force, const vec3& _point) { void RigidBody::applyForce(const vec3& _force, const vec3& _point) {
// If it is not a dynamic body, we do nothing
if (m_type != DYNAMIC) { if (m_type != DYNAMIC) {
return; return;
} }
// Awake the body if it was sleeping
if (m_isSleeping) { if (m_isSleeping) {
setIsSleeping(false); setIsSleeping(false);
} }
// Add the force and torque
m_externalForce += _force; m_externalForce += _force;
m_externalTorque += (_point - m_centerOfMassWorld).cross(_force); m_externalTorque += (_point - m_centerOfMassWorld).cross(_force);
} }
void RigidBody::applyTorque(const vec3& _torque) { void RigidBody::applyTorque(const vec3& _torque) {
// If it is not a dynamic body, we do nothing
if (m_type != DYNAMIC) { if (m_type != DYNAMIC) {
return; return;
} }
// Awake the body if it was sleeping
if (m_isSleeping) { if (m_isSleeping) {
setIsSleeping(false); setIsSleeping(false);
} }
// Add the torque
m_externalTorque += _torque; m_externalTorque += _torque;
} }

View File

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

View File

@ -5,7 +5,6 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/collision/broadphase/BroadPhaseAlgorithm.hpp> #include <ephysics/collision/broadphase/BroadPhaseAlgorithm.hpp>
#include <ephysics/engine/OverlappingPair.hpp> #include <ephysics/engine/OverlappingPair.hpp>
@ -18,206 +17,136 @@
#include <set> #include <set>
#include <utility> #include <utility>
/// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
// Declarations class BroadPhaseAlgorithm;
class BroadPhaseAlgorithm; class CollisionWorld;
class CollisionWorld; class CollisionCallback;
class CollisionCallback;
class TestCollisionBetweenShapesCallback : public NarrowPhaseCallback {
// Class TestCollisionBetweenShapesCallback private:
class TestCollisionBetweenShapesCallback : public NarrowPhaseCallback { CollisionCallback* m_collisionCallback; //!<
public:
private: // Constructor
TestCollisionBetweenShapesCallback(CollisionCallback* _callback):
CollisionCallback* m_collisionCallback; m_collisionCallback(_callback) {
public: }
// Constructor // Called by a narrow-phase collision algorithm when a new contact has been found
TestCollisionBetweenShapesCallback(CollisionCallback* callback) virtual void notifyContact(OverlappingPair* _overlappingPair,
: m_collisionCallback(callback) { const ContactPointInfo& _contactInfo);
};
}
/**
// Called by a narrow-phase collision algorithm when a new contact has been found * @brief It computes the collision detection algorithms. We first
virtual void notifyContact(OverlappingPair* overlappingPair, * perform a broad-phase algorithm to know which pairs of bodies can
const ContactPointInfo& contactInfo); * collide and then we run a narrow-phase algorithm to compute the
}; * collision contacts between bodies.
*/
// Class CollisionDetection class CollisionDetection : public NarrowPhaseCallback {
/** private :
* This class computes the collision detection algorithms. We first CollisionDispatch* m_collisionDispatch; //!< Collision Detection Dispatch configuration
* perform a broad-phase algorithm to know which pairs of bodies can DefaultCollisionDispatch m_defaultCollisionDispatch; //!< Default collision dispatch configuration
* collide and then we run a narrow-phase algorithm to compute the NarrowPhaseAlgorithm* m_collisionMatrix[NB_COLLISION_SHAPE_TYPES][NB_COLLISION_SHAPE_TYPES]; //!< Collision detection matrix (algorithms to use)
* collision contacts between bodies. MemoryAllocator& m_memoryAllocator; //!< Reference to the memory allocator
*/ CollisionWorld* m_world; //!< Pointer to the physics world
class CollisionDetection : public NarrowPhaseCallback { 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)
private : BroadPhaseAlgorithm m_broadPhaseAlgorithm; //!< Broad-phase algorithm
// TODO : Delete this
// -------------------- Attributes -------------------- // GJKAlgorithm m_narrowPhaseGJKAlgorithm; //!< Narrow-phase GJK algorithm
std::set<bodyindexpair> m_noCollisionPairs; //!< Set of pair of bodies that cannot collide between each other
/// Collision Detection Dispatch configuration bool m_isCollisionShapesAdded; //!< True if some collision shapes have been added previously
CollisionDispatch* m_collisionDispatch; /// Private copy-constructor
CollisionDetection(const CollisionDetection& _collisionDetection);
/// Default collision dispatch configuration /// Private assignment operator
DefaultCollisionDispatch m_defaultCollisionDispatch; CollisionDetection& operator=(const CollisionDetection& _collisionDetection);
/// Compute the broad-phase collision detection
/// Collision detection matrix (algorithms to use) void computeBroadPhase();
NarrowPhaseAlgorithm* m_collisionMatrix[NB_COLLISION_SHAPE_TYPES][NB_COLLISION_SHAPE_TYPES]; /// Compute the narrow-phase collision detection
void computeNarrowPhase();
/// Reference to the memory allocator /// Add a contact manifold to the linked list of contact manifolds of the two bodies
MemoryAllocator& m_memoryAllocator; /// involed in the corresponding contact.
void addContactManifoldToBody(OverlappingPair* _pair);
/// Pointer to the physics world /// Delete all the contact points in the currently overlapping pairs
CollisionWorld* m_world; void clearContactPoints();
/// Fill-in the collision detection matrix
/// Broad-phase overlapping pairs void fillInCollisionMatrix();
std::map<overlappingpairid, OverlappingPair*> m_overlappingPairs; /// Add all the contact manifold of colliding pairs to their bodies
void addAllContactManifoldsToBodies();
/// Overlapping pairs in contact (during the current Narrow-phase collision detection) public :
std::map<overlappingpairid, OverlappingPair*> m_contactOverlappingPairs; /// Constructor
CollisionDetection(CollisionWorld* _world, MemoryAllocator& _memoryAllocator);
/// Broad-phase algorithm /// Destructor
BroadPhaseAlgorithm m_broadPhaseAlgorithm; ~CollisionDetection();
/// Set the collision dispatch configuration
/// Narrow-phase GJK algorithm void setCollisionDispatch(CollisionDispatch* _collisionDispatch);
// TODO : Delete this /// Return the Narrow-phase collision detection algorithm to use between two types of shapes
GJKAlgorithm m_narrowPhaseGJKAlgorithm; NarrowPhaseAlgorithm* getCollisionAlgorithm(CollisionShapeType _shape1Type,
CollisionShapeType _shape2Type) const;
/// Set of pair of bodies that cannot collide between each other /// Add a proxy collision shape to the collision detection
std::set<bodyindexpair> m_noCollisionPairs; void addProxyCollisionShape(ProxyShape* _proxyShape, const AABB& _aabb);
/// Remove a proxy collision shape from the collision detection
/// True if some collision shapes have been added previously void removeProxyCollisionShape(ProxyShape* _proxyShape);
bool m_isCollisionShapesAdded; /// Update a proxy collision shape (that has moved for instance)
void updateProxyCollisionShape(ProxyShape* _shape,
// -------------------- Methods -------------------- // const AABB& _aabb,
const vec3& _displacement = vec3(0, 0, 0),
/// Private copy-constructor bool _forceReinsert = false);
CollisionDetection(const CollisionDetection& collisionDetection); /// Add a pair of bodies that cannot collide with each other
void addNoCollisionPair(CollisionBody* _body1, CollisionBody* _body2);
/// Private assignment operator /// Remove a pair of bodies that cannot collide with each other
CollisionDetection& operator=(const CollisionDetection& collisionDetection); void removeNoCollisionPair(CollisionBody* _body1, CollisionBody* _body2);
/// Ask for a collision shape to be tested again during broad-phase.
/// Compute the broad-phase collision detection void askForBroadPhaseCollisionCheck(ProxyShape* _shape);
void computeBroadPhase(); /// Compute the collision detection
void computeCollisionDetection();
/// Compute the narrow-phase collision detection /// Compute the collision detection
void computeNarrowPhase(); void testCollisionBetweenShapes(CollisionCallback* _callback,
const std::set<uint32_t>& _shapes1,
/// Add a contact manifold to the linked list of contact manifolds of the two bodies const std::set<uint32_t>& _shapes2);
/// involed in the corresponding contact. /// Report collision between two sets of shapes
void addContactManifoldToBody(OverlappingPair* pair); void reportCollisionBetweenShapes(CollisionCallback* _callback,
const std::set<uint32_t>& _shapes1,
/// Delete all the contact points in the currently overlapping pairs const std::set<uint32_t>& _shapes2) ;
void clearContactPoints(); /// Ray casting method
void raycast(RaycastCallback* _raycastCallback,
/// Fill-in the collision detection matrix const Ray& _ray,
void fillInCollisionMatrix(); unsigned short _raycastWithCategoryMaskBits) const;
/// Test if the AABBs of two bodies overlap
/// Add all the contact manifold of colliding pairs to their bodies bool testAABBOverlap(const CollisionBody* _body1,
void addAllContactManifoldsToBodies(); const CollisionBody* _body2) const;
/// Test if the AABBs of two proxy shapes overlap
public : bool testAABBOverlap(const ProxyShape* _shape1,
const ProxyShape* _shape2) const;
// -------------------- Methods -------------------- // /// Allow the broadphase to notify the collision detection about an overlapping pair.
void broadPhaseNotifyOverlappingPair(ProxyShape* _shape1, ProxyShape* _shape2);
/// Constructor /// Compute the narrow-phase collision detection
CollisionDetection(CollisionWorld* world, MemoryAllocator& memoryAllocator); void computeNarrowPhaseBetweenShapes(CollisionCallback* _callback,
const std::set<uint32_t>& _shapes1,
/// Destructor const std::set<uint32_t>& _shapes2);
~CollisionDetection(); /// Return a pointer to the world
CollisionWorld* getWorld();
/// Set the collision dispatch configuration /// Return the world event listener
void setCollisionDispatch(CollisionDispatch* collisionDispatch); EventListener* getWorldEventListener();
/// Return a reference to the world memory allocator
/// Return the Narrow-phase collision detection algorithm to use between two types of shapes MemoryAllocator& getWorldMemoryAllocator();
NarrowPhaseAlgorithm* getCollisionAlgorithm(CollisionShapeType shape1Type, /// Called by a narrow-phase collision algorithm when a new contact has been found
CollisionShapeType shape2Type) const; virtual void notifyContact(OverlappingPair* _overlappingPair, const ContactPointInfo& _contactInfo);
/// Create a new contact
/// Add a proxy collision shape to the collision detection void createContact(OverlappingPair* _overlappingPair, const ContactPointInfo& _contactInfo);
void addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb); friend class DynamicsWorld;
friend class ConvexMeshShape;
/// Remove a proxy collision shape from the collision detection };
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);
/// Add a pair of bodies that cannot collide with each other
void addNoCollisionPair(CollisionBody* body1, CollisionBody* body2);
/// Remove a pair of bodies that cannot collide with each other
void removeNoCollisionPair(CollisionBody* body1, CollisionBody* body2);
/// Ask for a collision shape to be tested again during broad-phase.
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);
/// Report collision between two sets of shapes
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;
/// Test if the AABBs of two bodies overlap
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;
/// Allow the broadphase to notify the collision detection about an overlapping pair.
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);
/// 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);
/// Create a new contact
void createContact(OverlappingPair* overlappingPair, const ContactPointInfo& contactInfo);
// -------------------- Friendship -------------------- //
friend class DynamicsWorld;
friend class ConvexMeshShape;
};
// Return the Narrow-phase collision detection algorithm to use between two types of shapes // Return the Narrow-phase collision detection algorithm to use between two types of shapes
inline NarrowPhaseAlgorithm* CollisionDetection::getCollisionAlgorithm(CollisionShapeType shape1Type, NarrowPhaseAlgorithm* CollisionDetection::getCollisionAlgorithm(CollisionShapeType shape1Type, CollisionShapeType shape2Type) const {
CollisionShapeType shape2Type) const {
return m_collisionMatrix[shape1Type][shape2Type]; return m_collisionMatrix[shape1Type][shape2Type];
} }
// Set the collision dispatch configuration // Set the collision dispatch configuration
inline void CollisionDetection::setCollisionDispatch(CollisionDispatch* collisionDispatch) { void CollisionDetection::setCollisionDispatch(CollisionDispatch* collisionDispatch) {
m_collisionDispatch = collisionDispatch; m_collisionDispatch = collisionDispatch;
m_collisionDispatch->init(this, &m_memoryAllocator); m_collisionDispatch->init(this, &m_memoryAllocator);
@ -227,7 +156,7 @@ inline void CollisionDetection::setCollisionDispatch(CollisionDispatch* collisio
} }
// Add a body to the collision detection // Add a body to the collision detection
inline void CollisionDetection::addProxyCollisionShape(ProxyShape* proxyShape, void CollisionDetection::addProxyCollisionShape(ProxyShape* proxyShape,
const AABB& aabb) { const AABB& aabb) {
// Add the body to the broad-phase // 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 // Add a pair of bodies that cannot collide with each other
inline void CollisionDetection::addNoCollisionPair(CollisionBody* body1, void CollisionDetection::addNoCollisionPair(CollisionBody* body1,
CollisionBody* body2) { CollisionBody* body2) {
m_noCollisionPairs.insert(OverlappingPair::computeBodiesIndexPair(body1, body2)); m_noCollisionPairs.insert(OverlappingPair::computeBodiesIndexPair(body1, body2));
} }
// Remove a pair of bodies that cannot collide with each other // Remove a pair of bodies that cannot collide with each other
inline void CollisionDetection::removeNoCollisionPair(CollisionBody* body1, void CollisionDetection::removeNoCollisionPair(CollisionBody* body1,
CollisionBody* body2) { CollisionBody* body2) {
m_noCollisionPairs.erase(OverlappingPair::computeBodiesIndexPair(body1, 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. // 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 /// 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. /// 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); m_broadPhaseAlgorithm.addMovedCollisionShape(shape->m_broadPhaseID);
} }
// Update a proxy collision shape (that has moved for instance) // 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) { const vec3& displacement, bool forceReinsert) {
m_broadPhaseAlgorithm.updateProxyCollisionShape(shape, aabb, displacement); m_broadPhaseAlgorithm.updateProxyCollisionShape(shape, aabb, displacement);
} }
// Ray casting method // Ray casting method
inline void CollisionDetection::raycast(RaycastCallback* raycastCallback, void CollisionDetection::raycast(RaycastCallback* raycastCallback,
const Ray& ray, const Ray& ray,
unsigned short raycastWithCategoryMaskBits) const { unsigned short raycastWithCategoryMaskBits) const {
@ -276,7 +205,7 @@ inline void CollisionDetection::raycast(RaycastCallback* raycastCallback,
} }
// Test if the AABBs of two proxy shapes overlap // 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 { const ProxyShape* shape2) const {
// If one of the shape's body is not active, we return no overlap // 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 // Return a pointer to the world
inline CollisionWorld* CollisionDetection::getWorld() { CollisionWorld* CollisionDetection::getWorld() {
return m_world; return m_world;
} }

View File

@ -5,336 +5,250 @@
*/ */
#pragma once #pragma once
// Libraries
#include <vector> #include <vector>
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/collision/ProxyShape.hpp> #include <ephysics/collision/ProxyShape.hpp>
#include <ephysics/constraint/ContactPoint.hpp> #include <ephysics/constraint/ContactPoint.hpp>
#include <ephysics/memory/MemoryAllocator.hpp> #include <ephysics/memory/MemoryAllocator.hpp>
/// ReactPhysics3D namespace
namespace ephysics { 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 ContactManifold;
// Class declarations
class ContactManifold; /**
* @brief This structure represents a single element of a linked list of contact manifolds
// Structure ContactManifoldListElement */
/** struct ContactManifoldListElement {
* This structure represents a single element of a linked list of contact manifolds public:
*/ ContactManifold* contactManifold; //!< Pointer to the actual contact manifold
struct ContactManifoldListElement { ContactManifoldListElement* next; //!< Next element of the list
ContactManifoldListElement(ContactManifold* _initContactManifold,
public: ContactManifoldListElement* _initNext):
contactManifold(_initContactManifold),
// -------------------- Attributes -------------------- // next(_initNext) {
/// Pointer to the actual contact manifold }
ContactManifold* contactManifold; };
/// Next element of the list /**
ContactManifoldListElement* next; * @brief This class represents the set of contact points between two bodies.
* The contact manifold is implemented in a way to cache the contact
// -------------------- Methods -------------------- // * points among the frames for better stability following the
* "Contact Generation" presentation of Erwin Coumans at GDC 2010
/// Constructor * conference (bullet.googlecode.com/files/GDC10_Coumans_Erwin_Contact.pdf).
ContactManifoldListElement(ContactManifold* initContactManifold, * Some code of this class is based on the implementation of the
ContactManifoldListElement* initNext) * btPersistentManifold class from Bullet physics engine (www.http://bulletphysics.org).
:contactManifold(initContactManifold), next(initNext) { * The contacts between two bodies are added one after the other in the cache.
* When the cache is full, we have to remove one point. The idea is to keep
} * the point with the deepest penetration depth and also to keep the
}; * points producing the larger area (for a more stable contact manifold).
* The new added point is always kept.
// Class ContactManifold */
/** class ContactManifold {
* This class represents the set of contact points between two bodies. private:
* The contact manifold is implemented in a way to cache the contact ProxyShape* m_shape1; //!< Pointer to the first proxy shape of the contact
* points among the frames for better stability following the ProxyShape* m_shape2; //!< Pointer to the second proxy shape of the contact
* "Contact Generation" presentation of Erwin Coumans at GDC 2010 ContactPoint* m_contactPoints[MAX_CONTACT_POINTS_IN_MANIFOLD]; //!< Contact points in the manifold
* conference (bullet.googlecode.com/files/GDC10_Coumans_Erwin_Contact.pdf). int16_t m_normalDirectionId; //!< Normal direction Id (Unique Id representing the normal direction)
* Some code of this class is based on the implementation of the uint32_t m_nbContactPoints; //!< Number of contacts in the cache
* btPersistentManifold class from Bullet physics engine (www.http://bulletphysics.org). vec3 m_frictionVector1; //!< First friction vector of the contact manifold
* The contacts between two bodies are added one after the other in the cache. vec3 m_frictionvec2; //!< Second friction vector of the contact manifold
* When the cache is full, we have to remove one point. The idea is to keep float m_frictionImpulse1; //!< First friction constraint accumulated impulse
* the point with the deepest penetration depth and also to keep the float m_frictionImpulse2; //!< Second friction constraint accumulated impulse
* points producing the larger area (for a more stable contact manifold). float m_frictionTwistImpulse; //!< Twist friction constraint accumulated impulse
* The new added point is always kept. vec3 m_rollingResistanceImpulse; //!< Accumulated rolling resistance impulse
*/ bool m_isAlreadyInIsland; //!< True if the contact manifold has already been added int32_to an island
class ContactManifold { MemoryAllocator& m_memoryAllocator; //!< Reference to the memory allocator
/// Private copy-constructor
private: ContactManifold(const ContactManifold& _contactManifold) = delete;
/// Private assignment operator
// -------------------- Attributes -------------------- // ContactManifold& operator=(const ContactManifold& _contactManifold) = delete;
/// Return the index of maximum area
/// Pointer to the first proxy shape of the contact int32_t getMaxArea(float _area0, float _area1, float _area2, float _area3) const;
ProxyShape* m_shape1; /// Return the index of the contact with the larger penetration depth.
int32_t getIndexOfDeepestPenetration(ContactPoint* _newContact) const;
/// Pointer to the second proxy shape of the contact /// Return the index that will be removed.
ProxyShape* m_shape2; int32_t getIndexToRemove(int32_t _indexMaxPenetration, const vec3& _newPoint) const;
/// Remove a contact point from the manifold
/// Contact points in the manifold void removeContactPoint(uint32_t _index);
ContactPoint* m_contactPoints[MAX_CONTACT_POINTS_IN_MANIFOLD]; /// Return true if the contact manifold has already been added int32_to an island
bool isAlreadyInIsland() const;
/// Normal direction Id (Unique Id representing the normal direction) public:
int16_t m_normalDirectionId; /// Constructor
ContactManifold(ProxyShape* _shape1,
/// Number of contacts in the cache ProxyShape* _shape2,
uint32_t m_nbContactPoints; MemoryAllocator& _memoryAllocator,
int16_t _normalDirectionId);
/// First friction vector of the contact manifold /// Destructor
vec3 m_frictionVector1; ~ContactManifold();
/// Return a pointer to the first proxy shape of the contact
/// Second friction vector of the contact manifold ProxyShape* getShape1() const;
vec3 m_frictionvec2; /// Return a pointer to the second proxy shape of the contact
ProxyShape* getShape2() const;
/// First friction constraint accumulated impulse /// Return a pointer to the first body of the contact manifold
float m_frictionImpulse1; CollisionBody* getBody1() const;
/// Return a pointer to the second body of the contact manifold
/// Second friction constraint accumulated impulse CollisionBody* getBody2() const;
float m_frictionImpulse2; /// Return the normal direction Id
int16_t getNormalDirectionId() const;
/// Twist friction constraint accumulated impulse /// Add a contact point to the manifold
float m_frictionTwistImpulse; void addContactPoint(ContactPoint* _contact);
/// Update the contact manifold.
/// Accumulated rolling resistance impulse void update(const etk::Transform3D& _transform1,
vec3 m_rollingResistanceImpulse; const etk::Transform3D& _transform2);
/// Clear the contact manifold
/// True if the contact manifold has already been added int32_to an island void clear();
bool m_isAlreadyInIsland; /// Return the number of contact points in the manifold
uint32_t getNbContactPoints() const;
/// Reference to the memory allocator /// Return the first friction vector at the center of the contact manifold
MemoryAllocator& m_memoryAllocator; const vec3& getFrictionVector1() const;
/// set the first friction vector at the center of the contact manifold
// -------------------- Methods -------------------- // void setFrictionVector1(const vec3& _frictionVector1);
/// Return the second friction vector at the center of the contact manifold
/// Private copy-constructor const vec3& getFrictionvec2() const;
ContactManifold(const ContactManifold& contactManifold); /// set the second friction vector at the center of the contact manifold
void setFrictionvec2(const vec3& _frictionvec2);
/// Private assignment operator /// Return the first friction accumulated impulse
ContactManifold& operator=(const ContactManifold& contactManifold); float getFrictionImpulse1() const;
/// Set the first friction accumulated impulse
/// Return the index of maximum area void setFrictionImpulse1(float _frictionImpulse1);
int32_t getMaxArea(float area0, float area1, float area2, float area3) const; /// Return the second friction accumulated impulse
float getFrictionImpulse2() const;
/// Return the index of the contact with the larger penetration depth. /// Set the second friction accumulated impulse
int32_t getIndexOfDeepestPenetration(ContactPoint* newContact) const; void setFrictionImpulse2(float _frictionImpulse2);
/// Return the friction twist accumulated impulse
/// Return the index that will be removed. float getFrictionTwistImpulse() const;
int32_t getIndexToRemove(int32_t indexMaxPenetration, const vec3& newPoint) const; /// Set the friction twist accumulated impulse
void setFrictionTwistImpulse(float _frictionTwistImpulse);
/// Remove a contact point from the manifold /// Set the accumulated rolling resistance impulse
void removeContactPoint(uint32_t index); void setRollingResistanceImpulse(const vec3& _rollingResistanceImpulse);
/// Return a contact point of the manifold
/// Return true if the contact manifold has already been added int32_to an island ContactPoint* getContactPoint(uint32_t _index) const;
bool isAlreadyInIsland() const; /// Return the normalized averaged normal vector
vec3 getAverageContactNormal() const;
public: /// Return the largest depth of all the contact points
float getLargestContactDepth() const;
// -------------------- Methods -------------------- // friend class DynamicsWorld;
friend class Island;
/// Constructor friend class CollisionBody;
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);
/// Update the contact manifold.
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);
/// 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);
/// Return the first friction accumulated impulse
float getFrictionImpulse1() const;
/// Set the first friction accumulated impulse
void setFrictionImpulse1(float frictionImpulse1);
/// Return the second friction accumulated impulse
float getFrictionImpulse2() const;
/// Set the second friction accumulated impulse
void setFrictionImpulse2(float frictionImpulse2);
/// Return the friction twist accumulated impulse
float getFrictionTwistImpulse() const;
/// Set the friction twist accumulated impulse
void setFrictionTwistImpulse(float frictionTwistImpulse);
/// Set the accumulated rolling resistance impulse
void setRollingResistanceImpulse(const vec3& rollingResistanceImpulse);
/// Return a contact point of the manifold
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 // Return a pointer to the first proxy shape of the contact
inline ProxyShape* ContactManifold::getShape1() const { ProxyShape* ContactManifold::getShape1() const {
return m_shape1; return m_shape1;
} }
// Return a pointer to the second proxy shape of the contact // Return a pointer to the second proxy shape of the contact
inline ProxyShape* ContactManifold::getShape2() const { ProxyShape* ContactManifold::getShape2() const {
return m_shape2; return m_shape2;
} }
// Return a pointer to the first body of the contact manifold // 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 m_shape1->getBody();
} }
// Return a pointer to the second body of the contact manifold // 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 m_shape2->getBody();
} }
// Return the normal direction Id // Return the normal direction Id
inline int16_t ContactManifold::getNormalDirectionId() const { int16_t ContactManifold::getNormalDirectionId() const {
return m_normalDirectionId; return m_normalDirectionId;
} }
// Return the number of contact points in the manifold // Return the number of contact points in the manifold
inline uint32_t ContactManifold::getNbContactPoints() const { uint32_t ContactManifold::getNbContactPoints() const {
return m_nbContactPoints; return m_nbContactPoints;
} }
// Return the first friction vector at the center of the contact manifold // 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; return m_frictionVector1;
} }
// set the first friction vector at the center of the contact manifold // 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; m_frictionVector1 = frictionVector1;
} }
// Return the second friction vector at the center of the contact manifold // 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; return m_frictionvec2;
} }
// set the second friction vector at the center of the contact manifold // 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; m_frictionvec2 = frictionvec2;
} }
// Return the first friction accumulated impulse // Return the first friction accumulated impulse
inline float ContactManifold::getFrictionImpulse1() const { float ContactManifold::getFrictionImpulse1() const {
return m_frictionImpulse1; return m_frictionImpulse1;
} }
// Set the first friction accumulated impulse // Set the first friction accumulated impulse
inline void ContactManifold::setFrictionImpulse1(float frictionImpulse1) { void ContactManifold::setFrictionImpulse1(float frictionImpulse1) {
m_frictionImpulse1 = frictionImpulse1; m_frictionImpulse1 = frictionImpulse1;
} }
// Return the second friction accumulated impulse // Return the second friction accumulated impulse
inline float ContactManifold::getFrictionImpulse2() const { float ContactManifold::getFrictionImpulse2() const {
return m_frictionImpulse2; return m_frictionImpulse2;
} }
// Set the second friction accumulated impulse // Set the second friction accumulated impulse
inline void ContactManifold::setFrictionImpulse2(float frictionImpulse2) { void ContactManifold::setFrictionImpulse2(float frictionImpulse2) {
m_frictionImpulse2 = frictionImpulse2; m_frictionImpulse2 = frictionImpulse2;
} }
// Return the friction twist accumulated impulse // Return the friction twist accumulated impulse
inline float ContactManifold::getFrictionTwistImpulse() const { float ContactManifold::getFrictionTwistImpulse() const {
return m_frictionTwistImpulse; return m_frictionTwistImpulse;
} }
// Set the friction twist accumulated impulse // Set the friction twist accumulated impulse
inline void ContactManifold::setFrictionTwistImpulse(float frictionTwistImpulse) { void ContactManifold::setFrictionTwistImpulse(float frictionTwistImpulse) {
m_frictionTwistImpulse = frictionTwistImpulse; m_frictionTwistImpulse = frictionTwistImpulse;
} }
// Set the accumulated rolling resistance impulse // Set the accumulated rolling resistance impulse
inline void ContactManifold::setRollingResistanceImpulse(const vec3& rollingResistanceImpulse) { void ContactManifold::setRollingResistanceImpulse(const vec3& rollingResistanceImpulse) {
m_rollingResistanceImpulse = rollingResistanceImpulse; m_rollingResistanceImpulse = rollingResistanceImpulse;
} }
// Return a contact point of the manifold // 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); assert(index < m_nbContactPoints);
return m_contactPoints[index]; return m_contactPoints[index];
} }
// Return true if the contact manifold has already been added int32_to an island // 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 m_isAlreadyInIsland;
} }
// Return the normalized averaged normal vector // Return the normalized averaged normal vector
inline vec3 ContactManifold::getAverageContactNormal() const { vec3 ContactManifold::getAverageContactNormal() const {
vec3 averageNormal; vec3 averageNormal;
for (uint32_t i=0; i<m_nbContactPoints; i++) { for (uint32_t i=0; i<m_nbContactPoints; i++) {
averageNormal += m_contactPoints[i]->getNormal(); averageNormal += m_contactPoints[i]->getNormal();
} }
return averageNormal.safeNormalized(); return averageNormal.safeNormalized();
} }
// Return the largest depth of all the contact points // Return the largest depth of all the contact points
inline float ContactManifold::getLargestContactDepth() const { float ContactManifold::getLargestContactDepth() const {
float largestDepth = 0.0f; float largestDepth = 0.0f;
for (uint32_t i=0; i<m_nbContactPoints; i++) { for (uint32_t i=0; i<m_nbContactPoints; i++) {
float depth = m_contactPoints[i]->getPenetrationDepth(); float depth = m_contactPoints[i]->getPenetrationDepth();
if (depth > largestDepth) { if (depth > largestDepth) {
largestDepth = depth; largestDepth = depth;
} }
} }
return largestDepth; return largestDepth;
} }

View File

@ -5,121 +5,84 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/ContactManifold.hpp> #include <ephysics/collision/ContactManifold.hpp>
namespace ephysics { namespace ephysics {
const int32_t MAX_MANIFOLDS_IN_CONTACT_MANIFOLD_SET = 3; // Maximum number of contact manifolds in the set
// Constants const int32_t CONTACT_CUBEMAP_FACE_NB_SUBDIVISIONS = 3; // N Number for the N x N subdivisions of the cubemap
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
// Class ContactManifoldSet * collision can have more than one manifolds. Note that a contact manifold can
/** * contains several contact points.
* 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 class ContactManifoldSet {
* collision can have more than one manifolds. Note that a contact manifold can private:
* contains several contact points. int32_t m_nbMaxManifolds; //!< Maximum number of contact manifolds in the set
*/ int32_t m_nbManifolds; //!< Current number of contact manifolds in the set
class ContactManifoldSet { ProxyShape* m_shape1; //!< Pointer to the first proxy shape of the contact
ProxyShape* m_shape2; //!< Pointer to the second proxy shape of the contact
private: MemoryAllocator& m_memoryAllocator; //!< Reference to the memory allocator
ContactManifold* m_manifolds[MAX_MANIFOLDS_IN_CONTACT_MANIFOLD_SET]; //!< Contact manifolds of the set
// -------------------- Attributes -------------------- // /// Create a new contact manifold and add it to the set
void createManifold(short _normalDirectionId);
/// Maximum number of contact manifolds in the set /// Remove a contact manifold from the set
int32_t m_nbMaxManifolds; void removeManifold(int32_t _index);
// Return the index of the contact manifold with a similar average normal.
/// Current number of contact manifolds in the set int32_t selectManifoldWithSimilarNormal(int16_t _normalDirectionId) const;
int32_t m_nbManifolds; // 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
/// Pointer to the first proxy shape of the contact // normal vector int32_to of the of the bucket and returns a unique Id for the bucket
ProxyShape* m_shape1; int16_t computeCubemapNormalId(const vec3& _normal) const;
public:
/// Pointer to the second proxy shape of the contact /// Constructor
ProxyShape* m_shape2; ContactManifoldSet(ProxyShape* _shape1,
ProxyShape* _shape2,
/// Reference to the memory allocator MemoryAllocator& _memoryAllocator,
MemoryAllocator& m_memoryAllocator; int32_t _nbMaxManifolds);
/// Destructor
/// Contact manifolds of the set ~ContactManifoldSet();
ContactManifold* m_manifolds[MAX_MANIFOLDS_IN_CONTACT_MANIFOLD_SET]; /// Return the first proxy shape
ProxyShape* getShape1() const;
// -------------------- Methods -------------------- // /// Return the second proxy shape
ProxyShape* getShape2() const;
/// Create a new contact manifold and add it to the set /// Add a contact point to the manifold set
void createManifold(short normalDirectionId); void addContactPoint(ContactPoint* _contact);
/// Update the contact manifolds
/// Remove a contact manifold from the set void update();
void removeManifold(int32_t index); /// Clear the contact manifold set
void clear();
// Return the index of the contact manifold with a similar average normal. /// Return the number of manifolds in the set
int32_t selectManifoldWithSimilarNormal(int16_t normalDirectionId) const; int32_t getNbContactManifolds() const;
/// Return a given contact manifold
// Map the normal vector int32_to a cubemap face bucket (a face contains 4x4 buckets) ContactManifold* getContactManifold(int32_t _index) const;
// Each face of the cube is divided int32_to 4x4 buckets. This method maps the /// Return the total number of contact points in the set of manifolds
// normal vector int32_to of the of the bucket and returns a unique Id for the bucket int32_t getTotalNbContactPoints() const;
int16_t computeCubemapNormalId(const vec3& normal) const; };
public:
// -------------------- Methods -------------------- //
/// Constructor
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);
/// 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;
/// Return the total number of contact points in the set of manifolds
int32_t getTotalNbContactPoints() const;
};
// Return the first proxy shape // Return the first proxy shape
inline ProxyShape* ContactManifoldSet::getShape1() const { ProxyShape* ContactManifoldSet::getShape1() const {
return m_shape1; return m_shape1;
} }
// Return the second proxy shape // Return the second proxy shape
inline ProxyShape* ContactManifoldSet::getShape2() const { ProxyShape* ContactManifoldSet::getShape2() const {
return m_shape2; return m_shape2;
} }
// Return the number of manifolds in the set // Return the number of manifolds in the set
inline int32_t ContactManifoldSet::getNbContactManifolds() const { int32_t ContactManifoldSet::getNbContactManifolds() const {
return m_nbManifolds; return m_nbManifolds;
} }
// Return a given contact manifold // 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); assert(index >= 0 && index < m_nbManifolds);
return m_manifolds[index]; return m_manifolds[index];
} }
// Return the total number of contact points in the set of manifolds // 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; int32_t nbPoints = 0;
for (int32_t i=0; i<m_nbManifolds; i++) { for (int32_t i=0; i<m_nbManifolds; i++) {
nbPoints += m_manifolds[i]->getNbContactPoints(); nbPoints += m_manifolds[i]->getNbContactPoints();

View File

@ -157,7 +157,7 @@ class ProxyShape {
}; };
// Return the pointer to the cached collision data // Return the pointer to the cached collision data
inline void** ProxyShape::getCachedCollisionData() { void** ProxyShape::getCachedCollisionData() {
return &m_cachedCollisionData; return &m_cachedCollisionData;
} }
@ -165,7 +165,7 @@ inline void** ProxyShape::getCachedCollisionData() {
/** /**
* @return Pointer to the int32_ternal collision shape * @return Pointer to the int32_ternal collision shape
*/ */
inline const CollisionShape* ProxyShape::getCollisionShape() const { const CollisionShape* ProxyShape::getCollisionShape() const {
return m_collisionShape; return m_collisionShape;
} }
@ -173,7 +173,7 @@ inline const CollisionShape* ProxyShape::getCollisionShape() const {
/** /**
* @return Pointer to the parent body * @return Pointer to the parent body
*/ */
inline CollisionBody* ProxyShape::getBody() const { CollisionBody* ProxyShape::getBody() const {
return m_body; return m_body;
} }
@ -181,7 +181,7 @@ inline CollisionBody* ProxyShape::getBody() const {
/** /**
* @return Mass of the collision shape (in kilograms) * @return Mass of the collision shape (in kilograms)
*/ */
inline float ProxyShape::getMass() const { float ProxyShape::getMass() const {
return m_mass; 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 * @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; 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 * @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; 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 * @return The transformation that transforms the local-space of the collision shape
* to the local-space of the parent body * to the local-space of the parent body
*/ */
inline const etk::Transform3D& ProxyShape::getLocalToBodyTransform() const { const etk::Transform3D& ProxyShape::getLocalToBodyTransform() const {
return m_localToBodyTransform; return m_localToBodyTransform;
} }
// Set the local to parent body transform // 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; 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 * @return The transformation that transforms the local-space of the collision
* shape to the world-space * 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; 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 * @return Pointer to the next proxy shape in the linked list of proxy shapes
*/ */
inline ProxyShape* ProxyShape::getNext() { ProxyShape* ProxyShape::getNext() {
return m_next; 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 * @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; return m_next;
} }
@ -250,7 +250,7 @@ inline const ProxyShape* ProxyShape::getNext() const {
/** /**
* @return The collision category bits mask of the proxy shape * @return The collision category bits mask of the proxy shape
*/ */
inline unsigned short ProxyShape::getCollisionCategoryBits() const { unsigned short ProxyShape::getCollisionCategoryBits() const {
return m_collisionCategoryBits; return m_collisionCategoryBits;
} }
@ -258,7 +258,7 @@ inline unsigned short ProxyShape::getCollisionCategoryBits() const {
/** /**
* @param collisionCategoryBits The collision category bits mask of the proxy shape * @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; 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 * @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; 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 * @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; m_collideWithMaskBits = collideWithMaskBits;
} }
@ -282,7 +282,7 @@ inline void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBit
/** /**
* @return The local scaling vector * @return The local scaling vector
*/ */
inline vec3 ProxyShape::getLocalScaling() const { vec3 ProxyShape::getLocalScaling() const {
return m_collisionShape->getScaling(); return m_collisionShape->getScaling();
} }
@ -290,7 +290,7 @@ inline vec3 ProxyShape::getLocalScaling() const {
/** /**
* @param scaling The new local scaling vector * @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 // Set the local scaling of the collision shape
m_collisionShape->setLocalScaling(scaling); m_collisionShape->setLocalScaling(scaling);

View File

@ -4,17 +4,9 @@
* @license BSD 3 clauses (see license file) * @license BSD 3 clauses (see license file)
*/ */
// Libraries
#include <ephysics/collision/TriangleMesh.hpp> #include <ephysics/collision/TriangleMesh.hpp>
using namespace ephysics; ephysics::TriangleMesh::TriangleMesh() {
// Constructor
TriangleMesh::TriangleMesh() {
} }
// Destructor
TriangleMesh::~TriangleMesh() {
}

View File

@ -4,63 +4,50 @@
* @license BSD 3 clauses (see license file) * @license BSD 3 clauses (see license file)
*/ */
#pragma once #pragma once
// Libraries
#include <vector> #include <vector>
#include <cassert> #include <cassert>
#include <ephysics/collision/TriangleVertexArray.hpp> #include <ephysics/collision/TriangleVertexArray.hpp>
namespace ephysics { namespace ephysics {
/**
// Class TriangleMesh * @brief Represents a mesh made of triangles. A TriangleMesh contains
/** * one or several parts. Each part is a set of triangles represented in a
* This class represents a mesh made of triangles. A TriangleMesh contains * TriangleVertexArray object describing all the triangles vertices of the part.
* one or several parts. Each part is a set of triangles represented in a * A TriangleMesh object is used to create a ConcaveMeshShape from a triangle
* TriangleVertexArray object describing all the triangles vertices of the part. * mesh for instance.
* A TriangleMesh object is used to create a ConcaveMeshShape from a triangle */
* mesh for instance. class TriangleMesh {
*/ protected:
class TriangleMesh { std::vector<TriangleVertexArray*> m_triangleArrays; //!< All the triangle arrays of the mesh (one triangle array per part)
public:
protected: /**
* @brief Constructor
/// All the triangle arrays of the mesh (one triangle array per part) */
std::vector<TriangleVertexArray*> m_triangleArrays; TriangleMesh();
/**
public: * @brief Virtualisation of Destructor
*/
/// Constructor virtual ~TriangleMesh() = default;
TriangleMesh(); /**
* @brief Add a subpart of the mesh
/// Destructor */
virtual ~TriangleMesh(); void addSubpart(TriangleVertexArray* _triangleVertexArray) {
m_triangleArrays.push_back(_triangleVertexArray );
/// Add a subpart of the mesh }
void addSubpart(TriangleVertexArray* triangleVertexArray); /**
* @brief Get a pointer to a given subpart (triangle vertex array) of the mesh
/// Return a pointer to a given subpart (triangle vertex array) of the mesh */
TriangleVertexArray* getSubpart(uint32_t indexSubpart) const; TriangleVertexArray* getSubpart(uint32_t _indexSubpart) const {
assert(_indexSubpart < m_triangleArrays.size());
/// Return the number of subparts of the mesh return m_triangleArrays[_indexSubpart];
uint32_t getNbSubparts() const; }
}; /**
* @brief Get the number of subparts of the mesh
// Add a subpart of the mesh */
inline void TriangleMesh::addSubpart(TriangleVertexArray* triangleVertexArray) { uint32_t getNbSubparts() const {
m_triangleArrays.push_back(triangleVertexArray ); return m_triangleArrays.size();
} }
};
// 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 {
return m_triangleArrays.size();
}
} }

View File

@ -5,12 +5,9 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/configuration.hpp> #include <ephysics/configuration.hpp>
namespace ephysics { namespace ephysics {
// Class TriangleVertexArray
/** /**
* This class is used to describe the vertices and faces of a triangular mesh. * This class is used to describe the vertices and faces of a triangular mesh.
* A TriangleVertexArray represents a continuous array of vertices and indexes * A TriangleVertexArray represents a continuous array of vertices and indexes
@ -21,9 +18,7 @@ namespace ephysics {
* remains valid during the TriangleVertexArray life. * remains valid during the TriangleVertexArray life.
*/ */
class TriangleVertexArray { class TriangleVertexArray {
public: public:
/// Data type for the vertices in the array /// Data type for the vertices in the array
enum VertexDataType {VERTEX_FLOAT_TYPE, VERTEX_DOUBLE_TYPE}; enum VertexDataType {VERTEX_FLOAT_TYPE, VERTEX_DOUBLE_TYPE};
@ -31,35 +26,15 @@ class TriangleVertexArray {
enum IndexDataType {INDEX_INTEGER_TYPE, INDEX_SHORT_TYPE}; enum IndexDataType {INDEX_INTEGER_TYPE, INDEX_SHORT_TYPE};
protected: protected:
uint32_t m_numberVertices; //!< Number of vertices in the array
/// Number of vertices in the array unsigned char* m_verticesStart; //!< Pointer to the first vertex value in the array
uint32_t m_numberVertices; 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
/// Pointer to the first vertex value in the array unsigned char* m_indicesStart; //!< Pointer to the first vertex index of the array
unsigned char* m_verticesStart; 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
/// Stride (number of bytes) between the beginning of two vertices IndexDataType m_indexDataType; //!< Data type of the indices in the array
/// 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;
public: public:
/// Constructor /// Constructor
TriangleVertexArray(uint32_t nbVertices, void* verticesStart, int32_t verticesStride, TriangleVertexArray(uint32_t nbVertices, void* verticesStart, int32_t verticesStride,
uint32_t nbTriangles, void* indexesStart, int32_t indexesStride, uint32_t nbTriangles, void* indexesStart, int32_t indexesStride,

View File

@ -9,10 +9,8 @@
#include <ephysics/collision/CollisionDetection.hpp> #include <ephysics/collision/CollisionDetection.hpp>
#include <ephysics/engine/Profiler.hpp> #include <ephysics/engine/Profiler.hpp>
// We want to use the ReactPhysics3D namespace
using namespace ephysics; using namespace ephysics;
// Constructor
BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection) BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection)
:m_dynamicAABBTree(DYNAMIC_TREE_AABB_GAP), m_numberMovedShapes(0), m_numberAllocatedMovedShapes(8), :m_dynamicAABBTree(DYNAMIC_TREE_AABB_GAP), m_numberMovedShapes(0), m_numberAllocatedMovedShapes(8),
m_numberNonUsedMovedShapes(0), m_numberPotentialPairs(0), m_numberAllocatedPotentialPairs(8), m_numberNonUsedMovedShapes(0), m_numberPotentialPairs(0), m_numberAllocatedPotentialPairs(8),
@ -27,7 +25,6 @@ BroadPhaseAlgorithm::BroadPhaseAlgorithm(CollisionDetection& collisionDetection)
assert(m_potentialPairs != NULL); assert(m_potentialPairs != NULL);
} }
// Destructor
BroadPhaseAlgorithm::~BroadPhaseAlgorithm() { BroadPhaseAlgorithm::~BroadPhaseAlgorithm() {
// Release the memory for the array of non-static proxy shapes IDs // Release the memory for the array of non-static proxy shapes IDs
@ -37,8 +34,6 @@ BroadPhaseAlgorithm::~BroadPhaseAlgorithm() {
free(m_potentialPairs); 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) { void BroadPhaseAlgorithm::addMovedCollisionShape(int32_t broadPhaseID) {
// Allocate more elements in the array of shapes that have moved if necessary // 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++; 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) { void BroadPhaseAlgorithm::removeMovedCollisionShape(int32_t broadPhaseID) {
assert(m_numberNonUsedMovedShapes <= m_numberMovedShapes); 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) { void BroadPhaseAlgorithm::addProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb) {
// Add the collision shape int32_to the dynamic AABB tree and get its broad-phase ID // 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); addMovedCollisionShape(proxyShape->m_broadPhaseID);
} }
// Remove a proxy collision shape from the broad-phase collision detection
void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) { void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) {
int32_t broadPhaseID = proxyShape->m_broadPhaseID; int32_t broadPhaseID = proxyShape->m_broadPhaseID;
@ -122,7 +113,6 @@ void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) {
removeMovedCollisionShape(broadPhaseID); removeMovedCollisionShape(broadPhaseID);
} }
// Notify the broad-phase that a collision shape has moved and need to be updated
void BroadPhaseAlgorithm::updateProxyCollisionShape(ProxyShape* _proxyShape, void BroadPhaseAlgorithm::updateProxyCollisionShape(ProxyShape* _proxyShape,
const AABB& _aabb, const AABB& _aabb,
const vec3& _displacement, const vec3& _displacement,
@ -140,7 +130,6 @@ void BroadPhaseAlgorithm::updateProxyCollisionShape(ProxyShape* _proxyShape,
} }
} }
// Compute all the overlapping pairs of collision shapes
void BroadPhaseAlgorithm::computeOverlappingPairs() { void BroadPhaseAlgorithm::computeOverlappingPairs() {
// Reset the potential overlapping pairs // 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) { void BroadPhaseAlgorithm::notifyOverlappingNodes(int32_t node1ID, int32_t node2ID) {
// If both the nodes are the same, we do not create store the overlapping pair // 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++; m_numberPotentialPairs++;
} }
// Called when a overlapping node has been found during the call to
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
void AABBOverlapCallback::notifyOverlappingNode(int32_t nodeId) { void AABBOverlapCallback::notifyOverlappingNode(int32_t nodeId) {
m_broadPhaseAlgorithm.notifyOverlappingNodes(m_referenceNodeId, 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 BroadPhaseRaycastCallback::raycastBroadPhaseShape(int32_t nodeId, const Ray& ray) {
float hitFraction = float(-1.0); float hitFraction = float(-1.0);
@ -268,3 +253,22 @@ float BroadPhaseRaycastCallback::raycastBroadPhaseShape(int32_t nodeId, const Ra
return hitFraction; 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);
}

View File

@ -5,223 +5,131 @@
*/ */
#pragma once #pragma once
// Libraries
#include <vector> #include <vector>
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/collision/ProxyShape.hpp> #include <ephysics/collision/ProxyShape.hpp>
#include <ephysics/collision/broadphase/DynamicAABBTree.hpp> #include <ephysics/collision/broadphase/DynamicAABBTree.hpp>
#include <ephysics/engine/Profiler.hpp> #include <ephysics/engine/Profiler.hpp>
/// Namespace ReactPhysics3D
namespace ephysics { namespace ephysics {
// Declarations class CollisionDetection;
class CollisionDetection; class BroadPhaseAlgorithm;
class BroadPhaseAlgorithm;
/**
// Structure BroadPhasePair * @brief It represent a potential overlapping pair during the
/** * broad-phase collision detection.
* This structure represent a potential overlapping pair during the */
* broad-phase collision detection. struct BroadPhasePair {
*/ int32_t collisionShape1ID; //!< Broad-phase ID of the first collision shape
struct BroadPhasePair { int32_t collisionShape2ID; //!< Broad-phase ID of the second collision shape
/**
// -------------------- Attributes -------------------- // * @brief Method used to compare two pairs for sorting algorithm
* @param[in] _pair1 first pair of element
/// Broad-phase ID of the first collision shape * @param[in] _pair2 Second pair of element
int32_t collisionShape1ID; * @return _pair1 is smaller than _pair2
*/
/// Broad-phase ID of the second collision shape static bool smallerThan(const BroadPhasePair& _pair1, const BroadPhasePair& _pair2) {
int32_t collisionShape2ID; if (_pair1.collisionShape1ID < _pair2.collisionShape1ID) return true;
if (_pair1.collisionShape1ID == _pair2.collisionShape1ID) {
// -------------------- Methods -------------------- // return _pair1.collisionShape2ID < _pair2.collisionShape2ID;
}
/// Method used to compare two pairs for sorting algorithm return false;
static bool smallerThan(const BroadPhasePair& pair1, const BroadPhasePair& pair2);
};
// class AABBOverlapCallback
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) {
} }
};
// Called when a overlapping node has been found during the call to
// DynamicAABBTree:reportAllShapesOverlappingWithAABB() class AABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
virtual void notifyOverlappingNode(int32_t nodeId); private:
BroadPhaseAlgorithm& m_broadPhaseAlgorithm;
}; int32_t m_referenceNodeId;
public:
// Class BroadPhaseRaycastCallback // Constructor
/** AABBOverlapCallback(BroadPhaseAlgorithm& _broadPhaseAlgo, int32_t _referenceNodeId):
* Callback called when the AABB of a leaf node is hit by a ray the m_broadPhaseAlgorithm(_broadPhaseAlgo),
* broad-phase Dynamic AABB Tree. m_referenceNodeId(_referenceNodeId) {
*/
class BroadPhaseRaycastCallback : public DynamicAABBTreeRaycastCallback { }
// Called when a overlapping node has been found during the call to
private : // DynamicAABBTree:reportAllShapesOverlappingWithAABB()
virtual void notifyOverlappingNode(int32_t nodeId);
const DynamicAABBTree& m_dynamicAABBTree; };
unsigned short m_raycastWithCategoryMaskBits; /**
* Callback called when the AABB of a leaf node is hit by a ray the
RaycastTest& m_raycastTest; * broad-phase Dynamic AABB Tree.
*/
public: class BroadPhaseRaycastCallback : public DynamicAABBTreeRaycastCallback {
private :
// Constructor const DynamicAABBTree& m_dynamicAABBTree;
BroadPhaseRaycastCallback(const DynamicAABBTree& dynamicAABBTree, unsigned short raycastWithCategoryMaskBits, unsigned short m_raycastWithCategoryMaskBits;
RaycastTest& raycastTest) RaycastTest& m_raycastTest;
: m_dynamicAABBTree(dynamicAABBTree), m_raycastWithCategoryMaskBits(raycastWithCategoryMaskBits), public:
m_raycastTest(raycastTest) { // Constructor
BroadPhaseRaycastCallback(const DynamicAABBTree& _dynamicAABBTree,
} unsigned short _raycastWithCategoryMaskBits,
RaycastTest& _raycastTest):
// Called for a broad-phase shape that has to be tested for raycast m_dynamicAABBTree(_dynamicAABBTree),
virtual float raycastBroadPhaseShape(int32_t nodeId, const Ray& ray); m_raycastWithCategoryMaskBits(_raycastWithCategoryMaskBits),
m_raycastTest(_raycastTest) {
};
}
// Class BroadPhaseAlgorithm // Called for a broad-phase shape that has to be tested for raycast
/** virtual float raycastBroadPhaseShape(int32_t _nodeId, const Ray& _ray);
* This class 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 * @brief It represents the broad-phase collision detection. The
* tree data structure is used for fast broad-phase collision detection. * 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
class BroadPhaseAlgorithm { * later for collision during the narrow-phase collision detection. A dynamic AABB
* tree data structure is used for fast broad-phase collision detection.
protected : */
class BroadPhaseAlgorithm {
// -------------------- Attributes -------------------- // protected :
DynamicAABBTree m_dynamicAABBTree; //!< Dynamic AABB tree
/// 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.
DynamicAABBTree m_dynamicAABBTree; 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.
/// Array with the broad-phase IDs of all collision shapes that have moved (or have been uint32_t m_numberNonUsedMovedShapes; //!< Number of non-used elements in the array of shapes that have moved during the last simulation step.
/// created) during the last simulation step. Those are the shapes that need to be tested BroadPhasePair* m_potentialPairs; //!< Temporary array of potential overlapping pairs (with potential duplicates)
/// for overlapping in the next simulation step. uint32_t m_numberPotentialPairs; //!< Number of potential overlapping pairs
int32_t* m_movedShapes; uint32_t m_numberAllocatedPotentialPairs; //!< Number of allocated elements for the array of potential overlapping pairs
CollisionDetection& m_collisionDetection; //!< Reference to the collision detection object
/// Number of collision shapes in the array of shapes that have moved during the last /// Private copy-constructor
/// simulation step. BroadPhaseAlgorithm(const BroadPhaseAlgorithm& algorithm);
uint32_t m_numberMovedShapes; /// Private assignment operator
BroadPhaseAlgorithm& operator=(const BroadPhaseAlgorithm& algorithm);
/// Number of allocated elements for the array of shapes that have moved during the last public :
/// simulation step. /// Constructor
uint32_t m_numberAllocatedMovedShapes; BroadPhaseAlgorithm(CollisionDetection& _collisionDetection);
/// Destructor
/// Number of non-used elements in the array of shapes that have moved during the last virtual ~BroadPhaseAlgorithm();
/// simulation step. /// Add a proxy collision shape int32_to the broad-phase collision detection
uint32_t m_numberNonUsedMovedShapes; void addProxyCollisionShape(ProxyShape* _proxyShape, const AABB& _aabb);
/// Remove a proxy collision shape from the broad-phase collision detection
/// Temporary array of potential overlapping pairs (with potential duplicates) void removeProxyCollisionShape(ProxyShape* _proxyShape);
BroadPhasePair* m_potentialPairs; /// Notify the broad-phase that a collision shape has moved and need to be updated
void updateProxyCollisionShape(ProxyShape* _proxyShape,
/// Number of potential overlapping pairs const AABB& _aabb,
uint32_t m_numberPotentialPairs; const vec3& _displacement,
bool _forceReinsert = false);
/// Number of allocated elements for the array of potential overlapping pairs /// Add a collision shape in the array of shapes that have moved in the last simulation step
uint32_t m_numberAllocatedPotentialPairs; /// and that need to be tested again for broad-phase overlapping.
void addMovedCollisionShape(int32_t _broadPhaseID);
/// Reference to the collision detection object /// Remove a collision shape from the array of shapes that have moved in the last simulation
CollisionDetection& m_collisionDetection; /// step and that need to be tested again for broad-phase overlapping.
void removeMovedCollisionShape(int32_t _broadPhaseID);
// -------------------- Methods -------------------- // /// Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree
void notifyOverlappingNodes(int32_t _broadPhaseId1, int32_t _broadPhaseId2);
/// Private copy-constructor /// Compute all the overlapping pairs of collision shapes
BroadPhaseAlgorithm(const BroadPhaseAlgorithm& algorithm); void computeOverlappingPairs();
/// Return true if the two broad-phase collision shapes are overlapping
/// Private assignment operator bool testOverlappingShapes(const ProxyShape* _shape1, const ProxyShape* _shape2) const;
BroadPhaseAlgorithm& operator=(const BroadPhaseAlgorithm& algorithm); /// Ray casting method
void raycast(const Ray& _ray,
public : RaycastTest& _raycastTest,
unsigned short _raycastWithCategoryMaskBits) const;
// -------------------- Methods -------------------- // };
/// Constructor
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);
/// Remove a proxy collision shape from the broad-phase collision detection
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);
/// 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);
/// 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);
/// Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree
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;
/// 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);
}
} }

View File

@ -216,38 +216,38 @@ class DynamicAABBTree {
}; };
// Return true if the node is a leaf of the tree // Return true if the node is a leaf of the tree
inline bool TreeNode::isLeaf() const { bool TreeNode::isLeaf() const {
return (height == 0); return (height == 0);
} }
// Return the fat AABB corresponding to a given node ID // 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); assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
return m_nodes[nodeID].aabb; return m_nodes[nodeID].aabb;
} }
// Return the pointer to the data array of a given leaf node of the tree // 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(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
assert(m_nodes[nodeID].isLeaf()); assert(m_nodes[nodeID].isLeaf());
return m_nodes[nodeID].dataInt; return m_nodes[nodeID].dataInt;
} }
// Return the pointer to the data pointer of a given leaf node of the tree // 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(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
assert(m_nodes[nodeID].isLeaf()); assert(m_nodes[nodeID].isLeaf());
return m_nodes[nodeID].dataPointer; return m_nodes[nodeID].dataPointer;
} }
// Return the root AABB of the tree // Return the root AABB of the tree
inline AABB DynamicAABBTree::getRootAABB() const { AABB DynamicAABBTree::getRootAABB() const {
return getFatAABB(m_rootNodeID); return getFatAABB(m_rootNodeID);
} }
// Add an object int32_to the tree. This method creates a new leaf node in the tree and // 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. // 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); 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 // 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. // 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); int32_t nodeId = addObjectInternal(aabb);

View File

@ -5,39 +5,29 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp> #include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp>
namespace ephysics { namespace ephysics {
/**
// Class CollisionDispatch * @biref Abstract base class for dispatching the narrow-phase
/** * collision detection algorithm. Collision dispatching decides which collision
* This is the abstract base class for dispatching the narrow-phase * algorithm to use given two types of proxy collision shapes.
* collision detection algorithm. Collision dispatching decides which collision */
* algorithm to use given two types of proxy collision shapes. class CollisionDispatch {
*/ public:
class CollisionDispatch { /// Constructor
CollisionDispatch() {}
protected: /// Destructor
virtual ~CollisionDispatch() = default;
public: /// Initialize the collision dispatch configuration
virtual void init(CollisionDetection* _collisionDetection,
/// Constructor MemoryAllocator* _memoryAllocator) {
CollisionDispatch() {} }
/// Select and return the narrow-phase collision detection algorithm to
/// Destructor /// use between two types of collision shapes.
virtual ~CollisionDispatch() {} virtual NarrowPhaseAlgorithm* selectAlgorithm(int32_t _shape1Type,
int32_t _shape2Type) = 0;
/// Initialize the collision dispatch configuration };
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;
};
} }

View File

@ -88,28 +88,28 @@ void ConcaveVsConvexAlgorithm::testCollision(const CollisionShapeInfo& shape1Inf
void ConvexVsTriangleCallback::testTriangle(const vec3* trianglePoints) { void ConvexVsTriangleCallback::testTriangle(const vec3* trianglePoints) {
// Create a triangle collision shape // Create a triangle collision shape
float margin = mConcaveShape->getTriangleMargin(); float margin = m_concaveShape->getTriangleMargin();
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2], margin); TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2], margin);
// Select the collision algorithm to use between the triangle and the convex shape // Select the collision algorithm to use between the triangle and the convex shape
NarrowPhaseAlgorithm* algo = m_collisionDetection->getCollisionAlgorithm(triangleShape.getType(), 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 there is no collision algorithm between those two kinds of shapes
if (algo == NULL) return; if (algo == NULL) return;
// Notify the narrow-phase algorithm about the overlapping pair we are going to test // 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 // Create the CollisionShapeInfo objects
CollisionShapeInfo shapeConvexInfo(mConvexProxyShape, mConvexShape, mConvexProxyShape->getLocalToWorldTransform(), CollisionShapeInfo shapeConvexInfo(m_convexProxyShape, m_convexShape, m_convexProxyShape->getLocalToWorldTransform(),
mOverlappingPair, mConvexProxyShape->getCachedCollisionData()); m_overlappingPair, m_convexProxyShape->getCachedCollisionData());
CollisionShapeInfo shapeConcaveInfo(mConcaveProxyShape, &triangleShape, CollisionShapeInfo shapeConcaveInfo(m_concaveProxyShape, &triangleShape,
mConcaveProxyShape->getLocalToWorldTransform(), m_concaveProxyShape->getLocalToWorldTransform(),
mOverlappingPair, mConcaveProxyShape->getCachedCollisionData()); m_overlappingPair, m_concaveProxyShape->getCachedCollisionData());
// Use the collision algorithm to test collision between the triangle and the other convex shape // 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 // Process the concave triangle mesh collision using the smooth mesh collision algorithm described

View File

@ -5,207 +5,140 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp> #include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp>
#include <ephysics/collision/shapes/ConvexShape.hpp> #include <ephysics/collision/shapes/ConvexShape.hpp>
#include <ephysics/collision/shapes/ConcaveShape.hpp> #include <ephysics/collision/shapes/ConcaveShape.hpp>
#include <unordered_map> #include <unordered_map>
/// Namespace ReactPhysics3D
namespace ephysics { namespace ephysics {
// Class ConvexVsTriangleCallback /**
/** * @brief This class is used to encapsulate a callback method for
* This class is used to encapsulate a callback method for * collision detection between the triangle of a concave mesh shape
* collision detection between the triangle of a concave mesh shape * and a convex shape.
* and a convex shape. */
*/ class ConvexVsTriangleCallback : public TriangleCallback {
class ConvexVsTriangleCallback : public TriangleCallback { protected:
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;
}
/// Set the narrow-phase collision callback
void setNarrowPhaseCallback(NarrowPhaseCallback* _callback) {
m_narrowPhaseCallback = _callback;
}
/// Set the convex collision shape to test collision with
void setConvexShape(const ConvexShape* _convexShape) {
m_convexShape = _convexShape;
}
/// Set the concave collision shape
void setConcaveShape(const ConcaveShape* _concaveShape) {
m_concaveShape = _concaveShape;
}
/// Set the broadphase overlapping pair
void setOverlappingPair(OverlappingPair* _overlappingPair) {
m_overlappingPair = _overlappingPair;
}
/// Set the proxy shapes of the two collision shapes
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);
};
protected: /**
* @brief This class is used to store data about a contact with a triangle for the smooth
* mesh algorithm.
*/
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;
}
};
/// Pointer to the collision detection object struct ContactsDepthCompare {
CollisionDetection* m_collisionDetection; bool operator()(const SmoothMeshContactInfo& _contact1, const SmoothMeshContactInfo& _contact2) {
return _contact1.contactInfo.penetrationDepth < _contact2.contactInfo.penetrationDepth;
/// 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);
public:
/// Set the collision detection pointer
void setCollisionDetection(CollisionDetection* collisionDetection) {
m_collisionDetection = collisionDetection;
} }
};
/// Set the narrow-phase collision callback /**
void setNarrowPhaseCallback(NarrowPhaseCallback* callback) { * @brief This class is used as a narrow-phase callback to get narrow-phase contacts
mNarrowPhaseCallback = callback; * 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 {
private:
std::vector<SmoothMeshContactInfo>& m_contactPoints;
public:
// Constructor
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);
};
/// Set the convex collision shape to test collision with /**
void setConvexShape(const ConvexShape* convexShape) { * @brief This class is used to compute the narrow-phase collision detection
mConvexShape = convexShape; * 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.
/// Set the concave collision shape */
void setConcaveShape(const ConcaveShape* concaveShape) { class ConcaveVsConvexAlgorithm : public NarrowPhaseAlgorithm {
mConcaveShape = concaveShape; protected :
} /// Private copy-constructor
ConcaveVsConvexAlgorithm(const ConcaveVsConvexAlgorithm& _algorithm);
/// Set the broadphase overlapping pair /// Private assignment operator
void setOverlappingPair(OverlappingPair* overlappingPair) { ConcaveVsConvexAlgorithm& operator=(const ConcaveVsConvexAlgorithm& _algorithm);
mOverlappingPair = overlappingPair; /// Process the concave triangle mesh collision using the smooth mesh collision algorithm
} void processSmoothMeshCollision(OverlappingPair* _overlappingPair,
std::vector<SmoothMeshContactInfo> _contactPoints,
/// Set the proxy shapes of the two collision shapes NarrowPhaseCallback* _narrowPhaseCallback);
void setProxyShapes(ProxyShape* convexProxyShape, ProxyShape* concaveProxyShape) { /// Add a triangle vertex int32_to the set of processed triangles
mConvexProxyShape = convexProxyShape; void addProcessedVertex(std::unordered_multimap<int32_t, vec3>& _processTriangleVertices,
mConcaveProxyShape = concaveProxyShape; const vec3& _vertex) {
} processTriangleVertices.insert(std::make_pair(int32_t(vertex.x() * vertex.y() * vertex.z()), vertex));
}
/// Test collision between a triangle and the convex mesh shape /// Return true if the vertex is in the set of already processed vertices
virtual void testTriangle(const vec3* trianglePoints); bool hasVertexBeenProcessed(const std::unordered_multimap<int32_t, vec3>& _processTriangleVertices,
}; const vec3& _vertex) const;
public :
// Class SmoothMeshContactInfo /// Constructor
/** ConcaveVsConvexAlgorithm();
* This class is used to store data about a contact with a triangle for the smooth /// Destructor
* mesh algorithm. virtual ~ConcaveVsConvexAlgorithm();
*/ /// Compute a contact info if the two bounding volume collide
class SmoothMeshContactInfo { virtual void testCollision(const CollisionShapeInfo& _shape1Info,
const CollisionShapeInfo& _shape2Info,
public: NarrowPhaseCallback* _narrowPhaseCallback);
};
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;
}
};
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
* 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 {
private:
std::vector<SmoothMeshContactInfo>& m_contactPoints;
public:
// Constructor
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);
};
// Class ConcaveVsConvexAlgorithm
/**
* 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 {
protected :
// -------------------- Attributes -------------------- //
// -------------------- Methods -------------------- //
/// Private copy-constructor
ConcaveVsConvexAlgorithm(const ConcaveVsConvexAlgorithm& algorithm);
/// Private assignment operator
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);
/// Add a triangle vertex int32_to the set of processed triangles
void addProcessedVertex(std::unordered_multimap<int32_t, vec3>& processTriangleVertices,
const vec3& 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;
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));
}
} }

View File

@ -85,7 +85,7 @@ class NarrowPhaseAlgorithm {
}; };
// Set the current overlapping pair of bodies // Set the current overlapping pair of bodies
inline void NarrowPhaseAlgorithm::setCurrentOverlappingPair(OverlappingPair* overlappingPair) { void NarrowPhaseAlgorithm::setCurrentOverlappingPair(OverlappingPair* overlappingPair) {
mCurrentOverlappingPair = overlappingPair; mCurrentOverlappingPair = overlappingPair;
} }

View File

@ -4,53 +4,46 @@
* @license BSD 3 clauses (see license file) * @license BSD 3 clauses (see license file)
*/ */
// Libraries
#include <ephysics/collision/narrowphase/SphereVsSphereAlgorithm.hpp> #include <ephysics/collision/narrowphase/SphereVsSphereAlgorithm.hpp>
#include <ephysics/collision/shapes/SphereShape.hpp> #include <ephysics/collision/shapes/SphereShape.hpp>
// We want to use the ReactPhysics3D namespace ephysics::SphereVsSphereAlgorithm::SphereVsSphereAlgorithm() :
using namespace ephysics;
// Constructor
SphereVsSphereAlgorithm::SphereVsSphereAlgorithm() :
NarrowPhaseAlgorithm() { NarrowPhaseAlgorithm() {
} }
// Destructor void ephysics::SphereVsSphereAlgorithm::testCollision(const ephysics::CollisionShapeInfo& _shape1Info,
SphereVsSphereAlgorithm::~SphereVsSphereAlgorithm() { const ephysics::CollisionShapeInfo& _shape2Info,
ephysics::NarrowPhaseCallback* _narrowPhaseCallback) {
}
void SphereVsSphereAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
const CollisionShapeInfo& shape2Info,
NarrowPhaseCallback* narrowPhaseCallback) {
// Get the sphere collision shapes // Get the sphere collision shapes
const SphereShape* sphereShape1 = static_cast<const SphereShape*>(shape1Info.collisionShape); const ephysics::SphereShape* sphereShape1 = static_cast<const ephysics::SphereShape*>(_shape1Info.collisionShape);
const SphereShape* sphereShape2 = static_cast<const SphereShape*>(shape2Info.collisionShape); const ephysics::SphereShape* sphereShape2 = static_cast<const ephysics::SphereShape*>(_shape2Info.collisionShape);
// Get the local-space to world-space transforms // Get the local-space to world-space transforms
const etk::Transform3D& transform1 = shape1Info.shapeToWorldTransform; const etk::Transform3D& transform1 = _shape1Info.shapeToWorldTransform;
const etk::Transform3D& transform2 = shape2Info.shapeToWorldTransform; const etk::Transform3D& transform2 = _shape2Info.shapeToWorldTransform;
// Compute the distance between the centers // Compute the distance between the centers
vec3 vectorBetweenCenters = transform2.getPosition() - transform1.getPosition(); vec3 vectorBetweenCenters = transform2.getPosition() - transform1.getPosition();
float squaredDistanceBetweenCenters = vectorBetweenCenters.length2(); float squaredDistanceBetweenCenters = vectorBetweenCenters.length2();
// Compute the sum of the radius // Compute the sum of the radius
float sumRadius = sphereShape1->getRadius() + sphereShape2->getRadius(); float sumRadius = _sphereShape1->getRadius() + sphereShape2->getRadius();
// If the sphere collision shapes int32_tersect // If the sphere collision shapes intersect
if (squaredDistanceBetweenCenters <= sumRadius * sumRadius) { if (squaredDistanceBetweenCenters <= sumRadius * sumRadius) {
vec3 centerSphere2InBody1LocalSpace = transform1.getInverse() * transform2.getPosition(); vec3 centerSphere2InBody1LocalSpace = transform1.getInverse() * transform2.getPosition();
vec3 centerSphere1InBody2LocalSpace = transform2.getInverse() * transform1.getPosition(); vec3 centerSphere1InBody2LocalSpace = transform2.getInverse() * transform1.getPosition();
vec3 int32_tersectionOnBody1 = sphereShape1->getRadius() * vec3 intersectionOnBody1 = sphereShape1->getRadius() * centerSphere2InBody1LocalSpace.safeNormalized();
centerSphere2InBody1LocalSpace.safeNormalized(); vec3 intersectionOnBody2 = sphereShape2->getRadius() * centerSphere1InBody2LocalSpace.safeNormalized();
vec3 int32_tersectionOnBody2 = sphereShape2->getRadius() *
centerSphere1InBody2LocalSpace.safeNormalized();
float penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters); float penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters);
// Create the contact info object // Create the contact info object
ContactPointInfo contactInfo(shape1Info.proxyShape, shape2Info.proxyShape, shape1Info.collisionShape, ephysics::ContactPointInfo contactInfo(_shape1Info.proxyShape,
shape2Info.collisionShape, vectorBetweenCenters.safeNormalized(), penetrationDepth, _shape2Info.proxyShape,
int32_tersectionOnBody1, int32_tersectionOnBody2); _shape1Info.collisionShape,
_shape2Info.collisionShape,
vectorBetweenCenters.safeNormalized(),
penetrationDepth,
intersectionOnBody1,
intersectionOnBody2);
// Notify about the new contact // Notify about the new contact
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo); _narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
} }
} }

View File

@ -5,46 +5,34 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/body/Body.hpp> #include <ephysics/body/Body.hpp>
#include <ephysics/constraint/ContactPoint.hpp> #include <ephysics/constraint/ContactPoint.hpp>
#include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp> #include <ephysics/collision/narrowphase/NarrowPhaseAlgorithm.hpp>
/// Namespace ReactPhysics3D
namespace ephysics { 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. * between two sphere collision shapes.
*/ */
class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm { class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
protected : protected :
SphereVsSphereAlgorithm(const SphereVsSphereAlgorithm& algorithm) = delete;
// -------------------- Methods -------------------- // SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm) = delete;
/// Private copy-constructor
SphereVsSphereAlgorithm(const SphereVsSphereAlgorithm& algorithm);
/// Private assignment operator
SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm);
public : public :
/**
// -------------------- Methods -------------------- // * @brief Constructor
*/
/// Constructor
SphereVsSphereAlgorithm(); SphereVsSphereAlgorithm();
/**
/// Destructor * @brief Destructor
virtual ~SphereVsSphereAlgorithm(); */
virtual ~SphereVsSphereAlgorithm() = default;
/// Compute a contact info if the two bounding volume collide /**
virtual void testCollision(const CollisionShapeInfo& shape1Info, * @brief Compute a contact info if the two bounding volume collide
const CollisionShapeInfo& shape2Info, */
NarrowPhaseCallback* narrowPhaseCallback); virtual void testCollision(const CollisionShapeInfo& _shape1Info,
const CollisionShapeInfo& _shape2Info,
NarrowPhaseCallback* _narrowPhaseCallback);
}; };
} }

View File

@ -25,95 +25,88 @@ AABB::AABB(const vec3& minCoordinates, const vec3& maxCoordinates):
} }
AABB::AABB(const AABB& aabb): AABB::AABB(const AABB& _aabb):
m_minCoordinates(aabb.m_minCoordinates), m_minCoordinates(_aabb.m_minCoordinates),
m_maxCoordinates(aabb.m_maxCoordinates) { m_maxCoordinates(_aabb.m_maxCoordinates) {
} }
// Merge the AABB in parameter with the current one void AABB::mergeWithAABB(const AABB& _aabb) {
void AABB::mergeWithAABB(const AABB& aabb) { m_minCoordinates.setX(std::min(m_minCoordinates.x(), _aabb.m_minCoordinates.x()));
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.setY(std::min(m_minCoordinates.y(), aabb.m_minCoordinates.y())); m_minCoordinates.setZ(std::min(m_minCoordinates.z(), _aabb.m_minCoordinates.z()));
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.setX(std::max(m_maxCoordinates.x(), aabb.m_maxCoordinates.x())); m_maxCoordinates.setY(std::max(m_maxCoordinates.y(), _aabb.m_maxCoordinates.y()));
m_maxCoordinates.setY(std::max(m_maxCoordinates.y(), aabb.m_maxCoordinates.y())); m_maxCoordinates.setZ(std::max(m_maxCoordinates.z(), _aabb.m_maxCoordinates.z()));
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) {
void AABB::mergeTwoAABBs(const AABB& aabb1, const AABB& aabb2) { m_minCoordinates.setX(std::min(_aabb1.m_minCoordinates.x(), _aabb2.m_minCoordinates.x()));
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.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_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.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.setY(std::max(aabb1.m_maxCoordinates.y(), aabb2.m_maxCoordinates.y())); m_maxCoordinates.setZ(std::max(_aabb1.m_maxCoordinates.z(), _aabb2.m_maxCoordinates.z()));
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; bool isInside = true;
isInside = isInside && m_minCoordinates.x() <= aabb.m_minCoordinates.x(); isInside = isInside && m_minCoordinates.x() <= _aabb.m_minCoordinates.x();
isInside = isInside && m_minCoordinates.y() <= aabb.m_minCoordinates.y(); isInside = isInside && m_minCoordinates.y() <= _aabb.m_minCoordinates.y();
isInside = isInside && m_minCoordinates.z() <= aabb.m_minCoordinates.z(); isInside = isInside && m_minCoordinates.z() <= _aabb.m_minCoordinates.z();
isInside = isInside && m_maxCoordinates.x() >= aabb.m_maxCoordinates.x(); isInside = isInside && m_maxCoordinates.x() >= _aabb.m_maxCoordinates.x();
isInside = isInside && m_maxCoordinates.y() >= aabb.m_maxCoordinates.y(); isInside = isInside && m_maxCoordinates.y() >= _aabb.m_maxCoordinates.y();
isInside = isInside && m_maxCoordinates.z() >= aabb.m_maxCoordinates.z(); isInside = isInside && m_maxCoordinates.z() >= _aabb.m_maxCoordinates.z();
return isInside; return isInside;
} }
// Create and return an AABB for a triangle AABB AABB::createAABBForTriangle(const vec3* _trianglePoints) {
AABB AABB::createAABBForTriangle(const vec3* trianglePoints) { vec3 minCoords(_trianglePoints[0].x(), _trianglePoints[0].y(), _trianglePoints[0].z());
vec3 minCoords(trianglePoints[0].x(), trianglePoints[0].y(), trianglePoints[0].z()); vec3 maxCoords(_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()) {
if (trianglePoints[1].x() < minCoords.x()) { minCoords.setX(_trianglePoints[1].x());
minCoords.setX(trianglePoints[1].x());
} }
if (trianglePoints[1].y() < minCoords.y()) { if (_trianglePoints[1].y() < minCoords.y()) {
minCoords.setY(trianglePoints[1].y()); minCoords.setY(_trianglePoints[1].y());
} }
if (trianglePoints[1].z() < minCoords.z()) { if (_trianglePoints[1].z() < minCoords.z()) {
minCoords.setZ(trianglePoints[1].z()); minCoords.setZ(_trianglePoints[1].z());
} }
if (trianglePoints[2].x() < minCoords.x()) { if (_trianglePoints[2].x() < minCoords.x()) {
minCoords.setX(trianglePoints[2].x()); minCoords.setX(_trianglePoints[2].x());
} }
if (trianglePoints[2].y() < minCoords.y()) { if (_trianglePoints[2].y() < minCoords.y()) {
minCoords.setY(trianglePoints[2].y()); minCoords.setY(_trianglePoints[2].y());
} }
if (trianglePoints[2].z() < minCoords.z()) { if (_trianglePoints[2].z() < minCoords.z()) {
minCoords.setZ(trianglePoints[2].z()); minCoords.setZ(_trianglePoints[2].z());
} }
if (trianglePoints[1].x() > maxCoords.x()) { if (_trianglePoints[1].x() > maxCoords.x()) {
maxCoords.setX(trianglePoints[1].x()); maxCoords.setX(_trianglePoints[1].x());
} }
if (trianglePoints[1].y() > maxCoords.y()) { if (_trianglePoints[1].y() > maxCoords.y()) {
maxCoords.setY(trianglePoints[1].y()); maxCoords.setY(_trianglePoints[1].y());
} }
if (trianglePoints[1].z() > maxCoords.z()) { if (_trianglePoints[1].z() > maxCoords.z()) {
maxCoords.setZ(trianglePoints[1].z()); maxCoords.setZ(_trianglePoints[1].z());
} }
if (trianglePoints[2].x() > maxCoords.x()) { if (_trianglePoints[2].x() > maxCoords.x()) {
maxCoords.setX(trianglePoints[2].x()); maxCoords.setX(_trianglePoints[2].x());
} }
if (trianglePoints[2].y() > maxCoords.y()) { if (_trianglePoints[2].y() > maxCoords.y()) {
maxCoords.setY(trianglePoints[2].y()); maxCoords.setY(_trianglePoints[2].y());
} }
if (trianglePoints[2].z() > maxCoords.z()) { if (_trianglePoints[2].z() > maxCoords.z()) {
maxCoords.setZ(trianglePoints[2].z()); maxCoords.setZ(_trianglePoints[2].z());
} }
return AABB(minCoords, maxCoords); return AABB(minCoords, maxCoords);
} }
// Return true if the ray int32_tersects the AABB bool AABB::testRayIntersect(const Ray& _ray) const {
/// This method use the line vs AABB raycasting technique described in const vec3 point2 = _ray.point1 + _ray.maxFraction * (_ray.point2 - _ray.point1);
/// 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);
const vec3 e = m_maxCoordinates - m_minCoordinates; const vec3 e = m_maxCoordinates - m_minCoordinates;
const vec3 d = point2 - ray.point1; const vec3 d = point2 - _ray.point1;
const vec3 m = ray.point1 + point2 - m_minCoordinates - m_maxCoordinates; const vec3 m = _ray.point1 + point2 - m_minCoordinates - m_maxCoordinates;
// Test if the AABB face normals are separating axis // Test if the AABB face normals are separating axis
float adx = std::abs(d.x()); float adx = std::abs(d.x());
if (std::abs(m.x()) > e.x() + adx) { 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 // No separating axis has been found
return true; 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;
}

View File

@ -4,184 +4,147 @@
* @license BSD 3 clauses (see license file) * @license BSD 3 clauses (see license file)
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
/// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
/**
// Class AABB * @brief Represents a bounding volume of type "Axis Aligned
/** * Bounding Box". It's a box where all the edges are always aligned
* This class represents a bounding volume of type "Axis Aligned * with the world coordinate system. The AABB is defined by the
* Bounding Box". It's a box where all the edges are always aligned * minimum and maximum world coordinates of the three axis.
* with the world coordinate system. The AABB is defined by the */
* minimum and maximum world coordinates of the three axis. class AABB {
*/ private :
class AABB { /// 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 :
/**
* @brief default contructor
*/
AABB();
/**
* @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;
}
/**
* @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;
};
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
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 {
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;
}
}

View File

@ -5,19 +5,15 @@
*/ */
#pragma once #pragma once
// Libraries
#include <cfloat> #include <cfloat>
#include <ephysics/collision/shapes/ConvexShape.hpp> #include <ephysics/collision/shapes/ConvexShape.hpp>
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
/// ReactPhysics3D namespace
namespace ephysics { 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 * The three extents are half-widths of the box along the three
* axis x, y, z local axis. The "transform" of the corresponding * axis x, y, z local axis. The "transform" of the corresponding
* rigid body will give an orientation and a position to the box. This * 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. * default margin distance by not using the "margin" parameter in the constructor.
*/ */
class BoxShape : public ConvexShape { class BoxShape : public ConvexShape {
protected : protected :
/// Extent sizes of the box in the x, y and z direction vec3 m_extent; //!< Extent sizes of the box in the x, y and z direction
vec3 m_extent;
/// Private copy-constructor /// Private copy-constructor
BoxShape(const BoxShape& shape); BoxShape(const BoxShape& shape);
/// Private assignment operator /// Private assignment operator
BoxShape& operator=(const BoxShape& shape); BoxShape& operator=(const BoxShape& shape);
/// Return a local support point in a given direction without the object margin /// Return a local support point in a given direction without the object margin
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction, virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
void** cachedCollisionData) const; void** cachedCollisionData) const;
/// Return true if a point is inside the collision shape /// 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 /// 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 /// Return the number of bytes used by the collision shape
virtual size_t getSizeInBytes() const; virtual size_t getSizeInBytes() const;
public : public :
/// Constructor /// Constructor
BoxShape(const vec3& extent, float margin = OBJECT_MARGIN); BoxShape(const vec3& extent, float margin = OBJECT_MARGIN);
/// Destructor /// Destructor
virtual ~BoxShape() = default; virtual ~BoxShape() = default;
/// Return the extents of the box /// Return the extents of the box
vec3 getExtent() const; vec3 getExtent() const;
/// Set the scaling vector of the collision shape /// 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 /// 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 /// 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;
}; };
@ -77,12 +60,12 @@ class BoxShape : public ConvexShape {
/** /**
* @return The vector with the three extents of the box shape (in meters) * @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); return m_extent + vec3(m_margin, m_margin, m_margin);
} }
// Set the scaling vector of the collision shape // 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; 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 min The minimum bounds of the shape in local-space coordinates
* @param max The maximum 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 // Maximum bounds
_max = m_extent + vec3(m_margin, m_margin, m_margin); _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 // 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 sizeof(BoxShape);
} }
// Return a local support point in a given direction without the objec margin // 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 { void** cachedCollisionData) const {
return vec3(direction.x() < 0.0 ? -m_extent.x() : m_extent.x(), 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 // 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] && return (localPoint.x() < m_extent[0] && localPoint.x() > -m_extent[0] &&
localPoint.y() < m_extent[1] && localPoint.y() > -m_extent[1] && localPoint.y() < m_extent[1] && localPoint.y() > -m_extent[1] &&
localPoint.z() < m_extent[2] && localPoint.z() > -m_extent[2]); localPoint.z() < m_extent[2] && localPoint.z() > -m_extent[2]);

View File

@ -5,80 +5,76 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/shapes/ConvexShape.hpp> #include <ephysics/collision/shapes/ConvexShape.hpp>
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
// Class CapsuleShape /**
/** * @brief It represents a capsule collision shape that is defined around the Y axis.
* This class 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.
* 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)
* 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
* and its height (distance between the centers of the two spheres). This collision shape * does not have an explicit object margin distance. The margin is implicitly the radius
* does not have an explicit object margin distance. The margin is implicitly the radius * and height of the shape. Therefore, no need to specify an object margin for a
* and height of the shape. Therefore, no need to specify an object margin for a * capsule shape.
* capsule shape. */
*/ class CapsuleShape : public ConvexShape {
class CapsuleShape : public ConvexShape { protected:
protected: float m_halfHeight; //!< Half height of the capsule (height = distance between the centers of the two spheres)
/// Half height of the capsule (height = distance between the centers of the two spheres) /// Private copy-constructor
float m_halfHeight; CapsuleShape(const CapsuleShape& shape);
/// Private copy-constructor
CapsuleShape(const CapsuleShape& shape); /// Private assignment operator
CapsuleShape& operator=(const CapsuleShape& shape);
/// Private assignment operator
CapsuleShape& operator=(const CapsuleShape& shape); /// Return a local support point in a given direction without the object margin
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
/// Return a local support point in a given direction without the object margin 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;
/// 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;
/// Raycast method with feedback information
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; /// Raycasting method between a ray one of the two spheres end cap of the capsule
bool raycastWithSphereEndCap(const vec3& point1, const vec3& point2,
/// Raycasting method between a ray one of the two spheres end cap of the capsule const vec3& sphereCenter, float maxFraction,
bool raycastWithSphereEndCap(const vec3& point1, const vec3& point2, vec3& hitLocalPoint, float& hitFraction) const;
const vec3& sphereCenter, float maxFraction,
vec3& hitLocalPoint, float& hitFraction) const; /// Return the number of bytes used by the collision shape
virtual size_t getSizeInBytes() const;
/// Return the number of bytes used by the collision shape
virtual size_t getSizeInBytes() const; public :
/// Constructor
public : CapsuleShape(float _radius, float _height);
/// Constructor
CapsuleShape(float _radius, float _height); /// Destructor
virtual ~CapsuleShape();
/// Destructor
virtual ~CapsuleShape(); /// Return the radius of the capsule
float getRadius() const;
/// Return the radius of the capsule
float getRadius() const; /// Return the height of the capsule
float getHeight() const;
/// Return the height of the capsule
float getHeight() const; /// Set the scaling vector of the collision shape
virtual void setLocalScaling(const vec3& scaling);
/// 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 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;
/// Return the local inertia tensor of the collision shape };
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
};
// Get the radius of the capsule // Get the radius of the capsule
/** /**
* @return The radius of the capsule shape (in meters) * @return The radius of the capsule shape (in meters)
*/ */
inline float CapsuleShape::getRadius() const { float CapsuleShape::getRadius() const {
return m_margin; return m_margin;
} }
@ -86,12 +82,12 @@ inline float CapsuleShape::getRadius() const {
/** /**
* @return The height of the capsule shape (in meters) * @return The height of the capsule shape (in meters)
*/ */
inline float CapsuleShape::getHeight() const { float CapsuleShape::getHeight() const {
return m_halfHeight + m_halfHeight; return m_halfHeight + m_halfHeight;
} }
// Set the scaling vector of the collision shape // 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_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
m_margin = (m_margin / m_scaling.x()) * scaling.x(); 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 // Return the number of bytes used by the collision shape
inline size_t CapsuleShape::getSizeInBytes() const { size_t CapsuleShape::getSizeInBytes() const {
return sizeof(CapsuleShape); 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 min The minimum bounds of the shape in local-space coordinates
* @param max The maximum 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 // Maximum bounds
max.setX(m_margin); 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 /// 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 /// 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. /// 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 { void** cachedCollisionData) const {
// Support point top sphere // Support point top sphere

View File

@ -5,7 +5,6 @@
*/ */
#pragma once #pragma once
// Libraries
#include <cassert> #include <cassert>
#include <typeinfo> #include <typeinfo>
#include <etk/math/Vector3D.hpp> #include <etk/math/Vector3D.hpp>
@ -15,19 +14,14 @@
#include <ephysics/collision/RaycastInfo.hpp> #include <ephysics/collision/RaycastInfo.hpp>
#include <ephysics/memory/MemoryAllocator.hpp> #include <ephysics/memory/MemoryAllocator.hpp>
/// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
/// Type of the collision shape
enum CollisionShapeType {TRIANGLE, BOX, SPHERE, CONE, CYLINDER, enum CollisionShapeType {TRIANGLE, BOX, SPHERE, CONE, CYLINDER,
CAPSULE, CONVEX_MESH, CONCAVE_MESH, HEIGHTFIELD}; CAPSULE, CONVEX_MESH, CONCAVE_MESH, HEIGHTFIELD};
const int32_t NB_COLLISION_SHAPE_TYPES = 9; const int32_t NB_COLLISION_SHAPE_TYPES = 9;
// Declarations
class ProxyShape; class ProxyShape;
class CollisionBody; class CollisionBody;
// Class CollisionShape
/** /**
* This abstract class represents the collision shape associated with a * This abstract class represents the collision shape associated with a
* body that is used during the narrow-phase collision detection. * body that is used during the narrow-phase collision detection.
@ -37,9 +31,9 @@ class CollisionShape {
CollisionShapeType m_type; //!< Type of the collision shape CollisionShapeType m_type; //!< Type of the collision shape
vec3 m_scaling; //!< Scaling vector of the collision shape vec3 m_scaling; //!< Scaling vector of the collision shape
/// Private copy-constructor /// Private copy-constructor
CollisionShape(const CollisionShape& shape); CollisionShape(const CollisionShape& shape) = delete;
/// Private assignment operator /// Private assignment operator
CollisionShape& operator=(const CollisionShape& shape); CollisionShape& operator=(const CollisionShape& shape) = delete;
/// Return true if a point is inside the collision shape /// Return true if a point is inside the collision shape
virtual bool testPointInside(const vec3& worldPoint, ProxyShape* proxyShape) const=0; virtual bool testPointInside(const vec3& worldPoint, ProxyShape* proxyShape) const=0;
/// Raycast method with feedback information /// Raycast method with feedback information
@ -78,28 +72,28 @@ class CollisionShape {
/** /**
* @return The type of the collision shape (box, sphere, cylinder, ...) * @return The type of the collision shape (box, sphere, cylinder, ...)
*/ */
inline CollisionShapeType CollisionShape::getType() const { CollisionShapeType CollisionShape::getType() const {
return m_type; return m_type;
} }
// Return true if the collision shape type is a convex shape // 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 shapeType != CONCAVE_MESH && shapeType != HEIGHTFIELD;
} }
// Return the scaling vector of the collision shape // Return the scaling vector of the collision shape
inline vec3 CollisionShape::getScaling() const { vec3 CollisionShape::getScaling() const {
return m_scaling; return m_scaling;
} }
// Set the scaling vector of the collision shape // Set the scaling vector of the collision shape
inline void CollisionShape::setLocalScaling(const vec3& scaling) { void CollisionShape::setLocalScaling(const vec3& scaling) {
m_scaling = scaling; m_scaling = scaling;
} }
// Return the maximum number of contact manifolds allowed in an overlapping // Return the maximum number of contact manifolds allowed in an overlapping
// pair wit the given two collision shape types // pair wit the given two collision shape types
inline int32_t CollisionShape::computeNbMaxContactManifolds(CollisionShapeType shapeType1, int32_t CollisionShape::computeNbMaxContactManifolds(CollisionShapeType shapeType1,
CollisionShapeType shapeType2) { CollisionShapeType shapeType2) {
// If both shapes are convex // If both shapes are convex
if (isConvex(shapeType1) && isConvex(shapeType2)) { if (isConvex(shapeType1) && isConvex(shapeType2)) {

View File

@ -5,7 +5,6 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/shapes/ConcaveShape.hpp> #include <ephysics/collision/shapes/ConcaveShape.hpp>
#include <ephysics/collision/broadphase/DynamicAABBTree.hpp> #include <ephysics/collision/broadphase/DynamicAABBTree.hpp>
#include <ephysics/collision/TriangleMesh.hpp> #include <ephysics/collision/TriangleMesh.hpp>
@ -14,132 +13,105 @@
namespace ephysics { namespace ephysics {
class ConcaveMeshShape; class ConcaveMeshShape;
class ConvexTriangleAABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
class ConvexTriangleAABBOverlapCallback : public DynamicAABBTreeOverlapCallback { private:
private: TriangleCallback& m_triangleTestCallback; //!<
TriangleCallback& m_triangleTestCallback; //!< const ConcaveMeshShape& m_concaveMeshShape; //!< Reference to the concave mesh shape
const ConcaveMeshShape& m_concaveMeshShape; //!< Reference to the concave mesh shape const DynamicAABBTree& m_dynamicAABBTree; //!< Reference to the Dynamic AABB tree
const DynamicAABBTree& m_dynamicAABBTree; //!< Reference to the Dynamic AABB tree public:
public: // Constructor
// Constructor ConvexTriangleAABBOverlapCallback(TriangleCallback& _triangleCallback,
ConvexTriangleAABBOverlapCallback(TriangleCallback& _triangleCallback, const ConcaveMeshShape& _concaveShape,
const ConcaveMeshShape& _concaveShape, const DynamicAABBTree& _dynamicAABBTree):
const DynamicAABBTree& _dynamicAABBTree): m_triangleTestCallback(_triangleCallback),
m_triangleTestCallback(_triangleCallback), m_concaveMeshShape(_concaveShape),
m_concaveMeshShape(_concaveShape), m_dynamicAABBTree(_dynamicAABBTree) {
m_dynamicAABBTree(_dynamicAABBTree) {
}
} // Called when a overlapping node has been found during the call to
// Called when a overlapping node has been found during the call to // DynamicAABBTree:reportAllShapesOverlappingWithAABB()
// DynamicAABBTree:reportAllShapesOverlappingWithAABB() virtual void notifyOverlappingNode(int32_t _nodeId);
virtual void notifyOverlappingNode(int32_t _nodeId);
};
};
/// Class ConcaveMeshRaycastCallback
/// Class ConcaveMeshRaycastCallback class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback { private :
std::vector<int32_t> m_hitAABBNodes;
private : const DynamicAABBTree& m_dynamicAABBTree;
const ConcaveMeshShape& m_concaveMeshShape;
std::vector<int32_t> m_hitAABBNodes; ProxyShape* m_proxyShape;
const DynamicAABBTree& m_dynamicAABBTree; RaycastInfo& m_raycastInfo;
const ConcaveMeshShape& m_concaveMeshShape; const Ray& m_ray;
ProxyShape* m_proxyShape; bool mIsHit;
RaycastInfo& m_raycastInfo; public:
const Ray& m_ray; // Constructor
bool mIsHit; ConcaveMeshRaycastCallback(const DynamicAABBTree& _dynamicAABBTree,
const ConcaveMeshShape& _concaveMeshShape,
public: ProxyShape* _proxyShape,
RaycastInfo& _raycastInfo,
// Constructor const Ray& _ray):
ConcaveMeshRaycastCallback(const DynamicAABBTree& dynamicAABBTree, const ConcaveMeshShape& concaveMeshShape, m_dynamicAABBTree(_dynamicAABBTree),
ProxyShape* proxyShape, RaycastInfo& raycastInfo, const Ray& ray) m_concaveMeshShape(_concaveMeshShape),
: m_dynamicAABBTree(dynamicAABBTree), m_concaveMeshShape(concaveMeshShape), m_proxyShape(proxyShape), m_proxyShape(_proxyShape),
m_raycastInfo(raycastInfo), m_ray(ray), mIsHit(false) { 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); /// 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);
/// Raycast all collision shapes that have been collected /// Raycast all collision shapes that have been collected
void raycastTriangles(); void raycastTriangles();
/// Return true if a raycast hit has been found
/// Return true if a raycast hit has been found bool getIsHit() const {
bool getIsHit() const { return mIsHit;
return mIsHit; }
} };
}; /**
* @brief Represents a static concave mesh shape. Note that collision detection
// Class ConcaveMeshShape * with a concave mesh shape can be very expensive. You should use only use
/** * this shape for a static mesh.
* This class represents a static concave mesh shape. Note that collision detection */
* with a concave mesh shape can be very expensive. You should use only use class ConcaveMeshShape : public ConcaveShape {
* this shape for a static mesh. protected:
*/ TriangleMesh* m_triangleMesh; //!< Triangle mesh
class ConcaveMeshShape : public ConcaveShape { DynamicAABBTree m_dynamicAABBTree; //!< Dynamic AABB tree to accelerate collision with the triangles
/// Private copy-constructor
protected: ConcaveMeshShape(const ConcaveMeshShape& _shape) = delete;
/// Private assignment operator
// -------------------- Attributes -------------------- // ConcaveMeshShape& operator=(const ConcaveMeshShape& _shape) = delete;
/// Raycast method with feedback information
/// Triangle mesh virtual bool raycast(const Ray& _ray, RaycastInfo& _raycastInfo, ProxyShape* _proxyShape) const;
TriangleMesh* m_triangleMesh; /// Return the number of bytes used by the collision shape
virtual size_t getSizeInBytes() const;
/// Dynamic AABB tree to accelerate collision with the triangles /// Insert all the triangles int32_to the dynamic AABB tree
DynamicAABBTree m_dynamicAABBTree; void initBVHTree();
/// Return the three vertices coordinates (in the array outTriangleVertices) of a triangle
// -------------------- Methods -------------------- // /// given the start vertex index pointer of the triangle.
void getTriangleVerticesWithIndexPointer(int32_t _subPart,
/// Private copy-constructor int32_t _triangleIndex,
ConcaveMeshShape(const ConcaveMeshShape& shape); vec3* _outTriangleVertices) const;
public:
/// Private assignment operator /// Constructor
ConcaveMeshShape& operator=(const ConcaveMeshShape& shape); ConcaveMeshShape(TriangleMesh* triangleMesh);
/// Destructor
/// Raycast method with feedback information ~ConcaveMeshShape();
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; /// Return the local bounds of the shape in x, y and z directions.
virtual void getLocalBounds(vec3& min, vec3& max) const;
/// Return the number of bytes used by the collision shape /// Set the local scaling vector of the collision shape
virtual size_t getSizeInBytes() const; virtual void setLocalScaling(const vec3& scaling);
/// Return the local inertia tensor of the collision shape
/// Insert all the triangles int32_to the dynamic AABB tree virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
void initBVHTree(); /// Use a callback method on all triangles of the concave shape inside a given AABB
virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const;
/// Return the three vertices coordinates (in the array outTriangleVertices) of a triangle friend class ConvexTriangleAABBOverlapCallback;
/// given the start vertex index pointer of the triangle. friend class ConcaveMeshRaycastCallback;
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 // Return the number of bytes used by the collision shape
inline size_t ConcaveMeshShape::getSizeInBytes() const { size_t ConcaveMeshShape::getSizeInBytes() const {
return sizeof(ConcaveMeshShape); 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 min The minimum bounds of the shape in local-space coordinates
* @param max The maximum 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 // Get the AABB of the whole tree
AABB treeAABB = m_dynamicAABBTree.getRootAABB(); 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 // 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); CollisionShape::setLocalScaling(scaling);
@ -176,7 +148,7 @@ inline void ConcaveMeshShape::setLocalScaling(const vec3& scaling) {
* coordinates * coordinates
* @param mass Mass to use to compute the inertia tensor of the collision shape * @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 // Default inertia tensor
// Note that this is not very realistic for a concave triangle mesh. // 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 // Called when a overlapping node has been found during the call to
// DynamicAABBTree:reportAllShapesOverlappingWithAABB() // 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) // Get the node data (triangle index and mesh subpart index)
int32_t* data = m_dynamicAABBTree.getNodeDataInt(nodeId); int32_t* data = m_dynamicAABBTree.getNodeDataInt(nodeId);

View File

@ -5,109 +5,74 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/shapes/CollisionShape.hpp> #include <ephysics/collision/shapes/CollisionShape.hpp>
#include <ephysics/collision/shapes/TriangleShape.hpp> #include <ephysics/collision/shapes/TriangleShape.hpp>
// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
/**
// Class TriangleCallback * @brief It is used to encapsulate a callback method for
/** * a single triangle of a ConcaveMesh.
* This class is used to encapsulate a callback method for */
* a single triangle of a ConcaveMesh. class TriangleCallback {
*/ public:
class TriangleCallback { virtual ~TriangleCallback() = default;
/// Report a triangle
public: virtual void testTriangle(const vec3* _trianglePoints)=0;
virtual ~TriangleCallback() = default; };
/// Report a triangle /**
virtual void testTriangle(const vec3* trianglePoints)=0; * @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 {
protected :
// Class ConcaveShape bool m_isSmoothMeshCollisionEnabled; //!< True if the smooth mesh collision algorithm is enabled
/** float m_triangleMargin; //!< Margin use for collision detection for each triangle
* This abstract class represents a concave collision shape associated with a TriangleRaycastSide m_raycastTestType; //!< Raycast test type for the triangle (front, back, front-back)
* body that is used during the narrow-phase collision detection. /// Private copy-constructor
*/ ConcaveShape(const ConcaveShape& _shape) = delete;
class ConcaveShape : public CollisionShape { /// Private assignment operator
ConcaveShape& operator=(const ConcaveShape& _shape) = delete;
protected : /// Return true if a point is inside the collision shape
virtual bool testPointInside(const vec3& _localPoint, ProxyShape* _proxyShape) const;
// -------------------- Attributes -------------------- // public :
/// Constructor
/// True if the smooth mesh collision algorithm is enabled ConcaveShape(CollisionShapeType _type);
bool m_isSmoothMeshCollisionEnabled; /// Destructor
virtual ~ConcaveShape();
// Margin use for collision detection for each triangle /// Return the triangle margin
float m_triangleMargin; float getTriangleMargin() const;
/// Return the raycast test type (front, back, front-back)
/// Raycast test type for the triangle (front, back, front-back) TriangleRaycastSide getRaycastTestType() const;
TriangleRaycastSide m_raycastTestType; // Set the raycast test type (front, back, front-back)
void setRaycastTestType(TriangleRaycastSide _testType);
// -------------------- Methods -------------------- // /// Return true if the collision shape is convex, false if it is concave
virtual bool isConvex() const;
/// Private copy-constructor /// Use a callback method on all triangles of the concave shape inside a given AABB
ConcaveShape(const ConcaveShape& shape); virtual void testAllTriangles(TriangleCallback& _callback, const AABB& _localAABB) const=0;
/// Return true if the smooth mesh collision is enabled
/// Private assignment operator bool getIsSmoothMeshCollisionEnabled() const;
ConcaveShape& operator=(const ConcaveShape& shape); /// Enable/disable the smooth mesh collision algorithm
void setIsSmoothMeshCollisionEnabled(bool _isEnabled);
/// Return true if a point is inside the collision shape };
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
public :
// -------------------- Methods -------------------- //
/// Constructor
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);
/// 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;
/// Return true if the smooth mesh collision is enabled
bool getIsSmoothMeshCollisionEnabled() const;
/// Enable/disable the smooth mesh collision algorithm
void setIsSmoothMeshCollisionEnabled(bool isEnabled);
};
// Return the triangle margin // Return the triangle margin
inline float ConcaveShape::getTriangleMargin() const { float ConcaveShape::getTriangleMargin() const {
return m_triangleMargin; return m_triangleMargin;
} }
/// Return true if the collision shape is convex, false if it is concave /// 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 false;
} }
// Return true if a point is inside the collision shape // 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 false;
} }
// Return true if the smooth mesh collision is enabled // Return true if the smooth mesh collision is enabled
inline bool ConcaveShape::getIsSmoothMeshCollisionEnabled() const { bool ConcaveShape::getIsSmoothMeshCollisionEnabled() const {
return m_isSmoothMeshCollisionEnabled; 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 /// 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 /// of the triangle mesh. If it is enabled, collsions with the mesh will be smoother
/// but collisions computation is a bit more expensive. /// but collisions computation is a bit more expensive.
inline void ConcaveShape::setIsSmoothMeshCollisionEnabled(bool isEnabled) { void ConcaveShape::setIsSmoothMeshCollisionEnabled(bool isEnabled) {
m_isSmoothMeshCollisionEnabled = isEnabled; m_isSmoothMeshCollisionEnabled = isEnabled;
} }
// Return the raycast test type (front, back, front-back) // Return the raycast test type (front, back, front-back)
inline TriangleRaycastSide ConcaveShape::getRaycastTestType() const { TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
return m_raycastTestType; return m_raycastTestType;
} }
@ -128,7 +93,7 @@ inline TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
/** /**
* @param testType Raycast test type for the triangle (front, back, front-back) * @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; m_raycastTestType = testType;
} }

View File

@ -5,84 +5,63 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/shapes/ConvexShape.hpp> #include <ephysics/collision/shapes/ConvexShape.hpp>
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
/// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
/**
// Class ConeShape * @brief This class represents a cone collision shape centered at the
/** * origin and alligned with the Y axis. The cone is defined
* This class represents a cone collision shape centered at the * by its height and by the radius of its base. The center of the
* origin and alligned with the Y axis. The cone is defined * cone is at the half of the height. The "transform" of the
* by its height and by the radius of its base. The center of the * corresponding rigid body gives an orientation and a position
* cone is at the half of the height. The "transform" of the * to the cone. This collision shape uses an extra margin distance around
* corresponding rigid body gives an orientation and a position * it for collision detection purpose. The default margin is 4cm (if your
* to the cone. This collision shape uses an extra margin distance around * units are meters, which is recommended). In case, you want to simulate small
* it for collision detection purpose. The default margin is 4cm (if your * objects (smaller than the margin distance), you might want to reduce the margin
* units are meters, which is recommended). In case, you want to simulate small * by specifying your own margin distance using the "margin" parameter in the
* objects (smaller than the margin distance), you might want to reduce the margin * constructor of the cone shape. Otherwise, it is recommended to use the
* by specifying your own margin distance using the "margin" parameter in the * default margin distance by not using the "margin" parameter in the constructor.
* 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 {
*/ protected :
class ConeShape : public ConvexShape { float m_radius; //!< Radius of the base
protected : float m_halfHeight; //!< Half height of the cone
/// Radius of the base float m_sinTheta; //!< sine of the semi angle at the apex point
float m_radius; /// Private copy-constructor
/// Half height of the cone ConeShape(const ConeShape& _shape) = delete;
float m_halfHeight; /// Private assignment operator
/// sine of the semi angle at the apex point ConeShape& operator=(const ConeShape& _shape) = delete;
float m_sinTheta; /// Return a local support point in a given direction without the object margin
/// Private copy-constructor virtual vec3 getLocalSupportPointWithoutMargin(const vec3& _direction,
ConeShape(const ConeShape& shape); void** _cachedCollisionData) const;
/// Return true if a point is inside the collision shape
/// Private assignment operator virtual bool testPointInside(const vec3& _localPoint, ProxyShape* _proxyShape) const;
ConeShape& operator=(const ConeShape& shape); /// Raycast method with feedback information
virtual bool raycast(const Ray& _ray, RaycastInfo& _raycastInfo, ProxyShape* _proxyShape) const;
/// Return a local support point in a given direction without the object margin /// Return the number of bytes used by the collision shape
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction, virtual size_t getSizeInBytes() const;
void** cachedCollisionData) const; public :
/// Constructor
/// Return true if a point is inside the collision shape ConeShape(float _radius, float _height, float _margin = OBJECT_MARGIN);
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const; /// Return the radius
float getRadius() const;
/// Raycast method with feedback information /// Return the height
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; float getHeight() const;
/// Set the scaling vector of the collision shape
/// Return the number of bytes used by the collision shape virtual void setLocalScaling(const vec3& _scaling);
virtual size_t getSizeInBytes() const; /// Return the local bounds of the shape in x, y and z directions
virtual void getLocalBounds(vec3& _min, vec3& _max) const;
public : /// Return the local inertia tensor of the collision shape
virtual void computeLocalInertiaTensor(etk::Matrix3x3& _tensor, float _mass) const;
// -------------------- Methods -------------------- // };
/// Constructor
ConeShape(float m_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);
/// 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;
};
// Return the radius // Return the radius
/** /**
* @return Radius of the cone (in meters) * @return Radius of the cone (in meters)
*/ */
inline float ConeShape::getRadius() const { float ConeShape::getRadius() const {
return m_radius; return m_radius;
} }
@ -90,12 +69,12 @@ inline float ConeShape::getRadius() const {
/** /**
* @return Height of the cone (in meters) * @return Height of the cone (in meters)
*/ */
inline float ConeShape::getHeight() const { float ConeShape::getHeight() const {
return float(2.0) * m_halfHeight; return float(2.0) * m_halfHeight;
} }
// Set the scaling vector of the collision shape // 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_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
m_radius = (m_radius / m_scaling.x()) * scaling.x(); 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 // Return the number of bytes used by the collision shape
inline size_t ConeShape::getSizeInBytes() const { size_t ConeShape::getSizeInBytes() const {
return sizeof(ConeShape); 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 min The minimum bounds of the shape in local-space coordinates
* @param max The maximum 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 // Maximum bounds
max.setX(m_radius + m_margin); max.setX(m_radius + m_margin);
@ -132,7 +111,7 @@ inline void ConeShape::getLocalBounds(vec3& min, vec3& max) const {
* coordinates * coordinates
* @param mass Mass to use to compute the inertia tensor of the collision shape * @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 rSquare = m_radius * m_radius;
float diagXZ = float(0.15) * mass * (rSquare + m_halfHeight); float diagXZ = float(0.15) * mass * (rSquare + m_halfHeight);
tensor.setValue(diagXZ, 0.0, 0.0, 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 // 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) / const float radiusHeight = m_radius * (-localPoint.y() + m_halfHeight) /
(m_halfHeight * float(2.0)); (m_halfHeight * float(2.0));
return (localPoint.y() < m_halfHeight && localPoint.y() > -m_halfHeight) && return (localPoint.y() < m_halfHeight && localPoint.y() > -m_halfHeight) &&

View File

@ -128,13 +128,13 @@ class ConvexMeshShape : public ConvexShape {
}; };
/// Set the scaling vector of the collision shape /// Set the scaling vector of the collision shape
inline void ConvexMeshShape::setLocalScaling(const vec3& scaling) { void ConvexMeshShape::setLocalScaling(const vec3& scaling) {
ConvexShape::setLocalScaling(scaling); ConvexShape::setLocalScaling(scaling);
recalculateBounds(); recalculateBounds();
} }
// Return the number of bytes used by the collision shape // Return the number of bytes used by the collision shape
inline size_t ConvexMeshShape::getSizeInBytes() const { size_t ConvexMeshShape::getSizeInBytes() const {
return sizeof(ConvexMeshShape); 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 min The minimum bounds of the shape in local-space coordinates
* @param max The maximum 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; min = m_minBounds;
max = m_maxBounds; max = m_maxBounds;
} }
@ -156,7 +156,7 @@ inline void ConvexMeshShape::getLocalBounds(vec3& min, vec3& max) const {
* coordinates * coordinates
* @param mass Mass to use to compute the inertia tensor of the collision shape * @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; float factor = (1.0f / float(3.0)) * mass;
vec3 realExtent = 0.5f * (m_maxBounds - m_minBounds); vec3 realExtent = 0.5f * (m_maxBounds - m_minBounds);
assert(realExtent.x() > 0 && realExtent.y() > 0 && realExtent.z() > 0); 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 * @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 // Add the vertex in to vertices array
m_vertices.push_back(vertex); 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 v1 Index of the first vertex of the edge to add
* @param v2 Index of the second 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 the entry for vertex v1 does not exist in the adjacency list
if (m_edgesAdjacencyList.count(v1) == 0) { 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 * @return True if the edges information is used and false otherwise
*/ */
inline bool ConvexMeshShape::isEdgesInformationUsed() const { bool ConvexMeshShape::isEdgesInformationUsed() const {
return m_isEdgesInformationUsed; 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 * @param isEdgesUsed True if you want to use the edges information to speed up
* the collision detection with the convex mesh shape * the collision detection with the convex mesh shape
*/ */
inline void ConvexMeshShape::setIsEdgesInformationUsed(bool isEdgesUsed) { void ConvexMeshShape::setIsEdgesInformationUsed(bool isEdgesUsed) {
m_isEdgesInformationUsed = isEdgesUsed; m_isEdgesInformationUsed = isEdgesUsed;
} }
// Return true if a point is inside the collision shape // 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 { ProxyShape* proxyShape) const {
// Use the GJK algorithm to test if the point is inside the convex mesh // Use the GJK algorithm to test if the point is inside the convex mesh

View File

@ -67,7 +67,7 @@ class ConvexShape : public CollisionShape {
}; };
/// Return true if the collision shape is convex, false if it is concave /// Return true if the collision shape is convex, false if it is concave
inline bool ConvexShape::isConvex() const { bool ConvexShape::isConvex() const {
return true; return true;
} }
@ -75,7 +75,7 @@ inline bool ConvexShape::isConvex() const {
/** /**
* @return The margin (in meters) around the collision shape * @return The margin (in meters) around the collision shape
*/ */
inline float ConvexShape::getMargin() const { float ConvexShape::getMargin() const {
return m_margin; return m_margin;
} }

View File

@ -91,7 +91,7 @@ class CylinderShape : public ConvexShape {
/** /**
* @return Radius of the cylinder (in meters) * @return Radius of the cylinder (in meters)
*/ */
inline float CylinderShape::getRadius() const { float CylinderShape::getRadius() const {
return mRadius; return mRadius;
} }
@ -99,12 +99,12 @@ inline float CylinderShape::getRadius() const {
/** /**
* @return Height of the cylinder (in meters) * @return Height of the cylinder (in meters)
*/ */
inline float CylinderShape::getHeight() const { float CylinderShape::getHeight() const {
return m_halfHeight + m_halfHeight; return m_halfHeight + m_halfHeight;
} }
// Set the scaling vector of the collision shape // 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(); m_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
mRadius = (mRadius / m_scaling.x()) * scaling.x(); 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 // Return the number of bytes used by the collision shape
inline size_t CylinderShape::getSizeInBytes() const { size_t CylinderShape::getSizeInBytes() const {
return sizeof(CylinderShape); 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 min The minimum bounds of the shape in local-space coordinates
* @param max The maximum 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 // Maximum bounds
max.setX(mRadius + m_margin); max.setX(mRadius + m_margin);
max.setY(m_halfHeight + m_margin); max.setY(m_halfHeight + m_margin);
@ -139,7 +139,7 @@ inline void CylinderShape::getLocalBounds(vec3& min, vec3& max) const {
* coordinates * coordinates
* @param mass Mass to use to compute the inertia tensor of the collision shape * @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 height = float(2.0) * m_halfHeight;
float diag = (1.0f / float(12.0)) * mass * (3 * mRadius * mRadius + height * height); float diag = (1.0f / float(12.0)) * mass * (3 * mRadius * mRadius + height * height);
tensor.setValue(diag, 0.0, 0.0, 0.0, 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 // 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 return ( (localPoint.x() * localPoint.x() + localPoint.z() * localPoint.z()) < mRadius * mRadius
&& localPoint.y() < m_halfHeight && localPoint.y() < m_halfHeight
&& localPoint.y() > -m_halfHeight); && localPoint.y() > -m_halfHeight);

View File

@ -169,32 +169,32 @@ class HeightFieldShape : public ConcaveShape {
}; };
// Return the number of rows in the height field // Return the number of rows in the height field
inline int32_t HeightFieldShape::getNbRows() const { int32_t HeightFieldShape::getNbRows() const {
return m_numberRows; return m_numberRows;
} }
// Return the number of columns in the height field // Return the number of columns in the height field
inline int32_t HeightFieldShape::getNbColumns() const { int32_t HeightFieldShape::getNbColumns() const {
return m_numberColumns; return m_numberColumns;
} }
// Return the type of height value in the height field // 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 m_heightDataType;
} }
// Return the number of bytes used by the collision shape // Return the number of bytes used by the collision shape
inline size_t HeightFieldShape::getSizeInBytes() const { size_t HeightFieldShape::getSizeInBytes() const {
return sizeof(HeightFieldShape); return sizeof(HeightFieldShape);
} }
// Set the local scaling vector of the collision shape // 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); CollisionShape::setLocalScaling(scaling);
} }
// Return the height of a given (x,y) point in the height field // 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) { switch(m_heightDataType) {
case HEIGHT_FLOAT_TYPE : return ((float*)m_heightFieldData)[y * m_numberColumns + x]; 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 // 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); return (value < 0.0f) ? value - 0.5f : value + float(0.5);
} }
@ -215,7 +215,7 @@ inline int32_t HeightFieldShape::computeIntegerGridValue(float value) const {
* coordinates * coordinates
* @param mass Mass to use to compute the inertia tensor of the collision shape * @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 // Default inertia tensor
// Note that this is not very realistic for a concave triangle mesh. // Note that this is not very realistic for a concave triangle mesh.

View File

@ -5,154 +5,133 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/collision/shapes/ConvexShape.hpp> #include <ephysics/collision/shapes/ConvexShape.hpp>
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
// ReactPhysics3D namespace
namespace ephysics { 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 * at the origin and defined by its radius. This collision shape does not
* have an explicit object margin distance. The margin is implicitly the * have an explicit object margin distance. The margin is implicitly the
* radius of the sphere. Therefore, no need to specify an object margin * radius of the sphere. Therefore, no need to specify an object margin
* for a sphere shape. * for a sphere shape.
*/ */
class SphereShape : public ConvexShape { class SphereShape : public ConvexShape {
protected : protected :
// -------------------- Attributes -------------------- //
// -------------------- Methods -------------------- //
/// Private copy-constructor
SphereShape(const SphereShape& shape); SphereShape(const SphereShape& shape);
SphereShape& operator=(const SphereShape& shape) = delete;
/// Private assignment operator
SphereShape& operator=(const SphereShape& shape);
/// Return a local support point in a given direction without the object margin /// Return a local support point in a given direction without the object margin
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction, virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
void** cachedCollisionData) const; void** cachedCollisionData) const;
/// Return true if a point is inside the collision shape /// 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 /// 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 /// Return the number of bytes used by the collision shape
virtual size_t getSizeInBytes() const; virtual size_t getSizeInBytes() const;
public : public :
// -------------------- Methods -------------------- //
/// Constructor /// Constructor
SphereShape(float radius); SphereShape(float radius);
/// Destructor /// Destructor
virtual ~SphereShape(); virtual ~SphereShape();
/// Return the radius of the sphere /// Return the radius of the sphere
float getRadius() const; float getRadius() const;
/// Set the scaling vector of the collision shape /// 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. /// 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 /// 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;
/// Update the AABB of a body using its collision shape /// Update the AABB of a body using its collision shape
virtual void computeAABB(AABB& aabb, const etk::Transform3D& transform) const; virtual void computeAABB(AABB& aabb, const etk::Transform3D& transform) const;
}; };
// Get the radius of the sphere // Get the radius of the sphere
/** /**
* @brief
* @return Radius of the sphere (in meters) * @return Radius of the sphere (in meters)
*/ */
inline float SphereShape::getRadius() const { float SphereShape::getRadius() const {
return m_margin; return m_margin;
} }
* @brief
// Set the scaling vector of the collision shape // 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(); m_margin = (m_margin / m_scaling.x()) * scaling.x();
CollisionShape::setLocalScaling(scaling); CollisionShape::setLocalScaling(scaling);
} }
* @brief
// Return the number of bytes used by the collision shape // 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 sizeof(SphereShape);
} }
// Return a local support point in a given direction without the object margin /**
inline vec3 SphereShape::getLocalSupportPointWithoutMargin(const vec3& direction, * @brief Get a local support point in a given direction without the object margin
void** cachedCollisionData) const { * @param[in] _direction
* @param[in] _cachedCollisionData
// Return the center of the sphere (the radius is taken int32_to account in the object margin) * @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 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 * @brief Get the local bounds of the shape in x, y and z directions.
* @param max The maximum bounds of the shape in local-space coordinates * 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 // Maximum bounds
max.setX(m_margin); _max.setX(m_margin);
max.setY(m_margin); _max.setY(m_margin);
max.setZ(m_margin); _max.setZ(m_margin);
// Minimum bounds // Minimum bounds
min.setX(-m_margin); _min.setX(-m_margin);
min.setY(min.x()); _min.setY(_min.x());
min.setZ(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 * @brief Compute the local inertia tensor of the sphere
* coordinates * @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 * @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 { void SphereShape::computeLocalInertiaTensor(etk::Matrix3x3& _tensor, float _mass) const {
float diag = float(0.4) * mass * m_margin * m_margin; float _diag = 0.4f * _mass * m_margin * m_margin;
tensor.setValue(diag, 0.0, 0.0, tensor.setValue(_diag, 0.0f, 0.0f,
0.0, diag, 0.0, 0.0f, _diag, 0.0f,
0.0, 0.0, diag); 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 * @brief Update the AABB of a body using its collision shape
* computed in world-space coordinates * @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 * @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 // Get the local extents in x,y and z direction
vec3 extents(m_margin, m_margin, m_margin); vec3 extents(m_margin, m_margin, m_margin);
// Update the AABB with the new minimum and maximum coordinates // Update the AABB with the new minimum and maximum coordinates
aabb.setMin(transform.getPosition() - extents); _aabb.setMin(_transform.getPosition() - extents);
aabb.setMax(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 { * @brief Test if a point is inside a shape
return (localPoint.length2() < m_margin * m_margin); * @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);
} }
} }

View File

@ -22,9 +22,9 @@ using namespace ephysics;
*/ */
TriangleShape::TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3, float margin) TriangleShape::TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3, float margin)
: ConvexShape(TRIANGLE, margin) { : ConvexShape(TRIANGLE, margin) {
mPoints[0] = point1; m_points[0] = point1;
mPoints[1] = point2; m_points[1] = point2;
mPoints[2] = point3; m_points[2] = point3;
m_raycastTestType = FRONT; m_raycastTestType = FRONT;
} }
@ -41,9 +41,9 @@ bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
PROFILE("TriangleShape::raycast()"); PROFILE("TriangleShape::raycast()");
const vec3 pq = ray.point2 - ray.point1; const vec3 pq = ray.point2 - ray.point1;
const vec3 pa = mPoints[0] - ray.point1; const vec3 pa = m_points[0] - ray.point1;
const vec3 pb = mPoints[1] - ray.point1; const vec3 pb = m_points[1] - ray.point1;
const vec3 pc = mPoints[2] - 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 // Test if the line PQ is inside the eges BC, CA and AB. We use the triple
// product for this test. // product for this test.
@ -89,12 +89,12 @@ bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
w *= denom; w *= denom;
// Compute the local hit point using the barycentric coordinates // 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(); const float hitFraction = (localHitPoint - ray.point1).length() / pq.length();
if (hitFraction < 0.0f || hitFraction > ray.maxFraction) return false; 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; if (localHitNormal.dot(pq) > 0.0f) localHitNormal = -localHitNormal;
raycastInfo.body = proxyShape->getBody(); raycastInfo.body = proxyShape->getBody();

View File

@ -5,45 +5,28 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
#include <ephysics/collision/shapes/ConvexShape.hpp> #include <ephysics/collision/shapes/ConvexShape.hpp>
/// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
/// Raycast test side for the triangle /**
* @brief Raycast test side for the triangle
*/
enum TriangleRaycastSide { enum TriangleRaycastSide {
FRONT, //!< Raycast against front triangle
/// Raycast against front triangle BACK, //!< Raycast against back triangle
FRONT, FRONT_AND_BACK //!< Raycast against front and back triangle
/// Raycast against back triangle
BACK,
/// Raycast against front and back triangle
FRONT_AND_BACK
}; };
// Class TriangleShape
/** /**
* This class represents a triangle collision shape that is centered * This class represents a triangle collision shape that is centered
* at the origin and defined three points. * at the origin and defined three points.
*/ */
class TriangleShape : public ConvexShape { class TriangleShape : public ConvexShape {
protected: protected:
vec3 m_points[3]; //!< Three points of the triangle
// -------------------- Attribute -------------------- // TriangleRaycastSide m_raycastTestType; //!< Raycast test type for the triangle (front, back, front-back)
/// Three points of the triangle
vec3 mPoints[3];
/// Raycast test type for the triangle (front, back, front-back)
TriangleRaycastSide m_raycastTestType;
// -------------------- Methods -------------------- //
/// Private copy-constructor /// Private copy-constructor
TriangleShape(const TriangleShape& shape); TriangleShape(const TriangleShape& shape);
@ -64,9 +47,6 @@ class TriangleShape : public ConvexShape {
virtual size_t getSizeInBytes() const; virtual size_t getSizeInBytes() const;
public: public:
// -------------------- Methods -------------------- //
/// Constructor /// Constructor
TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3, TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3,
float margin = OBJECT_MARGIN); float margin = OBJECT_MARGIN);
@ -94,23 +74,20 @@ class TriangleShape : public ConvexShape {
/// Return the coordinates of a given vertex of the triangle /// Return the coordinates of a given vertex of the triangle
vec3 getVertex(int32_t index) const; vec3 getVertex(int32_t index) const;
// ---------- Friendship ---------- //
friend class ConcaveMeshRaycastCallback; friend class ConcaveMeshRaycastCallback;
friend class TriangleOverlapCallback; friend class TriangleOverlapCallback;
}; };
// Return the number of bytes used by the collision shape // 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 sizeof(TriangleShape);
} }
// Return a local support point in a given direction without the object margin // 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 { void** cachedCollisionData) const {
vec3 dotProducts(direction.dot(mPoints[0]), direction.dot(mPoints[1]), direction.dot(mPoints[2])); vec3 dotProducts(direction.dot(m_points[0]), direction.dot(m_points[1]), direction.dot(m_points[2]));
return mPoints[dotProducts.getMaxAxis()]; return m_points[dotProducts.getMaxAxis()];
} }
// Return the local bounds of the shape in x, y and z directions. // 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 min The minimum bounds of the shape in local-space coordinates
* @param max The maximum 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 xAxis(m_points[0].x(), m_points[1].x(), m_points[2].x());
const vec3 yAxis(mPoints[0].y(), mPoints[1].y(), mPoints[2].y()); const vec3 yAxis(m_points[0].y(), m_points[1].y(), m_points[2].y());
const vec3 zAxis(mPoints[0].z(), mPoints[1].z(), mPoints[2].z()); const vec3 zAxis(m_points[0].z(), m_points[1].z(), m_points[2].z());
min.setValue(xAxis.getMin(), yAxis.getMin(), zAxis.getMin()); min.setValue(xAxis.getMin(), yAxis.getMin(), zAxis.getMin());
max.setValue(xAxis.getMax(), yAxis.getMax(), zAxis.getMax()); 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 // 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; m_points[0] = (m_points[0] / m_scaling) * scaling;
mPoints[1] = (mPoints[1] / m_scaling) * scaling; m_points[1] = (m_points[1] / m_scaling) * scaling;
mPoints[2] = (mPoints[2] / m_scaling) * scaling; m_points[2] = (m_points[2] / m_scaling) * scaling;
CollisionShape::setLocalScaling(scaling); CollisionShape::setLocalScaling(scaling);
} }
@ -147,7 +124,7 @@ inline void TriangleShape::setLocalScaling(const vec3& scaling) {
* coordinates * coordinates
* @param mass Mass to use to compute the inertia tensor of the collision shape * @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(); tensor.setZero();
} }
@ -157,11 +134,11 @@ inline void TriangleShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, flo
* computed in world-space coordinates * computed in world-space coordinates
* @param transform etk::Transform3D used to compute the AABB of the collision shape * @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 worldPoint1 = transform * m_points[0];
const vec3 worldPoint2 = transform * mPoints[1]; const vec3 worldPoint2 = transform * m_points[1];
const vec3 worldPoint3 = transform * mPoints[2]; const vec3 worldPoint3 = transform * m_points[2];
const vec3 xAxis(worldPoint1.x(), worldPoint2.x(), worldPoint3.x()); const vec3 xAxis(worldPoint1.x(), worldPoint2.x(), worldPoint3.x());
const vec3 yAxis(worldPoint1.y(), worldPoint2.y(), worldPoint3.y()); 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 // 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 false;
} }
// Return the raycast test type (front, back, front-back) // Return the raycast test type (front, back, front-back)
inline TriangleRaycastSide TriangleShape::getRaycastTestType() const { TriangleRaycastSide TriangleShape::getRaycastTestType() const {
return m_raycastTestType; return m_raycastTestType;
} }
@ -184,7 +161,7 @@ inline TriangleRaycastSide TriangleShape::getRaycastTestType() const {
/** /**
* @param testType Raycast test type for the triangle (front, back, front-back) * @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; 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 * @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); assert(index >= 0 && index < 3);
return mPoints[index]; return m_points[index];
} }
} }

View File

@ -5,120 +5,68 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/constraint/Joint.hpp> #include <ephysics/constraint/Joint.hpp>
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
namespace ephysics { namespace ephysics {
/**
// Structure BallAndSocketJointInfo * @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.
* This structure 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 {
*/ public :
struct BallAndSocketJointInfo : public JointInfo { vec3 m_anchorPointWorldSpace; //!< Anchor point (in world-space coordinates)
/**
public : * @brief Constructor
* @param _rigidBody1 Pointer to the first body of the joint
// -------------------- Attributes -------------------- // * @param _rigidBody2 Pointer to the second body of the joint
* @param _initAnchorPointWorldSpace The anchor point in world-space coordinates
/// Anchor point (in world-space coordinates) */
vec3 m_anchorPointWorldSpace; BallAndSocketJointInfo(RigidBody* _rigidBody1,
RigidBody* _rigidBody2,
/// Constructor const vec3& _initAnchorPointWorldSpace):
/** JointInfo(_rigidBody1, _rigidBody2, BALLSOCKETJOINT),
* @param rigidBody1 Pointer to the first body of the joint m_anchorPointWorldSpace(_initAnchorPointWorldSpace) {
* @param rigidBody2 Pointer to the second body of the joint
* @param initAnchorPointWorldSpace The anchor point in world-space }
* coordinates };
*/ /**
BallAndSocketJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2, * @brief Represents a ball-and-socket joint that allows arbitrary rotation
const vec3& initAnchorPointWorldSpace) * between two bodies. This joint has three degrees of freedom. It can be used to
: JointInfo(rigidBody1, rigidBody2, BALLSOCKETJOINT), * create a chain of bodies for instance.
m_anchorPointWorldSpace(initAnchorPointWorldSpace) {} */
}; class BallAndSocketJoint : public Joint {
private:
// Class BallAndSocketJoint 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)
* This class represents a ball-and-socket joint that allows arbitrary rotation vec3 m_localAnchorPointBody2; //!< Anchor point of body 2 (in local-space coordinates of body 2)
* between two bodies. This joint has three degrees of freedom. It can be used to vec3 m_r1World; //!< Vector from center of body 2 to anchor point in world-space
* create a chain of bodies for instance. 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)
class BallAndSocketJoint : public Joint { etk::Matrix3x3 m_i2; //!< Inertia tensor of body 2 (in world-space coordinates)
vec3 m_biasVector; //!< Bias vector for the constraint
private : etk::Matrix3x3 m_inverseMassMatrix; //!< Inverse mass matrix K=JM^-1J^-t of the constraint
vec3 m_impulse; //!< Accumulated impulse
// -------------------- Constants -------------------- // /// Private copy-constructor
BallAndSocketJoint(const BallAndSocketJoint& constraint);
// Beta value for the bias factor of position correction /// Private assignment operator
static const float BETA; BallAndSocketJoint& operator=(const BallAndSocketJoint& constraint);
/// Return the number of bytes used by the joint
// -------------------- Attributes -------------------- // virtual size_t getSizeInBytes() const {
return sizeof(BallAndSocketJoint);
/// Anchor point of body 1 (in local-space coordinates of body 1) }
vec3 m_localAnchorPointBody1; /// Initialize before solving the constraint
virtual void initBeforeSolve(const ConstraintSolverData& constraintSolverData);
/// Anchor point of body 2 (in local-space coordinates of body 2) /// Warm start the constraint (apply the previous impulse at the beginning of the step)
vec3 m_localAnchorPointBody2; virtual void warmstart(const ConstraintSolverData& constraintSolverData);
/// Solve the velocity constraint
/// Vector from center of body 2 to anchor point in world-space virtual void solveVelocityConstraint(const ConstraintSolverData& constraintSolverData);
vec3 m_r1World; /// Solve the position constraint (for position error correction)
virtual void solvePositionConstraint(const ConstraintSolverData& constraintSolverData);
/// Vector from center of body 2 to anchor point in world-space public:
vec3 m_r2World; /// Constructor
BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo);
/// Inertia tensor of body 1 (in world-space coordinates) /// Destructor
etk::Matrix3x3 m_i1; virtual ~BallAndSocketJoint();
};
/// 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 -------------------- //
/// 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;
/// 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 -------------------- //
/// 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);
}
} }

View File

@ -14,22 +14,22 @@ using namespace std;
// Constructor // Constructor
ContactPoint::ContactPoint(const ContactPointInfo& contactInfo) ContactPoint::ContactPoint(const ContactPointInfo& contactInfo)
: m_body1(contactInfo.shape1->getBody()), m_body2(contactInfo.shape2->getBody()), : m_body1(contactInfo.shape1->getBody()), m_body2(contactInfo.shape2->getBody()),
mNormal(contactInfo.normal), m_normal(contactInfo.normal),
mPenetrationDepth(contactInfo.penetrationDepth), m_penetrationDepth(contactInfo.penetrationDepth),
mLocalPointOnBody1(contactInfo.localPoint1), m_localPointOnBody1(contactInfo.localPoint1),
mLocalPointOnBody2(contactInfo.localPoint2), m_localPointOnBody2(contactInfo.localPoint2),
m_worldPointOnBody1(contactInfo.shape1->getBody()->getTransform() * m_worldPointOnBody1(contactInfo.shape1->getBody()->getTransform() *
contactInfo.shape1->getLocalToBodyTransform() * contactInfo.shape1->getLocalToBodyTransform() *
contactInfo.localPoint1), contactInfo.localPoint1),
m_worldPointOnBody2(contactInfo.shape2->getBody()->getTransform() * m_worldPointOnBody2(contactInfo.shape2->getBody()->getTransform() *
contactInfo.shape2->getLocalToBodyTransform() * contactInfo.shape2->getLocalToBodyTransform() *
contactInfo.localPoint2), contactInfo.localPoint2),
mIsRestingContact(false) { m_isRestingContact(false) {
m_frictionVectors[0] = vec3(0, 0, 0); m_frictionVectors[0] = vec3(0, 0, 0);
m_frictionVectors[1] = vec3(0, 0, 0); m_frictionVectors[1] = vec3(0, 0, 0);
assert(mPenetrationDepth > 0.0); assert(m_penetrationDepth > 0.0);
} }

View File

@ -5,347 +5,269 @@
*/ */
#pragma once #pragma once
// Libraries
#include <ephysics/body/CollisionBody.hpp> #include <ephysics/body/CollisionBody.hpp>
#include <ephysics/collision/CollisionShapeInfo.hpp> #include <ephysics/collision/CollisionShapeInfo.hpp>
#include <ephysics/configuration.hpp> #include <ephysics/configuration.hpp>
#include <ephysics/mathematics/mathematics.hpp> #include <ephysics/mathematics/mathematics.hpp>
#include <ephysics/configuration.hpp> #include <ephysics/configuration.hpp>
/// ReactPhysics3D namespace
namespace ephysics { namespace ephysics {
// Structure ContactPointInfo /**
/** * @brief This structure contains informations about a collision contact
* This structure contains informations about a collision contact * computed during the narrow-phase collision detection. Those
* computed during the narrow-phase collision detection. Those * informations are used to compute the contact set for a contact
* informations are used to compute the contact set for a contact * between two bodies.
* between two bodies. */
*/ struct ContactPointInfo {
struct ContactPointInfo { public:
/// 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;
/// 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) {
}
};
private: /**
* @brief This class represents a collision contact point between two
// -------------------- Methods -------------------- // * bodies in the physics engine.
*/
public: class ContactPoint {
private :
// -------------------- Attributes -------------------- // CollisionBody* m_body1; //!< First rigid body of the contact
CollisionBody* m_body2; //!< Second rigid body of the contact
/// First proxy shape of the contact const vec3 m_normal; //!< Normalized normal vector of the contact (from body1 toward body2) in world space
ProxyShape* shape1; float m_penetrationDepth; //!< Penetration depth
const vec3 m_localPointOnBody1; //!< Contact point on body 1 in local space of body 1
/// Second proxy shape of the contact const vec3 m_localPointOnBody2; //!< Contact point on body 2 in local space of body 2
ProxyShape* shape2; vec3 m_worldPointOnBody1; //!< Contact point on body 1 in world space
vec3 m_worldPointOnBody2; //!< Contact point on body 2 in world space
/// First collision shape bool m_isRestingContact; //!< True if the contact is a resting contact (exists for more than one time step)
const CollisionShape* collisionShape1; vec3 m_frictionVectors[2]; //!< Two orthogonal vectors that span the tangential friction plane
float m_penetrationImpulse; //!< Cached penetration impulse
/// Second collision shape float m_frictionImpulse1; //!< Cached first friction impulse
const CollisionShape* collisionShape2; float m_frictionImpulse2; //!< Cached second friction impulse
vec3 m_rollingResistanceImpulse; //!< Cached rolling resistance impulse
/// Normalized normal vector of the collision contact in world space /// Private copy-constructor
vec3 normal; ContactPoint(const ContactPoint& contact) = delete;
/// Private assignment operator
/// Penetration depth of the contact ContactPoint& operator=(const ContactPoint& contact) = delete;
float penetrationDepth; public :
/// Constructor
/// Contact point of body 1 in local space of body 1 ContactPoint(const ContactPointInfo& contactInfo);
vec3 localPoint1; /// Destructor
~ContactPoint();
/// Contact point of body 2 in local space of body 2 /// Return the reference to the body 1
vec3 localPoint2; CollisionBody* getBody1() const;
/// Return the reference to the body 2
// -------------------- Methods -------------------- // CollisionBody* getBody2() const;
/// Return the normal vector of the contact
/// Constructor vec3 getNormal() const;
ContactPointInfo(ProxyShape* proxyShape1, ProxyShape* proxyShape2, const CollisionShape* collShape1, /// Set the penetration depth of the contact
const CollisionShape* collShape2, const vec3& normal, float penetrationDepth, void setPenetrationDepth(float _penetrationDepth);
const vec3& localPoint1, const vec3& localPoint2) /// Return the contact local point on body 1
: shape1(proxyShape1), shape2(proxyShape2), collisionShape1(collShape1), collisionShape2(collShape2), vec3 getLocalPointOnBody1() const;
normal(normal), penetrationDepth(penetrationDepth), localPoint1(localPoint1), /// Return the contact local point on body 2
localPoint2(localPoint2) { 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;
// Class ContactPoint /// Return the cached penetration impulse
/** float getPenetrationImpulse() const;
* This class represents a collision contact point between two /// Return the cached first friction impulse
* bodies in the physics engine. float getFrictionImpulse1() const;
*/ /// Return the cached second friction impulse
class ContactPoint { float getFrictionImpulse2() const;
/// Return the cached rolling resistance impulse
private : vec3 getRollingResistanceImpulse() const;
/// Set the cached penetration impulse
// -------------------- Attributes -------------------- // void setPenetrationImpulse(float _impulse);
/// Set the first cached friction impulse
/// First rigid body of the contact void setFrictionImpulse1(float _impulse);
CollisionBody* m_body1; /// Set the second cached friction impulse
void setFrictionImpulse2(float _impulse);
/// Second rigid body of the contact /// Set the cached rolling resistance impulse
CollisionBody* m_body2; void setRollingResistanceImpulse(const vec3& _impulse);
/// Set the contact world point on body 1
/// Normalized normal vector of the contact (from body1 toward body2) in world space void setWorldPointOnBody1(const vec3& _worldPoint);
const vec3 mNormal; /// Set the contact world point on body 2
void setWorldPointOnBody2(const vec3& _worldPoint);
/// Penetration depth /// Return true if the contact is a resting contact
float mPenetrationDepth; bool getIsRestingContact() const;
/// Set the m_isRestingContact variable
/// Contact point on body 1 in local space of body 1 void setIsRestingContact(bool _isRestingContact);
const vec3 mLocalPointOnBody1; /// Get the first friction vector
vec3 getFrictionVector1() const;
/// Contact point on body 2 in local space of body 2 /// Set the first friction vector
const vec3 mLocalPointOnBody2; void setFrictionVector1(const vec3& _frictionVector1);
/// Get the second friction vector
/// Contact point on body 1 in world space vec3 getFrictionvec2() const;
vec3 m_worldPointOnBody1; /// Set the second friction vector
void setFrictionvec2(const vec3& _frictionvec2);
/// Contact point on body 2 in world space /// Return the penetration depth
vec3 m_worldPointOnBody2; float getPenetrationDepth() const;
/// Return the number of bytes used by the contact point
/// True if the contact is a resting contact (exists for more than one time step) size_t getSizeInBytes() const;
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 -------------------- //
/// Private copy-constructor
ContactPoint(const ContactPoint& contact);
/// Private assignment operator
ContactPoint& operator=(const ContactPoint& contact);
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);
/// 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);
/// Set the first cached friction impulse
void setFrictionImpulse1(float impulse);
/// Set the second cached friction impulse
void setFrictionImpulse2(float impulse);
/// Set the cached rolling resistance impulse
void setRollingResistanceImpulse(const vec3& impulse);
/// Set the contact world point on body 1
void setWorldPointOnBody1(const vec3& worldPoint);
/// Set the contact world point on body 2
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);
/// Get the first friction vector
vec3 getFrictionVector1() const;
/// Set the first friction vector
void setFrictionVector1(const vec3& frictionVector1);
/// Get the second friction vector
vec3 getFrictionvec2() const;
/// Set the second friction vector
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 // Return the reference to the body 1
inline CollisionBody* ContactPoint::getBody1() const { CollisionBody* ContactPoint::getBody1() const {
return m_body1; return m_body1;
} }
// Return the reference to the body 2 // Return the reference to the body 2
inline CollisionBody* ContactPoint::getBody2() const { CollisionBody* ContactPoint::getBody2() const {
return m_body2; return m_body2;
} }
// Return the normal vector of the contact // Return the normal vector of the contact
inline vec3 ContactPoint::getNormal() const { vec3 ContactPoint::getNormal() const {
return mNormal; return m_normal;
} }
// Set the penetration depth of the contact // Set the penetration depth of the contact
inline void ContactPoint::setPenetrationDepth(float penetrationDepth) { void ContactPoint::setPenetrationDepth(float penetrationDepth) {
this->mPenetrationDepth = penetrationDepth; this->m_penetrationDepth = penetrationDepth;
} }
// Return the contact point on body 1 // Return the contact point on body 1
inline vec3 ContactPoint::getLocalPointOnBody1() const { vec3 ContactPoint::getLocalPointOnBody1() const {
return mLocalPointOnBody1; return m_localPointOnBody1;
} }
// Return the contact point on body 2 // Return the contact point on body 2
inline vec3 ContactPoint::getLocalPointOnBody2() const { vec3 ContactPoint::getLocalPointOnBody2() const {
return mLocalPointOnBody2; return m_localPointOnBody2;
} }
// Return the contact world point on body 1 // Return the contact world point on body 1
inline vec3 ContactPoint::getWorldPointOnBody1() const { vec3 ContactPoint::getWorldPointOnBody1() const {
return m_worldPointOnBody1; return m_worldPointOnBody1;
} }
// Return the contact world point on body 2 // Return the contact world point on body 2
inline vec3 ContactPoint::getWorldPointOnBody2() const { vec3 ContactPoint::getWorldPointOnBody2() const {
return m_worldPointOnBody2; return m_worldPointOnBody2;
} }
// Return the cached penetration impulse // Return the cached penetration impulse
inline float ContactPoint::getPenetrationImpulse() const { float ContactPoint::getPenetrationImpulse() const {
return mPenetrationImpulse; return m_penetrationImpulse;
} }
// Return the cached first friction impulse // Return the cached first friction impulse
inline float ContactPoint::getFrictionImpulse1() const { float ContactPoint::getFrictionImpulse1() const {
return m_frictionImpulse1; return m_frictionImpulse1;
} }
// Return the cached second friction impulse // Return the cached second friction impulse
inline float ContactPoint::getFrictionImpulse2() const { float ContactPoint::getFrictionImpulse2() const {
return m_frictionImpulse2; return m_frictionImpulse2;
} }
// Return the cached rolling resistance impulse // Return the cached rolling resistance impulse
inline vec3 ContactPoint::getRollingResistanceImpulse() const { vec3 ContactPoint::getRollingResistanceImpulse() const {
return m_rollingResistanceImpulse; return m_rollingResistanceImpulse;
} }
// Set the cached penetration impulse // Set the cached penetration impulse
inline void ContactPoint::setPenetrationImpulse(float impulse) { void ContactPoint::setPenetrationImpulse(float impulse) {
mPenetrationImpulse = impulse; m_penetrationImpulse = impulse;
} }
// Set the first cached friction impulse // Set the first cached friction impulse
inline void ContactPoint::setFrictionImpulse1(float impulse) { void ContactPoint::setFrictionImpulse1(float impulse) {
m_frictionImpulse1 = impulse; m_frictionImpulse1 = impulse;
} }
// Set the second cached friction impulse // Set the second cached friction impulse
inline void ContactPoint::setFrictionImpulse2(float impulse) { void ContactPoint::setFrictionImpulse2(float impulse) {
m_frictionImpulse2 = impulse; m_frictionImpulse2 = impulse;
} }
// Set the cached rolling resistance impulse // Set the cached rolling resistance impulse
inline void ContactPoint::setRollingResistanceImpulse(const vec3& impulse) { void ContactPoint::setRollingResistanceImpulse(const vec3& impulse) {
m_rollingResistanceImpulse = impulse; m_rollingResistanceImpulse = impulse;
} }
// Set the contact world point on body 1 // Set the contact world point on body 1
inline void ContactPoint::setWorldPointOnBody1(const vec3& worldPoint) { void ContactPoint::setWorldPointOnBody1(const vec3& worldPoint) {
m_worldPointOnBody1 = worldPoint; m_worldPointOnBody1 = worldPoint;
} }
// Set the contact world point on body 2 // Set the contact world point on body 2
inline void ContactPoint::setWorldPointOnBody2(const vec3& worldPoint) { void ContactPoint::setWorldPointOnBody2(const vec3& worldPoint) {
m_worldPointOnBody2 = worldPoint; m_worldPointOnBody2 = worldPoint;
} }
// Return true if the contact is a resting contact // Return true if the contact is a resting contact
inline bool ContactPoint::getIsRestingContact() const { bool ContactPoint::getIsRestingContact() const {
return mIsRestingContact; return m_isRestingContact;
} }
// Set the mIsRestingContact variable // Set the m_isRestingContact variable
inline void ContactPoint::setIsRestingContact(bool isRestingContact) { void ContactPoint::setIsRestingContact(bool isRestingContact) {
mIsRestingContact = isRestingContact; m_isRestingContact = isRestingContact;
} }
// Get the first friction vector // Get the first friction vector
inline vec3 ContactPoint::getFrictionVector1() const { vec3 ContactPoint::getFrictionVector1() const {
return m_frictionVectors[0]; return m_frictionVectors[0];
} }
// Set the first friction vector // Set the first friction vector
inline void ContactPoint::setFrictionVector1(const vec3& frictionVector1) { void ContactPoint::setFrictionVector1(const vec3& frictionVector1) {
m_frictionVectors[0] = frictionVector1; m_frictionVectors[0] = frictionVector1;
} }
// Get the second friction vector // Get the second friction vector
inline vec3 ContactPoint::getFrictionvec2() const { vec3 ContactPoint::getFrictionvec2() const {
return m_frictionVectors[1]; return m_frictionVectors[1];
} }
// Set the second friction vector // Set the second friction vector
inline void ContactPoint::setFrictionvec2(const vec3& frictionvec2) { void ContactPoint::setFrictionvec2(const vec3& frictionvec2) {
m_frictionVectors[1] = frictionvec2; m_frictionVectors[1] = frictionvec2;
} }
// Return the penetration depth of the contact // Return the penetration depth of the contact
inline float ContactPoint::getPenetrationDepth() const { float ContactPoint::getPenetrationDepth() const {
return mPenetrationDepth; return m_penetrationDepth;
} }
// Return the number of bytes used by the contact point // Return the number of bytes used by the contact point
inline size_t ContactPoint::getSizeInBytes() const { size_t ContactPoint::getSizeInBytes() const {
return sizeof(ContactPoint); return sizeof(ContactPoint);
} }

View File

@ -128,7 +128,7 @@ class FixedJoint : public Joint {
}; };
// Return the number of bytes used by the joint // Return the number of bytes used by the joint
inline size_t FixedJoint::getSizeInBytes() const { size_t FixedJoint::getSizeInBytes() const {
return sizeof(FixedJoint); return sizeof(FixedJoint);
} }

View File

@ -321,7 +321,7 @@ class HingeJoint : public Joint {
/** /**
* @return True if the limits of the joint are enabled and false otherwise * @return True if the limits of the joint are enabled and false otherwise
*/ */
inline bool HingeJoint::isLimitEnabled() const { bool HingeJoint::isLimitEnabled() const {
return mIsLimitEnabled; return mIsLimitEnabled;
} }
@ -329,7 +329,7 @@ inline bool HingeJoint::isLimitEnabled() const {
/** /**
* @return True if the motor of joint is enabled and false otherwise * @return True if the motor of joint is enabled and false otherwise
*/ */
inline bool HingeJoint::isMotorEnabled() const { bool HingeJoint::isMotorEnabled() const {
return mIsMotorEnabled; return mIsMotorEnabled;
} }
@ -337,7 +337,7 @@ inline bool HingeJoint::isMotorEnabled() const {
/** /**
* @return The minimum limit angle of the joint (in radian) * @return The minimum limit angle of the joint (in radian)
*/ */
inline float HingeJoint::getMinAngleLimit() const { float HingeJoint::getMinAngleLimit() const {
return mLowerLimit; return mLowerLimit;
} }
@ -345,7 +345,7 @@ inline float HingeJoint::getMinAngleLimit() const {
/** /**
* @return The maximum limit angle of the joint (in radian) * @return The maximum limit angle of the joint (in radian)
*/ */
inline float HingeJoint::getMaxAngleLimit() const { float HingeJoint::getMaxAngleLimit() const {
return mUpperLimit; return mUpperLimit;
} }
@ -353,7 +353,7 @@ inline float HingeJoint::getMaxAngleLimit() const {
/** /**
* @return The current speed of the joint motor (in radian per second) * @return The current speed of the joint motor (in radian per second)
*/ */
inline float HingeJoint::getMotorSpeed() const { float HingeJoint::getMotorSpeed() const {
return mMotorSpeed; return mMotorSpeed;
} }
@ -361,7 +361,7 @@ inline float HingeJoint::getMotorSpeed() const {
/** /**
* @return The maximum torque of the joint motor (in Newtons) * @return The maximum torque of the joint motor (in Newtons)
*/ */
inline float HingeJoint::getMaxMotorTorque() const { float HingeJoint::getMaxMotorTorque() const {
return mMaxMotorTorque; return mMaxMotorTorque;
} }
@ -370,12 +370,12 @@ inline float HingeJoint::getMaxMotorTorque() const {
* @param timeStep The current time step (in seconds) * @param timeStep The current time step (in seconds)
* @return The int32_tensity of the current torque (in Newtons) of the joint motor * @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 m_impulseMotor / timeStep;
} }
// Return the number of bytes used by the joint // Return the number of bytes used by the joint
inline size_t HingeJoint::getSizeInBytes() const { size_t HingeJoint::getSizeInBytes() const {
return sizeof(HingeJoint); return sizeof(HingeJoint);
} }

View File

@ -185,7 +185,7 @@ class Joint {
/** /**
* @return The first body involved in the joint * @return The first body involved in the joint
*/ */
inline RigidBody* Joint::getBody1() const { RigidBody* Joint::getBody1() const {
return m_body1; return m_body1;
} }
@ -193,7 +193,7 @@ inline RigidBody* Joint::getBody1() const {
/** /**
* @return The second body involved in the joint * @return The second body involved in the joint
*/ */
inline RigidBody* Joint::getBody2() const { RigidBody* Joint::getBody2() const {
return m_body2; return m_body2;
} }
@ -201,7 +201,7 @@ inline RigidBody* Joint::getBody2() const {
/** /**
* @return True if the joint is active * @return True if the joint is active
*/ */
inline bool Joint::isActive() const { bool Joint::isActive() const {
return (m_body1->isActive() && m_body2->isActive()); return (m_body1->isActive() && m_body2->isActive());
} }
@ -209,7 +209,7 @@ inline bool Joint::isActive() const {
/** /**
* @return The type of the joint * @return The type of the joint
*/ */
inline JointType Joint::getType() const { JointType Joint::getType() const {
return m_type; 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 * @return True if the collision is enabled between the two bodies of the joint
* is enabled and false otherwise * is enabled and false otherwise
*/ */
inline bool Joint::isCollisionEnabled() const { bool Joint::isCollisionEnabled() const {
return m_isCollisionEnabled; return m_isCollisionEnabled;
} }
// Return true if the joint has already been added int32_to an island // 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; return m_isAlreadyInIsland;
} }

View File

@ -322,7 +322,7 @@ class SliderJoint : public Joint {
/** /**
* @return True if the joint limits are enabled * @return True if the joint limits are enabled
*/ */
inline bool SliderJoint::isLimitEnabled() const { bool SliderJoint::isLimitEnabled() const {
return mIsLimitEnabled; return mIsLimitEnabled;
} }
@ -330,7 +330,7 @@ inline bool SliderJoint::isLimitEnabled() const {
/** /**
* @return True if the joint motor is enabled * @return True if the joint motor is enabled
*/ */
inline bool SliderJoint::isMotorEnabled() const { bool SliderJoint::isMotorEnabled() const {
return mIsMotorEnabled; return mIsMotorEnabled;
} }
@ -338,7 +338,7 @@ inline bool SliderJoint::isMotorEnabled() const {
/** /**
* @return The minimum translation limit of the joint (in meters) * @return The minimum translation limit of the joint (in meters)
*/ */
inline float SliderJoint::getMinTranslationLimit() const { float SliderJoint::getMinTranslationLimit() const {
return mLowerLimit; return mLowerLimit;
} }
@ -346,7 +346,7 @@ inline float SliderJoint::getMinTranslationLimit() const {
/** /**
* @return The maximum translation limit of the joint (in meters) * @return The maximum translation limit of the joint (in meters)
*/ */
inline float SliderJoint::getMaxTranslationLimit() const { float SliderJoint::getMaxTranslationLimit() const {
return mUpperLimit; return mUpperLimit;
} }
@ -354,7 +354,7 @@ inline float SliderJoint::getMaxTranslationLimit() const {
/** /**
* @return The current motor speed of the joint (in meters per second) * @return The current motor speed of the joint (in meters per second)
*/ */
inline float SliderJoint::getMotorSpeed() const { float SliderJoint::getMotorSpeed() const {
return mMotorSpeed; return mMotorSpeed;
} }
@ -362,7 +362,7 @@ inline float SliderJoint::getMotorSpeed() const {
/** /**
* @return The maximum force of the joint motor (in Newton x meters) * @return The maximum force of the joint motor (in Newton x meters)
*/ */
inline float SliderJoint::getMaxMotorForce() const { float SliderJoint::getMaxMotorForce() const {
return mMaxMotorForce; return mMaxMotorForce;
} }
@ -371,12 +371,12 @@ inline float SliderJoint::getMaxMotorForce() const {
* @param timeStep Time step (in seconds) * @param timeStep Time step (in seconds)
* @return The current force of the joint motor (in Newton x meters) * @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 m_impulseMotor / timeStep;
} }
// Return the number of bytes used by the joint // Return the number of bytes used by the joint
inline size_t SliderJoint::getSizeInBytes() const { size_t SliderJoint::getSizeInBytes() const {
return sizeof(SliderJoint); return sizeof(SliderJoint);
} }

View File

@ -84,12 +84,12 @@ namespace ephysics {
*/ */
void raycast(const Ray& _ray, void raycast(const Ray& _ray,
RaycastCallback* _raycastCallback, RaycastCallback* _raycastCallback,
unsigned short _raycastWithCategoryMaskBitss = 0xFFFF) const { unsigned short _raycastWithCategoryMaskBits = 0xFFFF) const {
m_collisionDetection.raycast(_raycastCallback, _ray, _raycastWithCategoryMaskBits); m_collisionDetection.raycast(_raycastCallback, _ray, _raycastWithCategoryMaskBits);
} }
/// Test if the AABBs of two bodies overlap /// Test if the AABBs of two bodies overlap
bool testAABBOverlap(const CollisionBody* body1, bool testAABBOverlap(const CollisionBody* _body1,
const CollisionBody* body2) const; const CollisionBody* _body2) const;
/** /**
* @brief Test if the AABBs of two proxy shapes overlap * @brief Test if the AABBs of two proxy shapes overlap
* @param _shape1 Pointer to the first proxy shape to test * @param _shape1 Pointer to the first proxy shape to test
@ -97,26 +97,26 @@ namespace ephysics {
*/ */
bool testAABBOverlap(const ProxyShape* _shape1, bool testAABBOverlap(const ProxyShape* _shape1,
const ProxyShape* _shape2) const { 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 /// Test and report collisions between a given shape and all the others
/// shapes of the world /// shapes of the world
virtual void testCollision(const ProxyShape* shape, virtual void testCollision(const ProxyShape* _shape,
CollisionCallback* callback); CollisionCallback* _callback);
/// Test and report collisions between two given shapes /// Test and report collisions between two given shapes
virtual void testCollision(const ProxyShape* shape1, virtual void testCollision(const ProxyShape* _shape1,
const ProxyShape* shape2, const ProxyShape* _shape2,
CollisionCallback* callback); CollisionCallback* _callback);
/// Test and report collisions between a body and all the others bodies of the /// Test and report collisions between a body and all the others bodies of the
/// world /// world
virtual void testCollision(const CollisionBody* body, virtual void testCollision(const CollisionBody* _body,
CollisionCallback* callback); CollisionCallback* _callback);
/// Test and report collisions between two bodies /// Test and report collisions between two bodies
virtual void testCollision(const CollisionBody* body1, virtual void testCollision(const CollisionBody* _body1,
const CollisionBody* body2, const CollisionBody* _body2,
CollisionCallback* callback); CollisionCallback* _callback);
/// Test and report collisions between all shapes of the world /// 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 CollisionDetection;
friend class CollisionBody; friend class CollisionBody;
friend class RigidBody; friend class RigidBody;

View File

@ -131,7 +131,7 @@ namespace ephysics {
}; };
// Set the constrained velocities arrays // Set the constrained velocities arrays
inline void ConstraintSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities, void ConstraintSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
vec3* constrainedAngularVelocities) { vec3* constrainedAngularVelocities) {
assert(constrainedLinearVelocities != NULL); assert(constrainedLinearVelocities != NULL);
assert(constrainedAngularVelocities != NULL); assert(constrainedAngularVelocities != NULL);
@ -140,7 +140,7 @@ inline void ConstraintSolver::setConstrainedVelocitiesArrays(vec3* constrainedLi
} }
// Set the constrained positions/orientations arrays // Set the constrained positions/orientations arrays
inline void ConstraintSolver::setConstrainedPositionsArrays(vec3* constrainedPositions, void ConstraintSolver::setConstrainedPositionsArrays(vec3* constrainedPositions,
etk::Quaternion* constrainedOrientations) { etk::Quaternion* constrainedOrientations) {
assert(constrainedPositions != NULL); assert(constrainedPositions != NULL);
assert(constrainedOrientations != NULL); assert(constrainedOrientations != NULL);

View File

@ -499,7 +499,7 @@ void ContactSolver::solve() {
ContactManifoldSolver& contactManifold = m_contactConstraints[c]; ContactManifoldSolver& contactManifold = m_contactConstraints[c];
float sumPenetrationImpulse = 0.0; float sum_penetrationImpulse = 0.0;
// Get the constrained velocities // Get the constrained velocities
const vec3& v1 = m_linearVelocities[contactManifold.indexBody1]; const vec3& v1 = m_linearVelocities[contactManifold.indexBody1];
@ -545,7 +545,7 @@ void ContactSolver::solve() {
// Apply the impulse to the bodies of the constraint // Apply the impulse to the bodies of the constraint
applyImpulse(impulsePenetration, contactManifold); applyImpulse(impulsePenetration, contactManifold);
sumPenetrationImpulse += contactPoint.penetrationImpulse; sum_penetrationImpulse += contactPoint.penetrationImpulse;
// If the split impulse position correction is active // If the split impulse position correction is active
if (m_isSplitImpulseActive) { if (m_isSplitImpulseActive) {
@ -661,7 +661,7 @@ void ContactSolver::solve() {
// Compute the Lagrange multiplier lambda // Compute the Lagrange multiplier lambda
float deltaLambda = -Jv * contactManifold.inverseFriction1Mass; float deltaLambda = -Jv * contactManifold.inverseFriction1Mass;
float frictionLimit = contactManifold.frictionCoefficient * sumPenetrationImpulse; float frictionLimit = contactManifold.frictionCoefficient * sum_penetrationImpulse;
lambdaTemp = contactManifold.friction1Impulse; lambdaTemp = contactManifold.friction1Impulse;
contactManifold.friction1Impulse = std::max(-frictionLimit, contactManifold.friction1Impulse = std::max(-frictionLimit,
std::min(contactManifold.friction1Impulse + std::min(contactManifold.friction1Impulse +
@ -688,7 +688,7 @@ void ContactSolver::solve() {
// Compute the Lagrange multiplier lambda // Compute the Lagrange multiplier lambda
deltaLambda = -Jv * contactManifold.inverseFriction2Mass; deltaLambda = -Jv * contactManifold.inverseFriction2Mass;
frictionLimit = contactManifold.frictionCoefficient * sumPenetrationImpulse; frictionLimit = contactManifold.frictionCoefficient * sum_penetrationImpulse;
lambdaTemp = contactManifold.friction2Impulse; lambdaTemp = contactManifold.friction2Impulse;
contactManifold.friction2Impulse = std::max(-frictionLimit, contactManifold.friction2Impulse = std::max(-frictionLimit,
std::min(contactManifold.friction2Impulse + std::min(contactManifold.friction2Impulse +
@ -713,7 +713,7 @@ void ContactSolver::solve() {
Jv = deltaV.dot(contactManifold.normal); Jv = deltaV.dot(contactManifold.normal);
deltaLambda = -Jv * (contactManifold.inverseTwistFrictionMass); deltaLambda = -Jv * (contactManifold.inverseTwistFrictionMass);
frictionLimit = contactManifold.frictionCoefficient * sumPenetrationImpulse; frictionLimit = contactManifold.frictionCoefficient * sum_penetrationImpulse;
lambdaTemp = contactManifold.frictionTwistImpulse; lambdaTemp = contactManifold.frictionTwistImpulse;
contactManifold.frictionTwistImpulse = std::max(-frictionLimit, contactManifold.frictionTwistImpulse = std::max(-frictionLimit,
std::min(contactManifold.frictionTwistImpulse std::min(contactManifold.frictionTwistImpulse
@ -740,7 +740,7 @@ void ContactSolver::solve() {
// Compute the Lagrange multiplier lambda // Compute the Lagrange multiplier lambda
vec3 deltaLambdaRolling = contactManifold.inverseRollingResistance * (-JvRolling); vec3 deltaLambdaRolling = contactManifold.inverseRollingResistance * (-JvRolling);
float rollingLimit = contactManifold.rollingResistanceFactor * sumPenetrationImpulse; float rollingLimit = contactManifold.rollingResistanceFactor * sum_penetrationImpulse;
vec3 lambdaTempRolling = contactManifold.rollingResistanceImpulse; vec3 lambdaTempRolling = contactManifold.rollingResistanceImpulse;
contactManifold.rollingResistanceImpulse = clamp(contactManifold.rollingResistanceImpulse + deltaLambdaRolling, contactManifold.rollingResistanceImpulse = clamp(contactManifold.rollingResistanceImpulse + deltaLambdaRolling,
rollingLimit); rollingLimit);

View File

@ -238,7 +238,7 @@ namespace ephysics {
}; };
// Set the split velocities arrays // Set the split velocities arrays
inline void ContactSolver::setSplitVelocitiesArrays(vec3* splitLinearVelocities, void ContactSolver::setSplitVelocitiesArrays(vec3* splitLinearVelocities,
vec3* splitAngularVelocities) { vec3* splitAngularVelocities) {
assert(splitLinearVelocities != NULL); assert(splitLinearVelocities != NULL);
assert(splitAngularVelocities != NULL); assert(splitAngularVelocities != NULL);
@ -247,7 +247,7 @@ inline void ContactSolver::setSplitVelocitiesArrays(vec3* splitLinearVelocities,
} }
// Set the constrained velocities arrays // Set the constrained velocities arrays
inline void ContactSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities, void ContactSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
vec3* constrainedAngularVelocities) { vec3* constrainedAngularVelocities) {
assert(constrainedLinearVelocities != NULL); assert(constrainedLinearVelocities != NULL);
assert(constrainedAngularVelocities != 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 // 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; return m_isSplitImpulseActive;
} }
// Activate or Deactivate the split impulses for contacts // Activate or Deactivate the split impulses for contacts
inline void ContactSolver::setIsSplitImpulseActive(bool isActive) { void ContactSolver::setIsSplitImpulseActive(bool isActive) {
m_isSplitImpulseActive = isActive; m_isSplitImpulseActive = isActive;
} }
// Activate or deactivate the solving of friction constraints at the center of // Activate or deactivate the solving of friction constraints at the center of
// the contact manifold instead of solving them at each contact point // 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; m_isSolveFrictionAtContactManifoldCenterActive = isActive;
} }
// Compute the collision restitution factor from the restitution factor of each body // 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 { RigidBody* body2) const {
float restitution1 = body1->getMaterial().getBounciness(); float restitution1 = body1->getMaterial().getBounciness();
float restitution2 = body2->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 // 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 { RigidBody *body2) const {
// Use the geometric mean to compute the mixed friction coefficient // Use the geometric mean to compute the mixed friction coefficient
return sqrt(body1->getMaterial().getFrictionCoefficient() * return sqrt(body1->getMaterial().getFrictionCoefficient() *
@ -290,13 +290,13 @@ inline float ContactSolver::computeMixedFrictionCoefficient(RigidBody *body1,
} }
// Compute th mixed rolling resistance factor between two bodies // Compute th mixed rolling resistance factor between two bodies
inline float ContactSolver::computeMixedRollingResistance(RigidBody* body1, float ContactSolver::computeMixedRollingResistance(RigidBody* body1,
RigidBody* body2) const { RigidBody* body2) const {
return float(0.5f) * (body1->getMaterial().getRollingResistance() + body2->getMaterial().getRollingResistance()); return float(0.5f) * (body1->getMaterial().getRollingResistance() + body2->getMaterial().getRollingResistance());
} }
// Compute a penetration constraint impulse // Compute a penetration constraint impulse
inline const Impulse ContactSolver::computePenetrationImpulse(float deltaLambda, const Impulse ContactSolver::computePenetrationImpulse(float deltaLambda,
const ContactPointSolver& contactPoint) const ContactPointSolver& contactPoint)
const { const {
return Impulse(-contactPoint.normal * deltaLambda, -contactPoint.r1CrossN * deltaLambda, 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 // Compute the first friction constraint impulse
inline const Impulse ContactSolver::computeFriction1Impulse(float deltaLambda, const Impulse ContactSolver::computeFriction1Impulse(float deltaLambda,
const ContactPointSolver& contactPoint) const ContactPointSolver& contactPoint)
const { const {
return Impulse(-contactPoint.frictionVector1 * deltaLambda, return Impulse(-contactPoint.frictionVector1 * deltaLambda,
@ -314,7 +314,7 @@ inline const Impulse ContactSolver::computeFriction1Impulse(float deltaLambda,
} }
// Compute the second friction constraint impulse // Compute the second friction constraint impulse
inline const Impulse ContactSolver::computeFriction2Impulse(float deltaLambda, const Impulse ContactSolver::computeFriction2Impulse(float deltaLambda,
const ContactPointSolver& contactPoint) const ContactPointSolver& contactPoint)
const { const {
return Impulse(-contactPoint.frictionvec2 * deltaLambda, return Impulse(-contactPoint.frictionvec2 * deltaLambda,

View File

@ -166,7 +166,7 @@ namespace ephysics {
}; };
// Reset the external force and torque applied to the bodies // Reset the external force and torque applied to the bodies
inline void DynamicsWorld::resetBodiesForceAndTorque() { void DynamicsWorld::resetBodiesForceAndTorque() {
// For each body of the world // For each body of the world
std::set<RigidBody*>::iterator it; std::set<RigidBody*>::iterator it;
@ -177,7 +177,7 @@ inline void DynamicsWorld::resetBodiesForceAndTorque() {
} }
// Get the number of iterations for the velocity constraint solver // Get the number of iterations for the velocity constraint solver
inline uint32_t DynamicsWorld::getNbIterationsVelocitySolver() const { uint32_t DynamicsWorld::getNbIterationsVelocitySolver() const {
return m_nbVelocitySolverIterations; return m_nbVelocitySolverIterations;
} }
@ -185,12 +185,12 @@ inline uint32_t DynamicsWorld::getNbIterationsVelocitySolver() const {
/** /**
* @param nbIterations Number of iterations for the velocity solver * @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; m_nbVelocitySolverIterations = nbIterations;
} }
// Get the number of iterations for the position constraint solver // Get the number of iterations for the position constraint solver
inline uint32_t DynamicsWorld::getNbIterationsPositionSolver() const { uint32_t DynamicsWorld::getNbIterationsPositionSolver() const {
return m_nbPositionSolverIterations; return m_nbPositionSolverIterations;
} }
@ -198,7 +198,7 @@ inline uint32_t DynamicsWorld::getNbIterationsPositionSolver() const {
/** /**
* @param nbIterations Number of iterations for the position solver * @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; 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) * @param technique Technique used for the position correction (Baumgarte or Split Impulses)
*/ */
inline void DynamicsWorld::setContactsPositionCorrectionTechnique( void DynamicsWorld::setContactsPositionCorrectionTechnique(
ContactsPositionCorrectionTechnique technique) { ContactsPositionCorrectionTechnique technique) {
if (technique == BAUMGARTE_CONTACTS) { if (technique == BAUMGARTE_CONTACTS) {
m_contactSolver.setIsSplitImpulseActive(false); 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) * @param technique Technique used for the joins position correction (Baumgarte or Non Linear Gauss Seidel)
*/ */
inline void DynamicsWorld::setJointsPositionCorrectionTechnique( void DynamicsWorld::setJointsPositionCorrectionTechnique(
JointsPositionCorrectionTechnique technique) { JointsPositionCorrectionTechnique technique) {
if (technique == BAUMGARTE_JOINTS) { if (technique == BAUMGARTE_JOINTS) {
m_constraintSolver.setIsNonLinearGaussSeidelPositionCorrectionActive(false); 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 * @param isActive True if you want the friction to be solved at the center of
* the contact manifold and false otherwise * the contact manifold and false otherwise
*/ */
inline void DynamicsWorld::setIsSolveFrictionAtContactManifoldCenterActive(bool isActive) { void DynamicsWorld::setIsSolveFrictionAtContactManifoldCenterActive(bool isActive) {
m_contactSolver.setIsSolveFrictionAtContactManifoldCenterActive(isActive); m_contactSolver.setIsSolveFrictionAtContactManifoldCenterActive(isActive);
} }
@ -244,7 +244,7 @@ inline void DynamicsWorld::setIsSolveFrictionAtContactManifoldCenterActive(bool
/** /**
* @return The current gravity vector (in meter per seconds squared) * @return The current gravity vector (in meter per seconds squared)
*/ */
inline vec3 DynamicsWorld::getGravity() const { vec3 DynamicsWorld::getGravity() const {
return m_gravity; return m_gravity;
} }
@ -252,7 +252,7 @@ inline vec3 DynamicsWorld::getGravity() const {
/** /**
* @param gravity The gravity vector (in meter per seconds squared) * @param gravity The gravity vector (in meter per seconds squared)
*/ */
inline void DynamicsWorld::setGravity(vec3& gravity) { void DynamicsWorld::setGravity(vec3& gravity) {
m_gravity = gravity; m_gravity = gravity;
} }
@ -260,7 +260,7 @@ inline void DynamicsWorld::setGravity(vec3& gravity) {
/** /**
* @return True if the gravity is enabled in the world * @return True if the gravity is enabled in the world
*/ */
inline bool DynamicsWorld::isGravityEnabled() const { bool DynamicsWorld::isGravityEnabled() const {
return m_isGravityEnabled; 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 * @param isGravityEnabled True if you want to enable the gravity in the world
* and false otherwise * and false otherwise
*/ */
inline void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) { void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) {
m_isGravityEnabled = isGravityEnabled; m_isGravityEnabled = isGravityEnabled;
} }
@ -277,7 +277,7 @@ inline void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) {
/** /**
* @return Number of rigid bodies in the world * @return Number of rigid bodies in the world
*/ */
inline uint32_t DynamicsWorld::getNbRigidBodies() const { uint32_t DynamicsWorld::getNbRigidBodies() const {
return m_rigidBodies.size(); return m_rigidBodies.size();
} }
@ -285,7 +285,7 @@ inline uint32_t DynamicsWorld::getNbRigidBodies() const {
/** /**
* @return Number of joints in the world * @return Number of joints in the world
*/ */
inline uint32_t DynamicsWorld::getNbJoints() const { uint32_t DynamicsWorld::getNbJoints() const {
return m_joints.size(); return m_joints.size();
} }
@ -293,7 +293,7 @@ inline uint32_t DynamicsWorld::getNbJoints() const {
/** /**
* @return Starting iterator of the set of rigid bodies * @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(); return m_rigidBodies.begin();
} }
@ -301,7 +301,7 @@ inline std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesBeginIterator
/** /**
* @return Ending iterator of the set of rigid bodies * @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(); 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 * @return True if the sleeping technique is enabled and false otherwise
*/ */
inline bool DynamicsWorld::isSleepingEnabled() const { bool DynamicsWorld::isSleepingEnabled() const {
return m_isSleepingEnabled; return m_isSleepingEnabled;
} }
@ -317,7 +317,7 @@ inline bool DynamicsWorld::isSleepingEnabled() const {
/** /**
* @return The sleep linear velocity (in meters per second) * @return The sleep linear velocity (in meters per second)
*/ */
inline float DynamicsWorld::getSleepLinearVelocity() const { float DynamicsWorld::getSleepLinearVelocity() const {
return m_sleepLinearVelocity; return m_sleepLinearVelocity;
} }
@ -328,7 +328,7 @@ inline float DynamicsWorld::getSleepLinearVelocity() const {
/** /**
* @param sleepLinearVelocity The sleep linear velocity (in meters per second) * @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); assert(sleepLinearVelocity >= 0.0f);
m_sleepLinearVelocity = sleepLinearVelocity; m_sleepLinearVelocity = sleepLinearVelocity;
} }
@ -337,7 +337,7 @@ inline void DynamicsWorld::setSleepLinearVelocity(float sleepLinearVelocity) {
/** /**
* @return The sleep angular velocity (in radian per second) * @return The sleep angular velocity (in radian per second)
*/ */
inline float DynamicsWorld::getSleepAngularVelocity() const { float DynamicsWorld::getSleepAngularVelocity() const {
return m_sleepAngularVelocity; return m_sleepAngularVelocity;
} }
@ -348,7 +348,7 @@ inline float DynamicsWorld::getSleepAngularVelocity() const {
/** /**
* @param sleepAngularVelocity The sleep angular velocity (in radian per second) * @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); assert(sleepAngularVelocity >= 0.0f);
m_sleepAngularVelocity = sleepAngularVelocity; 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) * @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; 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) * @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); assert(timeBeforeSleep >= 0.0f);
m_timeBeforeSleep = timeBeforeSleep; m_timeBeforeSleep = timeBeforeSleep;
} }
@ -377,7 +377,7 @@ inline void DynamicsWorld::setTimeBeforeSleep(float timeBeforeSleep) {
* @param eventListener Pointer to the event listener object that will receive * @param eventListener Pointer to the event listener object that will receive
* event callbacks during the simulation * event callbacks during the simulation
*/ */
inline void DynamicsWorld::setEventListener(EventListener* eventListener) { void DynamicsWorld::setEventListener(EventListener* eventListener) {
m_eventListener = eventListener; m_eventListener = eventListener;
} }

View File

@ -59,51 +59,51 @@ namespace ephysics {
}; };
// Add a body int32_to the island // Add a body int32_to the island
inline void Island::addBody(RigidBody* body) { void Island::addBody(RigidBody* body) {
assert(!body->isSleeping()); assert(!body->isSleeping());
m_bodies[m_numberBodies] = body; m_bodies[m_numberBodies] = body;
m_numberBodies++; m_numberBodies++;
} }
// Add a contact manifold int32_to the island // 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_contactManifolds[m_numberContactManifolds] = contactManifold;
m_numberContactManifolds++; m_numberContactManifolds++;
} }
// Add a joint int32_to the island // Add a joint int32_to the island
inline void Island::addJoint(Joint* joint) { void Island::addJoint(Joint* joint) {
m_joints[m_numberJoints] = joint; m_joints[m_numberJoints] = joint;
m_numberJoints++; m_numberJoints++;
} }
// Return the number of bodies in the island // Return the number of bodies in the island
inline uint32_t Island::getNbBodies() const { uint32_t Island::getNbBodies() const {
return m_numberBodies; return m_numberBodies;
} }
// Return the number of contact manifolds in the island // Return the number of contact manifolds in the island
inline uint32_t Island::getNbContactManifolds() const { uint32_t Island::getNbContactManifolds() const {
return m_numberContactManifolds; return m_numberContactManifolds;
} }
// Return the number of joints in the island // Return the number of joints in the island
inline uint32_t Island::getNbJoints() const { uint32_t Island::getNbJoints() const {
return m_numberJoints; return m_numberJoints;
} }
// Return a pointer to the array of bodies // Return a pointer to the array of bodies
inline RigidBody** Island::getBodies() { RigidBody** Island::getBodies() {
return m_bodies; return m_bodies;
} }
// Return a pointer to the array of contact manifolds // Return a pointer to the array of contact manifolds
inline ContactManifold** Island::getContactManifold() { ContactManifold** Island::getContactManifold() {
return m_contactManifolds; return m_contactManifolds;
} }
// Return a pointer to the array of joints // Return a pointer to the array of joints
inline Joint** Island::getJoints() { Joint** Island::getJoints() {
return m_joints; return m_joints;
} }

View File

@ -43,7 +43,7 @@ namespace ephysics {
/** /**
* @return Bounciness factor (between 0 and 1) where 1 is very bouncy * @return Bounciness factor (between 0 and 1) where 1 is very bouncy
*/ */
inline float Material::getBounciness() const { float Material::getBounciness() const {
return m_bounciness; 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 * @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); assert(bounciness >= 0.0f && bounciness <= 1.0f);
m_bounciness = bounciness; m_bounciness = bounciness;
} }
@ -62,7 +62,7 @@ inline void Material::setBounciness(float bounciness) {
/** /**
* @return Friction coefficient (positive value) * @return Friction coefficient (positive value)
*/ */
inline float Material::getFrictionCoefficient() const { float Material::getFrictionCoefficient() const {
return m_frictionCoefficient; return m_frictionCoefficient;
} }
@ -72,7 +72,7 @@ inline float Material::getFrictionCoefficient() const {
/** /**
* @param frictionCoefficient Friction coefficient (positive value) * @param frictionCoefficient Friction coefficient (positive value)
*/ */
inline void Material::setFrictionCoefficient(float frictionCoefficient) { void Material::setFrictionCoefficient(float frictionCoefficient) {
assert(frictionCoefficient >= 0.0f); assert(frictionCoefficient >= 0.0f);
m_frictionCoefficient = frictionCoefficient; m_frictionCoefficient = frictionCoefficient;
} }
@ -83,7 +83,7 @@ inline void Material::setFrictionCoefficient(float frictionCoefficient) {
/** /**
* @return The rolling resistance factor (positive value) * @return The rolling resistance factor (positive value)
*/ */
inline float Material::getRollingResistance() const { float Material::getRollingResistance() const {
return m_rollingResistance; return m_rollingResistance;
} }
@ -93,13 +93,13 @@ inline float Material::getRollingResistance() const {
/** /**
* @param rollingResistance The rolling resistance factor * @param rollingResistance The rolling resistance factor
*/ */
inline void Material::setRollingResistance(float rollingResistance) { void Material::setRollingResistance(float rollingResistance) {
assert(rollingResistance >= 0); assert(rollingResistance >= 0);
m_rollingResistance = rollingResistance; m_rollingResistance = rollingResistance;
} }
// Overloaded assignment operator // Overloaded assignment operator
inline Material& Material::operator=(const Material& material) { Material& Material::operator=(const Material& material) {
// Check for self-assignment // Check for self-assignment
if (this != &material) { if (this != &material) {

View File

@ -58,48 +58,48 @@ namespace ephysics {
}; };
// Return the pointer to first body // Return the pointer to first body
inline ProxyShape* OverlappingPair::getShape1() const { ProxyShape* OverlappingPair::getShape1() const {
return m_contactManifoldSet.getShape1(); return m_contactManifoldSet.getShape1();
} }
// Return the pointer to second body // Return the pointer to second body
inline ProxyShape* OverlappingPair::getShape2() const { ProxyShape* OverlappingPair::getShape2() const {
return m_contactManifoldSet.getShape2(); return m_contactManifoldSet.getShape2();
} }
// Add a contact to the contact manifold // Add a contact to the contact manifold
inline void OverlappingPair::addContact(ContactPoint* contact) { void OverlappingPair::addContact(ContactPoint* contact) {
m_contactManifoldSet.addContactPoint(contact); m_contactManifoldSet.addContactPoint(contact);
} }
// Update the contact manifold // Update the contact manifold
inline void OverlappingPair::update() { void OverlappingPair::update() {
m_contactManifoldSet.update(); m_contactManifoldSet.update();
} }
// Return the cached separating axis // Return the cached separating axis
inline vec3 OverlappingPair::getCachedSeparatingAxis() const { vec3 OverlappingPair::getCachedSeparatingAxis() const {
return m_cachedSeparatingAxis; return m_cachedSeparatingAxis;
} }
// Set the cached separating axis // Set the cached separating axis
inline void OverlappingPair::setCachedSeparatingAxis(const vec3& axis) { void OverlappingPair::setCachedSeparatingAxis(const vec3& axis) {
m_cachedSeparatingAxis = axis; m_cachedSeparatingAxis = axis;
} }
// Return the number of contact points in the contact manifold // 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 m_contactManifoldSet.getTotalNbContactPoints();
} }
// Return the contact manifold // Return the contact manifold
inline const ContactManifoldSet& OverlappingPair::getContactManifoldSet() { const ContactManifoldSet& OverlappingPair::getContactManifoldSet() {
return m_contactManifoldSet; return m_contactManifoldSet;
} }
// Return the pair of bodies index // 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); assert(shape1->m_broadPhaseID >= 0 && shape2->m_broadPhaseID >= 0);
// Construct the pair of body index // Construct the pair of body index
@ -111,7 +111,7 @@ inline overlappingpairid OverlappingPair::computeID(ProxyShape* shape1, ProxySha
} }
// Return the pair of bodies index // Return the pair of bodies index
inline bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body1, bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body1,
CollisionBody* body2) { CollisionBody* body2) {
// Construct the pair of body index // Construct the pair of body index
@ -123,7 +123,7 @@ inline bodyindexpair OverlappingPair::computeBodiesIndexPair(CollisionBody* body
} }
// Clear the contact points of the contact manifold // Clear the contact points of the contact manifold
inline void OverlappingPair::clearContactPoints() { void OverlappingPair::clearContactPoints() {
m_contactManifoldSet.clear(); m_contactManifoldSet.clear();
} }

View File

@ -147,113 +147,113 @@ namespace ephysics {
#define PROFILE(name) ProfileSample profileSample(name) #define PROFILE(name) ProfileSample profileSample(name)
// Return true if we are at the root of the profiler tree // 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 (m_currentParentNode->getParentNode() == nullptr);
} }
// Return true if we are at the end of a branch of the profiler tree // 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 (m_currentChildNode == nullptr);
} }
// Return the name of the current node // Return the name of the current node
inline const char* ProfileNodeIterator::getCurrentName() { const char* ProfileNodeIterator::getCurrentName() {
return m_currentChildNode->getName(); return m_currentChildNode->getName();
} }
// Return the total time of the current node // Return the total time of the current node
inline long double ProfileNodeIterator::getCurrentTotalTime() { long double ProfileNodeIterator::getCurrentTotalTime() {
return m_currentChildNode->getTotalTime(); return m_currentChildNode->getTotalTime();
} }
// Return the total number of calls of the current node // Return the total number of calls of the current node
inline uint32_t ProfileNodeIterator::getCurrentNbTotalCalls() { uint32_t ProfileNodeIterator::getCurrentNbTotalCalls() {
return m_currentChildNode->getNbTotalCalls(); return m_currentChildNode->getNbTotalCalls();
} }
// Return the name of the current parent node // Return the name of the current parent node
inline const char* ProfileNodeIterator::getCurrentParentName() { const char* ProfileNodeIterator::getCurrentParentName() {
return m_currentParentNode->getName(); return m_currentParentNode->getName();
} }
// Return the total time of the current parent node // Return the total time of the current parent node
inline long double ProfileNodeIterator::getCurrentParentTotalTime() { long double ProfileNodeIterator::getCurrentParentTotalTime() {
return m_currentParentNode->getTotalTime(); return m_currentParentNode->getTotalTime();
} }
// Return the total number of calls of the current parent node // Return the total number of calls of the current parent node
inline uint32_t ProfileNodeIterator::getCurrentParentNbTotalCalls() { uint32_t ProfileNodeIterator::getCurrentParentNbTotalCalls() {
return m_currentParentNode->getNbTotalCalls(); return m_currentParentNode->getNbTotalCalls();
} }
// Go to the first node // Go to the first node
inline void ProfileNodeIterator::first() { void ProfileNodeIterator::first() {
m_currentChildNode = m_currentParentNode->getChildNode(); m_currentChildNode = m_currentParentNode->getChildNode();
} }
// Go to the next node // Go to the next node
inline void ProfileNodeIterator::next() { void ProfileNodeIterator::next() {
m_currentChildNode = m_currentChildNode->getSiblingNode(); m_currentChildNode = m_currentChildNode->getSiblingNode();
} }
// Return a pointer to the parent node // Return a pointer to the parent node
inline ProfileNode* ProfileNode::getParentNode() { ProfileNode* ProfileNode::getParentNode() {
return m_parentNode; return m_parentNode;
} }
// Return a pointer to a sibling node // Return a pointer to a sibling node
inline ProfileNode* ProfileNode::getSiblingNode() { ProfileNode* ProfileNode::getSiblingNode() {
return m_siblingNode; return m_siblingNode;
} }
// Return a pointer to a child node // Return a pointer to a child node
inline ProfileNode* ProfileNode::getChildNode() { ProfileNode* ProfileNode::getChildNode() {
return m_childNode; return m_childNode;
} }
// Return the name of the node // Return the name of the node
inline const char* ProfileNode::getName() { const char* ProfileNode::getName() {
return m_name; return m_name;
} }
// Return the total number of call of the corresponding block of code // 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 m_numberTotalCalls;
} }
// Return the total time spent in the block of code // 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 m_totalTime;
} }
// Return the number of frames // Return the number of frames
inline uint32_t Profiler::getNbFrames() { uint32_t Profiler::getNbFrames() {
return m_frameCounter; return m_frameCounter;
} }
// Return the elasped time since the start/reset of the profiling // 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; long double currentTime = Timer::getCurrentSystemTime() * 1000.0;
return currentTime - m_profilingStartTime; return currentTime - m_profilingStartTime;
} }
// Increment the frame counter // Increment the frame counter
inline void Profiler::incrementFrameCounter() { void Profiler::incrementFrameCounter() {
m_frameCounter++; m_frameCounter++;
} }
// Return an iterator over the profiler tree starting at the root // Return an iterator over the profiler tree starting at the root
inline ProfileNodeIterator* Profiler::getIterator() { ProfileNodeIterator* Profiler::getIterator() {
return new ProfileNodeIterator(&m_rootNode); return new ProfileNodeIterator(&m_rootNode);
} }
// Destroy a previously allocated iterator // Destroy a previously allocated iterator
inline void Profiler::destroyIterator(ProfileNodeIterator* iterator) { void Profiler::destroyIterator(ProfileNodeIterator* iterator) {
delete iterator; delete iterator;
} }
// Destroy the profiler (release the memory) // Destroy the profiler (release the memory)
inline void Profiler::destroy() { void Profiler::destroy() {
m_rootNode.destroy(); m_rootNode.destroy();
} }

View File

@ -20,7 +20,6 @@
#endif #endif
/// Namespace ReactPhysics3D
namespace ephysics { namespace ephysics {
/** /**
* @brief This class will take care of the time in the physics engine. It * @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 // Return the timestep of the physics engine
inline double Timer::getTimeStep() const { double Timer::getTimeStep() const {
return m_timeStep; return m_timeStep;
} }
// Set the timestep of the physics engine // Set the timestep of the physics engine
inline void Timer::setTimeStep(double timeStep) { void Timer::setTimeStep(double timeStep) {
assert(timeStep > 0.0f); assert(timeStep > 0.0f);
m_timeStep = timeStep; m_timeStep = timeStep;
} }
// Return the current time // Return the current time
inline long double Timer::getPhysicsTime() const { long double Timer::getPhysicsTime() const {
return m_lastUpdateTime; return m_lastUpdateTime;
} }
// Return if the timer is running // Return if the timer is running
inline bool Timer::getIsRunning() const { bool Timer::getIsRunning() const {
return m_isRunning; return m_isRunning;
} }
// Start the timer // Start the timer
inline void Timer::start() { void Timer::start() {
if (!m_isRunning) { if (!m_isRunning) {
// Get the current system time // Get the current system time
m_lastUpdateTime = getCurrentSystemTime(); m_lastUpdateTime = getCurrentSystemTime();
m_accumulator = 0.0; m_accumulator = 0.0;
m_isRunning = true; m_isRunning = true;
} }
} }
// Stop the timer // Stop the timer
inline void Timer::stop() { void Timer::stop() {
m_isRunning = false; m_isRunning = false;
} }
// True if it's possible to take a new step // True if it's possible to take a new step
inline bool Timer::isPossibleToTakeStep() const { bool Timer::isPossibleToTakeStep() const {
return (m_accumulator >= m_timeStep); return (m_accumulator >= m_timeStep);
} }
// Take a new step => update the timer by adding the timeStep value to the current time // 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); assert(m_isRunning);
// Update the accumulator value // Update the accumulator value
@ -119,23 +116,15 @@ inline void Timer::nextStep() {
} }
// Compute the int32_terpolation factor // Compute the int32_terpolation factor
inline float Timer::computeInterpolationFactor() { float Timer::computeInterpolationFactor() {
return (float(m_accumulator / m_timeStep)); return (float(m_accumulator / m_timeStep));
} }
// Compute the time since the last update() call and add it to the accumulator // Compute the time since the last update() call and add it to the accumulator
inline void Timer::update() { void Timer::update() {
// Get the current system time
long double currentTime = getCurrentSystemTime(); long double currentTime = getCurrentSystemTime();
// Compute the delta display time between two display frames
m_deltaTime = currentTime - m_lastUpdateTime; m_deltaTime = currentTime - m_lastUpdateTime;
// Update the current display time
m_lastUpdateTime = currentTime; m_lastUpdateTime = currentTime;
// Update the accumulator value
m_accumulator += m_deltaTime; m_accumulator += m_deltaTime;
} }

View File

@ -25,12 +25,6 @@
// Libraries // Libraries
#include <test/TestSuite.hpp> #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/mathematics/TestMathematicsFunctions.hpp>
#include <test/tests/collision/TestPointInside.hpp> #include <test/tests/collision/TestPointInside.hpp>
#include <test/tests/collision/TestRaycast.hpp> #include <test/tests/collision/TestRaycast.hpp>