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