[DEV] remove all math from here and use etk versions
This commit is contained in:
parent
c58ef697ce
commit
572d64845c
@ -170,11 +170,11 @@ inline void Body::setIsActive(bool isActive) {
|
||||
inline void Body::setIsSleeping(bool isSleeping) {
|
||||
|
||||
if (isSleeping) {
|
||||
m_sleepTime = float(0.0);
|
||||
m_sleepTime = 0.0f;
|
||||
}
|
||||
else {
|
||||
if (m_isSleeping) {
|
||||
m_sleepTime = float(0.0);
|
||||
m_sleepTime = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ using namespace reactphysics3d;
|
||||
* @param world The physics world where the body is created
|
||||
* @param id ID of the body
|
||||
*/
|
||||
CollisionBody::CollisionBody(const Transform& transform, CollisionWorld& world, bodyindex id)
|
||||
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) {
|
||||
|
||||
@ -32,6 +32,15 @@ CollisionBody::~CollisionBody() {
|
||||
removeAllCollisionShapes();
|
||||
}
|
||||
|
||||
inline void CollisionBody::setType(BodyType _type) {
|
||||
m_type = _type;
|
||||
if (m_type == STATIC) {
|
||||
// Update the broad-phase state of the body
|
||||
updateBroadPhaseState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
@ -48,7 +57,7 @@ CollisionBody::~CollisionBody() {
|
||||
* the new collision shape you have added.
|
||||
*/
|
||||
ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
|
||||
const Transform& transform) {
|
||||
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(
|
||||
@ -188,7 +197,7 @@ void CollisionBody::updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool fo
|
||||
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, Vector3(0, 0, 0), forceReinsert);
|
||||
m_world.m_collisionDetection.updateProxyCollisionShape(proxyShape, aabb, vec3(0, 0, 0), forceReinsert);
|
||||
}
|
||||
|
||||
// Set whether or not the body is active
|
||||
@ -267,7 +276,7 @@ int32_t CollisionBody::resetIsAlreadyInIslandAndCountManifolds() {
|
||||
* @param worldPoint The point to test (in world-space coordinates)
|
||||
* @return True if the point is inside the body
|
||||
*/
|
||||
bool CollisionBody::testPointInside(const Vector3& worldPoint) const {
|
||||
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) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <ephysics/body/Body.h>
|
||||
#include <ephysics/mathematics/Transform.h>
|
||||
#include <etk/math/Transform3D.hpp>
|
||||
#include <ephysics/collision/shapes/AABB.h>
|
||||
#include <ephysics/collision/shapes/CollisionShape.h>
|
||||
#include <ephysics/collision/RaycastInfo.h>
|
||||
@ -50,7 +50,7 @@ class CollisionBody : public Body {
|
||||
BodyType m_type;
|
||||
|
||||
/// Position and orientation of the body
|
||||
Transform m_transform;
|
||||
etk::Transform3D m_transform;
|
||||
|
||||
/// First element of the linked list of proxy collision shapes of this body
|
||||
ProxyShape* m_proxyCollisionShapes;
|
||||
@ -96,29 +96,40 @@ class CollisionBody : public Body {
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
CollisionBody(const Transform& transform, CollisionWorld& world, bodyindex id);
|
||||
CollisionBody(const etk::Transform3D& transform, CollisionWorld& world, bodyindex id);
|
||||
|
||||
/// Destructor
|
||||
virtual ~CollisionBody();
|
||||
|
||||
/// Return the type of the body
|
||||
BodyType getType() const;
|
||||
|
||||
/// Set the type of the body
|
||||
void setType(BodyType type);
|
||||
/**
|
||||
* @brief Set the type of the body
|
||||
* The type of the body can either STATIC, KINEMATIC or DYNAMIC as described bellow:
|
||||
* STATIC : A static body has infinite mass, zero velocity but the position can be
|
||||
* changed manually. A static body does not collide with other static or kinematic bodies.
|
||||
* KINEMATIC : A kinematic body has infinite mass, the velocity can be changed manually and its
|
||||
* position is computed by the physics engine. A kinematic body does not collide with
|
||||
* other static or kinematic bodies.
|
||||
* DYNAMIC : A dynamic body has non-zero mass, non-zero velocity determined by forces and its
|
||||
* position is determined by the physics engine. A dynamic body can collide with other
|
||||
* dynamic, static or kinematic bodies.
|
||||
* @param[in] type The type of the body (STATIC, KINEMATIC, DYNAMIC)
|
||||
*/
|
||||
virtual void setType(BodyType _type);
|
||||
|
||||
/// Set whether or not the body is active
|
||||
virtual void setIsActive(bool isActive);
|
||||
|
||||
/// Return the current position and orientation
|
||||
const Transform& getTransform() const;
|
||||
const etk::Transform3D& getTransform() const;
|
||||
|
||||
/// Set the current position and orientation
|
||||
virtual void setTransform(const Transform& transform);
|
||||
virtual void setTransform(const etk::Transform3D& transform);
|
||||
|
||||
/// Add a collision shape to the body.
|
||||
virtual ProxyShape* addCollisionShape(CollisionShape* collisionShape,
|
||||
const Transform& transform);
|
||||
const etk::Transform3D& transform);
|
||||
|
||||
/// Remove a collision shape from the body
|
||||
virtual void removeCollisionShape(const ProxyShape* proxyShape);
|
||||
@ -127,7 +138,7 @@ class CollisionBody : public Body {
|
||||
const ContactManifoldListElement* getContactManifoldsList() const;
|
||||
|
||||
/// Return true if a point is inside the collision body
|
||||
bool testPointInside(const Vector3& worldPoint) const;
|
||||
bool testPointInside(const vec3& worldPoint) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
bool raycast(const Ray& ray, RaycastInfo& raycastInfo);
|
||||
@ -142,16 +153,16 @@ class CollisionBody : public Body {
|
||||
const ProxyShape* getProxyShapesList() const;
|
||||
|
||||
/// Return the world-space coordinates of a point given the local-space coordinates of the body
|
||||
Vector3 getWorldPoint(const Vector3& localPoint) const;
|
||||
vec3 getWorldPoint(const vec3& localPoint) const;
|
||||
|
||||
/// Return the world-space vector of a vector given in local-space coordinates of the body
|
||||
Vector3 getWorldVector(const Vector3& localVector) const;
|
||||
vec3 getWorldVector(const vec3& localVector) const;
|
||||
|
||||
/// Return the body local-space coordinates of a point given in the world-space coordinates
|
||||
Vector3 getLocalPoint(const Vector3& worldPoint) const;
|
||||
vec3 getLocalPoint(const vec3& worldPoint) const;
|
||||
|
||||
/// Return the body local-space coordinates of a vector given in the world-space coordinates
|
||||
Vector3 getLocalVector(const Vector3& worldVector) const;
|
||||
vec3 getLocalVector(const vec3& worldVector) const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
@ -171,35 +182,13 @@ inline BodyType CollisionBody::getType() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
// 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 type The type of the body (STATIC, KINEMATIC, DYNAMIC)
|
||||
*/
|
||||
inline void CollisionBody::setType(BodyType type) {
|
||||
m_type = type;
|
||||
|
||||
if (m_type == STATIC) {
|
||||
|
||||
// Update the broad-phase state of the body
|
||||
updateBroadPhaseState();
|
||||
}
|
||||
}
|
||||
|
||||
// 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 Transform& CollisionBody::getTransform() const {
|
||||
inline const etk::Transform3D& CollisionBody::getTransform() const {
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
@ -208,7 +197,7 @@ inline const Transform& CollisionBody::getTransform() const {
|
||||
* @param transform The transformation of the body that transforms the local-space
|
||||
* of the body int32_to world-space
|
||||
*/
|
||||
inline void CollisionBody::setTransform(const Transform& transform) {
|
||||
inline void CollisionBody::setTransform(const etk::Transform3D& transform) {
|
||||
|
||||
// Update the transform of the body
|
||||
m_transform = transform;
|
||||
@ -249,7 +238,7 @@ inline const ProxyShape* CollisionBody::getProxyShapesList() const {
|
||||
* @param localPoint A point in the local-space coordinates of the body
|
||||
* @return The point in world-space coordinates
|
||||
*/
|
||||
inline Vector3 CollisionBody::getWorldPoint(const Vector3& localPoint) const {
|
||||
inline vec3 CollisionBody::getWorldPoint(const vec3& localPoint) const {
|
||||
return m_transform * localPoint;
|
||||
}
|
||||
|
||||
@ -258,7 +247,7 @@ inline Vector3 CollisionBody::getWorldPoint(const Vector3& localPoint) const {
|
||||
* @param localVector A vector in the local-space coordinates of the body
|
||||
* @return The vector in world-space coordinates
|
||||
*/
|
||||
inline Vector3 CollisionBody::getWorldVector(const Vector3& localVector) const {
|
||||
inline vec3 CollisionBody::getWorldVector(const vec3& localVector) const {
|
||||
return m_transform.getOrientation() * localVector;
|
||||
}
|
||||
|
||||
@ -267,7 +256,7 @@ inline Vector3 CollisionBody::getWorldVector(const Vector3& localVector) const {
|
||||
* @param worldPoint A point in world-space coordinates
|
||||
* @return The point in the local-space coordinates of the body
|
||||
*/
|
||||
inline Vector3 CollisionBody::getLocalPoint(const Vector3& worldPoint) const {
|
||||
inline vec3 CollisionBody::getLocalPoint(const vec3& worldPoint) const {
|
||||
return m_transform.getInverse() * worldPoint;
|
||||
}
|
||||
|
||||
@ -276,7 +265,7 @@ inline Vector3 CollisionBody::getLocalPoint(const Vector3& worldPoint) const {
|
||||
* @param worldVector A vector in world-space coordinates
|
||||
* @return The vector in the local-space coordinates of the body
|
||||
*/
|
||||
inline Vector3 CollisionBody::getLocalVector(const Vector3& worldVector) const {
|
||||
inline vec3 CollisionBody::getLocalVector(const vec3& worldVector) const {
|
||||
return m_transform.getOrientation().getInverse() * worldVector;
|
||||
}
|
||||
|
||||
|
@ -13,20 +13,15 @@
|
||||
// We want to use the ReactPhysics3D namespace
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// 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::RigidBody(const Transform& transform, CollisionWorld& world, bodyindex id)
|
||||
: CollisionBody(transform, world, id), m_initMass(float(1.0)),
|
||||
|
||||
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(float(0.0)), m_angularDamping(float(0.0)),
|
||||
m_isGravityEnabled(true), m_linearDamping(0.0f), m_angularDamping(float(0.0)),
|
||||
m_jointsList(NULL) {
|
||||
|
||||
// Compute the inverse mass
|
||||
m_massInverse = float(1.0) / m_initMass;
|
||||
m_massInverse = 1.0f / m_initMass;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@ -34,63 +29,34 @@ RigidBody::~RigidBody() {
|
||||
assert(m_jointsList == NULL);
|
||||
}
|
||||
|
||||
// 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 type The type of the body (STATIC, KINEMATIC, DYNAMIC)
|
||||
*/
|
||||
void RigidBody::setType(BodyType type) {
|
||||
|
||||
if (m_type == type) return;
|
||||
|
||||
CollisionBody::setType(type);
|
||||
|
||||
// Recompute the total mass, center of mass and inertia tensor
|
||||
void RigidBody::setType(BodyType _type) {
|
||||
if (m_type == _type) {
|
||||
return;
|
||||
}
|
||||
CollisionBody::setType(_type);
|
||||
recomputeMassInformation();
|
||||
|
||||
// If it is a static body
|
||||
if (m_type == STATIC) {
|
||||
|
||||
// Reset the velocity to zero
|
||||
m_linearVelocity.setToZero();
|
||||
m_angularVelocity.setToZero();
|
||||
m_linearVelocity.setZero();
|
||||
m_angularVelocity.setZero();
|
||||
}
|
||||
|
||||
// If it is a static or a kinematic body
|
||||
if (m_type == STATIC || m_type == KINEMATIC) {
|
||||
|
||||
if ( m_type == STATIC
|
||||
|| m_type == KINEMATIC) {
|
||||
// Reset the inverse mass and inverse inertia tensor to zero
|
||||
m_massInverse = float(0.0);
|
||||
m_inertiaTensorLocal.setToZero();
|
||||
m_inertiaTensorLocalInverse.setToZero();
|
||||
|
||||
}
|
||||
else { // If it is a dynamic body
|
||||
m_massInverse = float(1.0) / m_initMass;
|
||||
m_massInverse = 0.0f;
|
||||
m_inertiaTensorLocal.setZero();
|
||||
m_inertiaTensorLocalInverse.setZero();
|
||||
} else {
|
||||
m_massInverse = 1.0f / m_initMass;
|
||||
m_inertiaTensorLocalInverse = m_inertiaTensorLocal.getInverse();
|
||||
}
|
||||
|
||||
// Awake the body
|
||||
setIsSleeping(false);
|
||||
|
||||
// Remove all the contacts with this body
|
||||
resetContactManifoldsList();
|
||||
|
||||
// Ask the broad-phase to test again the collision shapes of the body for collision
|
||||
// detection (as if the body has moved)
|
||||
// Ask the broad-phase to test again the collision shapes of the body for collision detection (as if the body has moved)
|
||||
askForBroadPhaseCollisionCheck();
|
||||
|
||||
// Reset the force and torque on the body
|
||||
m_externalForce.setToZero();
|
||||
m_externalTorque.setToZero();
|
||||
m_externalForce.setZero();
|
||||
m_externalTorque.setZero();
|
||||
}
|
||||
|
||||
// Set the local inertia tensor of the body (in local-space coordinates)
|
||||
@ -98,7 +64,7 @@ void RigidBody::setType(BodyType type) {
|
||||
* @param inertiaTensorLocal The 3x3 inertia tensor matrix of the body in local-space
|
||||
* coordinates
|
||||
*/
|
||||
void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
|
||||
void RigidBody::setInertiaTensorLocal(const etk::Matrix3x3& inertiaTensorLocal) {
|
||||
|
||||
if (m_type != DYNAMIC) return;
|
||||
|
||||
@ -113,11 +79,11 @@ void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
|
||||
* @param centerOfMassLocal The center of mass of the body in local-space
|
||||
* coordinates
|
||||
*/
|
||||
void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) {
|
||||
void RigidBody::setCenterOfMassLocal(const vec3& centerOfMassLocal) {
|
||||
|
||||
if (m_type != DYNAMIC) return;
|
||||
|
||||
const Vector3 oldCenterOfMass = m_centerOfMassWorld;
|
||||
const vec3 oldCenterOfMass = m_centerOfMassWorld;
|
||||
m_centerOfMassLocal = centerOfMassLocal;
|
||||
|
||||
// Compute the center of mass in world-space coordinates
|
||||
@ -127,31 +93,23 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) {
|
||||
m_linearVelocity += m_angularVelocity.cross(m_centerOfMassWorld - oldCenterOfMass);
|
||||
}
|
||||
|
||||
// Set the mass of the rigid body
|
||||
/**
|
||||
* @param mass The mass (in kilograms) of the body
|
||||
*/
|
||||
void RigidBody::setMass(float mass) {
|
||||
|
||||
if (m_type != DYNAMIC) return;
|
||||
|
||||
m_initMass = mass;
|
||||
|
||||
if (m_initMass > float(0.0)) {
|
||||
m_massInverse = float(1.0) / m_initMass;
|
||||
void RigidBody::setMass(float _mass) {
|
||||
if (m_type != DYNAMIC) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
m_initMass = float(1.0);
|
||||
m_massInverse = float(1.0);
|
||||
m_initMass = _mass;
|
||||
if (m_initMass > 0.0f) {
|
||||
m_massInverse = 1.0f / m_initMass;
|
||||
} else {
|
||||
m_initMass = 1.0f;
|
||||
m_massInverse = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a joint from the joints list
|
||||
void RigidBody::removeJointFrom_jointsList(MemoryAllocator& memoryAllocator, const Joint* joint) {
|
||||
|
||||
assert(joint != NULL);
|
||||
assert(m_jointsList != NULL);
|
||||
|
||||
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
|
||||
JointListElement* elementToRemove = m_jointsList;
|
||||
@ -161,7 +119,7 @@ void RigidBody::removeJointFrom_jointsList(MemoryAllocator& memoryAllocator, con
|
||||
}
|
||||
else { // If the element to remove is not the first one in the list
|
||||
JointListElement* currentElement = m_jointsList;
|
||||
while (currentElement->next != NULL) {
|
||||
while (currentElement->next != nullptr) {
|
||||
if (currentElement->next->joint == joint) {
|
||||
JointListElement* elementToRemove = currentElement->next;
|
||||
currentElement->next = elementToRemove->next;
|
||||
@ -191,10 +149,10 @@ void RigidBody::removeJointFrom_jointsList(MemoryAllocator& memoryAllocator, con
|
||||
* the new collision shape you have added.
|
||||
*/
|
||||
ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
|
||||
const Transform& transform,
|
||||
const etk::Transform3D& transform,
|
||||
float mass) {
|
||||
|
||||
assert(mass > float(0.0));
|
||||
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(
|
||||
@ -235,154 +193,120 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
|
||||
* @param proxyShape The pointer of the proxy shape you want to remove
|
||||
*/
|
||||
void RigidBody::removeCollisionShape(const ProxyShape* proxyShape) {
|
||||
|
||||
// Remove the collision shape
|
||||
CollisionBody::removeCollisionShape(proxyShape);
|
||||
|
||||
// Recompute the total mass, center of mass and inertia tensor
|
||||
recomputeMassInformation();
|
||||
}
|
||||
|
||||
// Set the linear velocity of the rigid body.
|
||||
/**
|
||||
* @param linearVelocity Linear velocity vector of the body
|
||||
*/
|
||||
void RigidBody::setLinearVelocity(const Vector3& linearVelocity) {
|
||||
|
||||
// If it is a static body, we do nothing
|
||||
if (m_type == STATIC) return;
|
||||
|
||||
// Update the linear velocity of the current body state
|
||||
m_linearVelocity = linearVelocity;
|
||||
|
||||
// If the linear velocity is not zero, awake the body
|
||||
if (m_linearVelocity.lengthSquare() > float(0.0)) {
|
||||
void RigidBody::setLinearVelocity(const vec3& _linearVelocity) {
|
||||
if (m_type == STATIC) {
|
||||
return;
|
||||
}
|
||||
m_linearVelocity = _linearVelocity;
|
||||
if (m_linearVelocity.length2() > 0.0f) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the angular velocity.
|
||||
/**
|
||||
* @param angularVelocity The angular velocity vector of the body
|
||||
*/
|
||||
void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
|
||||
|
||||
// If it is a static body, we do nothing
|
||||
if (m_type == STATIC) return;
|
||||
|
||||
// Set the angular velocity
|
||||
m_angularVelocity = angularVelocity;
|
||||
|
||||
// If the velocity is not zero, awake the body
|
||||
if (m_angularVelocity.lengthSquare() > float(0.0)) {
|
||||
void RigidBody::setAngularVelocity(const vec3& _angularVelocity) {
|
||||
if (m_type == STATIC) {
|
||||
return;
|
||||
}
|
||||
m_angularVelocity = _angularVelocity;
|
||||
if (m_angularVelocity.length2() > 0.0f) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 RigidBody::setTransform(const Transform& transform) {
|
||||
void RigidBody::setIsSleeping(bool _isSleeping) {
|
||||
if (_isSleeping) {
|
||||
m_linearVelocity.setZero();
|
||||
m_angularVelocity.setZero();
|
||||
m_externalForce.setZero();
|
||||
m_externalTorque.setZero();
|
||||
}
|
||||
Body::setIsSleeping(_isSleeping);
|
||||
}
|
||||
|
||||
// Update the transform of the body
|
||||
m_transform = transform;
|
||||
|
||||
const Vector3 oldCenterOfMass = m_centerOfMassWorld;
|
||||
|
||||
void RigidBody::setTransform(const etk::Transform3D& _transform) {
|
||||
m_transform = _transform;
|
||||
const vec3 oldCenterOfMass = m_centerOfMassWorld;
|
||||
// Compute the new center of mass in world-space coordinates
|
||||
m_centerOfMassWorld = m_transform * m_centerOfMassLocal;
|
||||
|
||||
// Update the linear velocity of the center of mass
|
||||
m_linearVelocity += m_angularVelocity.cross(m_centerOfMassWorld - oldCenterOfMass);
|
||||
|
||||
// Update the broad-phase state of the body
|
||||
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 = float(0.0);
|
||||
m_massInverse = float(0.0);
|
||||
m_inertiaTensorLocal.setToZero();
|
||||
m_inertiaTensorLocalInverse.setToZero();
|
||||
m_centerOfMassLocal.setToZero();
|
||||
|
||||
m_initMass = 0.0f;
|
||||
m_massInverse = 0.0f;
|
||||
m_inertiaTensorLocal.setZero();
|
||||
m_inertiaTensorLocalInverse.setZero();
|
||||
m_centerOfMassLocal.setZero();
|
||||
// If it is STATIC or KINEMATIC body
|
||||
if (m_type == STATIC || m_type == KINEMATIC) {
|
||||
m_centerOfMassWorld = m_transform.getPosition();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_type == DYNAMIC);
|
||||
|
||||
// Compute the total mass of the body
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
m_initMass += shape->getMass();
|
||||
m_centerOfMassLocal += shape->getLocalToBodyTransform().getPosition() * shape->getMass();
|
||||
}
|
||||
|
||||
if (m_initMass > float(0.0)) {
|
||||
m_massInverse = float(1.0) / m_initMass;
|
||||
if (m_initMass > 0.0f) {
|
||||
m_massInverse = 1.0f / m_initMass;
|
||||
} else {
|
||||
m_initMass = 1.0f;
|
||||
m_massInverse = 1.0f;
|
||||
}
|
||||
else {
|
||||
m_initMass = float(1.0);
|
||||
m_massInverse = float(1.0);
|
||||
}
|
||||
|
||||
// Compute the center of mass
|
||||
const Vector3 oldCenterOfMass = m_centerOfMassWorld;
|
||||
const vec3 oldCenterOfMass = m_centerOfMassWorld;
|
||||
m_centerOfMassLocal *= m_massInverse;
|
||||
m_centerOfMassWorld = m_transform * m_centerOfMassLocal;
|
||||
|
||||
// Compute the total mass and inertia tensor using all the collision shapes
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != NULL; shape = shape->m_next) {
|
||||
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
// Get the inertia tensor of the collision shape in its local-space
|
||||
Matrix3x3 inertiaTensor;
|
||||
etk::Matrix3x3 inertiaTensor;
|
||||
shape->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, shape->getMass());
|
||||
|
||||
// Convert the collision shape inertia tensor int32_to the local-space of the body
|
||||
const Transform& shapeTransform = shape->getLocalToBodyTransform();
|
||||
Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix();
|
||||
const etk::Transform3D& shapeTransform = shape->getLocalToBodyTransform();
|
||||
etk::Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix();
|
||||
inertiaTensor = rotationMatrix * inertiaTensor * rotationMatrix.getTranspose();
|
||||
|
||||
// Use the parallel axis theorem to convert the inertia tensor w.r.t the collision shape
|
||||
// center int32_to a inertia tensor w.r.t to the body origin.
|
||||
Vector3 offset = shapeTransform.getPosition() - m_centerOfMassLocal;
|
||||
float offsetSquare = offset.lengthSquare();
|
||||
Matrix3x3 offsetMatrix;
|
||||
offsetMatrix[0].setAllValues(offsetSquare, float(0.0), float(0.0));
|
||||
offsetMatrix[1].setAllValues(float(0.0), offsetSquare, float(0.0));
|
||||
offsetMatrix[2].setAllValues(float(0.0), float(0.0), offsetSquare);
|
||||
offsetMatrix[0] += offset * (-offset.x);
|
||||
offsetMatrix[1] += offset * (-offset.y);
|
||||
offsetMatrix[2] += offset * (-offset.z);
|
||||
vec3 offset = shapeTransform.getPosition() - m_centerOfMassLocal;
|
||||
float offsetSquare = offset.length2();
|
||||
vec3 off1 = offset * (-offset.x());
|
||||
vec3 off2 = offset * (-offset.y());
|
||||
vec3 off3 = offset * (-offset.z());
|
||||
etk::Matrix3x3 offsetMatrix(off1.x()+offsetSquare, off1.y(), off1.z(),
|
||||
off2.x(), off2.y()+offsetSquare, off2.z(),
|
||||
off3.x(), off3.y(), off3.z()+offsetSquare);
|
||||
offsetMatrix *= shape->getMass();
|
||||
|
||||
m_inertiaTensorLocal += inertiaTensor + offsetMatrix;
|
||||
}
|
||||
|
||||
// Compute the local inverse inertia tensor
|
||||
m_inertiaTensorLocalInverse = m_inertiaTensorLocal.getInverse();
|
||||
|
||||
// Update the linear velocity of the center of mass
|
||||
m_linearVelocity += m_angularVelocity.cross(m_centerOfMassWorld - oldCenterOfMass);
|
||||
}
|
||||
|
||||
// Update the broad-phase state for this body (because it has moved for instance)
|
||||
|
||||
void RigidBody::updateBroadPhaseState() const {
|
||||
|
||||
PROFILE("RigidBody::updateBroadPhaseState()");
|
||||
|
||||
DynamicsWorld& world = static_cast<DynamicsWorld&>(m_world);
|
||||
const Vector3 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 != NULL; shape = shape->m_next) {
|
||||
for (ProxyShape* shape = m_proxyCollisionShapes; shape != nullptr; shape = shape->m_next) {
|
||||
|
||||
// Recompute the world-space AABB of the collision shape
|
||||
AABB aabb;
|
||||
@ -393,3 +317,43 @@ 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;
|
||||
}
|
@ -5,14 +5,12 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cassert>
|
||||
#include <ephysics/body/CollisionBody.h>
|
||||
#include <ephysics/engine/Material.h>
|
||||
#include <ephysics/mathematics/mathematics.h>
|
||||
#include <ephysics/memory/MemoryAllocator.h>
|
||||
|
||||
/// Namespace reactphysics3d
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class declarations
|
||||
@ -20,177 +18,259 @@ struct JointListElement;
|
||||
class Joint;
|
||||
class DynamicsWorld;
|
||||
|
||||
// Class RigidBody
|
||||
/**
|
||||
* This class represents a rigid body of the physics
|
||||
* @brief This class represents a rigid body of the physics
|
||||
* engine. A rigid body is a non-deformable body that
|
||||
* has a constant mass. This class inherits from the
|
||||
* CollisionBody class.
|
||||
*/
|
||||
*/
|
||||
class RigidBody : public CollisionBody {
|
||||
|
||||
protected :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Intial mass of the body
|
||||
float m_initMass;
|
||||
|
||||
/// Center of mass of the body in local-space coordinates.
|
||||
/// The center of mass can therefore be different from the body origin
|
||||
Vector3 m_centerOfMassLocal;
|
||||
|
||||
/// Center of mass of the body in world-space coordinates
|
||||
Vector3 m_centerOfMassWorld;
|
||||
|
||||
/// Linear velocity of the body
|
||||
Vector3 m_linearVelocity;
|
||||
|
||||
/// Angular velocity of the body
|
||||
Vector3 m_angularVelocity;
|
||||
|
||||
/// Current external force on the body
|
||||
Vector3 m_externalForce;
|
||||
|
||||
/// Current external torque on the body
|
||||
Vector3 m_externalTorque;
|
||||
|
||||
/// Local inertia tensor of the body (in local-space) with respect to the
|
||||
/// center of mass of the body
|
||||
Matrix3x3 m_inertiaTensorLocal;
|
||||
|
||||
/// Inverse of the inertia tensor of the body
|
||||
Matrix3x3 m_inertiaTensorLocalInverse;
|
||||
|
||||
/// Inverse of the mass of the body
|
||||
float m_massInverse;
|
||||
|
||||
/// True if the gravity needs to be applied to this rigid body
|
||||
bool m_isGravityEnabled;
|
||||
|
||||
/// Material properties of the rigid body
|
||||
Material m_material;
|
||||
|
||||
/// Linear velocity damping factor
|
||||
float m_linearDamping;
|
||||
|
||||
/// Angular velocity damping factor
|
||||
float m_angularDamping;
|
||||
|
||||
/// First element of the linked list of joints involving this body
|
||||
JointListElement* m_jointsList;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
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);
|
||||
|
||||
/// Remove a joint from the joints list
|
||||
void removeJointFrom_jointsList(MemoryAllocator& memoryAllocator, const Joint* joint);
|
||||
|
||||
/// Update the transform of the body after a change of the center of mass
|
||||
void updateTransformWithCenterOfMass();
|
||||
|
||||
/// Update the broad-phase state for this body (because it has moved for instance)
|
||||
/**
|
||||
* @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 :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
RigidBody(const Transform& transform, CollisionWorld& world, bodyindex id);
|
||||
/**
|
||||
* @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();
|
||||
|
||||
/// Set the type of the body (static, kinematic or dynamic)
|
||||
void setType(BodyType type);
|
||||
|
||||
/// Set the current position and orientation
|
||||
virtual void setTransform(const Transform& transform);
|
||||
|
||||
/// Return the mass of the body
|
||||
float getMass() const;
|
||||
|
||||
/// Return the linear velocity
|
||||
Vector3 getLinearVelocity() const;
|
||||
|
||||
/// Set the linear velocity of the body.
|
||||
void setLinearVelocity(const Vector3& linearVelocity);
|
||||
|
||||
/// Return the angular velocity
|
||||
Vector3 getAngularVelocity() const;
|
||||
|
||||
/// Set the angular velocity.
|
||||
void setAngularVelocity(const Vector3& angularVelocity);
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
/// Return the local inertia tensor of the body (in body coordinates)
|
||||
const Matrix3x3& getInertiaTensorLocal() const;
|
||||
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 Matrix3x3& inertiaTensorLocal);
|
||||
void setInertiaTensorLocal(const etk::Matrix3x3& inertiaTensorLocal);
|
||||
|
||||
/// Set the local center of mass of the body (in local-space coordinates)
|
||||
void setCenterOfMassLocal(const Vector3& centerOfMassLocal);
|
||||
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);
|
||||
|
||||
/// Set the mass of the rigid body
|
||||
void setMass(float mass);
|
||||
|
||||
/// Return the inertia tensor in world coordinates.
|
||||
Matrix3x3 getInertiaTensorWorld() const;
|
||||
|
||||
/// Return the inverse of the inertia tensor in world coordinates.
|
||||
Matrix3x3 getInertiaTensorInverseWorld() const;
|
||||
|
||||
/// Return true if the gravity needs to be applied to this rigid body
|
||||
bool isGravityEnabled() const;
|
||||
|
||||
/// Set the variable to know if the gravity is applied to this rigid body
|
||||
void enableGravity(bool isEnabled);
|
||||
|
||||
/// Return a reference to the material properties of the rigid body
|
||||
Material& getMaterial();
|
||||
|
||||
/// Set a new material for this rigid body
|
||||
void setMaterial(const Material& material);
|
||||
|
||||
/// Return the linear velocity damping factor
|
||||
float getLinearDamping() const;
|
||||
|
||||
/// Set the linear damping factor
|
||||
void setLinearDamping(float linearDamping);
|
||||
|
||||
/// Return the angular velocity damping factor
|
||||
float getAngularDamping() const;
|
||||
|
||||
/// Set the angular damping factor
|
||||
void setAngularDamping(float angularDamping);
|
||||
|
||||
/// Return the first element of the linked list of joints involving this body
|
||||
const JointListElement* getJointsList() const;
|
||||
|
||||
/// Return the first element of the linked list of joints involving this body
|
||||
JointListElement* getJointsList();
|
||||
|
||||
/// Apply an external force to the body at its center of mass.
|
||||
void applyForceToCenterOfMass(const Vector3& force);
|
||||
|
||||
/// Apply an external force to the body at a given point (in world-space coordinates).
|
||||
void applyForce(const Vector3& force, const Vector3& point);
|
||||
|
||||
/// Apply an external torque to the body.
|
||||
void applyTorque(const Vector3& torque);
|
||||
/**
|
||||
* @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 Transform& transform,
|
||||
const etk::Transform3D& transform,
|
||||
float mass);
|
||||
|
||||
/// Remove a collision shape from the body
|
||||
@ -200,8 +280,6 @@ class RigidBody : public CollisionBody {
|
||||
/// the collision shapes attached to the body.
|
||||
void recomputeMassInformation();
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicsWorld;
|
||||
friend class ContactSolver;
|
||||
friend class BallAndSocketJoint;
|
||||
@ -210,247 +288,18 @@ class RigidBody : public CollisionBody {
|
||||
friend class FixedJoint;
|
||||
};
|
||||
|
||||
// Method that return the mass of the body
|
||||
/**
|
||||
* @return The mass (in kilograms) of the body
|
||||
*/
|
||||
inline float RigidBody::getMass() const {
|
||||
return m_initMass;
|
||||
}
|
||||
|
||||
// Return the linear velocity
|
||||
/**
|
||||
* @return The linear velocity vector of the body
|
||||
*/
|
||||
inline Vector3 RigidBody::getLinearVelocity() const {
|
||||
return m_linearVelocity;
|
||||
}
|
||||
|
||||
// Return the angular velocity of the body
|
||||
/**
|
||||
* @return The angular velocity vector of the body
|
||||
*/
|
||||
inline Vector3 RigidBody::getAngularVelocity() const {
|
||||
return m_angularVelocity;
|
||||
}
|
||||
|
||||
// Return the local inertia tensor of the body (in local-space coordinates)
|
||||
/**
|
||||
* @return The 3x3 inertia tensor matrix of the body (in local-space coordinates)
|
||||
*/
|
||||
inline const Matrix3x3& RigidBody::getInertiaTensorLocal() const {
|
||||
return m_inertiaTensorLocal;
|
||||
}
|
||||
|
||||
// Return 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
|
||||
*/
|
||||
inline Matrix3x3 RigidBody::getInertiaTensorWorld() const {
|
||||
|
||||
// Compute and return the inertia tensor in world coordinates
|
||||
return m_transform.getOrientation().getMatrix() * m_inertiaTensorLocal *
|
||||
m_transform.getOrientation().getMatrix().getTranspose();
|
||||
}
|
||||
|
||||
// Return 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
|
||||
*/
|
||||
inline Matrix3x3 RigidBody::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();
|
||||
}
|
||||
|
||||
// Return true if the gravity needs to be applied to this rigid body
|
||||
/**
|
||||
* @return True if the gravity is applied to the body
|
||||
*/
|
||||
inline bool RigidBody::isGravityEnabled() const {
|
||||
return m_isGravityEnabled;
|
||||
}
|
||||
|
||||
// Set the variable to know if the gravity is applied to this rigid body
|
||||
/**
|
||||
* @param isEnabled True if you want the gravity to be applied to this body
|
||||
*/
|
||||
inline void RigidBody::enableGravity(bool isEnabled) {
|
||||
m_isGravityEnabled = isEnabled;
|
||||
}
|
||||
|
||||
// Return a reference to the material properties of the rigid body
|
||||
/**
|
||||
* @return A reference to the material of the body
|
||||
*/
|
||||
inline Material& RigidBody::getMaterial() {
|
||||
return m_material;
|
||||
}
|
||||
|
||||
// Set a new material for this rigid body
|
||||
/**
|
||||
* @param material The material you want to set to the body
|
||||
*/
|
||||
inline void RigidBody::setMaterial(const Material& material) {
|
||||
m_material = material;
|
||||
}
|
||||
|
||||
// Return the linear velocity damping factor
|
||||
/**
|
||||
* @return The linear damping factor of this body
|
||||
*/
|
||||
inline float RigidBody::getLinearDamping() const {
|
||||
return m_linearDamping;
|
||||
}
|
||||
|
||||
// Set the linear damping factor. This is the ratio of the linear velocity
|
||||
// that the body will lose every at seconds of simulation.
|
||||
/**
|
||||
* @param linearDamping The linear damping factor of this body
|
||||
*/
|
||||
inline void RigidBody::setLinearDamping(float linearDamping) {
|
||||
assert(linearDamping >= float(0.0));
|
||||
m_linearDamping = linearDamping;
|
||||
}
|
||||
|
||||
// Return the angular velocity damping factor
|
||||
/**
|
||||
* @return The angular damping factor of this body
|
||||
*/
|
||||
inline float RigidBody::getAngularDamping() const {
|
||||
return m_angularDamping;
|
||||
}
|
||||
|
||||
// Set the angular damping factor. This is the ratio of the angular velocity
|
||||
// that the body will lose at every seconds of simulation.
|
||||
/**
|
||||
* @param angularDamping The angular damping factor of this body
|
||||
*/
|
||||
inline void RigidBody::setAngularDamping(float angularDamping) {
|
||||
assert(angularDamping >= float(0.0));
|
||||
m_angularDamping = angularDamping;
|
||||
}
|
||||
|
||||
// Return 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
|
||||
*/
|
||||
inline const JointListElement* RigidBody::getJointsList() const {
|
||||
return m_jointsList;
|
||||
}
|
||||
|
||||
// Return 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
|
||||
*/
|
||||
inline JointListElement* RigidBody::getJointsList() {
|
||||
return m_jointsList;
|
||||
}
|
||||
|
||||
// Set the variable to know whether or not the body is sleeping
|
||||
inline void RigidBody::setIsSleeping(bool isSleeping) {
|
||||
|
||||
if (isSleeping) {
|
||||
m_linearVelocity.setToZero();
|
||||
m_angularVelocity.setToZero();
|
||||
m_externalForce.setToZero();
|
||||
m_externalTorque.setToZero();
|
||||
}
|
||||
|
||||
Body::setIsSleeping(isSleeping);
|
||||
}
|
||||
|
||||
// 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 force The external force to apply on the center of mass of the body
|
||||
*/
|
||||
inline void RigidBody::applyForceToCenterOfMass(const Vector3& 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;
|
||||
}
|
||||
|
||||
// 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 force The force to apply on the body
|
||||
* @param point The point where the force is applied (in world-space coordinates)
|
||||
*/
|
||||
inline void RigidBody::applyForce(const Vector3& force, const Vector3& 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);
|
||||
}
|
||||
|
||||
// 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 torque The external torque to apply on the body
|
||||
*/
|
||||
inline void RigidBody::applyTorque(const Vector3& 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;
|
||||
}
|
||||
|
||||
/// Update the transform of the body after a change of the center of mass
|
||||
inline void RigidBody::updateTransformWithCenterOfMass() {
|
||||
|
||||
// Translate the body according to the translation of the center of mass position
|
||||
m_transform.setPosition(m_centerOfMassWorld - m_transform.getOrientation() * m_centerOfMassLocal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ class CollisionDetection : public NarrowPhaseCallback {
|
||||
|
||||
/// Update a proxy collision shape (that has moved for instance)
|
||||
void updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb,
|
||||
const Vector3& displacement = Vector3(0, 0, 0), bool forceReinsert = false);
|
||||
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);
|
||||
@ -257,7 +257,7 @@ inline void CollisionDetection::askForBroadPhaseCollisionCheck(ProxyShape* shape
|
||||
|
||||
// Update a proxy collision shape (that has moved for instance)
|
||||
inline void CollisionDetection::updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb,
|
||||
const Vector3& displacement, bool forceReinsert) {
|
||||
const vec3& displacement, bool forceReinsert) {
|
||||
m_broadPhaseAlgorithm.updateProxyCollisionShape(shape, aabb, displacement);
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,15 @@ struct CollisionShapeInfo {
|
||||
/// Pointer to the collision shape
|
||||
const CollisionShape* collisionShape;
|
||||
|
||||
/// Transform that maps from collision shape local-space to world-space
|
||||
Transform shapeToWorldTransform;
|
||||
/// etk::Transform3D that maps from collision shape local-space to world-space
|
||||
etk::Transform3D shapeToWorldTransform;
|
||||
|
||||
/// Cached collision data of the proxy shape
|
||||
void** cachedCollisionData;
|
||||
|
||||
/// Constructor
|
||||
CollisionShapeInfo(ProxyShape* proxyCollisionShape, const CollisionShape* shape,
|
||||
const Transform& shapeLocalToWorldTransform, OverlappingPair* pair,
|
||||
const etk::Transform3D& shapeLocalToWorldTransform, OverlappingPair* pair,
|
||||
void** cachedData)
|
||||
: overlappingPair(pair), proxyShape(proxyCollisionShape), collisionShape(shape),
|
||||
shapeToWorldTransform(shapeLocalToWorldTransform),
|
||||
|
@ -35,7 +35,7 @@ void ContactManifold::addContactPoint(ContactPoint* contact) {
|
||||
// Check if the new point point does not correspond to a same contact point
|
||||
// already in the manifold.
|
||||
float distance = (m_contactPoints[i]->getWorldPointOnBody1() -
|
||||
contact->getWorldPointOnBody1()).lengthSquare();
|
||||
contact->getWorldPointOnBody1()).length2();
|
||||
if (distance <= PERSISTENT_CONTACT_DIST_THRESHOLD*PERSISTENT_CONTACT_DIST_THRESHOLD) {
|
||||
|
||||
// Delete the new contact
|
||||
@ -86,7 +86,7 @@ void ContactManifold::removeContactPoint(uint32_t index) {
|
||||
/// with a negative penetration depth (meaning that the bodies are not penetrating anymore) and also
|
||||
/// the contacts with a too large distance between the contact points in the plane orthogonal to the
|
||||
/// contact normal.
|
||||
void ContactManifold::update(const Transform& transform1, const Transform& transform2) {
|
||||
void ContactManifold::update(const etk::Transform3D& transform1, const etk::Transform3D& transform2) {
|
||||
|
||||
if (m_nbContactPoints == 0) return;
|
||||
|
||||
@ -117,13 +117,13 @@ void ContactManifold::update(const Transform& transform1, const Transform& trans
|
||||
else {
|
||||
// Compute the distance of the two contact points in the plane
|
||||
// orthogonal to the contact normal
|
||||
Vector3 projOfPoint1 = m_contactPoints[i]->getWorldPointOnBody1() +
|
||||
vec3 projOfPoint1 = m_contactPoints[i]->getWorldPointOnBody1() +
|
||||
m_contactPoints[i]->getNormal() * distanceNormal;
|
||||
Vector3 projDifference = m_contactPoints[i]->getWorldPointOnBody2() - projOfPoint1;
|
||||
vec3 projDifference = m_contactPoints[i]->getWorldPointOnBody2() - projOfPoint1;
|
||||
|
||||
// If the orthogonal distance is larger than the valid distance
|
||||
// threshold, we remove the contact
|
||||
if (projDifference.lengthSquare() > squarePersistentContactThreshold) {
|
||||
if (projDifference.length2() > squarePersistentContactThreshold) {
|
||||
removeContactPoint(i);
|
||||
}
|
||||
}
|
||||
@ -162,7 +162,7 @@ int32_t ContactManifold::getIndexOfDeepestPenetration(ContactPoint* newContact)
|
||||
/// only estimate it because we do not compute the actual diagonals of the quadrialteral. Therefore,
|
||||
/// this is only a guess that is faster to compute. This idea comes from the Bullet Physics library
|
||||
/// by Erwin Coumans (http://wwww.bulletphysics.org).
|
||||
int32_t ContactManifold::getIndexToRemove(int32_t indexMaxPenetration, const Vector3& newPoint) const {
|
||||
int32_t ContactManifold::getIndexToRemove(int32_t indexMaxPenetration, const vec3& newPoint) const {
|
||||
|
||||
assert(m_nbContactPoints == MAX_CONTACT_POINTS_IN_MANIFOLD);
|
||||
|
||||
@ -173,35 +173,35 @@ int32_t ContactManifold::getIndexToRemove(int32_t indexMaxPenetration, const Vec
|
||||
|
||||
if (indexMaxPenetration != 0) {
|
||||
// Compute the area
|
||||
Vector3 vector1 = newPoint - m_contactPoints[1]->getLocalPointOnBody1();
|
||||
Vector3 vector2 = m_contactPoints[3]->getLocalPointOnBody1() -
|
||||
vec3 vector1 = newPoint - m_contactPoints[1]->getLocalPointOnBody1();
|
||||
vec3 vector2 = m_contactPoints[3]->getLocalPointOnBody1() -
|
||||
m_contactPoints[2]->getLocalPointOnBody1();
|
||||
Vector3 crossProduct = vector1.cross(vector2);
|
||||
area0 = crossProduct.lengthSquare();
|
||||
vec3 crossProduct = vector1.cross(vector2);
|
||||
area0 = crossProduct.length2();
|
||||
}
|
||||
if (indexMaxPenetration != 1) {
|
||||
// Compute the area
|
||||
Vector3 vector1 = newPoint - m_contactPoints[0]->getLocalPointOnBody1();
|
||||
Vector3 vector2 = m_contactPoints[3]->getLocalPointOnBody1() -
|
||||
vec3 vector1 = newPoint - m_contactPoints[0]->getLocalPointOnBody1();
|
||||
vec3 vector2 = m_contactPoints[3]->getLocalPointOnBody1() -
|
||||
m_contactPoints[2]->getLocalPointOnBody1();
|
||||
Vector3 crossProduct = vector1.cross(vector2);
|
||||
area1 = crossProduct.lengthSquare();
|
||||
vec3 crossProduct = vector1.cross(vector2);
|
||||
area1 = crossProduct.length2();
|
||||
}
|
||||
if (indexMaxPenetration != 2) {
|
||||
// Compute the area
|
||||
Vector3 vector1 = newPoint - m_contactPoints[0]->getLocalPointOnBody1();
|
||||
Vector3 vector2 = m_contactPoints[3]->getLocalPointOnBody1() -
|
||||
vec3 vector1 = newPoint - m_contactPoints[0]->getLocalPointOnBody1();
|
||||
vec3 vector2 = m_contactPoints[3]->getLocalPointOnBody1() -
|
||||
m_contactPoints[1]->getLocalPointOnBody1();
|
||||
Vector3 crossProduct = vector1.cross(vector2);
|
||||
area2 = crossProduct.lengthSquare();
|
||||
vec3 crossProduct = vector1.cross(vector2);
|
||||
area2 = crossProduct.length2();
|
||||
}
|
||||
if (indexMaxPenetration != 3) {
|
||||
// Compute the area
|
||||
Vector3 vector1 = newPoint - m_contactPoints[0]->getLocalPointOnBody1();
|
||||
Vector3 vector2 = m_contactPoints[2]->getLocalPointOnBody1() -
|
||||
vec3 vector1 = newPoint - m_contactPoints[0]->getLocalPointOnBody1();
|
||||
vec3 vector2 = m_contactPoints[2]->getLocalPointOnBody1() -
|
||||
m_contactPoints[1]->getLocalPointOnBody1();
|
||||
Vector3 crossProduct = vector1.cross(vector2);
|
||||
area3 = crossProduct.lengthSquare();
|
||||
vec3 crossProduct = vector1.cross(vector2);
|
||||
area3 = crossProduct.length2();
|
||||
}
|
||||
|
||||
// Return the index of the contact to remove
|
||||
|
@ -84,10 +84,10 @@ class ContactManifold {
|
||||
uint32_t m_nbContactPoints;
|
||||
|
||||
/// First friction vector of the contact manifold
|
||||
Vector3 m_frictionVector1;
|
||||
vec3 m_frictionVector1;
|
||||
|
||||
/// Second friction vector of the contact manifold
|
||||
Vector3 m_frictionVector2;
|
||||
vec3 m_frictionvec2;
|
||||
|
||||
/// First friction constraint accumulated impulse
|
||||
float m_frictionImpulse1;
|
||||
@ -99,7 +99,7 @@ class ContactManifold {
|
||||
float m_frictionTwistImpulse;
|
||||
|
||||
/// Accumulated rolling resistance impulse
|
||||
Vector3 m_rollingResistanceImpulse;
|
||||
vec3 m_rollingResistanceImpulse;
|
||||
|
||||
/// True if the contact manifold has already been added int32_to an island
|
||||
bool m_isAlreadyInIsland;
|
||||
@ -122,7 +122,7 @@ class ContactManifold {
|
||||
int32_t getIndexOfDeepestPenetration(ContactPoint* newContact) const;
|
||||
|
||||
/// Return the index that will be removed.
|
||||
int32_t getIndexToRemove(int32_t indexMaxPenetration, const Vector3& newPoint) const;
|
||||
int32_t getIndexToRemove(int32_t indexMaxPenetration, const vec3& newPoint) const;
|
||||
|
||||
/// Remove a contact point from the manifold
|
||||
void removeContactPoint(uint32_t index);
|
||||
@ -160,7 +160,7 @@ class ContactManifold {
|
||||
void addContactPoint(ContactPoint* contact);
|
||||
|
||||
/// Update the contact manifold.
|
||||
void update(const Transform& transform1, const Transform& transform2);
|
||||
void update(const etk::Transform3D& transform1, const etk::Transform3D& transform2);
|
||||
|
||||
/// Clear the contact manifold
|
||||
void clear();
|
||||
@ -169,16 +169,16 @@ class ContactManifold {
|
||||
uint32_t getNbContactPoints() const;
|
||||
|
||||
/// Return the first friction vector at the center of the contact manifold
|
||||
const Vector3& getFrictionVector1() const;
|
||||
const vec3& getFrictionVector1() const;
|
||||
|
||||
/// set the first friction vector at the center of the contact manifold
|
||||
void setFrictionVector1(const Vector3& m_frictionVector1);
|
||||
void setFrictionVector1(const vec3& m_frictionVector1);
|
||||
|
||||
/// Return the second friction vector at the center of the contact manifold
|
||||
const Vector3& getFrictionVector2() const;
|
||||
const vec3& getFrictionvec2() const;
|
||||
|
||||
/// set the second friction vector at the center of the contact manifold
|
||||
void setFrictionVector2(const Vector3& m_frictionVector2);
|
||||
void setFrictionvec2(const vec3& m_frictionvec2);
|
||||
|
||||
/// Return the first friction accumulated impulse
|
||||
float getFrictionImpulse1() const;
|
||||
@ -199,13 +199,13 @@ class ContactManifold {
|
||||
void setFrictionTwistImpulse(float frictionTwistImpulse);
|
||||
|
||||
/// Set the accumulated rolling resistance impulse
|
||||
void setRollingResistanceImpulse(const Vector3& rollingResistanceImpulse);
|
||||
void setRollingResistanceImpulse(const vec3& rollingResistanceImpulse);
|
||||
|
||||
/// Return a contact point of the manifold
|
||||
ContactPoint* getContactPoint(uint32_t index) const;
|
||||
|
||||
/// Return the normalized averaged normal vector
|
||||
Vector3 getAverageContactNormal() const;
|
||||
vec3 getAverageContactNormal() const;
|
||||
|
||||
/// Return the largest depth of all the contact points
|
||||
float getLargestContactDepth() const;
|
||||
@ -248,23 +248,23 @@ inline uint32_t ContactManifold::getNbContactPoints() const {
|
||||
}
|
||||
|
||||
// Return the first friction vector at the center of the contact manifold
|
||||
inline const Vector3& ContactManifold::getFrictionVector1() const {
|
||||
inline 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 Vector3& frictionVector1) {
|
||||
inline void ContactManifold::setFrictionVector1(const vec3& frictionVector1) {
|
||||
m_frictionVector1 = frictionVector1;
|
||||
}
|
||||
|
||||
// Return the second friction vector at the center of the contact manifold
|
||||
inline const Vector3& ContactManifold::getFrictionVector2() const {
|
||||
return m_frictionVector2;
|
||||
inline const vec3& ContactManifold::getFrictionvec2() const {
|
||||
return m_frictionvec2;
|
||||
}
|
||||
|
||||
// set the second friction vector at the center of the contact manifold
|
||||
inline void ContactManifold::setFrictionVector2(const Vector3& frictionVector2) {
|
||||
m_frictionVector2 = frictionVector2;
|
||||
inline void ContactManifold::setFrictionvec2(const vec3& frictionvec2) {
|
||||
m_frictionvec2 = frictionvec2;
|
||||
}
|
||||
|
||||
// Return the first friction accumulated impulse
|
||||
@ -298,7 +298,7 @@ inline void ContactManifold::setFrictionTwistImpulse(float frictionTwistImpulse)
|
||||
}
|
||||
|
||||
// Set the accumulated rolling resistance impulse
|
||||
inline void ContactManifold::setRollingResistanceImpulse(const Vector3& rollingResistanceImpulse) {
|
||||
inline void ContactManifold::setRollingResistanceImpulse(const vec3& rollingResistanceImpulse) {
|
||||
m_rollingResistanceImpulse = rollingResistanceImpulse;
|
||||
}
|
||||
|
||||
@ -314,14 +314,14 @@ inline bool ContactManifold::isAlreadyInIsland() const {
|
||||
}
|
||||
|
||||
// Return the normalized averaged normal vector
|
||||
inline Vector3 ContactManifold::getAverageContactNormal() const {
|
||||
Vector3 averageNormal;
|
||||
inline vec3 ContactManifold::getAverageContactNormal() const {
|
||||
vec3 averageNormal;
|
||||
|
||||
for (uint32_t i=0; i<m_nbContactPoints; i++) {
|
||||
averageNormal += m_contactPoints[i]->getNormal();
|
||||
}
|
||||
|
||||
return averageNormal.getUnit();
|
||||
return averageNormal.safeNormalized();
|
||||
}
|
||||
|
||||
// Return the largest depth of all the contact points
|
||||
|
@ -129,29 +129,29 @@ int32_t ContactManifoldSet::selectManifoldWithSimilarNormal(int16_t normalDirect
|
||||
// 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 ContactManifoldSet::computeCubemapNormalId(const Vector3& normal) const {
|
||||
int16_t ContactManifoldSet::computeCubemapNormalId(const vec3& normal) const {
|
||||
|
||||
assert(normal.lengthSquare() > MACHINE_EPSILON);
|
||||
assert(normal.length2() > MACHINE_EPSILON);
|
||||
|
||||
int32_t faceNo;
|
||||
float u, v;
|
||||
float max = max3(fabs(normal.x), fabs(normal.y), fabs(normal.z));
|
||||
Vector3 normalScaled = normal / max;
|
||||
float max = max3(fabs(normal.x()), fabs(normal.y()), fabs(normal.z()));
|
||||
vec3 normalScaled = normal / max;
|
||||
|
||||
if (normalScaled.x >= normalScaled.y && normalScaled.x >= normalScaled.z) {
|
||||
faceNo = normalScaled.x > 0 ? 0 : 1;
|
||||
u = normalScaled.y;
|
||||
v = normalScaled.z;
|
||||
if (normalScaled.x() >= normalScaled.y() && normalScaled.x() >= normalScaled.z()) {
|
||||
faceNo = normalScaled.x() > 0 ? 0 : 1;
|
||||
u = normalScaled.y();
|
||||
v = normalScaled.z();
|
||||
}
|
||||
else if (normalScaled.y >= normalScaled.x && normalScaled.y >= normalScaled.z) {
|
||||
faceNo = normalScaled.y > 0 ? 2 : 3;
|
||||
u = normalScaled.x;
|
||||
v = normalScaled.z;
|
||||
else if (normalScaled.y() >= normalScaled.x() && normalScaled.y() >= normalScaled.z()) {
|
||||
faceNo = normalScaled.y() > 0 ? 2 : 3;
|
||||
u = normalScaled.x();
|
||||
v = normalScaled.z();
|
||||
}
|
||||
else {
|
||||
faceNo = normalScaled.z > 0 ? 4 : 5;
|
||||
u = normalScaled.x;
|
||||
v = normalScaled.y;
|
||||
faceNo = normalScaled.z() > 0 ? 4 : 5;
|
||||
u = normalScaled.x();
|
||||
v = normalScaled.y();
|
||||
}
|
||||
|
||||
int32_t indexU = floor(((u + 1)/2) * CONTACT_CUBEMAP_FACE_NB_SUBDIVISIONS);
|
||||
|
@ -59,7 +59,7 @@ class ContactManifoldSet {
|
||||
// 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 Vector3& normal) const;
|
||||
int16_t computeCubemapNormalId(const vec3& normal) const;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -13,10 +13,10 @@ using namespace reactphysics3d;
|
||||
/**
|
||||
* @param body Pointer to the parent body
|
||||
* @param shape Pointer to the collision shape
|
||||
* @param transform Transformation from collision shape local-space to body local-space
|
||||
* @param transform etk::Transform3Dation from collision shape local-space to body local-space
|
||||
* @param mass Mass of the collision shape (in kilograms)
|
||||
*/
|
||||
ProxyShape::ProxyShape(CollisionBody* body, CollisionShape* shape, const Transform& transform, float mass)
|
||||
ProxyShape::ProxyShape(CollisionBody* body, CollisionShape* shape, const etk::Transform3D& transform, float mass)
|
||||
:m_body(body), m_collisionShape(shape), m_localToBodyTransform(transform), m_mass(mass),
|
||||
m_next(NULL), m_broadPhaseID(-1), m_cachedCollisionData(NULL), m_userData(NULL),
|
||||
m_collisionCategoryBits(0x0001), m_collideWithMaskBits(0xFFFF) {
|
||||
@ -37,9 +37,9 @@ ProxyShape::~ProxyShape() {
|
||||
* @param worldPoint Point to test in world-space coordinates
|
||||
* @return True if the point is inside the collision shape
|
||||
*/
|
||||
bool ProxyShape::testPointInside(const Vector3& worldPoint) {
|
||||
const Transform localToWorld = m_body->getTransform() * m_localToBodyTransform;
|
||||
const Vector3 localPoint = localToWorld.getInverse() * worldPoint;
|
||||
bool ProxyShape::testPointInside(const vec3& worldPoint) {
|
||||
const etk::Transform3D localToWorld = m_body->getTransform() * m_localToBodyTransform;
|
||||
const vec3 localPoint = localToWorld.getInverse() * worldPoint;
|
||||
return m_collisionShape->testPointInside(localPoint, this);
|
||||
}
|
||||
|
||||
@ -56,8 +56,8 @@ bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
|
||||
if (!m_body->isActive()) return false;
|
||||
|
||||
// Convert the ray int32_to the local-space of the collision shape
|
||||
const Transform localToWorldTransform = getLocalToWorldTransform();
|
||||
const Transform worldToLocalTransform = localToWorldTransform.getInverse();
|
||||
const etk::Transform3D localToWorldTransform = getLocalToWorldTransform();
|
||||
const etk::Transform3D worldToLocalTransform = localToWorldTransform.getInverse();
|
||||
Ray rayLocal(worldToLocalTransform * ray.point1,
|
||||
worldToLocalTransform * ray.point2,
|
||||
ray.maxFraction);
|
||||
|
@ -34,7 +34,7 @@ class ProxyShape {
|
||||
CollisionShape* m_collisionShape;
|
||||
|
||||
/// Local-space to parent body-space transform (does not change over time)
|
||||
Transform m_localToBodyTransform;
|
||||
etk::Transform3D m_localToBodyTransform;
|
||||
|
||||
/// Mass (in kilogramms) of the corresponding collision shape
|
||||
float m_mass;
|
||||
@ -78,7 +78,7 @@ class ProxyShape {
|
||||
|
||||
/// Constructor
|
||||
ProxyShape(CollisionBody* body, CollisionShape* shape,
|
||||
const Transform& transform, float mass);
|
||||
const etk::Transform3D& transform, float mass);
|
||||
|
||||
/// Destructor
|
||||
virtual ~ProxyShape();
|
||||
@ -99,16 +99,16 @@ class ProxyShape {
|
||||
void setUserData(void* userData);
|
||||
|
||||
/// Return the local to parent body transform
|
||||
const Transform& getLocalToBodyTransform() const;
|
||||
const etk::Transform3D& getLocalToBodyTransform() const;
|
||||
|
||||
/// Set the local to parent body transform
|
||||
void setLocalToBodyTransform(const Transform& transform);
|
||||
void setLocalToBodyTransform(const etk::Transform3D& transform);
|
||||
|
||||
/// Return the local to world transform
|
||||
const Transform getLocalToWorldTransform() const;
|
||||
const etk::Transform3D getLocalToWorldTransform() const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
bool testPointInside(const Vector3& worldPoint);
|
||||
bool testPointInside(const vec3& worldPoint);
|
||||
|
||||
/// Raycast method with feedback information
|
||||
bool raycast(const Ray& ray, RaycastInfo& raycastInfo);
|
||||
@ -135,10 +135,10 @@ class ProxyShape {
|
||||
void** getCachedCollisionData();
|
||||
|
||||
/// Return the local scaling vector of the collision shape
|
||||
Vector3 getLocalScaling() const;
|
||||
vec3 getLocalScaling() const;
|
||||
|
||||
/// Set the local scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
@ -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 Transform& ProxyShape::getLocalToBodyTransform() const {
|
||||
inline const etk::Transform3D& ProxyShape::getLocalToBodyTransform() const {
|
||||
return m_localToBodyTransform;
|
||||
}
|
||||
|
||||
// Set the local to parent body transform
|
||||
inline void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
|
||||
inline void ProxyShape::setLocalToBodyTransform(const etk::Transform3D& transform) {
|
||||
|
||||
m_localToBodyTransform = transform;
|
||||
|
||||
@ -226,7 +226,7 @@ inline void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
|
||||
* @return The transformation that transforms the local-space of the collision
|
||||
* shape to the world-space
|
||||
*/
|
||||
inline const Transform ProxyShape::getLocalToWorldTransform() const {
|
||||
inline const etk::Transform3D ProxyShape::getLocalToWorldTransform() const {
|
||||
return m_body->m_transform * m_localToBodyTransform;
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ inline void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBit
|
||||
/**
|
||||
* @return The local scaling vector
|
||||
*/
|
||||
inline Vector3 ProxyShape::getLocalScaling() const {
|
||||
inline vec3 ProxyShape::getLocalScaling() const {
|
||||
return m_collisionShape->getScaling();
|
||||
}
|
||||
|
||||
@ -290,7 +290,7 @@ inline Vector3 ProxyShape::getLocalScaling() const {
|
||||
/**
|
||||
* @param scaling The new local scaling vector
|
||||
*/
|
||||
inline void ProxyShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void ProxyShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
// Set the local scaling of the collision shape
|
||||
m_collisionShape->setLocalScaling(scaling);
|
||||
|
@ -6,7 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <etk/math/Vector3D.hpp>
|
||||
#include <ephysics/mathematics/Ray.h>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
@ -38,10 +38,10 @@ struct RaycastInfo {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Hit point in world-space coordinates
|
||||
Vector3 worldPoint;
|
||||
vec3 worldPoint;
|
||||
|
||||
/// Surface normal at hit point in world-space coordinates
|
||||
Vector3 worldNormal;
|
||||
vec3 worldNormal;
|
||||
|
||||
/// Fraction distance of the hit point between point1 and point2 of the ray
|
||||
/// The hit point "p" is such that p = point1 + hitFraction * (point2 - point1)
|
||||
|
@ -124,7 +124,7 @@ void BroadPhaseAlgorithm::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
||||
|
||||
// Notify the broad-phase that a collision shape has moved and need to be updated
|
||||
void BroadPhaseAlgorithm::updateProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb,
|
||||
const Vector3& displacement, bool forceReinsert) {
|
||||
const vec3& displacement, bool forceReinsert) {
|
||||
|
||||
int32_t broadPhaseID = proxyShape->m_broadPhaseID;
|
||||
|
||||
|
@ -165,7 +165,7 @@ class BroadPhaseAlgorithm {
|
||||
|
||||
/// Notify the broad-phase that a collision shape has moved and need to be updated
|
||||
void updateProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb,
|
||||
const Vector3& displacement, bool forceReinsert = false);
|
||||
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.
|
||||
|
@ -16,7 +16,7 @@ using namespace reactphysics3d;
|
||||
const int32_t TreeNode::NULL_TREE_NODE = -1;
|
||||
|
||||
// Constructor
|
||||
DynamicAABBTree::DynamicAABBTree(float extraAABBGap) : mExtraAABBGap(extraAABBGap) {
|
||||
DynamicAABBTree::DynamicAABBTree(float extraAABBGap) : m_extraAABBGap(extraAABBGap) {
|
||||
|
||||
init();
|
||||
}
|
||||
@ -25,36 +25,36 @@ DynamicAABBTree::DynamicAABBTree(float extraAABBGap) : mExtraAABBGap(extraAABBGa
|
||||
DynamicAABBTree::~DynamicAABBTree() {
|
||||
|
||||
// Free the allocated memory for the nodes
|
||||
free(mNodes);
|
||||
free(m_nodes);
|
||||
}
|
||||
|
||||
// Initialize the tree
|
||||
void DynamicAABBTree::init() {
|
||||
|
||||
m_rootNodeID = TreeNode::NULL_TREE_NODE;
|
||||
mNbNodes = 0;
|
||||
mNbAllocatedNodes = 8;
|
||||
m_numberNodes = 0;
|
||||
m_numberAllocatedNodes = 8;
|
||||
|
||||
// Allocate memory for the nodes of the tree
|
||||
mNodes = (TreeNode*) malloc(mNbAllocatedNodes * sizeof(TreeNode));
|
||||
assert(mNodes);
|
||||
memset(mNodes, 0, mNbAllocatedNodes * sizeof(TreeNode));
|
||||
m_nodes = (TreeNode*) malloc(m_numberAllocatedNodes * sizeof(TreeNode));
|
||||
assert(m_nodes);
|
||||
memset(m_nodes, 0, m_numberAllocatedNodes * sizeof(TreeNode));
|
||||
|
||||
// Initialize the allocated nodes
|
||||
for (int32_t i=0; i<mNbAllocatedNodes - 1; i++) {
|
||||
mNodes[i].nextNodeID = i + 1;
|
||||
mNodes[i].height = -1;
|
||||
for (int32_t i=0; i<m_numberAllocatedNodes - 1; i++) {
|
||||
m_nodes[i].nextNodeID = i + 1;
|
||||
m_nodes[i].height = -1;
|
||||
}
|
||||
mNodes[mNbAllocatedNodes - 1].nextNodeID = TreeNode::NULL_TREE_NODE;
|
||||
mNodes[mNbAllocatedNodes - 1].height = -1;
|
||||
mFreeNodeID = 0;
|
||||
m_nodes[m_numberAllocatedNodes - 1].nextNodeID = TreeNode::NULL_TREE_NODE;
|
||||
m_nodes[m_numberAllocatedNodes - 1].height = -1;
|
||||
m_freeNodeID = 0;
|
||||
}
|
||||
|
||||
// Clear all the nodes and reset the tree
|
||||
void DynamicAABBTree::reset() {
|
||||
|
||||
// Free the allocated memory for the nodes
|
||||
free(mNodes);
|
||||
free(m_nodes);
|
||||
|
||||
// Initialize the tree
|
||||
init();
|
||||
@ -64,34 +64,34 @@ void DynamicAABBTree::reset() {
|
||||
int32_t DynamicAABBTree::allocateNode() {
|
||||
|
||||
// If there is no more allocated node to use
|
||||
if (mFreeNodeID == TreeNode::NULL_TREE_NODE) {
|
||||
if (m_freeNodeID == TreeNode::NULL_TREE_NODE) {
|
||||
|
||||
assert(mNbNodes == mNbAllocatedNodes);
|
||||
assert(m_numberNodes == m_numberAllocatedNodes);
|
||||
|
||||
// Allocate more nodes in the tree
|
||||
mNbAllocatedNodes *= 2;
|
||||
TreeNode* oldNodes = mNodes;
|
||||
mNodes = (TreeNode*) malloc(mNbAllocatedNodes * sizeof(TreeNode));
|
||||
assert(mNodes);
|
||||
memcpy(mNodes, oldNodes, mNbNodes * sizeof(TreeNode));
|
||||
m_numberAllocatedNodes *= 2;
|
||||
TreeNode* oldNodes = m_nodes;
|
||||
m_nodes = (TreeNode*) malloc(m_numberAllocatedNodes * sizeof(TreeNode));
|
||||
assert(m_nodes);
|
||||
memcpy(m_nodes, oldNodes, m_numberNodes * sizeof(TreeNode));
|
||||
free(oldNodes);
|
||||
|
||||
// Initialize the allocated nodes
|
||||
for (int32_t i=mNbNodes; i<mNbAllocatedNodes - 1; i++) {
|
||||
mNodes[i].nextNodeID = i + 1;
|
||||
mNodes[i].height = -1;
|
||||
for (int32_t i=m_numberNodes; i<m_numberAllocatedNodes - 1; i++) {
|
||||
m_nodes[i].nextNodeID = i + 1;
|
||||
m_nodes[i].height = -1;
|
||||
}
|
||||
mNodes[mNbAllocatedNodes - 1].nextNodeID = TreeNode::NULL_TREE_NODE;
|
||||
mNodes[mNbAllocatedNodes - 1].height = -1;
|
||||
mFreeNodeID = mNbNodes;
|
||||
m_nodes[m_numberAllocatedNodes - 1].nextNodeID = TreeNode::NULL_TREE_NODE;
|
||||
m_nodes[m_numberAllocatedNodes - 1].height = -1;
|
||||
m_freeNodeID = m_numberNodes;
|
||||
}
|
||||
|
||||
// Get the next free node
|
||||
int32_t freeNodeID = mFreeNodeID;
|
||||
mFreeNodeID = mNodes[freeNodeID].nextNodeID;
|
||||
mNodes[freeNodeID].parentID = TreeNode::NULL_TREE_NODE;
|
||||
mNodes[freeNodeID].height = 0;
|
||||
mNbNodes++;
|
||||
int32_t freeNodeID = m_freeNodeID;
|
||||
m_freeNodeID = m_nodes[freeNodeID].nextNodeID;
|
||||
m_nodes[freeNodeID].parentID = TreeNode::NULL_TREE_NODE;
|
||||
m_nodes[freeNodeID].height = 0;
|
||||
m_numberNodes++;
|
||||
|
||||
return freeNodeID;
|
||||
}
|
||||
@ -99,13 +99,13 @@ int32_t DynamicAABBTree::allocateNode() {
|
||||
// Release a node
|
||||
void DynamicAABBTree::releaseNode(int32_t nodeID) {
|
||||
|
||||
assert(mNbNodes > 0);
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
assert(mNodes[nodeID].height >= 0);
|
||||
mNodes[nodeID].nextNodeID = mFreeNodeID;
|
||||
mNodes[nodeID].height = -1;
|
||||
mFreeNodeID = nodeID;
|
||||
mNbNodes--;
|
||||
assert(m_numberNodes > 0);
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
assert(m_nodes[nodeID].height >= 0);
|
||||
m_nodes[nodeID].nextNodeID = m_freeNodeID;
|
||||
m_nodes[nodeID].height = -1;
|
||||
m_freeNodeID = nodeID;
|
||||
m_numberNodes--;
|
||||
}
|
||||
|
||||
// Internally add an object int32_to the tree
|
||||
@ -115,16 +115,16 @@ int32_t DynamicAABBTree::addObjectInternal(const AABB& aabb) {
|
||||
int32_t nodeID = allocateNode();
|
||||
|
||||
// Create the fat aabb to use in the tree
|
||||
const Vector3 gap(mExtraAABBGap, mExtraAABBGap, mExtraAABBGap);
|
||||
mNodes[nodeID].aabb.setMin(aabb.getMin() - gap);
|
||||
mNodes[nodeID].aabb.setMax(aabb.getMax() + gap);
|
||||
const vec3 gap(m_extraAABBGap, m_extraAABBGap, m_extraAABBGap);
|
||||
m_nodes[nodeID].aabb.setMin(aabb.getMin() - gap);
|
||||
m_nodes[nodeID].aabb.setMax(aabb.getMax() + gap);
|
||||
|
||||
// Set the height of the node in the tree
|
||||
mNodes[nodeID].height = 0;
|
||||
m_nodes[nodeID].height = 0;
|
||||
|
||||
// Insert the new leaf node in the tree
|
||||
insertLeafNode(nodeID);
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
|
||||
assert(nodeID >= 0);
|
||||
|
||||
@ -135,8 +135,8 @@ int32_t DynamicAABBTree::addObjectInternal(const AABB& aabb) {
|
||||
// Remove an object from the tree
|
||||
void DynamicAABBTree::removeObject(int32_t nodeID) {
|
||||
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
|
||||
// Remove the node from the tree
|
||||
removeLeafNode(nodeID);
|
||||
@ -150,16 +150,16 @@ void DynamicAABBTree::removeObject(int32_t nodeID) {
|
||||
/// argument is the linear velocity of the AABB multiplied by the elapsed time between two
|
||||
/// frames. If the "forceReinsert" parameter is true, we force a removal and reinsertion of the node
|
||||
/// (this can be useful if the shape AABB has become much smaller than the previous one for instance).
|
||||
bool DynamicAABBTree::updateObject(int32_t nodeID, const AABB& newAABB, const Vector3& displacement, bool forceReinsert) {
|
||||
bool DynamicAABBTree::updateObject(int32_t nodeID, const AABB& newAABB, const vec3& displacement, bool forceReinsert) {
|
||||
|
||||
PROFILE("DynamicAABBTree::updateObject()");
|
||||
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
assert(mNodes[nodeID].height >= 0);
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
assert(m_nodes[nodeID].height >= 0);
|
||||
|
||||
// If the new AABB is still inside the fat AABB of the node
|
||||
if (!forceReinsert && mNodes[nodeID].aabb.contains(newAABB)) {
|
||||
if (!forceReinsert && m_nodes[nodeID].aabb.contains(newAABB)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -167,32 +167,29 @@ bool DynamicAABBTree::updateObject(int32_t nodeID, const AABB& newAABB, const Ve
|
||||
removeLeafNode(nodeID);
|
||||
|
||||
// Compute the fat AABB by inflating the AABB with a constant gap
|
||||
mNodes[nodeID].aabb = newAABB;
|
||||
const Vector3 gap(mExtraAABBGap, mExtraAABBGap, mExtraAABBGap);
|
||||
mNodes[nodeID].aabb.m_minCoordinates -= gap;
|
||||
mNodes[nodeID].aabb.m_maxCoordinates += gap;
|
||||
m_nodes[nodeID].aabb = newAABB;
|
||||
const vec3 gap(m_extraAABBGap, m_extraAABBGap, m_extraAABBGap);
|
||||
m_nodes[nodeID].aabb.m_minCoordinates -= gap;
|
||||
m_nodes[nodeID].aabb.m_maxCoordinates += gap;
|
||||
|
||||
// Inflate the fat AABB in direction of the linear motion of the AABB
|
||||
if (displacement.x < float(0.0)) {
|
||||
mNodes[nodeID].aabb.m_minCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.x;
|
||||
if (displacement.x() < 0.0f) {
|
||||
m_nodes[nodeID].aabb.m_minCoordinates.setX(m_nodes[nodeID].aabb.m_minCoordinates.x() + DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.x());
|
||||
} else {
|
||||
m_nodes[nodeID].aabb.m_maxCoordinates.setY(m_nodes[nodeID].aabb.m_maxCoordinates.x() + DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.x());
|
||||
}
|
||||
else {
|
||||
mNodes[nodeID].aabb.m_maxCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.x;
|
||||
if (displacement.y() < 0.0f) {
|
||||
m_nodes[nodeID].aabb.m_minCoordinates.setY(m_nodes[nodeID].aabb.m_minCoordinates.y() + DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.y());
|
||||
} else {
|
||||
m_nodes[nodeID].aabb.m_maxCoordinates.setY(m_nodes[nodeID].aabb.m_maxCoordinates.y() + DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.y());
|
||||
}
|
||||
if (displacement.y < float(0.0)) {
|
||||
mNodes[nodeID].aabb.m_minCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.y;
|
||||
}
|
||||
else {
|
||||
mNodes[nodeID].aabb.m_maxCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.y;
|
||||
}
|
||||
if (displacement.z < float(0.0)) {
|
||||
mNodes[nodeID].aabb.m_minCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.z;
|
||||
}
|
||||
else {
|
||||
mNodes[nodeID].aabb.m_maxCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.z;
|
||||
if (displacement.z() < 0.0f) {
|
||||
m_nodes[nodeID].aabb.m_minCoordinates.setZ(m_nodes[nodeID].aabb.m_minCoordinates.z() + DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.z());
|
||||
} else {
|
||||
m_nodes[nodeID].aabb.m_maxCoordinates.setZ(m_nodes[nodeID].aabb.m_maxCoordinates.z() + DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.z());
|
||||
}
|
||||
|
||||
assert(mNodes[nodeID].aabb.contains(newAABB));
|
||||
assert(m_nodes[nodeID].aabb.contains(newAABB));
|
||||
|
||||
// Reinsert the node int32_to the tree
|
||||
insertLeafNode(nodeID);
|
||||
@ -208,24 +205,24 @@ void DynamicAABBTree::insertLeafNode(int32_t nodeID) {
|
||||
// If the tree is empty
|
||||
if (m_rootNodeID == TreeNode::NULL_TREE_NODE) {
|
||||
m_rootNodeID = nodeID;
|
||||
mNodes[m_rootNodeID].parentID = TreeNode::NULL_TREE_NODE;
|
||||
m_nodes[m_rootNodeID].parentID = TreeNode::NULL_TREE_NODE;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(m_rootNodeID != TreeNode::NULL_TREE_NODE);
|
||||
|
||||
// Find the best sibling node for the new node
|
||||
AABB newNodeAABB = mNodes[nodeID].aabb;
|
||||
AABB newNodeAABB = m_nodes[nodeID].aabb;
|
||||
int32_t currentNodeID = m_rootNodeID;
|
||||
while (!mNodes[currentNodeID].isLeaf()) {
|
||||
while (!m_nodes[currentNodeID].isLeaf()) {
|
||||
|
||||
int32_t leftChild = mNodes[currentNodeID].children[0];
|
||||
int32_t rightChild = mNodes[currentNodeID].children[1];
|
||||
int32_t leftChild = m_nodes[currentNodeID].children[0];
|
||||
int32_t rightChild = m_nodes[currentNodeID].children[1];
|
||||
|
||||
// Compute the merged AABB
|
||||
float volumeAABB = mNodes[currentNodeID].aabb.getVolume();
|
||||
float volumeAABB = m_nodes[currentNodeID].aabb.getVolume();
|
||||
AABB mergedAABBs;
|
||||
mergedAABBs.mergeTwoAABBs(mNodes[currentNodeID].aabb, newNodeAABB);
|
||||
mergedAABBs.mergeTwoAABBs(m_nodes[currentNodeID].aabb, newNodeAABB);
|
||||
float mergedVolume = mergedAABBs.getVolume();
|
||||
|
||||
// Compute the cost of making the current node the sibbling of the new node
|
||||
@ -237,24 +234,24 @@ void DynamicAABBTree::insertLeafNode(int32_t nodeID) {
|
||||
// Compute the cost of descending int32_to the left child
|
||||
float costLeft;
|
||||
AABB currentAndLeftAABB;
|
||||
currentAndLeftAABB.mergeTwoAABBs(newNodeAABB, mNodes[leftChild].aabb);
|
||||
if (mNodes[leftChild].isLeaf()) { // If the left child is a leaf
|
||||
currentAndLeftAABB.mergeTwoAABBs(newNodeAABB, m_nodes[leftChild].aabb);
|
||||
if (m_nodes[leftChild].isLeaf()) { // If the left child is a leaf
|
||||
costLeft = currentAndLeftAABB.getVolume() + costI;
|
||||
}
|
||||
else {
|
||||
float leftChildVolume = mNodes[leftChild].aabb.getVolume();
|
||||
float leftChildVolume = m_nodes[leftChild].aabb.getVolume();
|
||||
costLeft = costI + currentAndLeftAABB.getVolume() - leftChildVolume;
|
||||
}
|
||||
|
||||
// Compute the cost of descending int32_to the right child
|
||||
float costRight;
|
||||
AABB currentAndRightAABB;
|
||||
currentAndRightAABB.mergeTwoAABBs(newNodeAABB, mNodes[rightChild].aabb);
|
||||
if (mNodes[rightChild].isLeaf()) { // If the right child is a leaf
|
||||
currentAndRightAABB.mergeTwoAABBs(newNodeAABB, m_nodes[rightChild].aabb);
|
||||
if (m_nodes[rightChild].isLeaf()) { // If the right child is a leaf
|
||||
costRight = currentAndRightAABB.getVolume() + costI;
|
||||
}
|
||||
else {
|
||||
float rightChildVolume = mNodes[rightChild].aabb.getVolume();
|
||||
float rightChildVolume = m_nodes[rightChild].aabb.getVolume();
|
||||
costRight = costI + currentAndRightAABB.getVolume() - rightChildVolume;
|
||||
}
|
||||
|
||||
@ -274,69 +271,69 @@ void DynamicAABBTree::insertLeafNode(int32_t nodeID) {
|
||||
int32_t siblingNode = currentNodeID;
|
||||
|
||||
// Create a new parent for the new node and the sibling node
|
||||
int32_t oldParentNode = mNodes[siblingNode].parentID;
|
||||
int32_t oldParentNode = m_nodes[siblingNode].parentID;
|
||||
int32_t newParentNode = allocateNode();
|
||||
mNodes[newParentNode].parentID = oldParentNode;
|
||||
mNodes[newParentNode].aabb.mergeTwoAABBs(mNodes[siblingNode].aabb, newNodeAABB);
|
||||
mNodes[newParentNode].height = mNodes[siblingNode].height + 1;
|
||||
assert(mNodes[newParentNode].height > 0);
|
||||
m_nodes[newParentNode].parentID = oldParentNode;
|
||||
m_nodes[newParentNode].aabb.mergeTwoAABBs(m_nodes[siblingNode].aabb, newNodeAABB);
|
||||
m_nodes[newParentNode].height = m_nodes[siblingNode].height + 1;
|
||||
assert(m_nodes[newParentNode].height > 0);
|
||||
|
||||
// If the sibling node was not the root node
|
||||
if (oldParentNode != TreeNode::NULL_TREE_NODE) {
|
||||
assert(!mNodes[oldParentNode].isLeaf());
|
||||
if (mNodes[oldParentNode].children[0] == siblingNode) {
|
||||
mNodes[oldParentNode].children[0] = newParentNode;
|
||||
assert(!m_nodes[oldParentNode].isLeaf());
|
||||
if (m_nodes[oldParentNode].children[0] == siblingNode) {
|
||||
m_nodes[oldParentNode].children[0] = newParentNode;
|
||||
}
|
||||
else {
|
||||
mNodes[oldParentNode].children[1] = newParentNode;
|
||||
m_nodes[oldParentNode].children[1] = newParentNode;
|
||||
}
|
||||
mNodes[newParentNode].children[0] = siblingNode;
|
||||
mNodes[newParentNode].children[1] = nodeID;
|
||||
mNodes[siblingNode].parentID = newParentNode;
|
||||
mNodes[nodeID].parentID = newParentNode;
|
||||
m_nodes[newParentNode].children[0] = siblingNode;
|
||||
m_nodes[newParentNode].children[1] = nodeID;
|
||||
m_nodes[siblingNode].parentID = newParentNode;
|
||||
m_nodes[nodeID].parentID = newParentNode;
|
||||
}
|
||||
else { // If the sibling node was the root node
|
||||
mNodes[newParentNode].children[0] = siblingNode;
|
||||
mNodes[newParentNode].children[1] = nodeID;
|
||||
mNodes[siblingNode].parentID = newParentNode;
|
||||
mNodes[nodeID].parentID = newParentNode;
|
||||
m_nodes[newParentNode].children[0] = siblingNode;
|
||||
m_nodes[newParentNode].children[1] = nodeID;
|
||||
m_nodes[siblingNode].parentID = newParentNode;
|
||||
m_nodes[nodeID].parentID = newParentNode;
|
||||
m_rootNodeID = newParentNode;
|
||||
}
|
||||
|
||||
// Move up in the tree to change the AABBs that have changed
|
||||
currentNodeID = mNodes[nodeID].parentID;
|
||||
assert(!mNodes[currentNodeID].isLeaf());
|
||||
currentNodeID = m_nodes[nodeID].parentID;
|
||||
assert(!m_nodes[currentNodeID].isLeaf());
|
||||
while (currentNodeID != TreeNode::NULL_TREE_NODE) {
|
||||
|
||||
// Balance the sub-tree of the current node if it is not balanced
|
||||
currentNodeID = balanceSubTreeAtNode(currentNodeID);
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
|
||||
assert(!mNodes[currentNodeID].isLeaf());
|
||||
int32_t leftChild = mNodes[currentNodeID].children[0];
|
||||
int32_t rightChild = mNodes[currentNodeID].children[1];
|
||||
assert(!m_nodes[currentNodeID].isLeaf());
|
||||
int32_t leftChild = m_nodes[currentNodeID].children[0];
|
||||
int32_t rightChild = m_nodes[currentNodeID].children[1];
|
||||
assert(leftChild != TreeNode::NULL_TREE_NODE);
|
||||
assert(rightChild != TreeNode::NULL_TREE_NODE);
|
||||
|
||||
// Recompute the height of the node in the tree
|
||||
mNodes[currentNodeID].height = std::max(mNodes[leftChild].height,
|
||||
mNodes[rightChild].height) + 1;
|
||||
assert(mNodes[currentNodeID].height > 0);
|
||||
m_nodes[currentNodeID].height = std::max(m_nodes[leftChild].height,
|
||||
m_nodes[rightChild].height) + 1;
|
||||
assert(m_nodes[currentNodeID].height > 0);
|
||||
|
||||
// Recompute the AABB of the node
|
||||
mNodes[currentNodeID].aabb.mergeTwoAABBs(mNodes[leftChild].aabb, mNodes[rightChild].aabb);
|
||||
m_nodes[currentNodeID].aabb.mergeTwoAABBs(m_nodes[leftChild].aabb, m_nodes[rightChild].aabb);
|
||||
|
||||
currentNodeID = mNodes[currentNodeID].parentID;
|
||||
currentNodeID = m_nodes[currentNodeID].parentID;
|
||||
}
|
||||
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
}
|
||||
|
||||
// Remove a leaf node from the tree
|
||||
void DynamicAABBTree::removeLeafNode(int32_t nodeID) {
|
||||
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
|
||||
// If we are removing the root node (root node is a leaf in this case)
|
||||
if (m_rootNodeID == nodeID) {
|
||||
@ -344,28 +341,28 @@ void DynamicAABBTree::removeLeafNode(int32_t nodeID) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t parentNodeID = mNodes[nodeID].parentID;
|
||||
int32_t grandParentNodeID = mNodes[parentNodeID].parentID;
|
||||
int32_t parentNodeID = m_nodes[nodeID].parentID;
|
||||
int32_t grandParentNodeID = m_nodes[parentNodeID].parentID;
|
||||
int32_t siblingNodeID;
|
||||
if (mNodes[parentNodeID].children[0] == nodeID) {
|
||||
siblingNodeID = mNodes[parentNodeID].children[1];
|
||||
if (m_nodes[parentNodeID].children[0] == nodeID) {
|
||||
siblingNodeID = m_nodes[parentNodeID].children[1];
|
||||
}
|
||||
else {
|
||||
siblingNodeID = mNodes[parentNodeID].children[0];
|
||||
siblingNodeID = m_nodes[parentNodeID].children[0];
|
||||
}
|
||||
|
||||
// If the parent of the node to remove is not the root node
|
||||
if (grandParentNodeID != TreeNode::NULL_TREE_NODE) {
|
||||
|
||||
// Destroy the parent node
|
||||
if (mNodes[grandParentNodeID].children[0] == parentNodeID) {
|
||||
mNodes[grandParentNodeID].children[0] = siblingNodeID;
|
||||
if (m_nodes[grandParentNodeID].children[0] == parentNodeID) {
|
||||
m_nodes[grandParentNodeID].children[0] = siblingNodeID;
|
||||
}
|
||||
else {
|
||||
assert(mNodes[grandParentNodeID].children[1] == parentNodeID);
|
||||
mNodes[grandParentNodeID].children[1] = siblingNodeID;
|
||||
assert(m_nodes[grandParentNodeID].children[1] == parentNodeID);
|
||||
m_nodes[grandParentNodeID].children[1] = siblingNodeID;
|
||||
}
|
||||
mNodes[siblingNodeID].parentID = grandParentNodeID;
|
||||
m_nodes[siblingNodeID].parentID = grandParentNodeID;
|
||||
releaseNode(parentNodeID);
|
||||
|
||||
// Now, we need to recompute the AABBs of the node on the path back to the root
|
||||
@ -376,27 +373,27 @@ void DynamicAABBTree::removeLeafNode(int32_t nodeID) {
|
||||
// Balance the current sub-tree if necessary
|
||||
currentNodeID = balanceSubTreeAtNode(currentNodeID);
|
||||
|
||||
assert(!mNodes[currentNodeID].isLeaf());
|
||||
assert(!m_nodes[currentNodeID].isLeaf());
|
||||
|
||||
// Get the two children of the current node
|
||||
int32_t leftChildID = mNodes[currentNodeID].children[0];
|
||||
int32_t rightChildID = mNodes[currentNodeID].children[1];
|
||||
int32_t leftChildID = m_nodes[currentNodeID].children[0];
|
||||
int32_t rightChildID = m_nodes[currentNodeID].children[1];
|
||||
|
||||
// Recompute the AABB and the height of the current node
|
||||
mNodes[currentNodeID].aabb.mergeTwoAABBs(mNodes[leftChildID].aabb,
|
||||
mNodes[rightChildID].aabb);
|
||||
mNodes[currentNodeID].height = std::max(mNodes[leftChildID].height,
|
||||
mNodes[rightChildID].height) + 1;
|
||||
assert(mNodes[currentNodeID].height > 0);
|
||||
m_nodes[currentNodeID].aabb.mergeTwoAABBs(m_nodes[leftChildID].aabb,
|
||||
m_nodes[rightChildID].aabb);
|
||||
m_nodes[currentNodeID].height = std::max(m_nodes[leftChildID].height,
|
||||
m_nodes[rightChildID].height) + 1;
|
||||
assert(m_nodes[currentNodeID].height > 0);
|
||||
|
||||
currentNodeID = mNodes[currentNodeID].parentID;
|
||||
currentNodeID = m_nodes[currentNodeID].parentID;
|
||||
}
|
||||
}
|
||||
else { // If the parent of the node to remove is the root node
|
||||
|
||||
// The sibling node becomes the new root node
|
||||
m_rootNodeID = siblingNodeID;
|
||||
mNodes[siblingNodeID].parentID = TreeNode::NULL_TREE_NODE;
|
||||
m_nodes[siblingNodeID].parentID = TreeNode::NULL_TREE_NODE;
|
||||
releaseNode(parentNodeID);
|
||||
}
|
||||
}
|
||||
@ -408,7 +405,7 @@ int32_t DynamicAABBTree::balanceSubTreeAtNode(int32_t nodeID) {
|
||||
|
||||
assert(nodeID != TreeNode::NULL_TREE_NODE);
|
||||
|
||||
TreeNode* nodeA = mNodes + nodeID;
|
||||
TreeNode* nodeA = m_nodes + nodeID;
|
||||
|
||||
// If the node is a leaf or the height of A's sub-tree is less than 2
|
||||
if (nodeA->isLeaf() || nodeA->height < 2) {
|
||||
@ -420,10 +417,10 @@ int32_t DynamicAABBTree::balanceSubTreeAtNode(int32_t nodeID) {
|
||||
// Get the two children nodes
|
||||
int32_t nodeBID = nodeA->children[0];
|
||||
int32_t nodeCID = nodeA->children[1];
|
||||
assert(nodeBID >= 0 && nodeBID < mNbAllocatedNodes);
|
||||
assert(nodeCID >= 0 && nodeCID < mNbAllocatedNodes);
|
||||
TreeNode* nodeB = mNodes + nodeBID;
|
||||
TreeNode* nodeC = mNodes + nodeCID;
|
||||
assert(nodeBID >= 0 && nodeBID < m_numberAllocatedNodes);
|
||||
assert(nodeCID >= 0 && nodeCID < m_numberAllocatedNodes);
|
||||
TreeNode* nodeB = m_nodes + nodeBID;
|
||||
TreeNode* nodeC = m_nodes + nodeCID;
|
||||
|
||||
// Compute the factor of the left and right sub-trees
|
||||
int32_t balanceFactor = nodeC->height - nodeB->height;
|
||||
@ -435,10 +432,10 @@ int32_t DynamicAABBTree::balanceSubTreeAtNode(int32_t nodeID) {
|
||||
|
||||
int32_t nodeFID = nodeC->children[0];
|
||||
int32_t nodeGID = nodeC->children[1];
|
||||
assert(nodeFID >= 0 && nodeFID < mNbAllocatedNodes);
|
||||
assert(nodeGID >= 0 && nodeGID < mNbAllocatedNodes);
|
||||
TreeNode* nodeF = mNodes + nodeFID;
|
||||
TreeNode* nodeG = mNodes + nodeGID;
|
||||
assert(nodeFID >= 0 && nodeFID < m_numberAllocatedNodes);
|
||||
assert(nodeGID >= 0 && nodeGID < m_numberAllocatedNodes);
|
||||
TreeNode* nodeF = m_nodes + nodeFID;
|
||||
TreeNode* nodeG = m_nodes + nodeGID;
|
||||
|
||||
nodeC->children[0] = nodeID;
|
||||
nodeC->parentID = nodeA->parentID;
|
||||
@ -446,12 +443,12 @@ int32_t DynamicAABBTree::balanceSubTreeAtNode(int32_t nodeID) {
|
||||
|
||||
if (nodeC->parentID != TreeNode::NULL_TREE_NODE) {
|
||||
|
||||
if (mNodes[nodeC->parentID].children[0] == nodeID) {
|
||||
mNodes[nodeC->parentID].children[0] = nodeCID;
|
||||
if (m_nodes[nodeC->parentID].children[0] == nodeID) {
|
||||
m_nodes[nodeC->parentID].children[0] = nodeCID;
|
||||
}
|
||||
else {
|
||||
assert(mNodes[nodeC->parentID].children[1] == nodeID);
|
||||
mNodes[nodeC->parentID].children[1] = nodeCID;
|
||||
assert(m_nodes[nodeC->parentID].children[1] == nodeID);
|
||||
m_nodes[nodeC->parentID].children[1] = nodeCID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -505,10 +502,10 @@ int32_t DynamicAABBTree::balanceSubTreeAtNode(int32_t nodeID) {
|
||||
|
||||
int32_t nodeFID = nodeB->children[0];
|
||||
int32_t nodeGID = nodeB->children[1];
|
||||
assert(nodeFID >= 0 && nodeFID < mNbAllocatedNodes);
|
||||
assert(nodeGID >= 0 && nodeGID < mNbAllocatedNodes);
|
||||
TreeNode* nodeF = mNodes + nodeFID;
|
||||
TreeNode* nodeG = mNodes + nodeGID;
|
||||
assert(nodeFID >= 0 && nodeFID < m_numberAllocatedNodes);
|
||||
assert(nodeGID >= 0 && nodeGID < m_numberAllocatedNodes);
|
||||
TreeNode* nodeF = m_nodes + nodeFID;
|
||||
TreeNode* nodeG = m_nodes + nodeGID;
|
||||
|
||||
nodeB->children[0] = nodeID;
|
||||
nodeB->parentID = nodeA->parentID;
|
||||
@ -516,12 +513,12 @@ int32_t DynamicAABBTree::balanceSubTreeAtNode(int32_t nodeID) {
|
||||
|
||||
if (nodeB->parentID != TreeNode::NULL_TREE_NODE) {
|
||||
|
||||
if (mNodes[nodeB->parentID].children[0] == nodeID) {
|
||||
mNodes[nodeB->parentID].children[0] = nodeBID;
|
||||
if (m_nodes[nodeB->parentID].children[0] == nodeID) {
|
||||
m_nodes[nodeB->parentID].children[0] = nodeBID;
|
||||
}
|
||||
else {
|
||||
assert(mNodes[nodeB->parentID].children[1] == nodeID);
|
||||
mNodes[nodeB->parentID].children[1] = nodeBID;
|
||||
assert(m_nodes[nodeB->parentID].children[1] == nodeID);
|
||||
m_nodes[nodeB->parentID].children[1] = nodeBID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -590,7 +587,7 @@ void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb,
|
||||
if (nodeIDToVisit == TreeNode::NULL_TREE_NODE) continue;
|
||||
|
||||
// Get the corresponding node
|
||||
const TreeNode* nodeToVisit = mNodes + nodeIDToVisit;
|
||||
const TreeNode* nodeToVisit = m_nodes + nodeIDToVisit;
|
||||
|
||||
// If the AABB in parameter overlaps with the AABB of the node to visit
|
||||
if (aabb.testCollision(nodeToVisit->aabb)) {
|
||||
@ -632,7 +629,7 @@ void DynamicAABBTree::raycast(const Ray& ray, DynamicAABBTreeRaycastCallback &ca
|
||||
if (nodeID == TreeNode::NULL_TREE_NODE) continue;
|
||||
|
||||
// Get the corresponding node
|
||||
const TreeNode* node = mNodes + nodeID;
|
||||
const TreeNode* node = m_nodes + nodeID;
|
||||
|
||||
Ray rayTemp(ray.point1, ray.point2, maxFraction);
|
||||
|
||||
@ -647,12 +644,12 @@ void DynamicAABBTree::raycast(const Ray& ray, DynamicAABBTreeRaycastCallback &ca
|
||||
|
||||
// If the user returned a hitFraction of zero, it means that
|
||||
// the raycasting should stop here
|
||||
if (hitFraction == float(0.0)) {
|
||||
if (hitFraction == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user returned a positive fraction
|
||||
if (hitFraction > float(0.0)) {
|
||||
if (hitFraction > 0.0f) {
|
||||
|
||||
// We update the maxFraction value and the ray
|
||||
// AABB using the new maximum fraction
|
||||
@ -682,16 +679,16 @@ void DynamicAABBTree::check() const {
|
||||
checkNode(m_rootNodeID);
|
||||
|
||||
int32_t nbFreeNodes = 0;
|
||||
int32_t freeNodeID = mFreeNodeID;
|
||||
int32_t freeNodeID = m_freeNodeID;
|
||||
|
||||
// Check the free nodes
|
||||
while(freeNodeID != TreeNode::NULL_TREE_NODE) {
|
||||
assert(0 <= freeNodeID && freeNodeID < mNbAllocatedNodes);
|
||||
freeNodeID = mNodes[freeNodeID].nextNodeID;
|
||||
assert(0 <= freeNodeID && freeNodeID < m_numberAllocatedNodes);
|
||||
freeNodeID = m_nodes[freeNodeID].nextNodeID;
|
||||
nbFreeNodes++;
|
||||
}
|
||||
|
||||
assert(mNbNodes + nbFreeNodes == mNbAllocatedNodes);
|
||||
assert(m_numberNodes + nbFreeNodes == m_numberAllocatedNodes);
|
||||
}
|
||||
|
||||
// Check if the node structure is valid (for debugging purpose)
|
||||
@ -701,11 +698,11 @@ void DynamicAABBTree::checkNode(int32_t nodeID) const {
|
||||
|
||||
// If it is the root
|
||||
if (nodeID == m_rootNodeID) {
|
||||
assert(mNodes[nodeID].parentID == TreeNode::NULL_TREE_NODE);
|
||||
assert(m_nodes[nodeID].parentID == TreeNode::NULL_TREE_NODE);
|
||||
}
|
||||
|
||||
// Get the children nodes
|
||||
TreeNode* pNode = mNodes + nodeID;
|
||||
TreeNode* pNode = m_nodes + nodeID;
|
||||
assert(!pNode->isLeaf());
|
||||
int32_t leftChild = pNode->children[0];
|
||||
int32_t rightChild = pNode->children[1];
|
||||
@ -724,22 +721,22 @@ void DynamicAABBTree::checkNode(int32_t nodeID) const {
|
||||
else {
|
||||
|
||||
// Check that the children node IDs are valid
|
||||
assert(0 <= leftChild && leftChild < mNbAllocatedNodes);
|
||||
assert(0 <= rightChild && rightChild < mNbAllocatedNodes);
|
||||
assert(0 <= leftChild && leftChild < m_numberAllocatedNodes);
|
||||
assert(0 <= rightChild && rightChild < m_numberAllocatedNodes);
|
||||
|
||||
// Check that the children nodes have the correct parent node
|
||||
assert(mNodes[leftChild].parentID == nodeID);
|
||||
assert(mNodes[rightChild].parentID == nodeID);
|
||||
assert(m_nodes[leftChild].parentID == nodeID);
|
||||
assert(m_nodes[rightChild].parentID == nodeID);
|
||||
|
||||
// Check the height of node
|
||||
int32_t height = 1 + std::max(mNodes[leftChild].height, mNodes[rightChild].height);
|
||||
assert(mNodes[nodeID].height == height);
|
||||
int32_t height = 1 + std::max(m_nodes[leftChild].height, m_nodes[rightChild].height);
|
||||
assert(m_nodes[nodeID].height == height);
|
||||
|
||||
// Check the AABB of the node
|
||||
AABB aabb;
|
||||
aabb.mergeTwoAABBs(mNodes[leftChild].aabb, mNodes[rightChild].aabb);
|
||||
assert(aabb.getMin() == mNodes[nodeID].aabb.getMin());
|
||||
assert(aabb.getMax() == mNodes[nodeID].aabb.getMax());
|
||||
aabb.mergeTwoAABBs(m_nodes[leftChild].aabb, m_nodes[rightChild].aabb);
|
||||
assert(aabb.getMin() == m_nodes[nodeID].aabb.getMin());
|
||||
assert(aabb.getMax() == m_nodes[nodeID].aabb.getMax());
|
||||
|
||||
// Recursively check the children nodes
|
||||
checkNode(leftChild);
|
||||
@ -754,8 +751,8 @@ int32_t DynamicAABBTree::computeHeight() {
|
||||
|
||||
// Compute the height of a given node in the tree
|
||||
int32_t DynamicAABBTree::computeHeight(int32_t nodeID) {
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
TreeNode* node = mNodes + nodeID;
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
TreeNode* node = m_nodes + nodeID;
|
||||
|
||||
// If the node is a leaf, its height is zero
|
||||
if (node->isLeaf()) {
|
||||
|
@ -113,23 +113,23 @@ class DynamicAABBTree {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Pointer to the memory location of the nodes of the tree
|
||||
TreeNode* mNodes;
|
||||
TreeNode* m_nodes;
|
||||
|
||||
/// ID of the root node of the tree
|
||||
int32_t m_rootNodeID;
|
||||
|
||||
/// ID of the first node of the list of free (allocated) nodes in the tree that we can use
|
||||
int32_t mFreeNodeID;
|
||||
int32_t m_freeNodeID;
|
||||
|
||||
/// Number of allocated nodes in the tree
|
||||
int32_t mNbAllocatedNodes;
|
||||
int32_t m_numberAllocatedNodes;
|
||||
|
||||
/// Number of nodes in the tree
|
||||
int32_t mNbNodes;
|
||||
int32_t m_numberNodes;
|
||||
|
||||
/// Extra AABB Gap used to allow the collision shape to move a little bit
|
||||
/// without triggering a large modification of the tree which can be costly
|
||||
float mExtraAABBGap;
|
||||
float m_extraAABBGap;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -172,7 +172,7 @@ class DynamicAABBTree {
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
DynamicAABBTree(float extraAABBGap = float(0.0));
|
||||
DynamicAABBTree(float extraAABBGap = 0.0f);
|
||||
|
||||
/// Destructor
|
||||
virtual ~DynamicAABBTree();
|
||||
@ -187,7 +187,7 @@ class DynamicAABBTree {
|
||||
void removeObject(int32_t nodeID);
|
||||
|
||||
/// Update the dynamic tree after an object has moved.
|
||||
bool updateObject(int32_t nodeID, const AABB& newAABB, const Vector3& displacement, bool forceReinsert = false);
|
||||
bool updateObject(int32_t nodeID, const AABB& newAABB, const vec3& displacement, bool forceReinsert = false);
|
||||
|
||||
/// Return the fat AABB corresponding to a given node ID
|
||||
const AABB& getFatAABB(int32_t nodeID) const;
|
||||
@ -222,22 +222,22 @@ inline bool TreeNode::isLeaf() const {
|
||||
|
||||
// Return the fat AABB corresponding to a given node ID
|
||||
inline const AABB& DynamicAABBTree::getFatAABB(int32_t nodeID) const {
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
return mNodes[nodeID].aabb;
|
||||
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 {
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
return mNodes[nodeID].dataInt;
|
||||
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 {
|
||||
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
|
||||
assert(mNodes[nodeID].isLeaf());
|
||||
return mNodes[nodeID].dataPointer;
|
||||
assert(nodeID >= 0 && nodeID < m_numberAllocatedNodes);
|
||||
assert(m_nodes[nodeID].isLeaf());
|
||||
return m_nodes[nodeID].dataPointer;
|
||||
}
|
||||
|
||||
// Return the root AABB of the tree
|
||||
@ -251,8 +251,8 @@ inline int32_t DynamicAABBTree::addObject(const AABB& aabb, int32_t data1, int32
|
||||
|
||||
int32_t nodeId = addObjectInternal(aabb);
|
||||
|
||||
mNodes[nodeId].dataInt[0] = data1;
|
||||
mNodes[nodeId].dataInt[1] = data2;
|
||||
m_nodes[nodeId].dataInt[0] = data1;
|
||||
m_nodes[nodeId].dataInt[1] = data2;
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
@ -263,7 +263,7 @@ inline int32_t DynamicAABBTree::addObject(const AABB& aabb, void* data) {
|
||||
|
||||
int32_t nodeId = addObjectInternal(aabb);
|
||||
|
||||
mNodes[nodeId].dataPointer = data;
|
||||
m_nodes[nodeId].dataPointer = data;
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ void ConcaveVsConvexAlgorithm::testCollision(const CollisionShapeInfo& shape1Inf
|
||||
}
|
||||
|
||||
// Test collision between a triangle and the convex mesh shape
|
||||
void ConvexVsTriangleCallback::testTriangle(const Vector3* trianglePoints) {
|
||||
void ConvexVsTriangleCallback::testTriangle(const vec3* trianglePoints) {
|
||||
|
||||
// Create a triangle collision shape
|
||||
float margin = mConcaveShape->getTriangleMargin();
|
||||
@ -120,7 +120,7 @@ void ConcaveVsConvexAlgorithm::processSmoothMeshCollision(OverlappingPair* overl
|
||||
NarrowPhaseCallback* narrowPhaseCallback) {
|
||||
|
||||
// Set with the triangle vertices already processed to void further contacts with same triangle
|
||||
std::unordered_multimap<int32_t, Vector3> processTriangleVertices;
|
||||
std::unordered_multimap<int32_t, vec3> processTriangleVertices;
|
||||
|
||||
// Sort the list of narrow-phase contacts according to their penetration depth
|
||||
std::sort(contactPoints.begin(), contactPoints.end(), ContactsDepthCompare());
|
||||
@ -130,7 +130,7 @@ void ConcaveVsConvexAlgorithm::processSmoothMeshCollision(OverlappingPair* overl
|
||||
for (it = contactPoints.begin(); it != contactPoints.end(); ++it) {
|
||||
|
||||
const SmoothMeshContactInfo info = *it;
|
||||
const Vector3& contactPoint = info.isFirstShapeTriangle ? info.contactInfo.localPoint1 : info.contactInfo.localPoint2;
|
||||
const vec3& contactPoint = info.isFirstShapeTriangle ? info.contactInfo.localPoint1 : info.contactInfo.localPoint2;
|
||||
|
||||
// Compute the barycentric coordinates of the point in the triangle
|
||||
float u, v, w;
|
||||
@ -149,7 +149,7 @@ void ConcaveVsConvexAlgorithm::processSmoothMeshCollision(OverlappingPair* overl
|
||||
// If it is a vertex contact
|
||||
if (nbZeros == 2) {
|
||||
|
||||
Vector3 contactVertex = !isUZero ? info.triangleVertices[0] : (!isVZero ? info.triangleVertices[1] : info.triangleVertices[2]);
|
||||
vec3 contactVertex = !isUZero ? info.triangleVertices[0] : (!isVZero ? info.triangleVertices[1] : info.triangleVertices[2]);
|
||||
|
||||
// Check that this triangle vertex has not been processed yet
|
||||
if (!hasVertexBeenProcessed(processTriangleVertices, contactVertex)) {
|
||||
@ -160,8 +160,8 @@ void ConcaveVsConvexAlgorithm::processSmoothMeshCollision(OverlappingPair* overl
|
||||
}
|
||||
else if (nbZeros == 1) { // If it is an edge contact
|
||||
|
||||
Vector3 contactVertex1 = isUZero ? info.triangleVertices[1] : (isVZero ? info.triangleVertices[0] : info.triangleVertices[0]);
|
||||
Vector3 contactVertex2 = isUZero ? info.triangleVertices[2] : (isVZero ? info.triangleVertices[2] : info.triangleVertices[1]);
|
||||
vec3 contactVertex1 = isUZero ? info.triangleVertices[1] : (isVZero ? info.triangleVertices[0] : info.triangleVertices[0]);
|
||||
vec3 contactVertex2 = isUZero ? info.triangleVertices[2] : (isVZero ? info.triangleVertices[2] : info.triangleVertices[1]);
|
||||
|
||||
// Check that this triangle edge has not been processed yet
|
||||
if (!hasVertexBeenProcessed(processTriangleVertices, contactVertex1) &&
|
||||
@ -188,12 +188,12 @@ void ConcaveVsConvexAlgorithm::processSmoothMeshCollision(OverlappingPair* overl
|
||||
}
|
||||
|
||||
// We use the triangle normal as the contact normal
|
||||
Vector3 a = info.triangleVertices[1] - info.triangleVertices[0];
|
||||
Vector3 b = info.triangleVertices[2] - info.triangleVertices[0];
|
||||
Vector3 localNormal = a.cross(b);
|
||||
vec3 a = info.triangleVertices[1] - info.triangleVertices[0];
|
||||
vec3 b = info.triangleVertices[2] - info.triangleVertices[0];
|
||||
vec3 localNormal = a.cross(b);
|
||||
newContactInfo.normal = firstShape->getLocalToWorldTransform().getOrientation() * localNormal;
|
||||
Vector3 firstLocalPoint = info.isFirstShapeTriangle ? info.contactInfo.localPoint1 : info.contactInfo.localPoint2;
|
||||
Vector3 firstWorldPoint = firstShape->getLocalToWorldTransform() * firstLocalPoint;
|
||||
vec3 firstLocalPoint = info.isFirstShapeTriangle ? info.contactInfo.localPoint1 : info.contactInfo.localPoint2;
|
||||
vec3 firstWorldPoint = firstShape->getLocalToWorldTransform() * firstLocalPoint;
|
||||
newContactInfo.normal.normalize();
|
||||
if (newContactInfo.normal.dot(info.contactInfo.normal) < 0) {
|
||||
newContactInfo.normal = -newContactInfo.normal;
|
||||
@ -202,13 +202,13 @@ void ConcaveVsConvexAlgorithm::processSmoothMeshCollision(OverlappingPair* overl
|
||||
// We recompute the contact point on the second body with the new normal as described in
|
||||
// the Smooth Mesh Contacts with GJK of the Game Physics Pearls book (from Gino van Den Bergen and
|
||||
// Dirk Gregorius) to avoid adding torque
|
||||
Transform worldToLocalSecondPoint = secondShape->getLocalToWorldTransform().getInverse();
|
||||
etk::Transform3D worldToLocalSecondPoint = secondShape->getLocalToWorldTransform().getInverse();
|
||||
if (info.isFirstShapeTriangle) {
|
||||
Vector3 newSecondWorldPoint = firstWorldPoint + newContactInfo.normal;
|
||||
vec3 newSecondWorldPoint = firstWorldPoint + newContactInfo.normal;
|
||||
newContactInfo.localPoint2 = worldToLocalSecondPoint * newSecondWorldPoint;
|
||||
}
|
||||
else {
|
||||
Vector3 newSecondWorldPoint = firstWorldPoint - newContactInfo.normal;
|
||||
vec3 newSecondWorldPoint = firstWorldPoint - newContactInfo.normal;
|
||||
newContactInfo.localPoint1 = worldToLocalSecondPoint * newSecondWorldPoint;
|
||||
}
|
||||
|
||||
@ -225,13 +225,13 @@ void ConcaveVsConvexAlgorithm::processSmoothMeshCollision(OverlappingPair* overl
|
||||
}
|
||||
|
||||
// Return true if the vertex is in the set of already processed vertices
|
||||
bool ConcaveVsConvexAlgorithm::hasVertexBeenProcessed(const std::unordered_multimap<int32_t, Vector3>& processTriangleVertices, const Vector3& vertex) const {
|
||||
bool ConcaveVsConvexAlgorithm::hasVertexBeenProcessed(const std::unordered_multimap<int32_t, vec3>& processTriangleVertices, const vec3& vertex) const {
|
||||
|
||||
int32_t key = int32_t(vertex.x * vertex.y * vertex.z);
|
||||
int32_t key = int32_t(vertex.x() * vertex.y() * vertex.z());
|
||||
|
||||
auto range = processTriangleVertices.equal_range(key);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if (vertex.x == it->second.x && vertex.y == it->second.y && vertex.z == it->second.z) return true;
|
||||
if (vertex.x() == it->second.x() && vertex.y() == it->second.y() && vertex.z() == it->second.z()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -240,7 +240,7 @@ bool ConcaveVsConvexAlgorithm::hasVertexBeenProcessed(const std::unordered_multi
|
||||
// Called by a narrow-phase collision algorithm when a new contact has been found
|
||||
void SmoothCollisionNarrowPhaseCallback::notifyContact(OverlappingPair* overlappingPair,
|
||||
const ContactPointInfo& contactInfo) {
|
||||
Vector3 triangleVertices[3];
|
||||
vec3 triangleVertices[3];
|
||||
bool isFirstShapeTriangle;
|
||||
|
||||
// If the collision shape 1 is the triangle
|
||||
|
@ -83,7 +83,7 @@ class ConvexVsTriangleCallback : public TriangleCallback {
|
||||
}
|
||||
|
||||
/// Test collision between a triangle and the convex mesh shape
|
||||
virtual void testTriangle(const Vector3* trianglePoints);
|
||||
virtual void testTriangle(const vec3* trianglePoints);
|
||||
};
|
||||
|
||||
// Class SmoothMeshContactInfo
|
||||
@ -97,11 +97,11 @@ class SmoothMeshContactInfo {
|
||||
|
||||
ContactPointInfo contactInfo;
|
||||
bool isFirstShapeTriangle;
|
||||
Vector3 triangleVertices[3];
|
||||
vec3 triangleVertices[3];
|
||||
|
||||
/// Constructor
|
||||
SmoothMeshContactInfo(const ContactPointInfo& contact, bool firstShapeTriangle, const Vector3& trianglePoint1,
|
||||
const Vector3& trianglePoint2, const Vector3& trianglePoint3)
|
||||
SmoothMeshContactInfo(const ContactPointInfo& contact, bool firstShapeTriangle, const vec3& trianglePoint1,
|
||||
const vec3& trianglePoint2, const vec3& trianglePoint3)
|
||||
: contactInfo(contact) {
|
||||
isFirstShapeTriangle = firstShapeTriangle;
|
||||
triangleVertices[0] = trianglePoint1;
|
||||
@ -179,12 +179,12 @@ class ConcaveVsConvexAlgorithm : public NarrowPhaseAlgorithm {
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
|
||||
/// Add a triangle vertex int32_to the set of processed triangles
|
||||
void addProcessedVertex(std::unordered_multimap<int32_t, Vector3>& processTriangleVertices,
|
||||
const Vector3& vertex);
|
||||
void addProcessedVertex(std::unordered_multimap<int32_t, vec3>& processTriangleVertices,
|
||||
const vec3& vertex);
|
||||
|
||||
/// Return true if the vertex is in the set of already processed vertices
|
||||
bool hasVertexBeenProcessed(const std::unordered_multimap<int32_t, Vector3>& processTriangleVertices,
|
||||
const Vector3& vertex) const;
|
||||
bool hasVertexBeenProcessed(const std::unordered_multimap<int32_t, vec3>& processTriangleVertices,
|
||||
const vec3& vertex) const;
|
||||
|
||||
public :
|
||||
|
||||
@ -203,8 +203,8 @@ class ConcaveVsConvexAlgorithm : public NarrowPhaseAlgorithm {
|
||||
};
|
||||
|
||||
// Add a triangle vertex int32_to the set of processed triangles
|
||||
inline void ConcaveVsConvexAlgorithm::addProcessedVertex(std::unordered_multimap<int32_t, Vector3>& processTriangleVertices, const Vector3& vertex) {
|
||||
processTriangleVertices.insert(std::make_pair(int32_t(vertex.x * vertex.y * vertex.z), vertex));
|
||||
inline void ConcaveVsConvexAlgorithm::addProcessedVertex(std::unordered_multimap<int32_t, vec3>& processTriangleVertices, const vec3& vertex) {
|
||||
processTriangleVertices.insert(std::make_pair(int32_t(vertex.x() * vertex.y() * vertex.z()), vertex));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,29 +26,29 @@ EPAAlgorithm::~EPAAlgorithm() {
|
||||
// Decide if the origin is in the tetrahedron.
|
||||
/// Return 0 if the origin is in the tetrahedron and return the number (1,2,3 or 4) of
|
||||
/// the vertex that is wrong if the origin is not in the tetrahedron
|
||||
int32_t EPAAlgorithm::isOriginInTetrahedron(const Vector3& p1, const Vector3& p2,
|
||||
const Vector3& p3, const Vector3& p4) const {
|
||||
int32_t EPAAlgorithm::isOriginInTetrahedron(const vec3& p1, const vec3& p2,
|
||||
const vec3& p3, const vec3& p4) const {
|
||||
|
||||
// Check vertex 1
|
||||
Vector3 normal1 = (p2-p1).cross(p3-p1);
|
||||
vec3 normal1 = (p2-p1).cross(p3-p1);
|
||||
if ((normal1.dot(p1) > 0.0) == (normal1.dot(p4) > 0.0)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Check vertex 2
|
||||
Vector3 normal2 = (p4-p2).cross(p3-p2);
|
||||
vec3 normal2 = (p4-p2).cross(p3-p2);
|
||||
if ((normal2.dot(p2) > 0.0) == (normal2.dot(p1) > 0.0)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check vertex 3
|
||||
Vector3 normal3 = (p4-p3).cross(p1-p3);
|
||||
vec3 normal3 = (p4-p3).cross(p1-p3);
|
||||
if ((normal3.dot(p3) > 0.0) == (normal3.dot(p2) > 0.0)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Check vertex 4
|
||||
Vector3 normal4 = (p2-p4).cross(p1-p4);
|
||||
vec3 normal4 = (p2-p4).cross(p1-p4);
|
||||
if ((normal4.dot(p4) > 0.0) == (normal4.dot(p3) > 0.0)) {
|
||||
return 3;
|
||||
}
|
||||
@ -65,10 +65,10 @@ int32_t EPAAlgorithm::isOriginInTetrahedron(const Vector3& p1, const Vector3& p2
|
||||
/// the correct penetration depth
|
||||
void EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simplex,
|
||||
CollisionShapeInfo shape1Info,
|
||||
const Transform& transform1,
|
||||
const etk::Transform3D& transform1,
|
||||
CollisionShapeInfo shape2Info,
|
||||
const Transform& transform2,
|
||||
Vector3& v,
|
||||
const etk::Transform3D& transform2,
|
||||
vec3& v,
|
||||
NarrowPhaseCallback* narrowPhaseCallback) {
|
||||
|
||||
PROFILE("EPAAlgorithm::computePenetrationDepthAndContactPoints()");
|
||||
@ -82,20 +82,20 @@ void EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simple
|
||||
void** shape1CachedCollisionData = shape1Info.cachedCollisionData;
|
||||
void** shape2CachedCollisionData = shape2Info.cachedCollisionData;
|
||||
|
||||
Vector3 suppPointsA[MAX_SUPPORT_POINTS]; // Support points of object A in local coordinates
|
||||
Vector3 suppPointsB[MAX_SUPPORT_POINTS]; // Support points of object B in local coordinates
|
||||
Vector3 points[MAX_SUPPORT_POINTS]; // Current points
|
||||
vec3 suppPointsA[MAX_SUPPORT_POINTS]; // Support points of object A in local coordinates
|
||||
vec3 suppPointsB[MAX_SUPPORT_POINTS]; // Support points of object B in local coordinates
|
||||
vec3 points[MAX_SUPPORT_POINTS]; // Current points
|
||||
TrianglesStore triangleStore; // Store the triangles
|
||||
TriangleEPA* triangleHeap[MAX_FACETS]; // Heap that contains the face
|
||||
// candidate of the EPA algorithm
|
||||
|
||||
// Transform a point from local space of body 2 to local
|
||||
// etk::Transform3D a point from local space of body 2 to local
|
||||
// space of body 1 (the GJK algorithm is done in local space of body 1)
|
||||
Transform body2Tobody1 = transform1.getInverse() * transform2;
|
||||
etk::Transform3D body2Tobody1 = transform1.getInverse() * transform2;
|
||||
|
||||
// Matrix that transform a direction from local
|
||||
// space of body 1 int32_to local space of body 2
|
||||
Quaternion rotateToBody2 = transform2.getOrientation().getInverse() *
|
||||
etk::Quaternion rotateToBody2 = transform2.getOrientation().getInverse() *
|
||||
transform1.getOrientation();
|
||||
|
||||
// Get the simplex computed previously by the GJK algorithm
|
||||
@ -130,22 +130,22 @@ void EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simple
|
||||
// v1, v2 and v3.
|
||||
|
||||
// Direction of the segment
|
||||
Vector3 d = (points[1] - points[0]).getUnit();
|
||||
vec3 d = (points[1] - points[0]).safeNormalized();
|
||||
|
||||
// Choose the coordinate axis from the minimal absolute component of the vector d
|
||||
int32_t minAxis = d.getAbsoluteVector().getMinAxis();
|
||||
int32_t minAxis = d.absolute().getMinAxis();
|
||||
|
||||
// Compute sin(60)
|
||||
const float sin60 = float(sqrt(3.0)) * float(0.5);
|
||||
const float sin60 = float(sqrt(3.0)) * 0.5f;
|
||||
|
||||
// Create a rotation quaternion to rotate the vector v1 to get the vectors
|
||||
// v2 and v3
|
||||
Quaternion rotationQuat(d.x * sin60, d.y * sin60, d.z * sin60, 0.5);
|
||||
etk::Quaternion rotationQuat(d.x() * sin60, d.y() * sin60, d.z() * sin60, 0.5);
|
||||
|
||||
// Compute the vector v1, v2, v3
|
||||
Vector3 v1 = d.cross(Vector3(minAxis == 0, minAxis == 1, minAxis == 2));
|
||||
Vector3 v2 = rotationQuat * v1;
|
||||
Vector3 v3 = rotationQuat * v2;
|
||||
vec3 v1 = d.cross(vec3(minAxis == 0, minAxis == 1, minAxis == 2));
|
||||
vec3 v2 = rotationQuat * v1;
|
||||
vec3 v3 = rotationQuat * v2;
|
||||
|
||||
// Compute the support point in the direction of v1
|
||||
suppPointsA[2] = shape1->getLocalSupportPointWithMargin(v1, shape1CachedCollisionData);
|
||||
@ -256,9 +256,9 @@ void EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simple
|
||||
// tetrahedron that contains the origin.
|
||||
|
||||
// Compute the normal of the triangle
|
||||
Vector3 v1 = points[1] - points[0];
|
||||
Vector3 v2 = points[2] - points[0];
|
||||
Vector3 n = v1.cross(v2);
|
||||
vec3 v1 = points[1] - points[0];
|
||||
vec3 v2 = points[2] - points[0];
|
||||
vec3 n = v1.cross(v2);
|
||||
|
||||
// Compute the two new vertices to obtain a hexahedron
|
||||
suppPointsA[3] = shape1->getLocalSupportPointWithMargin(n, shape1CachedCollisionData);
|
||||
@ -404,13 +404,13 @@ void EPAAlgorithm::computePenetrationDepthAndContactPoints(const Simplex& simple
|
||||
|
||||
// Compute the contact info
|
||||
v = transform1.getOrientation() * triangle->getClosestPoint();
|
||||
Vector3 pALocal = triangle->computeClosestPointOfObject(suppPointsA);
|
||||
Vector3 pBLocal = body2Tobody1.getInverse() * triangle->computeClosestPointOfObject(suppPointsB);
|
||||
Vector3 normal = v.getUnit();
|
||||
vec3 pALocal = triangle->computeClosestPointOfObject(suppPointsA);
|
||||
vec3 pBLocal = body2Tobody1.getInverse() * triangle->computeClosestPointOfObject(suppPointsB);
|
||||
vec3 normal = v.safeNormalized();
|
||||
float penetrationDepth = v.length();
|
||||
assert(penetrationDepth > 0.0);
|
||||
|
||||
if (normal.lengthSquare() < MACHINE_EPSILON) return;
|
||||
if (normal.length2() < MACHINE_EPSILON) return;
|
||||
|
||||
// Create the contact info object
|
||||
ContactPointInfo contactInfo(shape1Info.proxyShape, shape2Info.proxyShape, shape1Info.collisionShape,
|
||||
|
@ -85,8 +85,8 @@ class EPAAlgorithm {
|
||||
float upperBoundSquarePenDepth);
|
||||
|
||||
/// Decide if the origin is in the tetrahedron.
|
||||
int32_t isOriginInTetrahedron(const Vector3& p1, const Vector3& p2,
|
||||
const Vector3& p3, const Vector3& p4) const;
|
||||
int32_t isOriginInTetrahedron(const vec3& p1, const vec3& p2,
|
||||
const vec3& p3, const vec3& p4) const;
|
||||
|
||||
public:
|
||||
|
||||
@ -104,10 +104,10 @@ class EPAAlgorithm {
|
||||
/// Compute the penetration depth with EPA algorithm.
|
||||
void computePenetrationDepthAndContactPoints(const Simplex& simplex,
|
||||
CollisionShapeInfo shape1Info,
|
||||
const Transform& transform1,
|
||||
const etk::Transform3D& transform1,
|
||||
CollisionShapeInfo shape2Info,
|
||||
const Transform& transform2,
|
||||
Vector3& v,
|
||||
const etk::Transform3D& transform2,
|
||||
vec3& v,
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
};
|
||||
|
||||
|
@ -47,7 +47,7 @@ uint32_t EdgeEPA::getTargetVertexIndex() const {
|
||||
}
|
||||
|
||||
// Execute the recursive silhouette algorithm from this edge
|
||||
bool EdgeEPA::computeSilhouette(const Vector3* vertices, uint32_t indexNewVertex,
|
||||
bool EdgeEPA::computeSilhouette(const vec3* vertices, uint32_t indexNewVertex,
|
||||
TrianglesStore& triangleStore) {
|
||||
// If the edge has not already been visited
|
||||
if (!mOwnerTriangle->getIsObsolete()) {
|
||||
|
@ -62,7 +62,7 @@ class EdgeEPA {
|
||||
uint32_t getTargetVertexIndex() const;
|
||||
|
||||
/// Execute the recursive silhouette algorithm from this edge
|
||||
bool computeSilhouette(const Vector3* vertices, uint32_t index, TrianglesStore& triangleStore);
|
||||
bool computeSilhouette(const vec3* vertices, uint32_t index, TrianglesStore& triangleStore);
|
||||
|
||||
/// Assignment operator
|
||||
EdgeEPA& operator=(const EdgeEPA& edge);
|
||||
|
@ -31,11 +31,11 @@ TriangleEPA::~TriangleEPA() {
|
||||
}
|
||||
|
||||
// Compute the point v closest to the origin of this triangle
|
||||
bool TriangleEPA::computeClosestPoint(const Vector3* vertices) {
|
||||
const Vector3& p0 = vertices[mIndicesVertices[0]];
|
||||
bool TriangleEPA::computeClosestPoint(const vec3* vertices) {
|
||||
const vec3& p0 = vertices[mIndicesVertices[0]];
|
||||
|
||||
Vector3 v1 = vertices[mIndicesVertices[1]] - p0;
|
||||
Vector3 v2 = vertices[mIndicesVertices[2]] - p0;
|
||||
vec3 v1 = vertices[mIndicesVertices[1]] - p0;
|
||||
vec3 v2 = vertices[mIndicesVertices[2]] - p0;
|
||||
float v1Dotv1 = v1.dot(v1);
|
||||
float v1Dotv2 = v1.dot(v2);
|
||||
float v2Dotv2 = v2.dot(v2);
|
||||
@ -52,7 +52,7 @@ bool TriangleEPA::computeClosestPoint(const Vector3* vertices) {
|
||||
// If the determinant is positive
|
||||
if (mDet > 0.0) {
|
||||
// Compute the closest point v
|
||||
mClosestPoint = p0 + float(1.0) / mDet * (mLambda1 * v1 + mLambda2 * v2);
|
||||
mClosestPoint = p0 + 1.0f / mDet * (mLambda1 * v1 + mLambda2 * v2);
|
||||
|
||||
// Compute the square distance of closest point to the origin
|
||||
mDistSquare = mClosestPoint.dot(mClosestPoint);
|
||||
@ -101,7 +101,7 @@ void reactphysics3d::halfLink(const EdgeEPA& edge0, const EdgeEPA& edge1) {
|
||||
/// face from the new vertex, computes the silhouette and create the new faces from the new vertex in
|
||||
/// order that we always have a convex polytope. The faces visible from the new vertex are set
|
||||
/// obselete and will not be considered as being a candidate face in the future.
|
||||
bool TriangleEPA::computeSilhouette(const Vector3* vertices, uint32_t indexNewVertex,
|
||||
bool TriangleEPA::computeSilhouette(const vec3* vertices, uint32_t indexNewVertex,
|
||||
TrianglesStore& triangleStore) {
|
||||
|
||||
uint32_t first = triangleStore.getNbTriangles();
|
||||
|
@ -42,7 +42,7 @@ class TriangleEPA {
|
||||
float mDet;
|
||||
|
||||
/// Point v closest to the origin on the affine hull of the triangle
|
||||
Vector3 mClosestPoint;
|
||||
vec3 mClosestPoint;
|
||||
|
||||
/// Lambda1 value such that v = lambda0 * y_0 + lambda1 * y_1 + lambda2 * y_2
|
||||
float mLambda1;
|
||||
@ -90,22 +90,22 @@ class TriangleEPA {
|
||||
bool getIsObsolete() const;
|
||||
|
||||
/// Return the point closest to the origin
|
||||
const Vector3& getClosestPoint() const;
|
||||
const vec3& getClosestPoint() const;
|
||||
|
||||
// Return true if the closest point on affine hull is inside the triangle
|
||||
bool isClosestPointInternalToTriangle() const;
|
||||
|
||||
/// Return true if the triangle is visible from a given vertex
|
||||
bool isVisibleFromVertex(const Vector3* vertices, uint32_t index) const;
|
||||
bool isVisibleFromVertex(const vec3* vertices, uint32_t index) const;
|
||||
|
||||
/// Compute the point v closest to the origin of this triangle
|
||||
bool computeClosestPoint(const Vector3* vertices);
|
||||
bool computeClosestPoint(const vec3* vertices);
|
||||
|
||||
/// Compute the point of an object closest to the origin
|
||||
Vector3 computeClosestPointOfObject(const Vector3* supportPointsOfObject) const;
|
||||
vec3 computeClosestPointOfObject(const vec3* supportPointsOfObject) const;
|
||||
|
||||
/// Execute the recursive silhouette algorithm from this triangle face.
|
||||
bool computeSilhouette(const Vector3* vertices, uint32_t index, TrianglesStore& triangleStore);
|
||||
bool computeSilhouette(const vec3* vertices, uint32_t index, TrianglesStore& triangleStore);
|
||||
|
||||
/// Access operator
|
||||
uint32_t operator[](int32_t i) const;
|
||||
@ -145,7 +145,7 @@ inline bool TriangleEPA::getIsObsolete() const {
|
||||
}
|
||||
|
||||
// Return the point closest to the origin
|
||||
inline const Vector3& TriangleEPA::getClosestPoint() const {
|
||||
inline const vec3& TriangleEPA::getClosestPoint() const {
|
||||
return mClosestPoint;
|
||||
}
|
||||
|
||||
@ -155,15 +155,15 @@ inline bool TriangleEPA::isClosestPointInternalToTriangle() const {
|
||||
}
|
||||
|
||||
// Return true if the triangle is visible from a given vertex
|
||||
inline bool TriangleEPA::isVisibleFromVertex(const Vector3* vertices, uint32_t index) const {
|
||||
Vector3 closestToVert = vertices[index] - mClosestPoint;
|
||||
inline bool TriangleEPA::isVisibleFromVertex(const vec3* vertices, uint32_t index) const {
|
||||
vec3 closestToVert = vertices[index] - mClosestPoint;
|
||||
return (mClosestPoint.dot(closestToVert) > 0.0);
|
||||
}
|
||||
|
||||
// Compute the point of an object closest to the origin
|
||||
inline Vector3 TriangleEPA::computeClosestPointOfObject(const Vector3* supportPointsOfObject) const{
|
||||
const Vector3& p0 = supportPointsOfObject[mIndicesVertices[0]];
|
||||
return p0 + float(1.0)/mDet * (mLambda1 * (supportPointsOfObject[mIndicesVertices[1]] - p0) +
|
||||
inline vec3 TriangleEPA::computeClosestPointOfObject(const vec3* supportPointsOfObject) const{
|
||||
const vec3& p0 = supportPointsOfObject[mIndicesVertices[0]];
|
||||
return p0 + 1.0f/mDet * (mLambda1 * (supportPointsOfObject[mIndicesVertices[1]] - p0) +
|
||||
mLambda2 * (supportPointsOfObject[mIndicesVertices[2]] - p0));
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ class TrianglesStore {
|
||||
TriangleEPA& last();
|
||||
|
||||
/// Create a new triangle
|
||||
TriangleEPA* newTriangle(const Vector3* vertices, uint32_t v0, uint32_t v1, uint32_t v2);
|
||||
TriangleEPA* newTriangle(const vec3* vertices, uint32_t v0, uint32_t v1, uint32_t v2);
|
||||
|
||||
/// Access operator
|
||||
TriangleEPA& operator[](int32_t i);
|
||||
@ -92,7 +92,7 @@ inline TriangleEPA& TrianglesStore::last() {
|
||||
}
|
||||
|
||||
// Create a new triangle
|
||||
inline TriangleEPA* TrianglesStore::newTriangle(const Vector3* vertices,
|
||||
inline TriangleEPA* TrianglesStore::newTriangle(const vec3* vertices,
|
||||
uint32_t v0,uint32_t v1, uint32_t v2) {
|
||||
TriangleEPA* newTriangle = NULL;
|
||||
|
||||
|
@ -43,11 +43,11 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
|
||||
PROFILE("GJKAlgorithm::testCollision()");
|
||||
|
||||
Vector3 suppA; // Support point of object A
|
||||
Vector3 suppB; // Support point of object B
|
||||
Vector3 w; // Support point of Minkowski difference A-B
|
||||
Vector3 pA; // Closest point of object A
|
||||
Vector3 pB; // Closest point of object B
|
||||
vec3 suppA; // Support point of object A
|
||||
vec3 suppB; // Support point of object B
|
||||
vec3 w; // Support point of Minkowski difference A-B
|
||||
vec3 pA; // Closest point of object A
|
||||
vec3 pB; // Closest point of object B
|
||||
float vDotw;
|
||||
float prevDistSquare;
|
||||
|
||||
@ -61,16 +61,16 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
void** shape2CachedCollisionData = shape2Info.cachedCollisionData;
|
||||
|
||||
// Get the local-space to world-space transforms
|
||||
const Transform transform1 = shape1Info.shapeToWorldTransform;
|
||||
const Transform transform2 = shape2Info.shapeToWorldTransform;
|
||||
const etk::Transform3D transform1 = shape1Info.shapeToWorldTransform;
|
||||
const etk::Transform3D transform2 = shape2Info.shapeToWorldTransform;
|
||||
|
||||
// Transform a point from local space of body 2 to local
|
||||
// etk::Transform3D a point from local space of body 2 to local
|
||||
// space of body 1 (the GJK algorithm is done in local space of body 1)
|
||||
Transform body2Tobody1 = transform1.getInverse() * transform2;
|
||||
etk::Transform3D body2Tobody1 = transform1.getInverse() * transform2;
|
||||
|
||||
// Matrix that transform a direction from local
|
||||
// space of body 1 int32_to local space of body 2
|
||||
Matrix3x3 rotateToBody2 = transform2.getOrientation().getMatrix().getTranspose() *
|
||||
etk::Matrix3x3 rotateToBody2 = transform2.getOrientation().getMatrix().getTranspose() *
|
||||
transform1.getOrientation().getMatrix();
|
||||
|
||||
// Initialize the margin (sum of margins of both objects)
|
||||
@ -82,7 +82,7 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
Simplex simplex;
|
||||
|
||||
// Get the previous point V (last cached separating axis)
|
||||
Vector3 v = mCurrentOverlappingPair->getCachedSeparatingAxis();
|
||||
vec3 v = mCurrentOverlappingPair->getCachedSeparatingAxis();
|
||||
|
||||
// Initialize the upper bound for the square distance
|
||||
float distSquare = DECIMAL_LARGEST;
|
||||
@ -123,7 +123,7 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
pB = body2Tobody1.getInverse() * (pB + (shape2->getMargin() / dist) * v);
|
||||
|
||||
// Compute the contact info
|
||||
Vector3 normal = transform1.getOrientation() * (-v.getUnit());
|
||||
vec3 normal = transform1.getOrientation() * (-v.safeNormalized());
|
||||
float penetrationDepth = margin - dist;
|
||||
|
||||
// Reject the contact if the penetration depth is negative (due too numerical errors)
|
||||
@ -156,7 +156,7 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
pB = body2Tobody1.getInverse() * (pB + (shape2->getMargin() / dist) * v);
|
||||
|
||||
// Compute the contact info
|
||||
Vector3 normal = transform1.getOrientation() * (-v.getUnit());
|
||||
vec3 normal = transform1.getOrientation() * (-v.safeNormalized());
|
||||
float penetrationDepth = margin - dist;
|
||||
|
||||
// Reject the contact if the penetration depth is negative (due too numerical errors)
|
||||
@ -187,7 +187,7 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
pB = body2Tobody1.getInverse() * (pB + (shape2->getMargin() / dist) * v);
|
||||
|
||||
// Compute the contact info
|
||||
Vector3 normal = transform1.getOrientation() * (-v.getUnit());
|
||||
vec3 normal = transform1.getOrientation() * (-v.safeNormalized());
|
||||
float penetrationDepth = margin - dist;
|
||||
|
||||
// Reject the contact if the penetration depth is negative (due too numerical errors)
|
||||
@ -205,14 +205,14 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
|
||||
// Store and update the squared distance of the closest point
|
||||
prevDistSquare = distSquare;
|
||||
distSquare = v.lengthSquare();
|
||||
distSquare = v.length2();
|
||||
|
||||
// If the distance to the closest point doesn't improve a lot
|
||||
if (prevDistSquare - distSquare <= MACHINE_EPSILON * prevDistSquare) {
|
||||
simplex.backupClosestPointInSimplex(v);
|
||||
|
||||
// Get the new squared distance
|
||||
distSquare = v.lengthSquare();
|
||||
distSquare = v.length2();
|
||||
|
||||
// Compute the closet points of both objects (without the margins)
|
||||
simplex.computeClosestPointsOfAandB(pA, pB);
|
||||
@ -225,7 +225,7 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
pB = body2Tobody1.getInverse() * (pB + (shape2->getMargin() / dist) * v);
|
||||
|
||||
// Compute the contact info
|
||||
Vector3 normal = transform1.getOrientation() * (-v.getUnit());
|
||||
vec3 normal = transform1.getOrientation() * (-v.safeNormalized());
|
||||
float penetrationDepth = margin - dist;
|
||||
|
||||
// Reject the contact if the penetration depth is negative (due too numerical errors)
|
||||
@ -257,17 +257,17 @@ void GJKAlgorithm::testCollision(const CollisionShapeInfo& shape1Info,
|
||||
/// a polytope must exist. Then, we give that polytope to the EPA algorithm to
|
||||
/// compute the correct penetration depth and contact points of the enlarged objects.
|
||||
void GJKAlgorithm::computePenetrationDepthForEnlargedObjects(const CollisionShapeInfo& shape1Info,
|
||||
const Transform& transform1,
|
||||
const etk::Transform3D& transform1,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
const Transform& transform2,
|
||||
const etk::Transform3D& transform2,
|
||||
NarrowPhaseCallback* narrowPhaseCallback,
|
||||
Vector3& v) {
|
||||
vec3& v) {
|
||||
PROFILE("GJKAlgorithm::computePenetrationDepthForEnlargedObjects()");
|
||||
|
||||
Simplex simplex;
|
||||
Vector3 suppA;
|
||||
Vector3 suppB;
|
||||
Vector3 w;
|
||||
vec3 suppA;
|
||||
vec3 suppB;
|
||||
vec3 w;
|
||||
float vDotw;
|
||||
float distSquare = DECIMAL_LARGEST;
|
||||
float prevDistSquare;
|
||||
@ -281,12 +281,12 @@ void GJKAlgorithm::computePenetrationDepthForEnlargedObjects(const CollisionShap
|
||||
void** shape1CachedCollisionData = shape1Info.cachedCollisionData;
|
||||
void** shape2CachedCollisionData = shape2Info.cachedCollisionData;
|
||||
|
||||
// Transform a point from local space of body 2 to local space
|
||||
// etk::Transform3D a point from local space of body 2 to local space
|
||||
// of body 1 (the GJK algorithm is done in local space of body 1)
|
||||
Transform body2ToBody1 = transform1.getInverse() * transform2;
|
||||
etk::Transform3D body2ToBody1 = transform1.getInverse() * transform2;
|
||||
|
||||
// Matrix that transform a direction from local space of body 1 int32_to local space of body 2
|
||||
Matrix3x3 rotateToBody2 = transform2.getOrientation().getMatrix().getTranspose() *
|
||||
etk::Matrix3x3 rotateToBody2 = transform2.getOrientation().getMatrix().getTranspose() *
|
||||
transform1.getOrientation().getMatrix();
|
||||
|
||||
do {
|
||||
@ -319,7 +319,7 @@ void GJKAlgorithm::computePenetrationDepthForEnlargedObjects(const CollisionShap
|
||||
|
||||
// Store and update the square distance
|
||||
prevDistSquare = distSquare;
|
||||
distSquare = v.lengthSquare();
|
||||
distSquare = v.length2();
|
||||
|
||||
if (prevDistSquare - distSquare <= MACHINE_EPSILON * prevDistSquare) {
|
||||
return;
|
||||
@ -337,10 +337,10 @@ void GJKAlgorithm::computePenetrationDepthForEnlargedObjects(const CollisionShap
|
||||
}
|
||||
|
||||
// Use the GJK Algorithm to find if a point is inside a convex collision shape
|
||||
bool GJKAlgorithm::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) {
|
||||
bool GJKAlgorithm::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) {
|
||||
|
||||
Vector3 suppA; // Support point of object A
|
||||
Vector3 w; // Support point of Minkowski difference A-B
|
||||
vec3 suppA; // Support point of object A
|
||||
vec3 w; // Support point of Minkowski difference A-B
|
||||
float prevDistSquare;
|
||||
|
||||
assert(proxyShape->getCollisionShape()->isConvex());
|
||||
@ -350,13 +350,13 @@ bool GJKAlgorithm::testPointInside(const Vector3& localPoint, ProxyShape* proxyS
|
||||
void** shapeCachedCollisionData = proxyShape->getCachedCollisionData();
|
||||
|
||||
// Support point of object B (object B is a single point)
|
||||
const Vector3 suppB(localPoint);
|
||||
const vec3 suppB(localPoint);
|
||||
|
||||
// Create a simplex set
|
||||
Simplex simplex;
|
||||
|
||||
// Initial supporting direction
|
||||
Vector3 v(1, 1, 1);
|
||||
vec3 v(1, 1, 1);
|
||||
|
||||
// Initialize the upper bound for the square distance
|
||||
float distSquare = DECIMAL_LARGEST;
|
||||
@ -387,7 +387,7 @@ bool GJKAlgorithm::testPointInside(const Vector3& localPoint, ProxyShape* proxyS
|
||||
|
||||
// Store and update the squared distance of the closest point
|
||||
prevDistSquare = distSquare;
|
||||
distSquare = v.lengthSquare();
|
||||
distSquare = v.length2();
|
||||
|
||||
// If the distance to the closest point doesn't improve a lot
|
||||
if (prevDistSquare - distSquare <= MACHINE_EPSILON * prevDistSquare) {
|
||||
@ -413,29 +413,29 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* proxyShape, RaycastInfo&
|
||||
|
||||
void** shapeCachedCollisionData = proxyShape->getCachedCollisionData();
|
||||
|
||||
Vector3 suppA; // Current lower bound point on the ray (starting at ray's origin)
|
||||
Vector3 suppB; // Support point on the collision shape
|
||||
vec3 suppA; // Current lower bound point on the ray (starting at ray's origin)
|
||||
vec3 suppB; // Support point on the collision shape
|
||||
const float machineEpsilonSquare = MACHINE_EPSILON * MACHINE_EPSILON;
|
||||
const float epsilon = float(0.0001);
|
||||
|
||||
// Convert the ray origin and direction int32_to the local-space of the collision shape
|
||||
Vector3 rayDirection = ray.point2 - ray.point1;
|
||||
vec3 rayDirection = ray.point2 - ray.point1;
|
||||
|
||||
// If the points of the segment are two close, return no hit
|
||||
if (rayDirection.lengthSquare() < machineEpsilonSquare) return false;
|
||||
if (rayDirection.length2() < machineEpsilonSquare) return false;
|
||||
|
||||
Vector3 w;
|
||||
vec3 w;
|
||||
|
||||
// Create a simplex set
|
||||
Simplex simplex;
|
||||
|
||||
Vector3 n(float(0.0), float(0.0), float(0.0));
|
||||
float lambda = float(0.0);
|
||||
vec3 n(0.0f, float(0.0), float(0.0));
|
||||
float lambda = 0.0f;
|
||||
suppA = ray.point1; // Current lower bound point on the ray (starting at ray's origin)
|
||||
suppB = shape->getLocalSupportPointWithoutMargin(rayDirection, shapeCachedCollisionData);
|
||||
Vector3 v = suppA - suppB;
|
||||
vec3 v = suppA - suppB;
|
||||
float vDotW, vDotR;
|
||||
float distSquare = v.lengthSquare();
|
||||
float distSquare = v.length2();
|
||||
int32_t nbIterations = 0;
|
||||
|
||||
// GJK Algorithm loop
|
||||
@ -472,10 +472,10 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* proxyShape, RaycastInfo&
|
||||
// Compute the closest point
|
||||
if (simplex.computeClosestPoint(v)) {
|
||||
|
||||
distSquare = v.lengthSquare();
|
||||
distSquare = v.length2();
|
||||
}
|
||||
else {
|
||||
distSquare = float(0.0);
|
||||
distSquare = 0.0f;
|
||||
}
|
||||
|
||||
// If the current lower bound distance is larger than the maximum raycasting distance
|
||||
@ -488,8 +488,8 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* proxyShape, RaycastInfo&
|
||||
if (lambda < MACHINE_EPSILON) return false;
|
||||
|
||||
// Compute the closet points of both objects (without the margins)
|
||||
Vector3 pointA;
|
||||
Vector3 pointB;
|
||||
vec3 pointA;
|
||||
vec3 pointB;
|
||||
simplex.computeClosestPointsOfAandB(pointA, pointB);
|
||||
|
||||
// A raycast hit has been found, we fill in the raycast info
|
||||
@ -498,11 +498,11 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* proxyShape, RaycastInfo&
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
|
||||
if (n.lengthSquare() >= machineEpsilonSquare) { // The normal vector is valid
|
||||
if (n.length2() >= machineEpsilonSquare) { // The normal vector is valid
|
||||
raycastInfo.worldNormal = n;
|
||||
}
|
||||
else { // Degenerated normal vector, we return a zero normal vector
|
||||
raycastInfo.worldNormal = Vector3(float(0), float(0), float(0));
|
||||
raycastInfo.worldNormal = vec3(float(0), float(0), float(0));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -55,11 +55,11 @@ class GJKAlgorithm : public NarrowPhaseAlgorithm {
|
||||
|
||||
/// Compute the penetration depth for enlarged objects.
|
||||
void computePenetrationDepthForEnlargedObjects(const CollisionShapeInfo& shape1Info,
|
||||
const Transform& transform1,
|
||||
const etk::Transform3D& transform1,
|
||||
const CollisionShapeInfo& shape2Info,
|
||||
const Transform& transform2,
|
||||
const etk::Transform3D& transform2,
|
||||
NarrowPhaseCallback* narrowPhaseCallback,
|
||||
Vector3& v);
|
||||
vec3& v);
|
||||
|
||||
public :
|
||||
|
||||
@ -81,7 +81,7 @@ class GJKAlgorithm : public NarrowPhaseAlgorithm {
|
||||
NarrowPhaseCallback* narrowPhaseCallback);
|
||||
|
||||
/// Use the GJK Algorithm to find if a point is inside a convex collision shape
|
||||
bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape);
|
||||
bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape);
|
||||
|
||||
/// Ray casting algorithm agains a convex collision shape using the GJK Algorithm
|
||||
bool raycast(const Ray& ray, ProxyShape* proxyShape, RaycastInfo& raycastInfo);
|
||||
|
@ -25,7 +25,7 @@ Simplex::~Simplex() {
|
||||
/// suppPointA : support point of object A in a direction -v
|
||||
/// suppPointB : support point of object B in a direction v
|
||||
/// point : support point of object (A-B) => point = suppPointA - suppPointB
|
||||
void Simplex::addPoint(const Vector3& point, const Vector3& suppPointA, const Vector3& suppPointB) {
|
||||
void Simplex::addPoint(const vec3& point, const vec3& suppPointA, const vec3& suppPointB) {
|
||||
assert(!isFull());
|
||||
|
||||
mLastFound = 0;
|
||||
@ -57,7 +57,7 @@ void Simplex::addPoint(const Vector3& point, const Vector3& suppPointA, const Ve
|
||||
}
|
||||
|
||||
// Return true if the point is in the simplex
|
||||
bool Simplex::isPointInSimplex(const Vector3& point) const {
|
||||
bool Simplex::isPointInSimplex(const vec3& point) const {
|
||||
int32_t i;
|
||||
Bits bit;
|
||||
|
||||
@ -93,8 +93,8 @@ void Simplex::updateCache() {
|
||||
}
|
||||
|
||||
// Return the points of the simplex
|
||||
uint32_t Simplex::getSimplex(Vector3* suppPointsA, Vector3* suppPointsB,
|
||||
Vector3* points) const {
|
||||
uint32_t Simplex::getSimplex(vec3* suppPointsA, vec3* suppPointsB,
|
||||
vec3* points) const {
|
||||
uint32_t nbVertices = 0;
|
||||
int32_t i;
|
||||
Bits bit;
|
||||
@ -272,10 +272,10 @@ bool Simplex::isValidSubset(Bits subset) const {
|
||||
/// pA = sum(lambda_i * a_i) where "a_i" are the support points of object A
|
||||
/// pB = sum(lambda_i * b_i) where "b_i" are the support points of object B
|
||||
/// with lambda_i = deltaX_i / deltaX
|
||||
void Simplex::computeClosestPointsOfAandB(Vector3& pA, Vector3& pB) const {
|
||||
void Simplex::computeClosestPointsOfAandB(vec3& pA, vec3& pB) const {
|
||||
float deltaX = 0.0;
|
||||
pA.setAllValues(0.0, 0.0, 0.0);
|
||||
pB.setAllValues(0.0, 0.0, 0.0);
|
||||
pA.setValue(0.0, 0.0, 0.0);
|
||||
pB.setValue(0.0, 0.0, 0.0);
|
||||
int32_t i;
|
||||
Bits bit;
|
||||
|
||||
@ -290,7 +290,7 @@ void Simplex::computeClosestPointsOfAandB(Vector3& pA, Vector3& pB) const {
|
||||
}
|
||||
|
||||
assert(deltaX > 0.0);
|
||||
float factor = float(1.0) / deltaX;
|
||||
float factor = 1.0f / deltaX;
|
||||
pA *= factor;
|
||||
pB *= factor;
|
||||
}
|
||||
@ -299,7 +299,7 @@ void Simplex::computeClosestPointsOfAandB(Vector3& pA, Vector3& pB) const {
|
||||
/// This method executes the Jonhnson's algorithm for computing the point
|
||||
/// "v" of simplex that is closest to the origin. The method returns true
|
||||
/// if a closest point has been found.
|
||||
bool Simplex::computeClosestPoint(Vector3& v) {
|
||||
bool Simplex::computeClosestPoint(vec3& v) {
|
||||
Bits subset;
|
||||
|
||||
// For each possible simplex set
|
||||
@ -326,13 +326,13 @@ bool Simplex::computeClosestPoint(Vector3& v) {
|
||||
}
|
||||
|
||||
// Backup the closest point
|
||||
void Simplex::backupClosestPointInSimplex(Vector3& v) {
|
||||
void Simplex::backupClosestPointInSimplex(vec3& v) {
|
||||
float minDistSquare = DECIMAL_LARGEST;
|
||||
Bits bit;
|
||||
|
||||
for (bit = mAllBits; bit != 0x0; bit--) {
|
||||
if (isSubset(bit, mAllBits) && isProperSubset(bit)) {
|
||||
Vector3 u = computeClosestPointForSubset(bit);
|
||||
vec3 u = computeClosestPointForSubset(bit);
|
||||
float distSquare = u.dot(u);
|
||||
if (distSquare < minDistSquare) {
|
||||
minDistSquare = distSquare;
|
||||
@ -345,8 +345,8 @@ void Simplex::backupClosestPointInSimplex(Vector3& v) {
|
||||
|
||||
// Return the closest point "v" in the convex hull of the points in the subset
|
||||
// represented by the bits "subset"
|
||||
Vector3 Simplex::computeClosestPointForSubset(Bits subset) {
|
||||
Vector3 v(0.0, 0.0, 0.0); // Closet point v = sum(lambda_i * points[i])
|
||||
vec3 Simplex::computeClosestPointForSubset(Bits subset) {
|
||||
vec3 v(0.0, 0.0, 0.0); // Closet point v = sum(lambda_i * points[i])
|
||||
mMaxLengthSquare = 0.0;
|
||||
float deltaX = 0.0; // deltaX = sum of all det[subset][i]
|
||||
int32_t i;
|
||||
@ -371,5 +371,5 @@ Vector3 Simplex::computeClosestPointForSubset(Bits subset) {
|
||||
assert(deltaX > 0.0);
|
||||
|
||||
// Return the closet point "v" in the convex hull for the given subset
|
||||
return (float(1.0) / deltaX) * v;
|
||||
return (1.0f / deltaX) * v;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class Simplex {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Current points
|
||||
Vector3 mPoints[4];
|
||||
vec3 mPoints[4];
|
||||
|
||||
/// pointsLengthSquare[i] = (points[i].length)^2
|
||||
float mPointsLengthSquare[4];
|
||||
@ -40,13 +40,13 @@ class Simplex {
|
||||
float mMaxLengthSquare;
|
||||
|
||||
/// Support points of object A in local coordinates
|
||||
Vector3 mSuppPointsA[4];
|
||||
vec3 mSuppPointsA[4];
|
||||
|
||||
/// Support points of object B in local coordinates
|
||||
Vector3 mSuppPointsB[4];
|
||||
vec3 mSuppPointsB[4];
|
||||
|
||||
/// diff[i][j] contains points[i] - points[j]
|
||||
Vector3 mDiffLength[4][4];
|
||||
vec3 mDiffLength[4][4];
|
||||
|
||||
/// Cached determinant values
|
||||
float mDet[16][4];
|
||||
@ -94,7 +94,7 @@ class Simplex {
|
||||
void computeDeterminants();
|
||||
|
||||
/// Return the closest point "v" in the convex hull of a subset of points
|
||||
Vector3 computeClosestPointForSubset(Bits subset);
|
||||
vec3 computeClosestPointForSubset(Bits subset);
|
||||
|
||||
public:
|
||||
|
||||
@ -113,29 +113,29 @@ class Simplex {
|
||||
bool isEmpty() const;
|
||||
|
||||
/// Return the points of the simplex
|
||||
uint32_t getSimplex(Vector3* mSuppPointsA, Vector3* mSuppPointsB,
|
||||
Vector3* mPoints) const;
|
||||
uint32_t getSimplex(vec3* mSuppPointsA, vec3* mSuppPointsB,
|
||||
vec3* mPoints) const;
|
||||
|
||||
/// Return the maximum squared length of a point
|
||||
float getMaxLengthSquareOfAPoint() const;
|
||||
|
||||
/// Add a new support point of (A-B) int32_to the simplex.
|
||||
void addPoint(const Vector3& point, const Vector3& suppPointA, const Vector3& suppPointB);
|
||||
void addPoint(const vec3& point, const vec3& suppPointA, const vec3& suppPointB);
|
||||
|
||||
/// Return true if the point is in the simplex
|
||||
bool isPointInSimplex(const Vector3& point) const;
|
||||
bool isPointInSimplex(const vec3& point) const;
|
||||
|
||||
/// Return true if the set is affinely dependent
|
||||
bool isAffinelyDependent() const;
|
||||
|
||||
/// Backup the closest point
|
||||
void backupClosestPointInSimplex(Vector3& point);
|
||||
void backupClosestPointInSimplex(vec3& point);
|
||||
|
||||
/// Compute the closest points "pA" and "pB" of object A and B.
|
||||
void computeClosestPointsOfAandB(Vector3& pA, Vector3& pB) const;
|
||||
void computeClosestPointsOfAandB(vec3& pA, vec3& pB) const;
|
||||
|
||||
/// Compute the closest point to the origin of the current simplex.
|
||||
bool computeClosestPoint(Vector3& v);
|
||||
bool computeClosestPoint(vec3& v);
|
||||
};
|
||||
|
||||
// Return true if some bits of "a" overlap with bits of "b"
|
||||
|
@ -29,26 +29,26 @@ void SphereVsSphereAlgorithm::testCollision(const CollisionShapeInfo& shape1Info
|
||||
const SphereShape* sphereShape1 = static_cast<const SphereShape*>(shape1Info.collisionShape);
|
||||
const SphereShape* sphereShape2 = static_cast<const SphereShape*>(shape2Info.collisionShape);
|
||||
// Get the local-space to world-space transforms
|
||||
const Transform& transform1 = shape1Info.shapeToWorldTransform;
|
||||
const Transform& transform2 = shape2Info.shapeToWorldTransform;
|
||||
const etk::Transform3D& transform1 = shape1Info.shapeToWorldTransform;
|
||||
const etk::Transform3D& transform2 = shape2Info.shapeToWorldTransform;
|
||||
// Compute the distance between the centers
|
||||
Vector3 vectorBetweenCenters = transform2.getPosition() - transform1.getPosition();
|
||||
float squaredDistanceBetweenCenters = vectorBetweenCenters.lengthSquare();
|
||||
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
|
||||
if (squaredDistanceBetweenCenters <= sumRadius * sumRadius) {
|
||||
Vector3 centerSphere2InBody1LocalSpace = transform1.getInverse() * transform2.getPosition();
|
||||
Vector3 centerSphere1InBody2LocalSpace = transform2.getInverse() * transform1.getPosition();
|
||||
Vector3 int32_tersectionOnBody1 = sphereShape1->getRadius() *
|
||||
centerSphere2InBody1LocalSpace.getUnit();
|
||||
Vector3 int32_tersectionOnBody2 = sphereShape2->getRadius() *
|
||||
centerSphere1InBody2LocalSpace.getUnit();
|
||||
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();
|
||||
float penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters);
|
||||
|
||||
// Create the contact info object
|
||||
ContactPointInfo contactInfo(shape1Info.proxyShape, shape2Info.proxyShape, shape1Info.collisionShape,
|
||||
shape2Info.collisionShape, vectorBetweenCenters.getUnit(), penetrationDepth,
|
||||
shape2Info.collisionShape, vectorBetweenCenters.safeNormalized(), penetrationDepth,
|
||||
int32_tersectionOnBody1, int32_tersectionOnBody2);
|
||||
// Notify about the new contact
|
||||
narrowPhaseCallback->notifyContact(shape1Info.overlappingPair, contactInfo);
|
||||
|
@ -19,15 +19,17 @@ AABB::AABB() {
|
||||
}
|
||||
|
||||
// Constructor
|
||||
AABB::AABB(const Vector3& minCoordinates, const Vector3& maxCoordinates)
|
||||
:m_minCoordinates(minCoordinates), m_maxCoordinates(maxCoordinates) {
|
||||
|
||||
AABB::AABB(const vec3& minCoordinates, const vec3& maxCoordinates):
|
||||
m_minCoordinates(minCoordinates),
|
||||
m_maxCoordinates(maxCoordinates) {
|
||||
|
||||
}
|
||||
|
||||
// Copy-constructor
|
||||
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) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@ -37,62 +39,76 @@ AABB::~AABB() {
|
||||
|
||||
// Merge the AABB in parameter with the current one
|
||||
void AABB::mergeWithAABB(const AABB& aabb) {
|
||||
m_minCoordinates.x = std::min(m_minCoordinates.x, aabb.m_minCoordinates.x);
|
||||
m_minCoordinates.y = std::min(m_minCoordinates.y, aabb.m_minCoordinates.y);
|
||||
m_minCoordinates.z = std::min(m_minCoordinates.z, aabb.m_minCoordinates.z);
|
||||
|
||||
m_maxCoordinates.x = std::max(m_maxCoordinates.x, aabb.m_maxCoordinates.x);
|
||||
m_maxCoordinates.y = std::max(m_maxCoordinates.y, aabb.m_maxCoordinates.y);
|
||||
m_maxCoordinates.z = std::max(m_maxCoordinates.z, aabb.m_maxCoordinates.z);
|
||||
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.x = std::min(aabb1.m_minCoordinates.x, aabb2.m_minCoordinates.x);
|
||||
m_minCoordinates.y = std::min(aabb1.m_minCoordinates.y, aabb2.m_minCoordinates.y);
|
||||
m_minCoordinates.z = std::min(aabb1.m_minCoordinates.z, aabb2.m_minCoordinates.z);
|
||||
|
||||
m_maxCoordinates.x = std::max(aabb1.m_maxCoordinates.x, aabb2.m_maxCoordinates.x);
|
||||
m_maxCoordinates.y = std::max(aabb1.m_maxCoordinates.y, aabb2.m_maxCoordinates.y);
|
||||
m_maxCoordinates.z = std::max(aabb1.m_maxCoordinates.z, aabb2.m_maxCoordinates.z);
|
||||
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 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 Vector3* trianglePoints) {
|
||||
|
||||
Vector3 minCoords(trianglePoints[0].x, trianglePoints[0].y, trianglePoints[0].z);
|
||||
Vector3 maxCoords(trianglePoints[0].x, trianglePoints[0].y, trianglePoints[0].z);
|
||||
|
||||
if (trianglePoints[1].x < minCoords.x) minCoords.x = trianglePoints[1].x;
|
||||
if (trianglePoints[1].y < minCoords.y) minCoords.y = trianglePoints[1].y;
|
||||
if (trianglePoints[1].z < minCoords.z) minCoords.z = trianglePoints[1].z;
|
||||
|
||||
if (trianglePoints[2].x < minCoords.x) minCoords.x = trianglePoints[2].x;
|
||||
if (trianglePoints[2].y < minCoords.y) minCoords.y = trianglePoints[2].y;
|
||||
if (trianglePoints[2].z < minCoords.z) minCoords.z = trianglePoints[2].z;
|
||||
|
||||
if (trianglePoints[1].x > maxCoords.x) maxCoords.x = trianglePoints[1].x;
|
||||
if (trianglePoints[1].y > maxCoords.y) maxCoords.y = trianglePoints[1].y;
|
||||
if (trianglePoints[1].z > maxCoords.z) maxCoords.z = trianglePoints[1].z;
|
||||
|
||||
if (trianglePoints[2].x > maxCoords.x) maxCoords.x = trianglePoints[2].x;
|
||||
if (trianglePoints[2].y > maxCoords.y) maxCoords.y = trianglePoints[2].y;
|
||||
if (trianglePoints[2].z > maxCoords.z) maxCoords.z = trianglePoints[2].z;
|
||||
|
||||
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].z() < minCoords.z()) {
|
||||
minCoords.setZ(trianglePoints[1].z());
|
||||
}
|
||||
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].z() < minCoords.z()) {
|
||||
minCoords.setZ(trianglePoints[2].z());
|
||||
}
|
||||
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].z() > maxCoords.z()) {
|
||||
maxCoords.setZ(trianglePoints[1].z());
|
||||
}
|
||||
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].z() > maxCoords.z()) {
|
||||
maxCoords.setZ(trianglePoints[2].z());
|
||||
}
|
||||
return AABB(minCoords, maxCoords);
|
||||
}
|
||||
|
||||
@ -100,33 +116,40 @@ AABB AABB::createAABBForTriangle(const Vector3* trianglePoints) {
|
||||
/// 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 Vector3 point2 = ray.point1 + ray.maxFraction * (ray.point2 - ray.point1);
|
||||
const Vector3 e = m_maxCoordinates - m_minCoordinates;
|
||||
const Vector3 d = point2 - ray.point1;
|
||||
const Vector3 m = ray.point1 + point2 - m_minCoordinates - m_maxCoordinates;
|
||||
|
||||
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;
|
||||
// Test if the AABB face normals are separating axis
|
||||
float adx = std::abs(d.x);
|
||||
if (std::abs(m.x) > e.x + adx) return false;
|
||||
float ady = std::abs(d.y);
|
||||
if (std::abs(m.y) > e.y + ady) return false;
|
||||
float adz = std::abs(d.z);
|
||||
if (std::abs(m.z) > e.z + adz) return false;
|
||||
|
||||
float adx = std::abs(d.x());
|
||||
if (std::abs(m.x()) > e.x() + adx) {
|
||||
return false;
|
||||
}
|
||||
float ady = std::abs(d.y());
|
||||
if (std::abs(m.y()) > e.y() + ady) {
|
||||
return false;
|
||||
}
|
||||
float adz = std::abs(d.z());
|
||||
if (std::abs(m.z()) > e.z() + adz) {
|
||||
return false;
|
||||
}
|
||||
// Add in an epsilon term to counteract arithmetic errors when segment is
|
||||
// (near) parallel to a coordinate axis (see text for detail)
|
||||
const float epsilon = 0.00001;
|
||||
adx += epsilon;
|
||||
ady += epsilon;
|
||||
adz += epsilon;
|
||||
|
||||
// Test if the cross products between face normals and ray direction are
|
||||
// separating axis
|
||||
if (std::abs(m.y * d.z - m.z * d.y) > e.y * adz + e.z * ady) return false;
|
||||
if (std::abs(m.z * d.x - m.x * d.z) > e.x * adz + e.z * adx) return false;
|
||||
if (std::abs(m.x * d.y - m.y * d.x) > e.x * ady + e.y * adx) return false;
|
||||
|
||||
if (std::abs(m.y() * d.z() - m.z() * d.y()) > e.y() * adz + e.z() * ady) {
|
||||
return false;
|
||||
}
|
||||
if (std::abs(m.z() * d.x() - m.x() * d.z()) > e.x() * adz + e.z() * adx) {
|
||||
return false;
|
||||
}
|
||||
if (std::abs(m.x() * d.y() - m.y() * d.x()) > e.x() * ady + e.y() * adx) {
|
||||
return false;
|
||||
}
|
||||
// No separating axis has been found
|
||||
return true;
|
||||
}
|
||||
|
@ -25,10 +25,10 @@ class AABB {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Minimum world coordinates of the AABB on the x,y and z axis
|
||||
Vector3 m_minCoordinates;
|
||||
vec3 m_minCoordinates;
|
||||
|
||||
/// Maximum world coordinates of the AABB on the x,y and z axis
|
||||
Vector3 m_maxCoordinates;
|
||||
vec3 m_maxCoordinates;
|
||||
|
||||
public :
|
||||
|
||||
@ -38,7 +38,7 @@ class AABB {
|
||||
AABB();
|
||||
|
||||
/// Constructor
|
||||
AABB(const Vector3& minCoordinates, const Vector3& maxCoordinates);
|
||||
AABB(const vec3& minCoordinates, const vec3& maxCoordinates);
|
||||
|
||||
/// Copy-constructor
|
||||
AABB(const AABB& aabb);
|
||||
@ -47,22 +47,22 @@ class AABB {
|
||||
~AABB();
|
||||
|
||||
/// Return the center point
|
||||
Vector3 getCenter() const;
|
||||
vec3 getCenter() const;
|
||||
|
||||
/// Return the minimum coordinates of the AABB
|
||||
const Vector3& getMin() const;
|
||||
const vec3& getMin() const;
|
||||
|
||||
/// Set the minimum coordinates of the AABB
|
||||
void setMin(const Vector3& min);
|
||||
void setMin(const vec3& min);
|
||||
|
||||
/// Return the maximum coordinates of the AABB
|
||||
const Vector3& getMax() const;
|
||||
const vec3& getMax() const;
|
||||
|
||||
/// Set the maximum coordinates of the AABB
|
||||
void setMax(const Vector3& max);
|
||||
void setMax(const vec3& max);
|
||||
|
||||
/// Return the size of the AABB in the three dimension x, y and z
|
||||
Vector3 getExtent() const;
|
||||
vec3 getExtent() const;
|
||||
|
||||
/// Inflate each side of the AABB by a given size
|
||||
void inflate(float dx, float dy, float dz);
|
||||
@ -83,16 +83,16 @@ class AABB {
|
||||
bool contains(const AABB& aabb) const;
|
||||
|
||||
/// Return true if a point is inside the AABB
|
||||
bool contains(const Vector3& point) const;
|
||||
bool contains(const vec3& point) const;
|
||||
|
||||
/// Return true if the AABB of a triangle int32_tersects the AABB
|
||||
bool testCollisionTriangleAABB(const Vector3* trianglePoints) const;
|
||||
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 Vector3* trianglePoints);
|
||||
static AABB createAABBForTriangle(const vec3* trianglePoints);
|
||||
|
||||
/// Assignment operator
|
||||
AABB& operator=(const AABB& aabb);
|
||||
@ -103,79 +103,79 @@ class AABB {
|
||||
};
|
||||
|
||||
// Return the center point of the AABB in world coordinates
|
||||
inline Vector3 AABB::getCenter() const {
|
||||
return (m_minCoordinates + m_maxCoordinates) * float(0.5);
|
||||
inline vec3 AABB::getCenter() const {
|
||||
return (m_minCoordinates + m_maxCoordinates) * 0.5f;
|
||||
}
|
||||
|
||||
// Return the minimum coordinates of the AABB
|
||||
inline const Vector3& AABB::getMin() const {
|
||||
inline const vec3& AABB::getMin() const {
|
||||
return m_minCoordinates;
|
||||
}
|
||||
|
||||
// Set the minimum coordinates of the AABB
|
||||
inline void AABB::setMin(const Vector3& min) {
|
||||
inline void AABB::setMin(const vec3& min) {
|
||||
m_minCoordinates = min;
|
||||
}
|
||||
|
||||
// Return the maximum coordinates of the AABB
|
||||
inline const Vector3& AABB::getMax() const {
|
||||
inline const vec3& AABB::getMax() const {
|
||||
return m_maxCoordinates;
|
||||
}
|
||||
|
||||
// Set the maximum coordinates of the AABB
|
||||
inline void AABB::setMax(const Vector3& max) {
|
||||
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 Vector3 AABB::getExtent() const {
|
||||
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 += Vector3(dx, dy, dz);
|
||||
m_minCoordinates -= Vector3(dx, dy, 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;
|
||||
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 Vector3 diff = m_maxCoordinates - m_minCoordinates;
|
||||
return (diff.x * diff.y * diff.z);
|
||||
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 Vector3* trianglePoints) const {
|
||||
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 (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;
|
||||
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 Vector3& point) const {
|
||||
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);
|
||||
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
|
||||
|
@ -18,11 +18,11 @@ using namespace reactphysics3d;
|
||||
* @param extent The vector with the three extents of the box (in meters)
|
||||
* @param margin The collision margin (in meters) around the collision shape
|
||||
*/
|
||||
BoxShape::BoxShape(const Vector3& extent, float margin)
|
||||
: ConvexShape(BOX, margin), m_extent(extent - Vector3(margin, margin, margin)) {
|
||||
assert(extent.x > float(0.0) && extent.x > margin);
|
||||
assert(extent.y > float(0.0) && extent.y > margin);
|
||||
assert(extent.z > float(0.0) && extent.z > margin);
|
||||
BoxShape::BoxShape(const vec3& extent, float margin)
|
||||
: ConvexShape(BOX, margin), m_extent(extent - vec3(margin, margin, margin)) {
|
||||
assert(extent.x() > 0.0f && extent.x() > margin);
|
||||
assert(extent.y() > 0.0f && extent.y() > margin);
|
||||
assert(extent.z() > 0.0f && extent.z() > margin);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@ -36,13 +36,13 @@ BoxShape::~BoxShape() {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
void BoxShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
float factor = (float(1.0) / float(3.0)) * mass;
|
||||
Vector3 realExtent = m_extent + Vector3(mMargin, mMargin, mMargin);
|
||||
float xSquare = realExtent.x * realExtent.x;
|
||||
float ySquare = realExtent.y * realExtent.y;
|
||||
float zSquare = realExtent.z * realExtent.z;
|
||||
tensor.setAllValues(factor * (ySquare + zSquare), 0.0, 0.0,
|
||||
void BoxShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
float factor = (1.0f / float(3.0)) * mass;
|
||||
vec3 realExtent = m_extent + vec3(m_margin, m_margin, m_margin);
|
||||
float xSquare = realExtent.x() * realExtent.x();
|
||||
float ySquare = realExtent.y() * realExtent.y();
|
||||
float zSquare = realExtent.z() * realExtent.z();
|
||||
tensor.setValue(factor * (ySquare + zSquare), 0.0, 0.0,
|
||||
0.0, factor * (xSquare + zSquare), 0.0,
|
||||
0.0, 0.0, factor * (xSquare + ySquare));
|
||||
}
|
||||
@ -50,11 +50,11 @@ void BoxShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
// Raycast method with feedback information
|
||||
bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||
|
||||
Vector3 rayDirection = ray.point2 - ray.point1;
|
||||
vec3 rayDirection = ray.point2 - ray.point1;
|
||||
float tMin = DECIMAL_SMALLEST;
|
||||
float tMax = DECIMAL_LARGEST;
|
||||
Vector3 normalDirection(float(0), float(0), float(0));
|
||||
Vector3 currentNormal;
|
||||
vec3 normalDirection(float(0), float(0), float(0));
|
||||
vec3 currentNormal;
|
||||
|
||||
// For each of the three slabs
|
||||
for (int32_t i=0; i<3; i++) {
|
||||
@ -68,12 +68,12 @@ bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pro
|
||||
else {
|
||||
|
||||
// Compute the int32_tersection of the ray with the near and far plane of the slab
|
||||
float oneOverD = float(1.0) / rayDirection[i];
|
||||
float oneOverD = 1.0f / rayDirection[i];
|
||||
float t1 = (-m_extent[i] - ray.point1[i]) * oneOverD;
|
||||
float t2 = (m_extent[i] - ray.point1[i]) * oneOverD;
|
||||
currentNormal[0] = (i == 0) ? -m_extent[i] : float(0.0);
|
||||
currentNormal[1] = (i == 1) ? -m_extent[i] : float(0.0);
|
||||
currentNormal[2] = (i == 2) ? -m_extent[i] : float(0.0);
|
||||
currentNormal[0] = (i == 0) ? -m_extent[i] : 0.0f;
|
||||
currentNormal[1] = (i == 1) ? -m_extent[i] : 0.0f;
|
||||
currentNormal[2] = (i == 2) ? -m_extent[i] : 0.0f;
|
||||
|
||||
// Swap t1 and t2 if need so that t1 is int32_tersection with near plane and
|
||||
// t2 with far plane
|
||||
@ -98,10 +98,10 @@ bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pro
|
||||
}
|
||||
|
||||
// If tMin is negative, we return no hit
|
||||
if (tMin < float(0.0) || tMin > ray.maxFraction) return false;
|
||||
if (tMin < 0.0f || tMin > ray.maxFraction) return false;
|
||||
|
||||
// The ray int32_tersects the three slabs, we compute the hit point
|
||||
Vector3 localHitPoint = ray.point1 + tMin * rayDirection;
|
||||
vec3 localHitPoint = ray.point1 + tMin * rayDirection;
|
||||
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
|
@ -36,7 +36,7 @@ class BoxShape : public ConvexShape {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Extent sizes of the box in the x, y and z direction
|
||||
Vector3 m_extent;
|
||||
vec3 m_extent;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -47,11 +47,11 @@ class BoxShape : public ConvexShape {
|
||||
BoxShape& operator=(const BoxShape& shape);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
@ -64,36 +64,36 @@ class BoxShape : public ConvexShape {
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
BoxShape(const Vector3& extent, float margin = OBJECT_MARGIN);
|
||||
BoxShape(const vec3& extent, float margin = OBJECT_MARGIN);
|
||||
|
||||
/// Destructor
|
||||
virtual ~BoxShape();
|
||||
|
||||
/// Return the extents of the box
|
||||
Vector3 getExtent() const;
|
||||
vec3 getExtent() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
};
|
||||
|
||||
// Return the extents of the box
|
||||
/**
|
||||
* @return The vector with the three extents of the box shape (in meters)
|
||||
*/
|
||||
inline Vector3 BoxShape::getExtent() const {
|
||||
return m_extent + Vector3(mMargin, mMargin, mMargin);
|
||||
inline 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 Vector3& scaling) {
|
||||
inline void BoxShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
m_extent = (m_extent / mScaling) * scaling;
|
||||
m_extent = (m_extent / m_scaling) * scaling;
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
@ -104,10 +104,10 @@ inline void BoxShape::setLocalScaling(const Vector3& 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(Vector3& min, Vector3& max) const {
|
||||
inline void BoxShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
// Maximum bounds
|
||||
max = m_extent + Vector3(mMargin, mMargin, mMargin);
|
||||
max = m_extent + vec3(m_margin, m_margin, m_margin);
|
||||
|
||||
// Minimum bounds
|
||||
min = -max;
|
||||
@ -119,19 +119,19 @@ inline size_t BoxShape::getSizeInBytes() const {
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the objec margin
|
||||
inline Vector3 BoxShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
inline vec3 BoxShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
return Vector3(direction.x < 0.0 ? -m_extent.x : m_extent.x,
|
||||
direction.y < 0.0 ? -m_extent.y : m_extent.y,
|
||||
direction.z < 0.0 ? -m_extent.z : m_extent.z);
|
||||
return vec3(direction.x() < 0.0 ? -m_extent.x() : m_extent.x(),
|
||||
direction.y() < 0.0 ? -m_extent.y() : m_extent.y(),
|
||||
direction.z() < 0.0 ? -m_extent.z() : m_extent.z());
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool BoxShape::testPointInside(const Vector3& 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]);
|
||||
inline 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]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ using namespace reactphysics3d;
|
||||
* @param height The height of the capsule (in meters)
|
||||
*/
|
||||
CapsuleShape::CapsuleShape(float radius, float height)
|
||||
: ConvexShape(CAPSULE, radius), mHalfHeight(height * float(0.5)) {
|
||||
assert(radius > float(0.0));
|
||||
assert(height > float(0.0));
|
||||
: ConvexShape(CAPSULE, radius), m_halfHeight(height * 0.5f) {
|
||||
assert(radius > 0.0f);
|
||||
assert(height > 0.0f);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@ -34,38 +34,38 @@ CapsuleShape::~CapsuleShape() {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
void CapsuleShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
void CapsuleShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
|
||||
// The inertia tensor formula for a capsule can be found in : Game Engine Gems, Volume 1
|
||||
|
||||
float height = mHalfHeight + mHalfHeight;
|
||||
float radiusSquare = mMargin * mMargin;
|
||||
float height = m_halfHeight + m_halfHeight;
|
||||
float radiusSquare = m_margin * m_margin;
|
||||
float heightSquare = height * height;
|
||||
float radiusSquareDouble = radiusSquare + radiusSquare;
|
||||
float factor1 = float(2.0) * mMargin / (float(4.0) * mMargin + float(3.0) * height);
|
||||
float factor2 = float(3.0) * height / (float(4.0) * mMargin + float(3.0) * height);
|
||||
float factor1 = float(2.0) * m_margin / (float(4.0) * m_margin + float(3.0) * height);
|
||||
float factor2 = float(3.0) * height / (float(4.0) * m_margin + float(3.0) * height);
|
||||
float sum1 = float(0.4) * radiusSquareDouble;
|
||||
float sum2 = float(0.75) * height * mMargin + float(0.5) * heightSquare;
|
||||
float sum2 = float(0.75) * height * m_margin + 0.5f * heightSquare;
|
||||
float sum3 = float(0.25) * radiusSquare + float(1.0 / 12.0) * heightSquare;
|
||||
float IxxAndzz = factor1 * mass * (sum1 + sum2) + factor2 * mass * sum3;
|
||||
float Iyy = factor1 * mass * sum1 + factor2 * mass * float(0.25) * radiusSquareDouble;
|
||||
tensor.setAllValues(IxxAndzz, 0.0, 0.0,
|
||||
tensor.setValue(IxxAndzz, 0.0, 0.0,
|
||||
0.0, Iyy, 0.0,
|
||||
0.0, 0.0, IxxAndzz);
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
bool CapsuleShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
|
||||
bool CapsuleShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
|
||||
const float diffYCenterSphere1 = localPoint.y - mHalfHeight;
|
||||
const float diffYCenterSphere2 = localPoint.y + mHalfHeight;
|
||||
const float xSquare = localPoint.x * localPoint.x;
|
||||
const float zSquare = localPoint.z * localPoint.z;
|
||||
const float squareRadius = mMargin * mMargin;
|
||||
const float diffYCenterSphere1 = localPoint.y() - m_halfHeight;
|
||||
const float diffYCenterSphere2 = localPoint.y() + m_halfHeight;
|
||||
const float xSquare = localPoint.x() * localPoint.x();
|
||||
const float zSquare = localPoint.z() * localPoint.z();
|
||||
const float squareRadius = m_margin * m_margin;
|
||||
|
||||
// Return true if the point is inside the cylinder or one of the two spheres of the capsule
|
||||
return ((xSquare + zSquare) < squareRadius &&
|
||||
localPoint.y < mHalfHeight && localPoint.y > -mHalfHeight) ||
|
||||
localPoint.y() < m_halfHeight && localPoint.y() > -m_halfHeight) ||
|
||||
(xSquare + zSquare + diffYCenterSphere1 * diffYCenterSphere1) < squareRadius ||
|
||||
(xSquare + zSquare + diffYCenterSphere2 * diffYCenterSphere2) < squareRadius;
|
||||
}
|
||||
@ -73,13 +73,13 @@ bool CapsuleShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyS
|
||||
// Raycast method with feedback information
|
||||
bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||
|
||||
const Vector3 n = ray.point2 - ray.point1;
|
||||
const vec3 n = ray.point2 - ray.point1;
|
||||
|
||||
const float epsilon = float(0.01);
|
||||
Vector3 p(float(0), -mHalfHeight, float(0));
|
||||
Vector3 q(float(0), mHalfHeight, float(0));
|
||||
Vector3 d = q - p;
|
||||
Vector3 m = ray.point1 - p;
|
||||
vec3 p(float(0), -m_halfHeight, float(0));
|
||||
vec3 q(float(0), m_halfHeight, float(0));
|
||||
vec3 d = q - p;
|
||||
vec3 m = ray.point1 - p;
|
||||
float t;
|
||||
|
||||
float mDotD = m.dot(d);
|
||||
@ -87,38 +87,38 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape*
|
||||
float dDotD = d.dot(d);
|
||||
|
||||
// Test if the segment is outside the cylinder
|
||||
float vec1DotD = (ray.point1 - Vector3(float(0.0), -mHalfHeight - mMargin, float(0.0))).dot(d);
|
||||
if (vec1DotD < float(0.0) && vec1DotD + nDotD < float(0.0)) return false;
|
||||
float ddotDExtraCaps = float(2.0) * mMargin * d.y;
|
||||
float vec1DotD = (ray.point1 - vec3(0.0f, -m_halfHeight - m_margin, float(0.0))).dot(d);
|
||||
if (vec1DotD < 0.0f && vec1DotD + nDotD < float(0.0)) return false;
|
||||
float ddotDExtraCaps = float(2.0) * m_margin * d.y();
|
||||
if (vec1DotD > dDotD + ddotDExtraCaps && vec1DotD + nDotD > dDotD + ddotDExtraCaps) return false;
|
||||
|
||||
float nDotN = n.dot(n);
|
||||
float mDotN = m.dot(n);
|
||||
|
||||
float a = dDotD * nDotN - nDotD * nDotD;
|
||||
float k = m.dot(m) - mMargin * mMargin;
|
||||
float k = m.dot(m) - m_margin * m_margin;
|
||||
float c = dDotD * k - mDotD * mDotD;
|
||||
|
||||
// If the ray is parallel to the capsule axis
|
||||
if (std::abs(a) < epsilon) {
|
||||
|
||||
// If the origin is outside the surface of the capusle's cylinder, we return no hit
|
||||
if (c > float(0.0)) return false;
|
||||
if (c > 0.0f) return false;
|
||||
|
||||
// Here we know that the segment int32_tersect an endcap of the capsule
|
||||
|
||||
// If the ray int32_tersects with the "p" endcap of the capsule
|
||||
if (mDotD < float(0.0)) {
|
||||
if (mDotD < 0.0f) {
|
||||
|
||||
// Check int32_tersection between the ray and the "p" sphere endcap of the capsule
|
||||
Vector3 hitLocalPoint;
|
||||
vec3 hitLocalPoint;
|
||||
float hitFraction;
|
||||
if (raycastWithSphereEndCap(ray.point1, ray.point2, p, ray.maxFraction, hitLocalPoint, hitFraction)) {
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = hitFraction;
|
||||
raycastInfo.worldPoint = hitLocalPoint;
|
||||
Vector3 normalDirection = hitLocalPoint - p;
|
||||
vec3 normalDirection = hitLocalPoint - p;
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -129,14 +129,14 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape*
|
||||
else if (mDotD > dDotD) { // If the ray int32_tersects with the "q" endcap of the cylinder
|
||||
|
||||
// Check int32_tersection between the ray and the "q" sphere endcap of the capsule
|
||||
Vector3 hitLocalPoint;
|
||||
vec3 hitLocalPoint;
|
||||
float hitFraction;
|
||||
if (raycastWithSphereEndCap(ray.point1, ray.point2, q, ray.maxFraction, hitLocalPoint, hitFraction)) {
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = hitFraction;
|
||||
raycastInfo.worldPoint = hitLocalPoint;
|
||||
Vector3 normalDirection = hitLocalPoint - q;
|
||||
vec3 normalDirection = hitLocalPoint - q;
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -152,24 +152,24 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape*
|
||||
float discriminant = b * b - a * c;
|
||||
|
||||
// If the discriminant is negative, no real roots and therfore, no hit
|
||||
if (discriminant < float(0.0)) return false;
|
||||
if (discriminant < 0.0f) return false;
|
||||
|
||||
// Compute the smallest root (first int32_tersection along the ray)
|
||||
float t0 = t = (-b - std::sqrt(discriminant)) / a;
|
||||
|
||||
// If the int32_tersection is outside the finite cylinder of the capsule on "p" endcap side
|
||||
float value = mDotD + t * nDotD;
|
||||
if (value < float(0.0)) {
|
||||
if (value < 0.0f) {
|
||||
|
||||
// Check int32_tersection between the ray and the "p" sphere endcap of the capsule
|
||||
Vector3 hitLocalPoint;
|
||||
vec3 hitLocalPoint;
|
||||
float hitFraction;
|
||||
if (raycastWithSphereEndCap(ray.point1, ray.point2, p, ray.maxFraction, hitLocalPoint, hitFraction)) {
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = hitFraction;
|
||||
raycastInfo.worldPoint = hitLocalPoint;
|
||||
Vector3 normalDirection = hitLocalPoint - p;
|
||||
vec3 normalDirection = hitLocalPoint - p;
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -180,14 +180,14 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape*
|
||||
else if (value > dDotD) { // If the int32_tersection is outside the finite cylinder on the "q" side
|
||||
|
||||
// Check int32_tersection between the ray and the "q" sphere endcap of the capsule
|
||||
Vector3 hitLocalPoint;
|
||||
vec3 hitLocalPoint;
|
||||
float hitFraction;
|
||||
if (raycastWithSphereEndCap(ray.point1, ray.point2, q, ray.maxFraction, hitLocalPoint, hitFraction)) {
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = hitFraction;
|
||||
raycastInfo.worldPoint = hitLocalPoint;
|
||||
Vector3 normalDirection = hitLocalPoint - q;
|
||||
vec3 normalDirection = hitLocalPoint - q;
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -200,52 +200,52 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape*
|
||||
|
||||
// If the int32_tersection is behind the origin of the ray or beyond the maximum
|
||||
// raycasting distance, we return no hit
|
||||
if (t < float(0.0) || t > ray.maxFraction) return false;
|
||||
if (t < 0.0f || t > ray.maxFraction) return false;
|
||||
|
||||
// Compute the hit information
|
||||
Vector3 localHitPoint = ray.point1 + t * n;
|
||||
vec3 localHitPoint = ray.point1 + t * n;
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = t;
|
||||
raycastInfo.worldPoint = localHitPoint;
|
||||
Vector3 v = localHitPoint - p;
|
||||
Vector3 w = (v.dot(d) / d.lengthSquare()) * d;
|
||||
Vector3 normalDirection = (localHitPoint - (p + w)).getUnit();
|
||||
vec3 v = localHitPoint - p;
|
||||
vec3 w = (v.dot(d) / d.length2()) * d;
|
||||
vec3 normalDirection = (localHitPoint - (p + w)).safeNormalized();
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Raycasting method between a ray one of the two spheres end cap of the capsule
|
||||
bool CapsuleShape::raycastWithSphereEndCap(const Vector3& point1, const Vector3& point2,
|
||||
const Vector3& sphereCenter, float maxFraction,
|
||||
Vector3& hitLocalPoint, float& hitFraction) const {
|
||||
bool CapsuleShape::raycastWithSphereEndCap(const vec3& point1, const vec3& point2,
|
||||
const vec3& sphereCenter, float maxFraction,
|
||||
vec3& hitLocalPoint, float& hitFraction) const {
|
||||
|
||||
const Vector3 m = point1 - sphereCenter;
|
||||
float c = m.dot(m) - mMargin * mMargin;
|
||||
const vec3 m = point1 - sphereCenter;
|
||||
float c = m.dot(m) - m_margin * m_margin;
|
||||
|
||||
// If the origin of the ray is inside the sphere, we return no int32_tersection
|
||||
if (c < float(0.0)) return false;
|
||||
if (c < 0.0f) return false;
|
||||
|
||||
const Vector3 rayDirection = point2 - point1;
|
||||
const vec3 rayDirection = point2 - point1;
|
||||
float b = m.dot(rayDirection);
|
||||
|
||||
// If the origin of the ray is outside the sphere and the ray
|
||||
// is pointing away from the sphere, there is no int32_tersection
|
||||
if (b > float(0.0)) return false;
|
||||
if (b > 0.0f) return false;
|
||||
|
||||
float raySquareLength = rayDirection.lengthSquare();
|
||||
float raySquareLength = rayDirection.length2();
|
||||
|
||||
// Compute the discriminant of the quadratic equation
|
||||
float discriminant = b * b - raySquareLength * c;
|
||||
|
||||
// If the discriminant is negative or the ray length is very small, there is no int32_tersection
|
||||
if (discriminant < float(0.0) || raySquareLength < MACHINE_EPSILON) return false;
|
||||
if (discriminant < 0.0f || raySquareLength < MACHINE_EPSILON) return false;
|
||||
|
||||
// Compute the solution "t" closest to the origin
|
||||
float t = -b - std::sqrt(discriminant);
|
||||
|
||||
assert(t >= float(0.0));
|
||||
assert(t >= 0.0f);
|
||||
|
||||
// If the hit point is withing the segment ray fraction
|
||||
if (t < maxFraction * raySquareLength) {
|
||||
|
@ -30,7 +30,7 @@ class CapsuleShape : public ConvexShape {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Half height of the capsule (height = distance between the centers of the two spheres)
|
||||
float mHalfHeight;
|
||||
float m_halfHeight;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -41,19 +41,19 @@ class CapsuleShape : public ConvexShape {
|
||||
CapsuleShape& operator=(const CapsuleShape& shape);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycasting method between a ray one of the two spheres end cap of the capsule
|
||||
bool raycastWithSphereEndCap(const Vector3& point1, const Vector3& point2,
|
||||
const Vector3& sphereCenter, float maxFraction,
|
||||
Vector3& hitLocalPoint, float& hitFraction) const;
|
||||
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;
|
||||
@ -75,13 +75,13 @@ class CapsuleShape : public ConvexShape {
|
||||
float getHeight() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
};
|
||||
|
||||
// Get the radius of the capsule
|
||||
@ -89,7 +89,7 @@ class CapsuleShape : public ConvexShape {
|
||||
* @return The radius of the capsule shape (in meters)
|
||||
*/
|
||||
inline float CapsuleShape::getRadius() const {
|
||||
return mMargin;
|
||||
return m_margin;
|
||||
}
|
||||
|
||||
// Return the height of the capsule
|
||||
@ -97,14 +97,14 @@ inline float CapsuleShape::getRadius() const {
|
||||
* @return The height of the capsule shape (in meters)
|
||||
*/
|
||||
inline float CapsuleShape::getHeight() const {
|
||||
return mHalfHeight + mHalfHeight;
|
||||
return m_halfHeight + m_halfHeight;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void CapsuleShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void CapsuleShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
mHalfHeight = (mHalfHeight / mScaling.y) * scaling.y;
|
||||
mMargin = (mMargin / mScaling.x) * scaling.x;
|
||||
m_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
|
||||
m_margin = (m_margin / m_scaling.x()) * scaling.x();
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
@ -120,17 +120,17 @@ 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(Vector3& min, Vector3& max) const {
|
||||
inline void CapsuleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
// Maximum bounds
|
||||
max.x = mMargin;
|
||||
max.y = mHalfHeight + mMargin;
|
||||
max.z = mMargin;
|
||||
max.setX(m_margin);
|
||||
max.setY(m_halfHeight + m_margin);
|
||||
max.setZ(m_margin);
|
||||
|
||||
// Minimum bounds
|
||||
min.x = -mMargin;
|
||||
min.y = -max.y;
|
||||
min.z = min.x;
|
||||
min.setX(-m_margin);
|
||||
min.setY(-max.y());
|
||||
min.setZ(min.x());
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the object margin.
|
||||
@ -140,21 +140,21 @@ inline void CapsuleShape::getLocalBounds(Vector3& min, Vector3& 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 Vector3 CapsuleShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
inline vec3 CapsuleShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
// Support point top sphere
|
||||
float dotProductTop = mHalfHeight * direction.y;
|
||||
float dotProductTop = m_halfHeight * direction.y();
|
||||
|
||||
// Support point bottom sphere
|
||||
float dotProductBottom = -mHalfHeight * direction.y;
|
||||
float dotProductBottom = -m_halfHeight * direction.y();
|
||||
|
||||
// Return the point with the maximum dot product
|
||||
if (dotProductTop > dotProductBottom) {
|
||||
return Vector3(0, mHalfHeight, 0);
|
||||
return vec3(0, m_halfHeight, 0);
|
||||
}
|
||||
else {
|
||||
return Vector3(0, -mHalfHeight, 0);
|
||||
return vec3(0, -m_halfHeight, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
CollisionShape::CollisionShape(CollisionShapeType type) : m_type(type), mScaling(1.0, 1.0, 1.0) {
|
||||
CollisionShape::CollisionShape(CollisionShapeType type) : m_type(type), m_scaling(1.0, 1.0, 1.0) {
|
||||
|
||||
}
|
||||
|
||||
@ -26,29 +26,29 @@ CollisionShape::~CollisionShape() {
|
||||
/**
|
||||
* @param[out] aabb The axis-aligned bounding box (AABB) of the collision shape
|
||||
* computed in world-space coordinates
|
||||
* @param transform Transform used to compute the AABB of the collision shape
|
||||
* @param transform etk::Transform3D used to compute the AABB of the collision shape
|
||||
*/
|
||||
void CollisionShape::computeAABB(AABB& aabb, const Transform& transform) const {
|
||||
void CollisionShape::computeAABB(AABB& aabb, const etk::Transform3D& transform) const {
|
||||
|
||||
PROFILE("CollisionShape::computeAABB()");
|
||||
|
||||
// Get the local bounds in x,y and z direction
|
||||
Vector3 minBounds;
|
||||
Vector3 maxBounds;
|
||||
vec3 minBounds;
|
||||
vec3 maxBounds;
|
||||
getLocalBounds(minBounds, maxBounds);
|
||||
|
||||
// Rotate the local bounds according to the orientation of the body
|
||||
Matrix3x3 worldAxis = transform.getOrientation().getMatrix().getAbsoluteMatrix();
|
||||
Vector3 worldMinBounds(worldAxis.getColumn(0).dot(minBounds),
|
||||
etk::Matrix3x3 worldAxis = transform.getOrientation().getMatrix().getAbsolute();
|
||||
vec3 worldMinBounds(worldAxis.getColumn(0).dot(minBounds),
|
||||
worldAxis.getColumn(1).dot(minBounds),
|
||||
worldAxis.getColumn(2).dot(minBounds));
|
||||
Vector3 worldMaxBounds(worldAxis.getColumn(0).dot(maxBounds),
|
||||
vec3 worldMaxBounds(worldAxis.getColumn(0).dot(maxBounds),
|
||||
worldAxis.getColumn(1).dot(maxBounds),
|
||||
worldAxis.getColumn(2).dot(maxBounds));
|
||||
|
||||
// Compute the minimum and maximum coordinates of the rotated extents
|
||||
Vector3 minCoordinates = transform.getPosition() + worldMinBounds;
|
||||
Vector3 maxCoordinates = transform.getPosition() + worldMaxBounds;
|
||||
vec3 minCoordinates = transform.getPosition() + worldMinBounds;
|
||||
vec3 maxCoordinates = transform.getPosition() + worldMaxBounds;
|
||||
|
||||
// Update the AABB with the new minimum and maximum coordinates
|
||||
aabb.setMin(minCoordinates);
|
||||
|
@ -8,8 +8,8 @@
|
||||
// Libraries
|
||||
#include <cassert>
|
||||
#include <typeinfo>
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <ephysics/mathematics/Matrix3x3.h>
|
||||
#include <etk/math/Vector3D.hpp>
|
||||
#include <etk/math/Matrix3x3.hpp>
|
||||
#include <ephysics/mathematics/Ray.h>
|
||||
#include <ephysics/collision/shapes/AABB.h>
|
||||
#include <ephysics/collision/RaycastInfo.h>
|
||||
@ -42,7 +42,7 @@ class CollisionShape {
|
||||
CollisionShapeType m_type;
|
||||
|
||||
/// Scaling vector of the collision shape
|
||||
Vector3 mScaling;
|
||||
vec3 m_scaling;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -53,7 +53,7 @@ class CollisionShape {
|
||||
CollisionShape& operator=(const CollisionShape& shape);
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& worldPoint, ProxyShape* proxyShape) const=0;
|
||||
virtual bool testPointInside(const vec3& worldPoint, ProxyShape* proxyShape) const=0;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const=0;
|
||||
@ -78,19 +78,19 @@ class CollisionShape {
|
||||
virtual bool isConvex() const=0;
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const=0;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const=0;
|
||||
|
||||
/// Return the scaling vector of the collision shape
|
||||
Vector3 getScaling() const;
|
||||
vec3 getScaling() const;
|
||||
|
||||
/// Set the local scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local inertia tensor of the collision shapes
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const=0;
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const=0;
|
||||
|
||||
/// Compute the world-space AABB of the collision shape given a transform
|
||||
virtual void computeAABB(AABB& aabb, const Transform& transform) const;
|
||||
virtual void computeAABB(AABB& aabb, const etk::Transform3D& transform) const;
|
||||
|
||||
/// Return true if the collision shape type is a convex shape
|
||||
static bool isConvex(CollisionShapeType shapeType);
|
||||
@ -119,13 +119,13 @@ inline bool CollisionShape::isConvex(CollisionShapeType shapeType) {
|
||||
}
|
||||
|
||||
// Return the scaling vector of the collision shape
|
||||
inline Vector3 CollisionShape::getScaling() const {
|
||||
return mScaling;
|
||||
inline vec3 CollisionShape::getScaling() const {
|
||||
return m_scaling;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void CollisionShape::setLocalScaling(const Vector3& scaling) {
|
||||
mScaling = scaling;
|
||||
inline void CollisionShape::setLocalScaling(const vec3& scaling) {
|
||||
m_scaling = scaling;
|
||||
}
|
||||
|
||||
// Return the maximum number of contact manifolds allowed in an overlapping
|
||||
|
@ -40,7 +40,7 @@ void ConcaveMeshShape::initBVHTree() {
|
||||
// For each triangle of the concave mesh
|
||||
for (uint32_t triangleIndex=0; triangleIndex<triangleVertexArray->getNbTriangles(); triangleIndex++) {
|
||||
void* vertexIndexPointer = (indicesStart + triangleIndex * 3 * indexStride);
|
||||
Vector3 trianglePoints[3];
|
||||
vec3 trianglePoints[3];
|
||||
// For each vertex of the triangle
|
||||
for (int32_t k=0; k < 3; k++) {
|
||||
// Get the index of the current vertex in the triangle
|
||||
@ -55,14 +55,14 @@ void ConcaveMeshShape::initBVHTree() {
|
||||
// Get the vertices components of the triangle
|
||||
if (vertexType == TriangleVertexArray::VERTEX_FLOAT_TYPE) {
|
||||
const float* vertices = (float*)(verticesStart + vertexIndex * vertexStride);
|
||||
trianglePoints[k][0] = float(vertices[0]) * mScaling.x;
|
||||
trianglePoints[k][1] = float(vertices[1]) * mScaling.y;
|
||||
trianglePoints[k][2] = float(vertices[2]) * mScaling.z;
|
||||
trianglePoints[k][0] = float(vertices[0]) * m_scaling.x();
|
||||
trianglePoints[k][1] = float(vertices[1]) * m_scaling.y();
|
||||
trianglePoints[k][2] = float(vertices[2]) * m_scaling.z();
|
||||
} else if (vertexType == TriangleVertexArray::VERTEX_DOUBLE_TYPE) {
|
||||
const double* vertices = (double*)(verticesStart + vertexIndex * vertexStride);
|
||||
trianglePoints[k][0] = float(vertices[0]) * mScaling.x;
|
||||
trianglePoints[k][1] = float(vertices[1]) * mScaling.y;
|
||||
trianglePoints[k][2] = float(vertices[2]) * mScaling.z;
|
||||
trianglePoints[k][0] = float(vertices[0]) * m_scaling.x();
|
||||
trianglePoints[k][1] = float(vertices[1]) * m_scaling.y();
|
||||
trianglePoints[k][2] = float(vertices[2]) * m_scaling.z();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@ -78,7 +78,7 @@ void ConcaveMeshShape::initBVHTree() {
|
||||
|
||||
// Return the three vertices coordinates (in the array outTriangleVertices) of a triangle
|
||||
// given the start vertex index pointer of the triangle
|
||||
void ConcaveMeshShape::getTriangleVerticesWithIndexPointer(int32_t subPart, int32_t triangleIndex, Vector3* outTriangleVertices) const {
|
||||
void ConcaveMeshShape::getTriangleVerticesWithIndexPointer(int32_t subPart, int32_t triangleIndex, vec3* outTriangleVertices) const {
|
||||
// Get the triangle vertex array of the current sub-part
|
||||
TriangleVertexArray* triangleVertexArray = m_triangleMesh->getSubpart(subPart);
|
||||
if (triangleVertexArray == nullptr) {
|
||||
@ -106,14 +106,14 @@ void ConcaveMeshShape::getTriangleVerticesWithIndexPointer(int32_t subPart, int3
|
||||
// Get the vertices components of the triangle
|
||||
if (vertexType == TriangleVertexArray::VERTEX_FLOAT_TYPE) {
|
||||
const float* vertices = (float*)(verticesStart + vertexIndex * vertexStride);
|
||||
outTriangleVertices[k][0] = float(vertices[0]) * mScaling.x;
|
||||
outTriangleVertices[k][1] = float(vertices[1]) * mScaling.y;
|
||||
outTriangleVertices[k][2] = float(vertices[2]) * mScaling.z;
|
||||
outTriangleVertices[k][0] = float(vertices[0]) * m_scaling.x();
|
||||
outTriangleVertices[k][1] = float(vertices[1]) * m_scaling.y();
|
||||
outTriangleVertices[k][2] = float(vertices[2]) * m_scaling.z();
|
||||
} else if (vertexType == TriangleVertexArray::VERTEX_DOUBLE_TYPE) {
|
||||
const double* vertices = (double*)(verticesStart + vertexIndex * vertexStride);
|
||||
outTriangleVertices[k][0] = float(vertices[0]) * mScaling.x;
|
||||
outTriangleVertices[k][1] = float(vertices[1]) * mScaling.y;
|
||||
outTriangleVertices[k][2] = float(vertices[2]) * mScaling.z;
|
||||
outTriangleVertices[k][0] = float(vertices[0]) * m_scaling.x();
|
||||
outTriangleVertices[k][1] = float(vertices[1]) * m_scaling.y();
|
||||
outTriangleVertices[k][2] = float(vertices[2]) * m_scaling.z();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@ -158,7 +158,7 @@ void ConcaveMeshRaycastCallback::raycastTriangles() {
|
||||
// Get the node data (triangle index and mesh subpart index)
|
||||
int32_t* data = m_dynamicAABBTree.getNodeDataInt(*it);
|
||||
// Get the triangle vertices for this node from the concave mesh shape
|
||||
Vector3 trianglePoints[3];
|
||||
vec3 trianglePoints[3];
|
||||
m_concaveMeshShape.getTriangleVerticesWithIndexPointer(data[0], data[1], trianglePoints);
|
||||
// Create a triangle collision shape
|
||||
float margin = m_concaveMeshShape.getTriangleMargin();
|
||||
@ -169,7 +169,7 @@ void ConcaveMeshRaycastCallback::raycastTriangles() {
|
||||
bool isTriangleHit = triangleShape.raycast(m_ray, raycastInfo, m_proxyShape);
|
||||
// If the ray hit the collision shape
|
||||
if (isTriangleHit && raycastInfo.hitFraction <= smallestHitFraction) {
|
||||
assert(raycastInfo.hitFraction >= float(0.0));
|
||||
assert(raycastInfo.hitFraction >= 0.0f);
|
||||
m_raycastInfo.body = raycastInfo.body;
|
||||
m_raycastInfo.proxyShape = raycastInfo.proxyShape;
|
||||
m_raycastInfo.hitFraction = raycastInfo.hitFraction;
|
||||
|
@ -117,7 +117,7 @@ class ConcaveMeshShape : public ConcaveShape {
|
||||
/// 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,
|
||||
Vector3* outTriangleVertices) const;
|
||||
vec3* outTriangleVertices) const;
|
||||
|
||||
public:
|
||||
|
||||
@ -128,13 +128,13 @@ class ConcaveMeshShape : public ConcaveShape {
|
||||
~ConcaveMeshShape();
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions.
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Set the local scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
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;
|
||||
@ -156,7 +156,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(Vector3& min, Vector3& max) const {
|
||||
inline void ConcaveMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
// Get the AABB of the whole tree
|
||||
AABB treeAABB = m_dynamicAABBTree.getRootAABB();
|
||||
@ -166,7 +166,7 @@ inline void ConcaveMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||
}
|
||||
|
||||
// Set the local scaling vector of the collision shape
|
||||
inline void ConcaveMeshShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void ConcaveMeshShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
|
||||
@ -183,13 +183,13 @@ inline void ConcaveMeshShape::setLocalScaling(const Vector3& scaling) {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void ConcaveMeshShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
inline void ConcaveMeshShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
|
||||
// Default inertia tensor
|
||||
// Note that this is not very realistic for a concave triangle mesh.
|
||||
// However, in most cases, it will only be used static bodies and therefore,
|
||||
// the inertia tensor is not used.
|
||||
tensor.setAllValues(mass, 0, 0,
|
||||
tensor.setValue(mass, 0, 0,
|
||||
0, mass, 0,
|
||||
0, 0, mass);
|
||||
}
|
||||
@ -202,7 +202,7 @@ inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int32_t nod
|
||||
int32_t* data = m_dynamicAABBTree.getNodeDataInt(nodeId);
|
||||
|
||||
// Get the triangle vertices for this node from the concave mesh shape
|
||||
Vector3 trianglePoints[3];
|
||||
vec3 trianglePoints[3];
|
||||
m_concaveMeshShape.getTriangleVerticesWithIndexPointer(data[0], data[1], trianglePoints);
|
||||
|
||||
// Call the callback to test narrow-phase collision with this triangle
|
||||
|
@ -23,7 +23,7 @@ class TriangleCallback {
|
||||
virtual ~TriangleCallback() = default;
|
||||
|
||||
/// Report a triangle
|
||||
virtual void testTriangle(const Vector3* trianglePoints)=0;
|
||||
virtual void testTriangle(const vec3* trianglePoints)=0;
|
||||
|
||||
};
|
||||
|
||||
@ -57,7 +57,7 @@ class ConcaveShape : public CollisionShape {
|
||||
ConcaveShape& operator=(const ConcaveShape& shape);
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
public :
|
||||
|
||||
@ -102,7 +102,7 @@ inline bool ConcaveShape::isConvex() const {
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool ConcaveShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
|
||||
inline bool ConcaveShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,9 @@ using namespace reactphysics3d;
|
||||
* @param margin Collision margin (in meters) around the collision shape
|
||||
*/
|
||||
ConeShape::ConeShape(float radius, float height, float margin)
|
||||
: ConvexShape(CONE, margin), mRadius(radius), mHalfHeight(height * float(0.5)) {
|
||||
assert(mRadius > float(0.0));
|
||||
assert(mHalfHeight > float(0.0));
|
||||
: ConvexShape(CONE, margin), mRadius(radius), m_halfHeight(height * 0.5f) {
|
||||
assert(mRadius > 0.0f);
|
||||
assert(m_halfHeight > 0.0f);
|
||||
|
||||
// Compute the sine of the semi-angle at the apex point
|
||||
mSinTheta = mRadius / (sqrt(mRadius * mRadius + height * height));
|
||||
@ -33,24 +33,24 @@ ConeShape::~ConeShape() {
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the object margin
|
||||
Vector3 ConeShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
vec3 ConeShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
const Vector3& v = direction;
|
||||
const vec3& v = direction;
|
||||
float sinThetaTimesLengthV = mSinTheta * v.length();
|
||||
Vector3 supportPoint;
|
||||
vec3 supportPoint;
|
||||
|
||||
if (v.y > sinThetaTimesLengthV) {
|
||||
supportPoint = Vector3(0.0, mHalfHeight, 0.0);
|
||||
if (v.y() > sinThetaTimesLengthV) {
|
||||
supportPoint = vec3(0.0, m_halfHeight, 0.0);
|
||||
}
|
||||
else {
|
||||
float projectedLength = sqrt(v.x * v.x + v.z * v.z);
|
||||
float projectedLength = sqrt(v.x() * v.x() + v.z() * v.z());
|
||||
if (projectedLength > MACHINE_EPSILON) {
|
||||
float d = mRadius / projectedLength;
|
||||
supportPoint = Vector3(v.x * d, -mHalfHeight, v.z * d);
|
||||
supportPoint = vec3(v.x() * d, -m_halfHeight, v.z() * d);
|
||||
}
|
||||
else {
|
||||
supportPoint = Vector3(0.0, -mHalfHeight, 0.0);
|
||||
supportPoint = vec3(0.0, -m_halfHeight, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,33 +63,33 @@ Vector3 ConeShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
// http://www.geometrictools.com/Documentation/IntersectionLineCone.pdf
|
||||
bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||
|
||||
const Vector3 r = ray.point2 - ray.point1;
|
||||
const vec3 r = ray.point2 - ray.point1;
|
||||
|
||||
const float epsilon = float(0.00001);
|
||||
Vector3 V(0, mHalfHeight, 0);
|
||||
Vector3 centerBase(0, -mHalfHeight, 0);
|
||||
Vector3 axis(0, float(-1.0), 0);
|
||||
float heightSquare = float(4.0) * mHalfHeight * mHalfHeight;
|
||||
vec3 V(0, m_halfHeight, 0);
|
||||
vec3 centerBase(0, -m_halfHeight, 0);
|
||||
vec3 axis(0, float(-1.0), 0);
|
||||
float heightSquare = float(4.0) * m_halfHeight * m_halfHeight;
|
||||
float cosThetaSquare = heightSquare / (heightSquare + mRadius * mRadius);
|
||||
float factor = float(1.0) - cosThetaSquare;
|
||||
Vector3 delta = ray.point1 - V;
|
||||
float c0 = -cosThetaSquare * delta.x * delta.x + factor * delta.y * delta.y -
|
||||
cosThetaSquare * delta.z * delta.z;
|
||||
float c1 = -cosThetaSquare * delta.x * r.x + factor * delta.y * r.y - cosThetaSquare * delta.z * r.z;
|
||||
float c2 = -cosThetaSquare * r.x * r.x + factor * r.y * r.y - cosThetaSquare * r.z * r.z;
|
||||
float factor = 1.0f - cosThetaSquare;
|
||||
vec3 delta = ray.point1 - V;
|
||||
float c0 = -cosThetaSquare * delta.x() * delta.x() + factor * delta.y() * delta.y() -
|
||||
cosThetaSquare * delta.z() * delta.z();
|
||||
float c1 = -cosThetaSquare * delta.x() * r.x() + factor * delta.y() * r.y() - cosThetaSquare * delta.z() * r.z();
|
||||
float c2 = -cosThetaSquare * r.x() * r.x() + factor * r.y() * r.y() - cosThetaSquare * r.z() * r.z();
|
||||
float tHit[] = {float(-1.0), float(-1.0), float(-1.0)};
|
||||
Vector3 localHitPoint[3];
|
||||
Vector3 localNormal[3];
|
||||
vec3 localHitPoint[3];
|
||||
vec3 localNormal[3];
|
||||
|
||||
// If c2 is different from zero
|
||||
if (std::abs(c2) > MACHINE_EPSILON) {
|
||||
float gamma = c1 * c1 - c0 * c2;
|
||||
|
||||
// If there is no real roots in the quadratic equation
|
||||
if (gamma < float(0.0)) {
|
||||
if (gamma < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
else if (gamma > float(0.0)) { // The equation has two real roots
|
||||
else if (gamma > 0.0f) { // The equation has two real roots
|
||||
|
||||
// Compute two int32_tersections
|
||||
float sqrRoot = std::sqrt(gamma);
|
||||
@ -124,31 +124,31 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr
|
||||
localHitPoint[1] = ray.point1 + tHit[1] * r;
|
||||
|
||||
// Only keep hit points in one side of the double cone (the cone we are int32_terested in)
|
||||
if (axis.dot(localHitPoint[0] - V) < float(0.0)) {
|
||||
if (axis.dot(localHitPoint[0] - V) < 0.0f) {
|
||||
tHit[0] = float(-1.0);
|
||||
}
|
||||
if (axis.dot(localHitPoint[1] - V) < float(0.0)) {
|
||||
if (axis.dot(localHitPoint[1] - V) < 0.0f) {
|
||||
tHit[1] = float(-1.0);
|
||||
}
|
||||
|
||||
// Only keep hit points that are within the correct height of the cone
|
||||
if (localHitPoint[0].y < float(-mHalfHeight)) {
|
||||
if (localHitPoint[0].y() < float(-m_halfHeight)) {
|
||||
tHit[0] = float(-1.0);
|
||||
}
|
||||
if (localHitPoint[1].y < float(-mHalfHeight)) {
|
||||
if (localHitPoint[1].y() < float(-m_halfHeight)) {
|
||||
tHit[1] = float(-1.0);
|
||||
}
|
||||
|
||||
// If the ray is in direction of the base plane of the cone
|
||||
if (r.y > epsilon) {
|
||||
if (r.y() > epsilon) {
|
||||
|
||||
// Compute the int32_tersection with the base plane of the cone
|
||||
tHit[2] = (-ray.point1.y - mHalfHeight) / (r.y);
|
||||
tHit[2] = (-ray.point1.y() - m_halfHeight) / (r.y());
|
||||
|
||||
// Only keep this int32_tersection if it is inside the cone radius
|
||||
localHitPoint[2] = ray.point1 + tHit[2] * r;
|
||||
|
||||
if ((localHitPoint[2] - centerBase).lengthSquare() > mRadius * mRadius) {
|
||||
if ((localHitPoint[2] - centerBase).length2() > mRadius * mRadius) {
|
||||
tHit[2] = float(-1.0);
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr
|
||||
int32_t hitIndex = -1;
|
||||
float t = DECIMAL_LARGEST;
|
||||
for (int32_t i=0; i<3; i++) {
|
||||
if (tHit[i] < float(0.0)) continue;
|
||||
if (tHit[i] < 0.0f) continue;
|
||||
if (tHit[i] < t) {
|
||||
hitIndex = i;
|
||||
t = tHit[hitIndex];
|
||||
@ -172,17 +172,17 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr
|
||||
|
||||
// Compute the normal direction for hit against side of the cone
|
||||
if (hitIndex != 2) {
|
||||
float h = float(2.0) * mHalfHeight;
|
||||
float value1 = (localHitPoint[hitIndex].x * localHitPoint[hitIndex].x +
|
||||
localHitPoint[hitIndex].z * localHitPoint[hitIndex].z);
|
||||
float h = float(2.0) * m_halfHeight;
|
||||
float value1 = (localHitPoint[hitIndex].x() * localHitPoint[hitIndex].x() +
|
||||
localHitPoint[hitIndex].z() * localHitPoint[hitIndex].z());
|
||||
float rOverH = mRadius / h;
|
||||
float value2 = float(1.0) + rOverH * rOverH;
|
||||
float factor = float(1.0) / std::sqrt(value1 * value2);
|
||||
float x = localHitPoint[hitIndex].x * factor;
|
||||
float z = localHitPoint[hitIndex].z * factor;
|
||||
localNormal[hitIndex].x = x;
|
||||
localNormal[hitIndex].y = std::sqrt(x * x + z * z) * rOverH;
|
||||
localNormal[hitIndex].z = z;
|
||||
float value2 = 1.0f + rOverH * rOverH;
|
||||
float factor = 1.0f / std::sqrt(value1 * value2);
|
||||
float x = localHitPoint[hitIndex].x() * factor;
|
||||
float z = localHitPoint[hitIndex].z() * factor;
|
||||
localNormal[hitIndex].setX(x);
|
||||
localNormal[hitIndex].setY(std::sqrt(x * x + z * z) * rOverH);
|
||||
localNormal[hitIndex].setZ(z);
|
||||
}
|
||||
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
|
@ -38,7 +38,7 @@ class ConeShape : public ConvexShape {
|
||||
float mRadius;
|
||||
|
||||
/// Half height of the cone
|
||||
float mHalfHeight;
|
||||
float m_halfHeight;
|
||||
|
||||
/// sine of the semi angle at the apex point
|
||||
float mSinTheta;
|
||||
@ -52,11 +52,11 @@ class ConeShape : public ConvexShape {
|
||||
ConeShape& operator=(const ConeShape& shape);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
@ -81,13 +81,13 @@ class ConeShape : public ConvexShape {
|
||||
float getHeight() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
};
|
||||
|
||||
// Return the radius
|
||||
@ -103,14 +103,14 @@ inline float ConeShape::getRadius() const {
|
||||
* @return Height of the cone (in meters)
|
||||
*/
|
||||
inline float ConeShape::getHeight() const {
|
||||
return float(2.0) * mHalfHeight;
|
||||
return float(2.0) * m_halfHeight;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void ConeShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void ConeShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
mHalfHeight = (mHalfHeight / mScaling.y) * scaling.y;
|
||||
mRadius = (mRadius / mScaling.x) * scaling.x;
|
||||
m_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
|
||||
mRadius = (mRadius / m_scaling.x()) * scaling.x();
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
@ -125,17 +125,17 @@ 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(Vector3& min, Vector3& max) const {
|
||||
inline void ConeShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
// Maximum bounds
|
||||
max.x = mRadius + mMargin;
|
||||
max.y = mHalfHeight + mMargin;
|
||||
max.z = max.x;
|
||||
max.setX(mRadius + m_margin);
|
||||
max.setY(m_halfHeight + m_margin);
|
||||
max.setZ(max.x());
|
||||
|
||||
// Minimum bounds
|
||||
min.x = -max.x;
|
||||
min.y = -max.y;
|
||||
min.z = min.x;
|
||||
min.setX(-max.x());
|
||||
min.setY(-max.y());
|
||||
min.setZ(min.x());
|
||||
}
|
||||
|
||||
// Return the local inertia tensor of the collision shape
|
||||
@ -144,20 +144,20 @@ inline void ConeShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void ConeShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
inline void ConeShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
float rSquare = mRadius * mRadius;
|
||||
float diagXZ = float(0.15) * mass * (rSquare + mHalfHeight);
|
||||
tensor.setAllValues(diagXZ, 0.0, 0.0,
|
||||
float diagXZ = float(0.15) * mass * (rSquare + m_halfHeight);
|
||||
tensor.setValue(diagXZ, 0.0, 0.0,
|
||||
0.0, float(0.3) * mass * rSquare,
|
||||
0.0, 0.0, 0.0, diagXZ);
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool ConeShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
|
||||
const float radiusHeight = mRadius * (-localPoint.y + mHalfHeight) /
|
||||
(mHalfHeight * float(2.0));
|
||||
return (localPoint.y < mHalfHeight && localPoint.y > -mHalfHeight) &&
|
||||
(localPoint.x * localPoint.x + localPoint.z * localPoint.z < radiusHeight *radiusHeight);
|
||||
inline bool ConeShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
const float radiusHeight = mRadius * (-localPoint.y() + m_halfHeight) /
|
||||
(m_halfHeight * float(2.0));
|
||||
return (localPoint.y() < m_halfHeight && localPoint.y() > -m_halfHeight) &&
|
||||
(localPoint.x() * localPoint.x() + localPoint.z() * localPoint.z() < radiusHeight *radiusHeight);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ ConvexMeshShape::ConvexMeshShape(const float* arrayVertices, uint32_t nbVertices
|
||||
// Copy all the vertices int32_to the int32_ternal array
|
||||
for (uint32_t i=0; i<m_numberVertices; i++) {
|
||||
const float* newPoint = (const float*) vertexPointer;
|
||||
m_vertices.push_back(Vector3(newPoint[0], newPoint[1], newPoint[2]));
|
||||
m_vertices.push_back(vec3(newPoint[0], newPoint[1], newPoint[2]));
|
||||
vertexPointer += stride;
|
||||
}
|
||||
|
||||
@ -63,15 +63,15 @@ ConvexMeshShape::ConvexMeshShape(TriangleVertexArray* triangleVertexArray, bool
|
||||
if (vertexType == TriangleVertexArray::VERTEX_FLOAT_TYPE) {
|
||||
const float* vertices = (float*)(verticesStart + v * vertexStride);
|
||||
|
||||
Vector3 vertex(vertices[0], vertices[1], vertices[2] );
|
||||
vertex = vertex * mScaling;
|
||||
vec3 vertex(vertices[0], vertices[1], vertices[2] );
|
||||
vertex = vertex * m_scaling;
|
||||
m_vertices.push_back(vertex);
|
||||
}
|
||||
else if (vertexType == TriangleVertexArray::VERTEX_DOUBLE_TYPE) {
|
||||
const double* vertices = (double*)(verticesStart + v * vertexStride);
|
||||
|
||||
Vector3 vertex(vertices[0], vertices[1], vertices[2] );
|
||||
vertex = vertex * mScaling;
|
||||
vec3 vertex(vertices[0], vertices[1], vertices[2] );
|
||||
vertex = vertex * m_scaling;
|
||||
m_vertices.push_back(vertex);
|
||||
}
|
||||
}
|
||||
@ -134,7 +134,7 @@ ConvexMeshShape::~ConvexMeshShape() {
|
||||
/// it as a start in a hill-climbing (local search) process to find the new support vertex which
|
||||
/// will be in most of the cases very close to the previous one. Using hill-climbing, this method
|
||||
/// runs in almost constant time.
|
||||
Vector3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
vec3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
assert(m_numberVertices == m_vertices.size());
|
||||
@ -184,7 +184,7 @@ Vector3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direct
|
||||
*((int32_t*)(*cachedCollisionData)) = maxVertex;
|
||||
|
||||
// Return the support vertex
|
||||
return m_vertices[maxVertex] * mScaling;
|
||||
return m_vertices[maxVertex] * m_scaling;
|
||||
}
|
||||
else { // If the edges information is not used
|
||||
|
||||
@ -204,10 +204,10 @@ Vector3 ConvexMeshShape::getLocalSupportPointWithoutMargin(const Vector3& direct
|
||||
}
|
||||
}
|
||||
|
||||
assert(maxDotProduct >= float(0.0));
|
||||
assert(maxDotProduct >= 0.0f);
|
||||
|
||||
// Return the vertex with the largest dot product in the support direction
|
||||
return m_vertices[indexMaxDotProduct] * mScaling;
|
||||
return m_vertices[indexMaxDotProduct] * m_scaling;
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,33 +217,43 @@ void ConvexMeshShape::recalculateBounds() {
|
||||
// TODO : Only works if the local origin is inside the mesh
|
||||
// => Make it more robust (init with first vertex of mesh instead)
|
||||
|
||||
m_minBounds.setToZero();
|
||||
m_maxBounds.setToZero();
|
||||
m_minBounds.setZero();
|
||||
m_maxBounds.setZero();
|
||||
|
||||
// For each vertex of the mesh
|
||||
for (uint32_t i=0; i<m_numberVertices; i++) {
|
||||
|
||||
if (m_vertices[i].x > m_maxBounds.x) m_maxBounds.x = m_vertices[i].x;
|
||||
if (m_vertices[i].x < m_minBounds.x) m_minBounds.x = m_vertices[i].x;
|
||||
if (m_vertices[i].x() > m_maxBounds.x()) {
|
||||
m_maxBounds.setX(m_vertices[i].x());
|
||||
}
|
||||
if (m_vertices[i].x() < m_minBounds.x()) {
|
||||
m_minBounds.setX(m_vertices[i].x());
|
||||
}
|
||||
if (m_vertices[i].y() > m_maxBounds.y()) {
|
||||
m_maxBounds.setY(m_vertices[i].y());
|
||||
}
|
||||
if (m_vertices[i].y() < m_minBounds.y()) {
|
||||
m_minBounds.setY(m_vertices[i].y());
|
||||
}
|
||||
|
||||
if (m_vertices[i].y > m_maxBounds.y) m_maxBounds.y = m_vertices[i].y;
|
||||
if (m_vertices[i].y < m_minBounds.y) m_minBounds.y = m_vertices[i].y;
|
||||
|
||||
if (m_vertices[i].z > m_maxBounds.z) m_maxBounds.z = m_vertices[i].z;
|
||||
if (m_vertices[i].z < m_minBounds.z) m_minBounds.z = m_vertices[i].z;
|
||||
if (m_vertices[i].z() > m_maxBounds.z()) {
|
||||
m_maxBounds.setZ(m_vertices[i].z());
|
||||
}
|
||||
if (m_vertices[i].z() < m_minBounds.z()) {
|
||||
m_minBounds.setZ(m_vertices[i].z());
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the local scaling factor
|
||||
m_maxBounds = m_maxBounds * mScaling;
|
||||
m_minBounds = m_minBounds * mScaling;
|
||||
m_maxBounds = m_maxBounds * m_scaling;
|
||||
m_minBounds = m_minBounds * m_scaling;
|
||||
|
||||
// Add the object margin to the bounds
|
||||
m_maxBounds += Vector3(mMargin, mMargin, mMargin);
|
||||
m_minBounds -= Vector3(mMargin, mMargin, mMargin);
|
||||
m_maxBounds += vec3(m_margin, m_margin, m_margin);
|
||||
m_minBounds -= vec3(m_margin, m_margin, m_margin);
|
||||
}
|
||||
|
||||
// Raycast method with feedback information
|
||||
bool ConvexMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||
return proxyShape->m_body->m_world.m_collisionDetection.m_narrowPhaseGJKAlgorithm.raycast(
|
||||
ray, proxyShape, raycastInfo);
|
||||
return proxyShape->m_body->m_world.m_collisionDetection.m_narrowPhaseGJKAlgorithm.raycast(ray, proxyShape, raycastInfo);
|
||||
}
|
||||
|
@ -44,16 +44,16 @@ class ConvexMeshShape : public ConvexShape {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Array with the vertices of the mesh
|
||||
std::vector<Vector3> m_vertices;
|
||||
std::vector<vec3> m_vertices;
|
||||
|
||||
/// Number of vertices in the mesh
|
||||
uint32_t m_numberVertices;
|
||||
|
||||
/// Mesh minimum bounds in the three local x, y and z directions
|
||||
Vector3 m_minBounds;
|
||||
vec3 m_minBounds;
|
||||
|
||||
/// Mesh maximum bounds in the three local x, y and z directions
|
||||
Vector3 m_maxBounds;
|
||||
vec3 m_maxBounds;
|
||||
|
||||
/// True if the shape contains the edges of the convex mesh in order to
|
||||
/// make the collision detection faster
|
||||
@ -74,14 +74,14 @@ class ConvexMeshShape : public ConvexShape {
|
||||
void recalculateBounds();
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin.
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
@ -108,13 +108,13 @@ class ConvexMeshShape : public ConvexShape {
|
||||
virtual ~ConvexMeshShape();
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape.
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
|
||||
/// Add a vertex int32_to the convex mesh
|
||||
void addVertex(const Vector3& vertex);
|
||||
void addVertex(const vec3& vertex);
|
||||
|
||||
/// Add an edge int32_to the convex mesh by specifying the two vertex indices of the edge.
|
||||
void addEdge(uint32_t v1, uint32_t v2);
|
||||
@ -128,7 +128,7 @@ class ConvexMeshShape : public ConvexShape {
|
||||
};
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
inline void ConvexMeshShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void ConvexMeshShape::setLocalScaling(const vec3& scaling) {
|
||||
ConvexShape::setLocalScaling(scaling);
|
||||
recalculateBounds();
|
||||
}
|
||||
@ -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(Vector3& min, Vector3& max) const {
|
||||
inline void ConvexMeshShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
min = m_minBounds;
|
||||
max = m_maxBounds;
|
||||
}
|
||||
@ -156,14 +156,14 @@ inline void ConvexMeshShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void ConvexMeshShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
float factor = (float(1.0) / float(3.0)) * mass;
|
||||
Vector3 realExtent = float(0.5) * (m_maxBounds - m_minBounds);
|
||||
assert(realExtent.x > 0 && realExtent.y > 0 && realExtent.z > 0);
|
||||
float xSquare = realExtent.x * realExtent.x;
|
||||
float ySquare = realExtent.y * realExtent.y;
|
||||
float zSquare = realExtent.z * realExtent.z;
|
||||
tensor.setAllValues(factor * (ySquare + zSquare), 0.0, 0.0,
|
||||
inline 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);
|
||||
float xSquare = realExtent.x() * realExtent.x();
|
||||
float ySquare = realExtent.y() * realExtent.y();
|
||||
float zSquare = realExtent.z() * realExtent.z();
|
||||
tensor.setValue(factor * (ySquare + zSquare), 0.0, 0.0,
|
||||
0.0, factor * (xSquare + zSquare), 0.0,
|
||||
0.0, 0.0, factor * (xSquare + ySquare));
|
||||
}
|
||||
@ -172,19 +172,31 @@ inline void ConvexMeshShape::computeLocalInertiaTensor(Matrix3x3& tensor, float
|
||||
/**
|
||||
* @param vertex Vertex to be added
|
||||
*/
|
||||
inline void ConvexMeshShape::addVertex(const Vector3& vertex) {
|
||||
inline void ConvexMeshShape::addVertex(const vec3& vertex) {
|
||||
|
||||
// Add the vertex in to vertices array
|
||||
m_vertices.push_back(vertex);
|
||||
m_numberVertices++;
|
||||
|
||||
// Update the bounds of the mesh
|
||||
if (vertex.x * mScaling.x > m_maxBounds.x) m_maxBounds.x = vertex.x * mScaling.x;
|
||||
if (vertex.x * mScaling.x < m_minBounds.x) m_minBounds.x = vertex.x * mScaling.x;
|
||||
if (vertex.y * mScaling.y > m_maxBounds.y) m_maxBounds.y = vertex.y * mScaling.y;
|
||||
if (vertex.y * mScaling.y < m_minBounds.y) m_minBounds.y = vertex.y * mScaling.y;
|
||||
if (vertex.z * mScaling.z > m_maxBounds.z) m_maxBounds.z = vertex.z * mScaling.z;
|
||||
if (vertex.z * mScaling.z < m_minBounds.z) m_minBounds.z = vertex.z * mScaling.z;
|
||||
if (vertex.x() * m_scaling.x() > m_maxBounds.x()) {
|
||||
m_maxBounds.setX(vertex.x() * m_scaling.x());
|
||||
}
|
||||
if (vertex.x() * m_scaling.x() < m_minBounds.x()) {
|
||||
m_minBounds.setX(vertex.x() * m_scaling.x());
|
||||
}
|
||||
if (vertex.y() * m_scaling.y() > m_maxBounds.y()) {
|
||||
m_maxBounds.setY(vertex.y() * m_scaling.y());
|
||||
}
|
||||
if (vertex.y() * m_scaling.y() < m_minBounds.y()) {
|
||||
m_minBounds.setY(vertex.y() * m_scaling.y());
|
||||
}
|
||||
if (vertex.z() * m_scaling.z() > m_maxBounds.z()) {
|
||||
m_maxBounds.setZ(vertex.z() * m_scaling.z());
|
||||
}
|
||||
if (vertex.z() * m_scaling.z() < m_minBounds.z()) {
|
||||
m_minBounds.setZ(vertex.z() * m_scaling.z());
|
||||
}
|
||||
}
|
||||
|
||||
// Add an edge int32_to the convex mesh by specifying the two vertex indices of the edge.
|
||||
@ -231,7 +243,7 @@ inline void ConvexMeshShape::setIsEdgesInformationUsed(bool isEdgesUsed) {
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool ConvexMeshShape::testPointInside(const Vector3& localPoint,
|
||||
inline bool ConvexMeshShape::testPointInside(const vec3& localPoint,
|
||||
ProxyShape* proxyShape) const {
|
||||
|
||||
// Use the GJK algorithm to test if the point is inside the convex mesh
|
||||
|
@ -13,7 +13,7 @@ using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
ConvexShape::ConvexShape(CollisionShapeType type, float margin)
|
||||
: CollisionShape(type), mMargin(margin) {
|
||||
: CollisionShape(type), m_margin(margin) {
|
||||
|
||||
}
|
||||
|
||||
@ -23,20 +23,20 @@ ConvexShape::~ConvexShape() {
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction with the object margin
|
||||
Vector3 ConvexShape::getLocalSupportPointWithMargin(const Vector3& direction,
|
||||
vec3 ConvexShape::getLocalSupportPointWithMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
// Get the support point without margin
|
||||
Vector3 supportPoint = getLocalSupportPointWithoutMargin(direction, cachedCollisionData);
|
||||
vec3 supportPoint = getLocalSupportPointWithoutMargin(direction, cachedCollisionData);
|
||||
|
||||
if (mMargin != float(0.0)) {
|
||||
if (m_margin != 0.0f) {
|
||||
|
||||
// Add the margin to the support point
|
||||
Vector3 unitVec(0.0, -1.0, 0.0);
|
||||
if (direction.lengthSquare() > MACHINE_EPSILON * MACHINE_EPSILON) {
|
||||
unitVec = direction.getUnit();
|
||||
vec3 unitVec(0.0, -1.0, 0.0);
|
||||
if (direction.length2() > MACHINE_EPSILON * MACHINE_EPSILON) {
|
||||
unitVec = direction.safeNormalized();
|
||||
}
|
||||
supportPoint += unitVec * mMargin;
|
||||
supportPoint += unitVec * m_margin;
|
||||
}
|
||||
|
||||
return supportPoint;
|
||||
|
@ -23,7 +23,7 @@ class ConvexShape : public CollisionShape {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Margin used for the GJK collision detection algorithm
|
||||
float mMargin;
|
||||
float m_margin;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -34,15 +34,15 @@ class ConvexShape : public CollisionShape {
|
||||
ConvexShape& operator=(const ConvexShape& shape);
|
||||
|
||||
// Return a local support point in a given direction with the object margin
|
||||
Vector3 getLocalSupportPointWithMargin(const Vector3& direction,
|
||||
vec3 getLocalSupportPointWithMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const=0;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& worldPoint, ProxyShape* proxyShape) const=0;
|
||||
virtual bool testPointInside(const vec3& worldPoint, ProxyShape* proxyShape) const=0;
|
||||
|
||||
public :
|
||||
|
||||
@ -76,7 +76,7 @@ inline bool ConvexShape::isConvex() const {
|
||||
* @return The margin (in meters) around the collision shape
|
||||
*/
|
||||
inline float ConvexShape::getMargin() const {
|
||||
return mMargin;
|
||||
return m_margin;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ using namespace reactphysics3d;
|
||||
*/
|
||||
CylinderShape::CylinderShape(float radius, float height, float margin)
|
||||
: ConvexShape(CYLINDER, margin), mRadius(radius),
|
||||
mHalfHeight(height/float(2.0)) {
|
||||
assert(radius > float(0.0));
|
||||
assert(height > float(0.0));
|
||||
m_halfHeight(height/float(2.0)) {
|
||||
assert(radius > 0.0f);
|
||||
assert(height > 0.0f);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@ -30,24 +30,25 @@ CylinderShape::~CylinderShape() {
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the object margin
|
||||
Vector3 CylinderShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
|
||||
Vector3 supportPoint(0.0, 0.0, 0.0);
|
||||
float uDotv = direction.y;
|
||||
Vector3 w(direction.x, 0.0, direction.z);
|
||||
float lengthW = sqrt(direction.x * direction.x + direction.z * direction.z);
|
||||
|
||||
vec3 CylinderShape::getLocalSupportPointWithoutMargin(const vec3& _direction, void** _cachedCollisionData) const {
|
||||
vec3 supportPoint(0.0, 0.0, 0.0);
|
||||
float uDotv = _direction.y();
|
||||
vec3 w(_direction.x(), 0.0, _direction.z());
|
||||
float lengthW = sqrt(_direction.x() * _direction.x() + _direction.z() * _direction.z());
|
||||
if (lengthW > MACHINE_EPSILON) {
|
||||
if (uDotv < 0.0) supportPoint.y = -mHalfHeight;
|
||||
else supportPoint.y = mHalfHeight;
|
||||
if (uDotv < 0.0) {
|
||||
supportPoint.setY(-m_halfHeight);
|
||||
} else {
|
||||
supportPoint.setY(m_halfHeight);
|
||||
}
|
||||
supportPoint += (mRadius / lengthW) * w;
|
||||
} else {
|
||||
if (uDotv < 0.0) {
|
||||
supportPoint.setY(-m_halfHeight);
|
||||
} else {
|
||||
supportPoint.setY(m_halfHeight);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uDotv < 0.0) supportPoint.y = -mHalfHeight;
|
||||
else supportPoint.y = mHalfHeight;
|
||||
}
|
||||
|
||||
return supportPoint;
|
||||
}
|
||||
|
||||
@ -56,13 +57,13 @@ Vector3 CylinderShape::getLocalSupportPointWithoutMargin(const Vector3& directio
|
||||
/// Morgan Kaufmann.
|
||||
bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||
|
||||
const Vector3 n = ray.point2 - ray.point1;
|
||||
const vec3 n = ray.point2 - ray.point1;
|
||||
|
||||
const float epsilon = float(0.01);
|
||||
Vector3 p(float(0), -mHalfHeight, float(0));
|
||||
Vector3 q(float(0), mHalfHeight, float(0));
|
||||
Vector3 d = q - p;
|
||||
Vector3 m = ray.point1 - p;
|
||||
vec3 p(float(0), -m_halfHeight, float(0));
|
||||
vec3 q(float(0), m_halfHeight, float(0));
|
||||
vec3 d = q - p;
|
||||
vec3 m = ray.point1 - p;
|
||||
float t;
|
||||
|
||||
float mDotD = m.dot(d);
|
||||
@ -70,7 +71,7 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
float dDotD = d.dot(d);
|
||||
|
||||
// Test if the segment is outside the cylinder
|
||||
if (mDotD < float(0.0) && mDotD + nDotD < float(0.0)) return false;
|
||||
if (mDotD < 0.0f && mDotD + nDotD < float(0.0)) return false;
|
||||
if (mDotD > dDotD && mDotD + nDotD > dDotD) return false;
|
||||
|
||||
float nDotN = n.dot(n);
|
||||
@ -84,26 +85,26 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
if (std::abs(a) < epsilon) {
|
||||
|
||||
// If the origin is outside the surface of the cylinder, we return no hit
|
||||
if (c > float(0.0)) return false;
|
||||
if (c > 0.0f) return false;
|
||||
|
||||
// Here we know that the segment int32_tersect an endcap of the cylinder
|
||||
|
||||
// If the ray int32_tersects with the "p" endcap of the cylinder
|
||||
if (mDotD < float(0.0)) {
|
||||
if (mDotD < 0.0f) {
|
||||
|
||||
t = -mDotN / nDotN;
|
||||
|
||||
// If the int32_tersection is behind the origin of the ray or beyond the maximum
|
||||
// raycasting distance, we return no hit
|
||||
if (t < float(0.0) || t > ray.maxFraction) return false;
|
||||
if (t < 0.0f || t > ray.maxFraction) return false;
|
||||
|
||||
// Compute the hit information
|
||||
Vector3 localHitPoint = ray.point1 + t * n;
|
||||
vec3 localHitPoint = ray.point1 + t * n;
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = t;
|
||||
raycastInfo.worldPoint = localHitPoint;
|
||||
Vector3 normalDirection(0, float(-1), 0);
|
||||
vec3 normalDirection(0, float(-1), 0);
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -114,15 +115,15 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
|
||||
// If the int32_tersection is behind the origin of the ray or beyond the maximum
|
||||
// raycasting distance, we return no hit
|
||||
if (t < float(0.0) || t > ray.maxFraction) return false;
|
||||
if (t < 0.0f || t > ray.maxFraction) return false;
|
||||
|
||||
// Compute the hit information
|
||||
Vector3 localHitPoint = ray.point1 + t * n;
|
||||
vec3 localHitPoint = ray.point1 + t * n;
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = t;
|
||||
raycastInfo.worldPoint = localHitPoint;
|
||||
Vector3 normalDirection(0, float(1.0), 0);
|
||||
vec3 normalDirection(0, 1.0f, 0);
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -135,35 +136,35 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
float discriminant = b * b - a * c;
|
||||
|
||||
// If the discriminant is negative, no real roots and therfore, no hit
|
||||
if (discriminant < float(0.0)) return false;
|
||||
if (discriminant < 0.0f) return false;
|
||||
|
||||
// Compute the smallest root (first int32_tersection along the ray)
|
||||
float t0 = t = (-b - std::sqrt(discriminant)) / a;
|
||||
|
||||
// If the int32_tersection is outside the cylinder on "p" endcap side
|
||||
float value = mDotD + t * nDotD;
|
||||
if (value < float(0.0)) {
|
||||
if (value < 0.0f) {
|
||||
|
||||
// If the ray is pointing away from the "p" endcap, we return no hit
|
||||
if (nDotD <= float(0.0)) return false;
|
||||
if (nDotD <= 0.0f) return false;
|
||||
|
||||
// Compute the int32_tersection against the "p" endcap (int32_tersection agains whole plane)
|
||||
t = -mDotD / nDotD;
|
||||
|
||||
// Keep the int32_tersection if the it is inside the cylinder radius
|
||||
if (k + t * (float(2.0) * mDotN + t) > float(0.0)) return false;
|
||||
if (k + t * (float(2.0) * mDotN + t) > 0.0f) return false;
|
||||
|
||||
// If the int32_tersection is behind the origin of the ray or beyond the maximum
|
||||
// raycasting distance, we return no hit
|
||||
if (t < float(0.0) || t > ray.maxFraction) return false;
|
||||
if (t < 0.0f || t > ray.maxFraction) return false;
|
||||
|
||||
// Compute the hit information
|
||||
Vector3 localHitPoint = ray.point1 + t * n;
|
||||
vec3 localHitPoint = ray.point1 + t * n;
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = t;
|
||||
raycastInfo.worldPoint = localHitPoint;
|
||||
Vector3 normalDirection(0, float(-1.0), 0);
|
||||
vec3 normalDirection(0, float(-1.0), 0);
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -171,26 +172,26 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
else if (value > dDotD) { // If the int32_tersection is outside the cylinder on the "q" side
|
||||
|
||||
// If the ray is pointing away from the "q" endcap, we return no hit
|
||||
if (nDotD >= float(0.0)) return false;
|
||||
if (nDotD >= 0.0f) return false;
|
||||
|
||||
// Compute the int32_tersection against the "q" endcap (int32_tersection against whole plane)
|
||||
t = (dDotD - mDotD) / nDotD;
|
||||
|
||||
// Keep the int32_tersection if it is inside the cylinder radius
|
||||
if (k + dDotD - float(2.0) * mDotD + t * (float(2.0) * (mDotN - nDotD) + t) >
|
||||
float(0.0)) return false;
|
||||
0.0f) return false;
|
||||
|
||||
// If the int32_tersection is behind the origin of the ray or beyond the maximum
|
||||
// raycasting distance, we return no hit
|
||||
if (t < float(0.0) || t > ray.maxFraction) return false;
|
||||
if (t < 0.0f || t > ray.maxFraction) return false;
|
||||
|
||||
// Compute the hit information
|
||||
Vector3 localHitPoint = ray.point1 + t * n;
|
||||
vec3 localHitPoint = ray.point1 + t * n;
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = t;
|
||||
raycastInfo.worldPoint = localHitPoint;
|
||||
Vector3 normalDirection(0, float(1.0), 0);
|
||||
vec3 normalDirection(0, 1.0f, 0);
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
@ -200,17 +201,17 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
|
||||
// If the int32_tersection is behind the origin of the ray or beyond the maximum
|
||||
// raycasting distance, we return no hit
|
||||
if (t < float(0.0) || t > ray.maxFraction) return false;
|
||||
if (t < 0.0f || t > ray.maxFraction) return false;
|
||||
|
||||
// Compute the hit information
|
||||
Vector3 localHitPoint = ray.point1 + t * n;
|
||||
vec3 localHitPoint = ray.point1 + t * n;
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
raycastInfo.hitFraction = t;
|
||||
raycastInfo.worldPoint = localHitPoint;
|
||||
Vector3 v = localHitPoint - p;
|
||||
Vector3 w = (v.dot(d) / d.lengthSquare()) * d;
|
||||
Vector3 normalDirection = (localHitPoint - (p + w));
|
||||
vec3 v = localHitPoint - p;
|
||||
vec3 w = (v.dot(d) / d.length2()) * d;
|
||||
vec3 normalDirection = (localHitPoint - (p + w));
|
||||
raycastInfo.worldNormal = normalDirection;
|
||||
|
||||
return true;
|
||||
|
@ -38,7 +38,7 @@ class CylinderShape : public ConvexShape {
|
||||
float mRadius;
|
||||
|
||||
/// Half height of the cylinder
|
||||
float mHalfHeight;
|
||||
float m_halfHeight;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -49,11 +49,11 @@ class CylinderShape : public ConvexShape {
|
||||
CylinderShape& operator=(const CylinderShape& shape);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
@ -78,13 +78,13 @@ class CylinderShape : public ConvexShape {
|
||||
float getHeight() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
virtual void computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const;
|
||||
};
|
||||
|
||||
// Return the radius
|
||||
@ -100,14 +100,14 @@ inline float CylinderShape::getRadius() const {
|
||||
* @return Height of the cylinder (in meters)
|
||||
*/
|
||||
inline float CylinderShape::getHeight() const {
|
||||
return mHalfHeight + mHalfHeight;
|
||||
return m_halfHeight + m_halfHeight;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void CylinderShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void CylinderShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
mHalfHeight = (mHalfHeight / mScaling.y) * scaling.y;
|
||||
mRadius = (mRadius / mScaling.x) * scaling.x;
|
||||
m_halfHeight = (m_halfHeight / m_scaling.y()) * scaling.y();
|
||||
mRadius = (mRadius / m_scaling.x()) * scaling.x();
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
@ -122,17 +122,15 @@ 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(Vector3& min, Vector3& max) const {
|
||||
|
||||
inline void CylinderShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
// Maximum bounds
|
||||
max.x = mRadius + mMargin;
|
||||
max.y = mHalfHeight + mMargin;
|
||||
max.z = max.x;
|
||||
|
||||
max.setX(mRadius + m_margin);
|
||||
max.setY(m_halfHeight + m_margin);
|
||||
max.setZ(max.x());
|
||||
// Minimum bounds
|
||||
min.x = -max.x;
|
||||
min.y = -max.y;
|
||||
min.z = min.x;
|
||||
min.setX(-max.x());
|
||||
min.setY(-max.y());
|
||||
min.setZ(min.x());
|
||||
}
|
||||
|
||||
// Return the local inertia tensor of the cylinder
|
||||
@ -141,18 +139,19 @@ inline void CylinderShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void CylinderShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
float height = float(2.0) * mHalfHeight;
|
||||
float diag = (float(1.0) / float(12.0)) * mass * (3 * mRadius * mRadius + height * height);
|
||||
tensor.setAllValues(diag, 0.0, 0.0, 0.0,
|
||||
float(0.5) * mass * mRadius * mRadius, 0.0,
|
||||
inline 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,
|
||||
0.5f * mass * mRadius * mRadius, 0.0,
|
||||
0.0, 0.0, diag);
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool CylinderShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const{
|
||||
return ((localPoint.x * localPoint.x + localPoint.z * localPoint.z) < mRadius * mRadius &&
|
||||
localPoint.y < mHalfHeight && localPoint.y > -mHalfHeight);
|
||||
inline 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,35 +23,35 @@ using namespace reactphysics3d;
|
||||
HeightFieldShape::HeightFieldShape(int32_t nbGridColumns, int32_t nbGridRows, float minHeight, float maxHeight,
|
||||
const void* heightFieldData, HeightDataType dataType, int32_t upAxis,
|
||||
float int32_tegerHeightScale)
|
||||
: ConcaveShape(HEIGHTFIELD), mNbColumns(nbGridColumns), mNbRows(nbGridRows),
|
||||
mWidth(nbGridColumns - 1), mLength(nbGridRows - 1), mMinHeight(minHeight),
|
||||
mMaxHeight(maxHeight), mUpAxis(upAxis), mIntegerHeightScale(int32_tegerHeightScale),
|
||||
mHeightDataType(dataType) {
|
||||
: ConcaveShape(HEIGHTFIELD), m_numberColumns(nbGridColumns), m_numberRows(nbGridRows),
|
||||
m_width(nbGridColumns - 1), m_length(nbGridRows - 1), m_minHeight(minHeight),
|
||||
m_maxHeight(maxHeight), m_upAxis(upAxis), m_integerHeightScale(int32_tegerHeightScale),
|
||||
m_heightDataType(dataType) {
|
||||
|
||||
assert(nbGridColumns >= 2);
|
||||
assert(nbGridRows >= 2);
|
||||
assert(mWidth >= 1);
|
||||
assert(mLength >= 1);
|
||||
assert(m_width >= 1);
|
||||
assert(m_length >= 1);
|
||||
assert(minHeight <= maxHeight);
|
||||
assert(upAxis == 0 || upAxis == 1 || upAxis == 2);
|
||||
|
||||
mHeightFieldData = heightFieldData;
|
||||
m_heightFieldData = heightFieldData;
|
||||
|
||||
float halfHeight = (mMaxHeight - mMinHeight) * float(0.5);
|
||||
float halfHeight = (m_maxHeight - m_minHeight) * 0.5f;
|
||||
assert(halfHeight >= 0);
|
||||
|
||||
// Compute the local AABB of the height field
|
||||
if (mUpAxis == 0) {
|
||||
mAABB.setMin(Vector3(-halfHeight, -mWidth * float(0.5), -mLength * float(0.5)));
|
||||
mAABB.setMax(Vector3(halfHeight, mWidth * float(0.5), mLength* float(0.5)));
|
||||
if (m_upAxis == 0) {
|
||||
m_AABB.setMin(vec3(-halfHeight, -m_width * 0.5f, -m_length * float(0.5)));
|
||||
m_AABB.setMax(vec3(halfHeight, m_width * 0.5f, m_length* float(0.5)));
|
||||
}
|
||||
else if (mUpAxis == 1) {
|
||||
mAABB.setMin(Vector3(-mWidth * float(0.5), -halfHeight, -mLength * float(0.5)));
|
||||
mAABB.setMax(Vector3(mWidth * float(0.5), halfHeight, mLength * float(0.5)));
|
||||
else if (m_upAxis == 1) {
|
||||
m_AABB.setMin(vec3(-m_width * 0.5f, -halfHeight, -m_length * float(0.5)));
|
||||
m_AABB.setMax(vec3(m_width * 0.5f, halfHeight, m_length * float(0.5)));
|
||||
}
|
||||
else if (mUpAxis == 2) {
|
||||
mAABB.setMin(Vector3(-mWidth * float(0.5), -mLength * float(0.5), -halfHeight));
|
||||
mAABB.setMax(Vector3(mWidth * float(0.5), mLength * float(0.5), halfHeight));
|
||||
else if (m_upAxis == 2) {
|
||||
m_AABB.setMin(vec3(-m_width * 0.5f, -m_length * float(0.5), -halfHeight));
|
||||
m_AABB.setMax(vec3(m_width * 0.5f, m_length * float(0.5), halfHeight));
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,9 +66,9 @@ HeightFieldShape::~HeightFieldShape() {
|
||||
* @param min The minimum bounds of the shape in local-space coordinates
|
||||
* @param max The maximum bounds of the shape in local-space coordinates
|
||||
*/
|
||||
void HeightFieldShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||
min = mAABB.getMin() * mScaling;
|
||||
max = mAABB.getMax() * mScaling;
|
||||
void HeightFieldShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
min = m_AABB.getMin() * m_scaling;
|
||||
max = m_AABB.getMax() * m_scaling;
|
||||
}
|
||||
|
||||
// Test collision with the triangles of the height field shape. The idea is to use the AABB
|
||||
@ -78,7 +78,7 @@ void HeightFieldShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||
void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const {
|
||||
|
||||
// Compute the non-scaled AABB
|
||||
Vector3 inverseScaling(float(1.0) / mScaling.x, float(1.0) / mScaling.y, float(1.0) / mScaling.z);
|
||||
vec3 inverseScaling(1.0f / m_scaling.x(), 1.0f / m_scaling.y(), float(1.0) / m_scaling.z());
|
||||
AABB aabb(localAABB.getMin() * inverseScaling, localAABB.getMax() * inverseScaling);
|
||||
|
||||
// Compute the int32_teger grid coordinates inside the area we need to test for collision
|
||||
@ -91,41 +91,41 @@ void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB&
|
||||
int32_t iMax = 0;
|
||||
int32_t jMin = 0;
|
||||
int32_t jMax = 0;
|
||||
switch(mUpAxis) {
|
||||
case 0 : iMin = clamp(minGridCoords[1], 0, mNbColumns - 1);
|
||||
iMax = clamp(maxGridCoords[1], 0, mNbColumns - 1);
|
||||
jMin = clamp(minGridCoords[2], 0, mNbRows - 1);
|
||||
jMax = clamp(maxGridCoords[2], 0, mNbRows - 1);
|
||||
switch(m_upAxis) {
|
||||
case 0 : iMin = clamp(minGridCoords[1], 0, m_numberColumns - 1);
|
||||
iMax = clamp(maxGridCoords[1], 0, m_numberColumns - 1);
|
||||
jMin = clamp(minGridCoords[2], 0, m_numberRows - 1);
|
||||
jMax = clamp(maxGridCoords[2], 0, m_numberRows - 1);
|
||||
break;
|
||||
case 1 : iMin = clamp(minGridCoords[0], 0, mNbColumns - 1);
|
||||
iMax = clamp(maxGridCoords[0], 0, mNbColumns - 1);
|
||||
jMin = clamp(minGridCoords[2], 0, mNbRows - 1);
|
||||
jMax = clamp(maxGridCoords[2], 0, mNbRows - 1);
|
||||
case 1 : iMin = clamp(minGridCoords[0], 0, m_numberColumns - 1);
|
||||
iMax = clamp(maxGridCoords[0], 0, m_numberColumns - 1);
|
||||
jMin = clamp(minGridCoords[2], 0, m_numberRows - 1);
|
||||
jMax = clamp(maxGridCoords[2], 0, m_numberRows - 1);
|
||||
break;
|
||||
case 2 : iMin = clamp(minGridCoords[0], 0, mNbColumns - 1);
|
||||
iMax = clamp(maxGridCoords[0], 0, mNbColumns - 1);
|
||||
jMin = clamp(minGridCoords[1], 0, mNbRows - 1);
|
||||
jMax = clamp(maxGridCoords[1], 0, mNbRows - 1);
|
||||
case 2 : iMin = clamp(minGridCoords[0], 0, m_numberColumns - 1);
|
||||
iMax = clamp(maxGridCoords[0], 0, m_numberColumns - 1);
|
||||
jMin = clamp(minGridCoords[1], 0, m_numberRows - 1);
|
||||
jMax = clamp(maxGridCoords[1], 0, m_numberRows - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(iMin >= 0 && iMin < mNbColumns);
|
||||
assert(iMax >= 0 && iMax < mNbColumns);
|
||||
assert(jMin >= 0 && jMin < mNbRows);
|
||||
assert(jMax >= 0 && jMax < mNbRows);
|
||||
assert(iMin >= 0 && iMin < m_numberColumns);
|
||||
assert(iMax >= 0 && iMax < m_numberColumns);
|
||||
assert(jMin >= 0 && jMin < m_numberRows);
|
||||
assert(jMax >= 0 && jMax < m_numberRows);
|
||||
|
||||
// For each sub-grid points (except the last ones one each dimension)
|
||||
for (int32_t i = iMin; i < iMax; i++) {
|
||||
for (int32_t j = jMin; j < jMax; j++) {
|
||||
|
||||
// Compute the four point of the current quad
|
||||
Vector3 p1 = getVertexAt(i, j);
|
||||
Vector3 p2 = getVertexAt(i, j + 1);
|
||||
Vector3 p3 = getVertexAt(i + 1, j);
|
||||
Vector3 p4 = getVertexAt(i + 1, j + 1);
|
||||
vec3 p1 = getVertexAt(i, j);
|
||||
vec3 p2 = getVertexAt(i, j + 1);
|
||||
vec3 p3 = getVertexAt(i + 1, j);
|
||||
vec3 p4 = getVertexAt(i + 1, j + 1);
|
||||
|
||||
// Generate the first triangle for the current grid rectangle
|
||||
Vector3 trianglePoints[3] = {p1, p2, p3};
|
||||
vec3 trianglePoints[3] = {p1, p2, p3};
|
||||
|
||||
// Test collision against the first triangle
|
||||
callback.testTriangle(trianglePoints);
|
||||
@ -146,29 +146,29 @@ void HeightFieldShape::testAllTriangles(TriangleCallback& callback, const AABB&
|
||||
void HeightFieldShape::computeMinMaxGridCoordinates(int32_t* minCoords, int32_t* maxCoords, const AABB& aabbToCollide) const {
|
||||
|
||||
// Clamp the min/max coords of the AABB to collide inside the height field AABB
|
||||
Vector3 minPoint = Vector3::max(aabbToCollide.getMin(), mAABB.getMin());
|
||||
minPoint = Vector3::min(minPoint, mAABB.getMax());
|
||||
vec3 minPoint = etk::max(aabbToCollide.getMin(), m_AABB.getMin());
|
||||
minPoint = etk::min(minPoint, m_AABB.getMax());
|
||||
|
||||
Vector3 maxPoint = Vector3::min(aabbToCollide.getMax(), mAABB.getMax());
|
||||
maxPoint = Vector3::max(maxPoint, mAABB.getMin());
|
||||
vec3 maxPoint = etk::min(aabbToCollide.getMax(), m_AABB.getMax());
|
||||
maxPoint = etk::max(maxPoint, m_AABB.getMin());
|
||||
|
||||
// Translate the min/max points such that the we compute grid points from [0 ... mNbWidthGridPoints]
|
||||
// and from [0 ... mNbLengthGridPoints] because the AABB coordinates range are [-mWdith/2 ... mWidth/2]
|
||||
// and [-mLength/2 ... mLength/2]
|
||||
const Vector3 translateVec = mAABB.getExtent() * float(0.5);
|
||||
// and from [0 ... mNbLengthGridPoints] because the AABB coordinates range are [-mWdith/2 ... m_width/2]
|
||||
// and [-m_length/2 ... m_length/2]
|
||||
const vec3 translateVec = m_AABB.getExtent() * 0.5f;
|
||||
minPoint += translateVec;
|
||||
maxPoint += translateVec;
|
||||
|
||||
// Convert the floating min/max coords of the AABB int32_to closest int32_teger
|
||||
// grid values (note that we use the closest grid coordinate that is out
|
||||
// of the AABB)
|
||||
minCoords[0] = computeIntegerGridValue(minPoint.x) - 1;
|
||||
minCoords[1] = computeIntegerGridValue(minPoint.y) - 1;
|
||||
minCoords[2] = computeIntegerGridValue(minPoint.z) - 1;
|
||||
minCoords[0] = computeIntegerGridValue(minPoint.x()) - 1;
|
||||
minCoords[1] = computeIntegerGridValue(minPoint.y()) - 1;
|
||||
minCoords[2] = computeIntegerGridValue(minPoint.z()) - 1;
|
||||
|
||||
maxCoords[0] = computeIntegerGridValue(maxPoint.x) + 1;
|
||||
maxCoords[1] = computeIntegerGridValue(maxPoint.y) + 1;
|
||||
maxCoords[2] = computeIntegerGridValue(maxPoint.z) + 1;
|
||||
maxCoords[0] = computeIntegerGridValue(maxPoint.x()) + 1;
|
||||
maxCoords[1] = computeIntegerGridValue(maxPoint.y()) + 1;
|
||||
maxCoords[2] = computeIntegerGridValue(maxPoint.z()) + 1;
|
||||
}
|
||||
|
||||
// Raycast method with feedback information
|
||||
@ -184,8 +184,8 @@ bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxySh
|
||||
TriangleOverlapCallback triangleCallback(ray, proxyShape, raycastInfo, *this);
|
||||
|
||||
// Compute the AABB for the ray
|
||||
const Vector3 rayEnd = ray.point1 + ray.maxFraction * (ray.point2 - ray.point1);
|
||||
const AABB rayAABB(Vector3::min(ray.point1, rayEnd), Vector3::max(ray.point1, rayEnd));
|
||||
const vec3 rayEnd = ray.point1 + ray.maxFraction * (ray.point2 - ray.point1);
|
||||
const AABB rayAABB(etk::min(ray.point1, rayEnd), etk::max(ray.point1, rayEnd));
|
||||
|
||||
testAllTriangles(triangleCallback, rayAABB);
|
||||
|
||||
@ -193,46 +193,46 @@ bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxySh
|
||||
}
|
||||
|
||||
// Return the vertex (local-coordinates) of the height field at a given (x,y) position
|
||||
Vector3 HeightFieldShape::getVertexAt(int32_t x, int32_t y) const {
|
||||
vec3 HeightFieldShape::getVertexAt(int32_t x, int32_t y) const {
|
||||
|
||||
// Get the height value
|
||||
const float height = getHeightAt(x, y);
|
||||
|
||||
// Height values origin
|
||||
const float heightOrigin = -(mMaxHeight - mMinHeight) * float(0.5) - mMinHeight;
|
||||
const float heightOrigin = -(m_maxHeight - m_minHeight) * 0.5f - m_minHeight;
|
||||
|
||||
Vector3 vertex;
|
||||
switch (mUpAxis) {
|
||||
case 0: vertex = Vector3(heightOrigin + height, -mWidth * float(0.5) + x, -mLength * float(0.5) + y);
|
||||
vec3 vertex;
|
||||
switch (m_upAxis) {
|
||||
case 0: vertex = vec3(heightOrigin + height, -m_width * 0.5f + x, -m_length * float(0.5) + y);
|
||||
break;
|
||||
case 1: vertex = Vector3(-mWidth * float(0.5) + x, heightOrigin + height, -mLength * float(0.5) + y);
|
||||
case 1: vertex = vec3(-m_width * 0.5f + x, heightOrigin + height, -m_length * float(0.5) + y);
|
||||
break;
|
||||
case 2: vertex = Vector3(-mWidth * float(0.5) + x, -mLength * float(0.5) + y, heightOrigin + height);
|
||||
case 2: vertex = vec3(-m_width * 0.5f + x, -m_length * float(0.5) + y, heightOrigin + height);
|
||||
break;
|
||||
default: assert(false);
|
||||
}
|
||||
|
||||
assert(mAABB.contains(vertex));
|
||||
assert(m_AABB.contains(vertex));
|
||||
|
||||
return vertex * mScaling;
|
||||
return vertex * m_scaling;
|
||||
}
|
||||
|
||||
// Raycast test between a ray and a triangle of the heightfield
|
||||
void TriangleOverlapCallback::testTriangle(const Vector3* trianglePoints) {
|
||||
void TriangleOverlapCallback::testTriangle(const vec3* trianglePoints) {
|
||||
|
||||
// Create a triangle collision shape
|
||||
float margin = mHeightFieldShape.getTriangleMargin();
|
||||
float margin = m_heightFieldShape.getTriangleMargin();
|
||||
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2], margin);
|
||||
triangleShape.setRaycastTestType(mHeightFieldShape.getRaycastTestType());
|
||||
triangleShape.setRaycastTestType(m_heightFieldShape.getRaycastTestType());
|
||||
|
||||
// Ray casting test against the collision shape
|
||||
RaycastInfo raycastInfo;
|
||||
bool isTriangleHit = triangleShape.raycast(m_ray, raycastInfo, m_proxyShape);
|
||||
|
||||
// If the ray hit the collision shape
|
||||
if (isTriangleHit && raycastInfo.hitFraction <= mSmallestHitFraction) {
|
||||
if (isTriangleHit && raycastInfo.hitFraction <= m_smallestHitFraction) {
|
||||
|
||||
assert(raycastInfo.hitFraction >= float(0.0));
|
||||
assert(raycastInfo.hitFraction >= 0.0f);
|
||||
|
||||
m_raycastInfo.body = raycastInfo.body;
|
||||
m_raycastInfo.proxyShape = raycastInfo.proxyShape;
|
||||
@ -242,7 +242,7 @@ void TriangleOverlapCallback::testTriangle(const Vector3* trianglePoints) {
|
||||
m_raycastInfo.meshSubpart = -1;
|
||||
m_raycastInfo.triangleIndex = -1;
|
||||
|
||||
mSmallestHitFraction = raycastInfo.hitFraction;
|
||||
mIsHit = true;
|
||||
m_smallestHitFraction = raycastInfo.hitFraction;
|
||||
m_isHit = true;
|
||||
}
|
||||
}
|
||||
|
@ -11,45 +11,40 @@
|
||||
#include <ephysics/engine/Profiler.h>
|
||||
|
||||
namespace reactphysics3d {
|
||||
class HeightFieldShape;
|
||||
/**
|
||||
* @brief This class is used for testing AABB and triangle overlap for raycasting
|
||||
*/
|
||||
class TriangleOverlapCallback : public TriangleCallback {
|
||||
protected:
|
||||
const Ray& m_ray;
|
||||
ProxyShape* m_proxyShape;
|
||||
RaycastInfo& m_raycastInfo;
|
||||
bool m_isHit;
|
||||
float m_smallestHitFraction;
|
||||
const HeightFieldShape& m_heightFieldShape;
|
||||
public:
|
||||
TriangleOverlapCallback(const Ray& _ray,
|
||||
ProxyShape* _proxyShape,
|
||||
RaycastInfo& _raycastInfo,
|
||||
const HeightFieldShape& _heightFieldShape):
|
||||
m_ray(_ray),
|
||||
m_proxyShape(_proxyShape),
|
||||
m_raycastInfo(_raycastInfo),
|
||||
m_heightFieldShape(_heightFieldShape) {
|
||||
m_isHit = false;
|
||||
m_smallestHitFraction = m_ray.maxFraction;
|
||||
}
|
||||
bool getIsHit() const {
|
||||
return m_isHit;
|
||||
}
|
||||
/// Raycast test between a ray and a triangle of the heightfield
|
||||
virtual void testTriangle(const vec3* _trianglePoints);
|
||||
};
|
||||
|
||||
class HeightFieldShape;
|
||||
|
||||
// Class TriangleOverlapCallback
|
||||
/**
|
||||
* This class is used for testing AABB and triangle overlap for raycasting
|
||||
*/
|
||||
class TriangleOverlapCallback : public TriangleCallback {
|
||||
|
||||
protected:
|
||||
|
||||
const Ray& m_ray;
|
||||
ProxyShape* m_proxyShape;
|
||||
RaycastInfo& m_raycastInfo;
|
||||
bool mIsHit;
|
||||
float mSmallestHitFraction;
|
||||
const HeightFieldShape& mHeightFieldShape;
|
||||
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
TriangleOverlapCallback(const Ray& ray, ProxyShape* proxyShape, RaycastInfo& raycastInfo,
|
||||
const HeightFieldShape& heightFieldShape)
|
||||
: m_ray(ray), m_proxyShape(proxyShape), m_raycastInfo(raycastInfo),
|
||||
mHeightFieldShape (heightFieldShape) {
|
||||
mIsHit = false;
|
||||
mSmallestHitFraction = m_ray.maxFraction;
|
||||
}
|
||||
|
||||
bool getIsHit() const {return mIsHit;}
|
||||
|
||||
/// Raycast test between a ray and a triangle of the heightfield
|
||||
virtual void testTriangle(const Vector3* trianglePoints);
|
||||
};
|
||||
|
||||
|
||||
// Class HeightFieldShape
|
||||
/**
|
||||
* This class represents a static height field that can be used to represent
|
||||
* @brief This class represents a static height field that can be used to represent
|
||||
* a terrain. The height field is made of a grid with rows and columns with a
|
||||
* height value at each grid point. Note that the height values are not copied int32_to the shape
|
||||
* but are shared instead. The height values can be of type int32_teger, float or double.
|
||||
@ -70,37 +65,37 @@ class HeightFieldShape : public ConcaveShape {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Number of columns in the grid of the height field
|
||||
int32_t mNbColumns;
|
||||
int32_t m_numberColumns;
|
||||
|
||||
/// Number of rows in the grid of the height field
|
||||
int32_t mNbRows;
|
||||
int32_t m_numberRows;
|
||||
|
||||
/// Height field width
|
||||
float mWidth;
|
||||
float m_width;
|
||||
|
||||
/// Height field length
|
||||
float mLength;
|
||||
float m_length;
|
||||
|
||||
/// Minimum height of the height field
|
||||
float mMinHeight;
|
||||
float m_minHeight;
|
||||
|
||||
/// Maximum height of the height field
|
||||
float mMaxHeight;
|
||||
float m_maxHeight;
|
||||
|
||||
/// Up axis direction (0 => x, 1 => y, 2 => z)
|
||||
int32_t mUpAxis;
|
||||
int32_t m_upAxis;
|
||||
|
||||
/// Height values scale for height field with int32_teger height values
|
||||
float mIntegerHeightScale;
|
||||
float m_integerHeightScale;
|
||||
|
||||
/// Data type of the height values
|
||||
HeightDataType mHeightDataType;
|
||||
HeightDataType m_heightDataType;
|
||||
|
||||
/// Array of data with all the height values of the height field
|
||||
const void* mHeightFieldData;
|
||||
const void* m_heightFieldData;
|
||||
|
||||
/// Local AABB of the height field (without scaling)
|
||||
AABB mAABB;
|
||||
AABB m_AABB;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -122,10 +117,10 @@ class HeightFieldShape : public ConcaveShape {
|
||||
/// 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,
|
||||
Vector3* outTriangleVertices) const;
|
||||
vec3* outTriangleVertices) const;
|
||||
|
||||
/// Return the vertex (local-coordinates) of the height field at a given (x,y) position
|
||||
Vector3 getVertexAt(int32_t x, int32_t y) const;
|
||||
vec3 getVertexAt(int32_t x, int32_t y) const;
|
||||
|
||||
/// Return the height of a given (x,y) point in the height field
|
||||
float getHeightAt(int32_t x, int32_t y) const;
|
||||
@ -156,13 +151,13 @@ class HeightFieldShape : public ConcaveShape {
|
||||
HeightDataType getHeightDataType() const;
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions.
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Set the local scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
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;
|
||||
@ -175,17 +170,17 @@ class HeightFieldShape : public ConcaveShape {
|
||||
|
||||
// Return the number of rows in the height field
|
||||
inline int32_t HeightFieldShape::getNbRows() const {
|
||||
return mNbRows;
|
||||
return m_numberRows;
|
||||
}
|
||||
|
||||
// Return the number of columns in the height field
|
||||
inline int32_t HeightFieldShape::getNbColumns() const {
|
||||
return mNbColumns;
|
||||
return m_numberColumns;
|
||||
}
|
||||
|
||||
// Return the type of height value in the height field
|
||||
inline HeightFieldShape::HeightDataType HeightFieldShape::getHeightDataType() const {
|
||||
return mHeightDataType;
|
||||
return m_heightDataType;
|
||||
}
|
||||
|
||||
// Return the number of bytes used by the collision shape
|
||||
@ -194,24 +189,24 @@ inline size_t HeightFieldShape::getSizeInBytes() const {
|
||||
}
|
||||
|
||||
// Set the local scaling vector of the collision shape
|
||||
inline void HeightFieldShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline 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 {
|
||||
|
||||
switch(mHeightDataType) {
|
||||
case HEIGHT_FLOAT_TYPE : return ((float*)mHeightFieldData)[y * mNbColumns + x];
|
||||
case HEIGHT_DOUBLE_TYPE : return ((double*)mHeightFieldData)[y * mNbColumns + x];
|
||||
case HEIGHT_INT_TYPE : return ((int32_t*)mHeightFieldData)[y * mNbColumns + x] * mIntegerHeightScale;
|
||||
switch(m_heightDataType) {
|
||||
case HEIGHT_FLOAT_TYPE : return ((float*)m_heightFieldData)[y * m_numberColumns + x];
|
||||
case HEIGHT_DOUBLE_TYPE : return ((double*)m_heightFieldData)[y * m_numberColumns + x];
|
||||
case HEIGHT_INT_TYPE : return ((int32_t*)m_heightFieldData)[y * m_numberColumns + x] * m_integerHeightScale;
|
||||
default: assert(false); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the closest inside int32_teger grid value of a given floating grid value
|
||||
inline int32_t HeightFieldShape::computeIntegerGridValue(float value) const {
|
||||
return (value < float(0.0)) ? value - float(0.5) : value + float(0.5);
|
||||
return (value < 0.0f) ? value - 0.5f : value + float(0.5);
|
||||
}
|
||||
|
||||
// Return the local inertia tensor
|
||||
@ -220,13 +215,13 @@ 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(Matrix3x3& tensor, float mass) const {
|
||||
inline void HeightFieldShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
|
||||
// Default inertia tensor
|
||||
// Note that this is not very realistic for a concave triangle mesh.
|
||||
// However, in most cases, it will only be used static bodies and therefore,
|
||||
// the inertia tensor is not used.
|
||||
tensor.setAllValues(mass, 0, 0,
|
||||
tensor.setValue(mass, 0, 0,
|
||||
0, mass, 0,
|
||||
0, 0, mass);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ using namespace reactphysics3d;
|
||||
* @param radius Radius of the sphere (in meters)
|
||||
*/
|
||||
SphereShape::SphereShape(float radius) : ConvexShape(SPHERE, radius) {
|
||||
assert(radius > float(0.0));
|
||||
assert(radius > 0.0f);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@ -28,31 +28,31 @@ SphereShape::~SphereShape() {
|
||||
// Raycast method with feedback information
|
||||
bool SphereShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||
|
||||
const Vector3 m = ray.point1;
|
||||
float c = m.dot(m) - mMargin * mMargin;
|
||||
const vec3 m = ray.point1;
|
||||
float c = m.dot(m) - m_margin * m_margin;
|
||||
|
||||
// If the origin of the ray is inside the sphere, we return no int32_tersection
|
||||
if (c < float(0.0)) return false;
|
||||
if (c < 0.0f) return false;
|
||||
|
||||
const Vector3 rayDirection = ray.point2 - ray.point1;
|
||||
const vec3 rayDirection = ray.point2 - ray.point1;
|
||||
float b = m.dot(rayDirection);
|
||||
|
||||
// If the origin of the ray is outside the sphere and the ray
|
||||
// is pointing away from the sphere, there is no int32_tersection
|
||||
if (b > float(0.0)) return false;
|
||||
if (b > 0.0f) return false;
|
||||
|
||||
float raySquareLength = rayDirection.lengthSquare();
|
||||
float raySquareLength = rayDirection.length2();
|
||||
|
||||
// Compute the discriminant of the quadratic equation
|
||||
float discriminant = b * b - raySquareLength * c;
|
||||
|
||||
// If the discriminant is negative or the ray length is very small, there is no int32_tersection
|
||||
if (discriminant < float(0.0) || raySquareLength < MACHINE_EPSILON) return false;
|
||||
if (discriminant < 0.0f || raySquareLength < MACHINE_EPSILON) return false;
|
||||
|
||||
// Compute the solution "t" closest to the origin
|
||||
float t = -b - std::sqrt(discriminant);
|
||||
|
||||
assert(t >= float(0.0));
|
||||
assert(t >= 0.0f);
|
||||
|
||||
// If the hit point is withing the segment ray fraction
|
||||
if (t < ray.maxFraction * raySquareLength) {
|
||||
|
@ -37,11 +37,11 @@ class SphereShape : public ConvexShape {
|
||||
SphereShape& operator=(const SphereShape& shape);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
@ -63,16 +63,16 @@ class SphereShape : public ConvexShape {
|
||||
float getRadius() const;
|
||||
|
||||
/// Set the scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions.
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
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 Transform& transform) const;
|
||||
virtual void computeAABB(AABB& aabb, const etk::Transform3D& transform) const;
|
||||
};
|
||||
|
||||
// Get the radius of the sphere
|
||||
@ -80,13 +80,13 @@ class SphereShape : public ConvexShape {
|
||||
* @return Radius of the sphere (in meters)
|
||||
*/
|
||||
inline float SphereShape::getRadius() const {
|
||||
return mMargin;
|
||||
return m_margin;
|
||||
}
|
||||
|
||||
// Set the scaling vector of the collision shape
|
||||
inline void SphereShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void SphereShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
mMargin = (mMargin / mScaling.x) * scaling.x;
|
||||
m_margin = (m_margin / m_scaling.x()) * scaling.x();
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
@ -97,11 +97,11 @@ inline size_t SphereShape::getSizeInBytes() const {
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the object margin
|
||||
inline Vector3 SphereShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
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)
|
||||
return Vector3(0.0, 0.0, 0.0);
|
||||
return vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// Return the local bounds of the shape in x, y and z directions.
|
||||
@ -110,17 +110,15 @@ inline Vector3 SphereShape::getLocalSupportPointWithoutMargin(const Vector3& dir
|
||||
* @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(Vector3& min, Vector3& max) const {
|
||||
|
||||
inline void SphereShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
// Maximum bounds
|
||||
max.x = mMargin;
|
||||
max.y = mMargin;
|
||||
max.z = mMargin;
|
||||
|
||||
max.setX(m_margin);
|
||||
max.setY(m_margin);
|
||||
max.setZ(m_margin);
|
||||
// Minimum bounds
|
||||
min.x = -mMargin;
|
||||
min.y = min.x;
|
||||
min.z = min.x;
|
||||
min.setX(-m_margin);
|
||||
min.setY(min.x());
|
||||
min.setZ(min.x());
|
||||
}
|
||||
|
||||
// Return the local inertia tensor of the sphere
|
||||
@ -129,23 +127,23 @@ inline void SphereShape::getLocalBounds(Vector3& min, Vector3& max) const {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void SphereShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
float diag = float(0.4) * mass * mMargin * mMargin;
|
||||
tensor.setAllValues(diag, 0.0, 0.0,
|
||||
0.0, diag, 0.0,
|
||||
0.0, 0.0, diag);
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 Transform used to compute the AABB of the collision shape
|
||||
* @param transform etk::Transform3D used to compute the AABB of the collision shape
|
||||
*/
|
||||
inline void SphereShape::computeAABB(AABB& aabb, const Transform& transform) const {
|
||||
inline void SphereShape::computeAABB(AABB& aabb, const etk::Transform3D& transform) const {
|
||||
|
||||
// Get the local extents in x,y and z direction
|
||||
Vector3 extents(mMargin, mMargin, mMargin);
|
||||
vec3 extents(m_margin, m_margin, m_margin);
|
||||
|
||||
// Update the AABB with the new minimum and maximum coordinates
|
||||
aabb.setMin(transform.getPosition() - extents);
|
||||
@ -153,8 +151,8 @@ inline void SphereShape::computeAABB(AABB& aabb, const Transform& transform) con
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool SphereShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
|
||||
return (localPoint.lengthSquare() < mMargin * mMargin);
|
||||
inline bool SphereShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
return (localPoint.length2() < m_margin * m_margin);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ using namespace reactphysics3d;
|
||||
* @param point3 Third point of the triangle
|
||||
* @param margin The collision margin (in meters) around the collision shape
|
||||
*/
|
||||
TriangleShape::TriangleShape(const Vector3& point1, const Vector3& point2, const Vector3& point3, float margin)
|
||||
TriangleShape::TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3, float margin)
|
||||
: ConvexShape(TRIANGLE, margin) {
|
||||
mPoints[0] = point1;
|
||||
mPoints[1] = point2;
|
||||
@ -40,28 +40,28 @@ bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
|
||||
PROFILE("TriangleShape::raycast()");
|
||||
|
||||
const Vector3 pq = ray.point2 - ray.point1;
|
||||
const Vector3 pa = mPoints[0] - ray.point1;
|
||||
const Vector3 pb = mPoints[1] - ray.point1;
|
||||
const Vector3 pc = mPoints[2] - ray.point1;
|
||||
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;
|
||||
|
||||
// Test if the line PQ is inside the eges BC, CA and AB. We use the triple
|
||||
// product for this test.
|
||||
const Vector3 m = pq.cross(pc);
|
||||
const vec3 m = pq.cross(pc);
|
||||
float u = pb.dot(m);
|
||||
if (m_raycastTestType == FRONT) {
|
||||
if (u < float(0.0)) return false;
|
||||
if (u < 0.0f) return false;
|
||||
}
|
||||
else if (m_raycastTestType == BACK) {
|
||||
if (u > float(0.0)) return false;
|
||||
if (u > 0.0f) return false;
|
||||
}
|
||||
|
||||
float v = -pa.dot(m);
|
||||
if (m_raycastTestType == FRONT) {
|
||||
if (v < float(0.0)) return false;
|
||||
if (v < 0.0f) return false;
|
||||
}
|
||||
else if (m_raycastTestType == BACK) {
|
||||
if (v > float(0.0)) return false;
|
||||
if (v > 0.0f) return false;
|
||||
}
|
||||
else if (m_raycastTestType == FRONT_AND_BACK) {
|
||||
if (!sameSign(u, v)) return false;
|
||||
@ -69,10 +69,10 @@ bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
|
||||
float w = pa.dot(pq.cross(pb));
|
||||
if (m_raycastTestType == FRONT) {
|
||||
if (w < float(0.0)) return false;
|
||||
if (w < 0.0f) return false;
|
||||
}
|
||||
else if (m_raycastTestType == BACK) {
|
||||
if (w > float(0.0)) return false;
|
||||
if (w > 0.0f) return false;
|
||||
}
|
||||
else if (m_raycastTestType == FRONT_AND_BACK) {
|
||||
if (!sameSign(u, w)) return false;
|
||||
@ -83,19 +83,19 @@ bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape
|
||||
|
||||
// Compute the barycentric coordinates (u, v, w) to determine the
|
||||
// int32_tersection point R, R = u * a + v * b + w * c
|
||||
float denom = float(1.0) / (u + v + w);
|
||||
float denom = 1.0f / (u + v + w);
|
||||
u *= denom;
|
||||
v *= denom;
|
||||
w *= denom;
|
||||
|
||||
// Compute the local hit point using the barycentric coordinates
|
||||
const Vector3 localHitPoint = u * mPoints[0] + v * mPoints[1] + w * mPoints[2];
|
||||
const vec3 localHitPoint = u * mPoints[0] + v * mPoints[1] + w * mPoints[2];
|
||||
const float hitFraction = (localHitPoint - ray.point1).length() / pq.length();
|
||||
|
||||
if (hitFraction < float(0.0) || hitFraction > ray.maxFraction) return false;
|
||||
if (hitFraction < 0.0f || hitFraction > ray.maxFraction) return false;
|
||||
|
||||
Vector3 localHitNormal = (mPoints[1] - mPoints[0]).cross(mPoints[2] - mPoints[0]);
|
||||
if (localHitNormal.dot(pq) > float(0.0)) localHitNormal = -localHitNormal;
|
||||
vec3 localHitNormal = (mPoints[1] - mPoints[0]).cross(mPoints[2] - mPoints[0]);
|
||||
if (localHitNormal.dot(pq) > 0.0f) localHitNormal = -localHitNormal;
|
||||
|
||||
raycastInfo.body = proxyShape->getBody();
|
||||
raycastInfo.proxyShape = proxyShape;
|
||||
|
@ -37,7 +37,7 @@ class TriangleShape : public ConvexShape {
|
||||
// -------------------- Attribute -------------------- //
|
||||
|
||||
/// Three points of the triangle
|
||||
Vector3 mPoints[3];
|
||||
vec3 mPoints[3];
|
||||
|
||||
/// Raycast test type for the triangle (front, back, front-back)
|
||||
TriangleRaycastSide m_raycastTestType;
|
||||
@ -51,11 +51,11 @@ class TriangleShape : public ConvexShape {
|
||||
TriangleShape& operator=(const TriangleShape& shape);
|
||||
|
||||
/// Return a local support point in a given direction without the object margin
|
||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
virtual vec3 getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const;
|
||||
|
||||
/// Return true if a point is inside the collision shape
|
||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||
virtual bool testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const;
|
||||
|
||||
/// Raycast method with feedback information
|
||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||
@ -68,23 +68,23 @@ class TriangleShape : public ConvexShape {
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
TriangleShape(const Vector3& point1, const Vector3& point2, const Vector3& point3,
|
||||
TriangleShape(const vec3& point1, const vec3& point2, const vec3& point3,
|
||||
float margin = OBJECT_MARGIN);
|
||||
|
||||
/// Destructor
|
||||
virtual ~TriangleShape();
|
||||
|
||||
/// Return the local bounds of the shape in x, y and z directions.
|
||||
virtual void getLocalBounds(Vector3& min, Vector3& max) const;
|
||||
virtual void getLocalBounds(vec3& min, vec3& max) const;
|
||||
|
||||
/// Set the local scaling vector of the collision shape
|
||||
virtual void setLocalScaling(const Vector3& scaling);
|
||||
virtual void setLocalScaling(const vec3& scaling);
|
||||
|
||||
/// Return the local inertia tensor of the collision shape
|
||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const;
|
||||
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 Transform& transform) const;
|
||||
virtual void computeAABB(AABB& aabb, const etk::Transform3D& transform) const;
|
||||
|
||||
/// Return the raycast test type (front, back, front-back)
|
||||
TriangleRaycastSide getRaycastTestType() const;
|
||||
@ -93,7 +93,7 @@ class TriangleShape : public ConvexShape {
|
||||
void setRaycastTestType(TriangleRaycastSide testType);
|
||||
|
||||
/// Return the coordinates of a given vertex of the triangle
|
||||
Vector3 getVertex(int32_t index) const;
|
||||
vec3 getVertex(int32_t index) const;
|
||||
|
||||
// ---------- Friendship ---------- //
|
||||
|
||||
@ -107,9 +107,9 @@ inline size_t TriangleShape::getSizeInBytes() const {
|
||||
}
|
||||
|
||||
// Return a local support point in a given direction without the object margin
|
||||
inline Vector3 TriangleShape::getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||
inline vec3 TriangleShape::getLocalSupportPointWithoutMargin(const vec3& direction,
|
||||
void** cachedCollisionData) const {
|
||||
Vector3 dotProducts(direction.dot(mPoints[0]), direction.dot(mPoints[1]), direction.dot(mPoints[2]));
|
||||
vec3 dotProducts(direction.dot(mPoints[0]), direction.dot(mPoints[1]), direction.dot(mPoints[2]));
|
||||
return mPoints[dotProducts.getMaxAxis()];
|
||||
}
|
||||
|
||||
@ -119,24 +119,24 @@ inline Vector3 TriangleShape::getLocalSupportPointWithoutMargin(const Vector3& d
|
||||
* @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(Vector3& min, Vector3& max) const {
|
||||
inline void TriangleShape::getLocalBounds(vec3& min, vec3& max) const {
|
||||
|
||||
const Vector3 xAxis(mPoints[0].x, mPoints[1].x, mPoints[2].x);
|
||||
const Vector3 yAxis(mPoints[0].y, mPoints[1].y, mPoints[2].y);
|
||||
const Vector3 zAxis(mPoints[0].z, mPoints[1].z, mPoints[2].z);
|
||||
min.setAllValues(xAxis.getMinValue(), yAxis.getMinValue(), zAxis.getMinValue());
|
||||
max.setAllValues(xAxis.getMaxValue(), yAxis.getMaxValue(), zAxis.getMaxValue());
|
||||
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());
|
||||
min.setValue(xAxis.getMin(), yAxis.getMin(), zAxis.getMin());
|
||||
max.setValue(xAxis.getMax(), yAxis.getMax(), zAxis.getMax());
|
||||
|
||||
min -= Vector3(mMargin, mMargin, mMargin);
|
||||
max += Vector3(mMargin, mMargin, mMargin);
|
||||
min -= vec3(m_margin, m_margin, m_margin);
|
||||
max += vec3(m_margin, m_margin, m_margin);
|
||||
}
|
||||
|
||||
// Set the local scaling vector of the collision shape
|
||||
inline void TriangleShape::setLocalScaling(const Vector3& scaling) {
|
||||
inline void TriangleShape::setLocalScaling(const vec3& scaling) {
|
||||
|
||||
mPoints[0] = (mPoints[0] / mScaling) * scaling;
|
||||
mPoints[1] = (mPoints[1] / mScaling) * scaling;
|
||||
mPoints[2] = (mPoints[2] / mScaling) * scaling;
|
||||
mPoints[0] = (mPoints[0] / m_scaling) * scaling;
|
||||
mPoints[1] = (mPoints[1] / m_scaling) * scaling;
|
||||
mPoints[2] = (mPoints[2] / m_scaling) * scaling;
|
||||
|
||||
CollisionShape::setLocalScaling(scaling);
|
||||
}
|
||||
@ -147,31 +147,31 @@ inline void TriangleShape::setLocalScaling(const Vector3& scaling) {
|
||||
* coordinates
|
||||
* @param mass Mass to use to compute the inertia tensor of the collision shape
|
||||
*/
|
||||
inline void TriangleShape::computeLocalInertiaTensor(Matrix3x3& tensor, float mass) const {
|
||||
tensor.setToZero();
|
||||
inline void TriangleShape::computeLocalInertiaTensor(etk::Matrix3x3& tensor, float mass) const {
|
||||
tensor.setZero();
|
||||
}
|
||||
|
||||
// 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 Transform used to compute the AABB of the collision shape
|
||||
* @param transform etk::Transform3D used to compute the AABB of the collision shape
|
||||
*/
|
||||
inline void TriangleShape::computeAABB(AABB& aabb, const Transform& transform) const {
|
||||
inline void TriangleShape::computeAABB(AABB& aabb, const etk::Transform3D& transform) const {
|
||||
|
||||
const Vector3 worldPoint1 = transform * mPoints[0];
|
||||
const Vector3 worldPoint2 = transform * mPoints[1];
|
||||
const Vector3 worldPoint3 = transform * mPoints[2];
|
||||
const vec3 worldPoint1 = transform * mPoints[0];
|
||||
const vec3 worldPoint2 = transform * mPoints[1];
|
||||
const vec3 worldPoint3 = transform * mPoints[2];
|
||||
|
||||
const Vector3 xAxis(worldPoint1.x, worldPoint2.x, worldPoint3.x);
|
||||
const Vector3 yAxis(worldPoint1.y, worldPoint2.y, worldPoint3.y);
|
||||
const Vector3 zAxis(worldPoint1.z, worldPoint2.z, worldPoint3.z);
|
||||
aabb.setMin(Vector3(xAxis.getMinValue(), yAxis.getMinValue(), zAxis.getMinValue()));
|
||||
aabb.setMax(Vector3(xAxis.getMaxValue(), yAxis.getMaxValue(), zAxis.getMaxValue()));
|
||||
const vec3 xAxis(worldPoint1.x(), worldPoint2.x(), worldPoint3.x());
|
||||
const vec3 yAxis(worldPoint1.y(), worldPoint2.y(), worldPoint3.y());
|
||||
const vec3 zAxis(worldPoint1.z(), worldPoint2.z(), worldPoint3.z());
|
||||
aabb.setMin(vec3(xAxis.getMin(), yAxis.getMin(), zAxis.getMin()));
|
||||
aabb.setMax(vec3(xAxis.getMax(), yAxis.getMax(), zAxis.getMax()));
|
||||
}
|
||||
|
||||
// Return true if a point is inside the collision shape
|
||||
inline bool TriangleShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
|
||||
inline bool TriangleShape::testPointInside(const vec3& localPoint, ProxyShape* proxyShape) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ inline void TriangleShape::setRaycastTestType(TriangleRaycastSide testType) {
|
||||
/**
|
||||
* @param index Index (0 to 2) of a vertex of the triangle
|
||||
*/
|
||||
inline Vector3 TriangleShape::getVertex(int32_t index) const {
|
||||
inline vec3 TriangleShape::getVertex(int32_t index) const {
|
||||
assert(index >= 0 && index < 3);
|
||||
return mPoints[index];
|
||||
}
|
||||
|
@ -53,10 +53,10 @@ namespace reactphysics3d {
|
||||
const float DEFAULT_FRICTION_COEFFICIENT = float(0.3);
|
||||
|
||||
/// Default bounciness factor for a rigid body
|
||||
const float DEFAULT_BOUNCINESS = float(0.5);
|
||||
const float DEFAULT_BOUNCINESS = 0.5f;
|
||||
|
||||
/// Default rolling resistance
|
||||
const float DEFAULT_ROLLING_RESISTANCE = float(0.0);
|
||||
const float DEFAULT_ROLLING_RESISTANCE = 0.0f;
|
||||
|
||||
/// True if the spleeping technique is enabled
|
||||
const bool SPLEEPING_ENABLED = true;
|
||||
@ -68,7 +68,7 @@ namespace reactphysics3d {
|
||||
const float PERSISTENT_CONTACT_DIST_THRESHOLD = float(0.03);
|
||||
|
||||
/// Velocity threshold for contact velocity restitution
|
||||
const float RESTITUTION_VELOCITY_THRESHOLD = float(1.0);
|
||||
const float RESTITUTION_VELOCITY_THRESHOLD = 1.0f;
|
||||
|
||||
/// Number of iterations when solving the velocity constraints of the Sequential Impulse technique
|
||||
const uint32_t DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS = 10;
|
||||
|
@ -15,7 +15,7 @@ const float BallAndSocketJoint::BETA = float(0.2);
|
||||
|
||||
// Constructor
|
||||
BallAndSocketJoint::BallAndSocketJoint(const BallAndSocketJointInfo& jointInfo)
|
||||
: Joint(jointInfo), m_impulse(Vector3(0, 0, 0)) {
|
||||
: Joint(jointInfo), m_impulse(vec3(0, 0, 0)) {
|
||||
|
||||
// Compute the local-space anchor point for each body
|
||||
m_localAnchorPointBody1 = m_body1->getTransform().getInverse() * jointInfo.m_anchorPointWorldSpace;
|
||||
@ -35,10 +35,10 @@ void BallAndSocketJoint::initBeforeSolve(const ConstraintSolverData& constraintS
|
||||
m_indexBody2 = constraintSolverData.mapBodyToConstrainedVelocityIndex.find(m_body2)->second;
|
||||
|
||||
// Get the bodies center of mass and orientations
|
||||
const Vector3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const Vector3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
const vec3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const vec3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const etk::Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const etk::Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
|
||||
// Get the inertia tensor of bodies
|
||||
m_i1 = m_body1->getInertiaTensorInverseWorld();
|
||||
@ -49,25 +49,25 @@ void BallAndSocketJoint::initBeforeSolve(const ConstraintSolverData& constraintS
|
||||
m_r2World = orientationBody2 * m_localAnchorPointBody2;
|
||||
|
||||
// Compute the corresponding skew-symmetric matrices
|
||||
Matrix3x3 skewSymmetricMatrixU1= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
Matrix3x3 skewSymmetricMatrixU2= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU1= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU2= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix)
|
||||
float inverseMassBodies = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
etk::Matrix3x3 massMatrix = etk::Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies) +
|
||||
skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose() +
|
||||
skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
|
||||
// Compute the inverse mass matrix K^-1
|
||||
m_inverseMassMatrix.setToZero();
|
||||
m_inverseMassMatrix.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrix = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
// Compute the bias "b" of the constraint
|
||||
m_biasVector.setToZero();
|
||||
m_biasVector.setZero();
|
||||
if (m_positionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
float biasFactor = (BETA / constraintSolverData.timeStep);
|
||||
m_biasVector = biasFactor * (x2 + m_r2World - x1 - m_r1World);
|
||||
@ -77,7 +77,7 @@ void BallAndSocketJoint::initBeforeSolve(const ConstraintSolverData& constraintS
|
||||
if (!constraintSolverData.isWarmStartingActive) {
|
||||
|
||||
// Reset the accumulated impulse
|
||||
m_impulse.setToZero();
|
||||
m_impulse.setZero();
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,21 +85,21 @@ void BallAndSocketJoint::initBeforeSolve(const ConstraintSolverData& constraintS
|
||||
void BallAndSocketJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the body 1
|
||||
const Vector3 linearImpulseBody1 = -m_impulse;
|
||||
const Vector3 angularImpulseBody1 = m_impulse.cross(m_r1World);
|
||||
const vec3 linearImpulseBody1 = -m_impulse;
|
||||
const vec3 angularImpulseBody1 = m_impulse.cross(m_r1World);
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += m_body1->m_massInverse * linearImpulseBody1;
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the body 2
|
||||
const Vector3 angularImpulseBody2 = -m_impulse.cross(m_r2World);
|
||||
const vec3 angularImpulseBody2 = -m_impulse.cross(m_r2World);
|
||||
|
||||
// Apply the impulse to the body to the body 2
|
||||
v2 += m_body2->m_massInverse * m_impulse;
|
||||
@ -110,28 +110,28 @@ void BallAndSocketJoint::warmstart(const ConstraintSolverData& constraintSolverD
|
||||
void BallAndSocketJoint::solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Compute J*v
|
||||
const Vector3 Jv = v2 + w2.cross(m_r2World) - v1 - w1.cross(m_r1World);
|
||||
const vec3 Jv = v2 + w2.cross(m_r2World) - v1 - w1.cross(m_r1World);
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
const Vector3 deltaLambda = m_inverseMassMatrix * (-Jv - m_biasVector);
|
||||
const vec3 deltaLambda = m_inverseMassMatrix * (-Jv - m_biasVector);
|
||||
m_impulse += deltaLambda;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the body 1
|
||||
const Vector3 linearImpulseBody1 = -deltaLambda;
|
||||
const Vector3 angularImpulseBody1 = deltaLambda.cross(m_r1World);
|
||||
const vec3 linearImpulseBody1 = -deltaLambda;
|
||||
const vec3 angularImpulseBody1 = deltaLambda.cross(m_r1World);
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += m_body1->m_massInverse * linearImpulseBody1;
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the body 2
|
||||
const Vector3 angularImpulseBody2 = -deltaLambda.cross(m_r2World);
|
||||
const vec3 angularImpulseBody2 = -deltaLambda.cross(m_r2World);
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
v2 += m_body2->m_massInverse * deltaLambda;
|
||||
@ -146,10 +146,10 @@ void BallAndSocketJoint::solvePositionConstraint(const ConstraintSolverData& con
|
||||
if (m_positionCorrectionTechnique != NON_LINEAR_GAUSS_SEIDEL) return;
|
||||
|
||||
// Get the bodies center of mass and orientations
|
||||
Vector3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
Vector3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
vec3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
vec3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
etk::Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
etk::Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -164,52 +164,52 @@ void BallAndSocketJoint::solvePositionConstraint(const ConstraintSolverData& con
|
||||
m_r2World = q2 * m_localAnchorPointBody2;
|
||||
|
||||
// Compute the corresponding skew-symmetric matrices
|
||||
Matrix3x3 skewSymmetricMatrixU1= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
Matrix3x3 skewSymmetricMatrixU2= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU1= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU2= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
|
||||
// Recompute the inverse mass matrix K=J^TM^-1J of of the 3 translation constraints
|
||||
float inverseMassBodies = inverseMassBody1 + inverseMassBody2;
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
etk::Matrix3x3 massMatrix = etk::Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies) +
|
||||
skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose() +
|
||||
skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
m_inverseMassMatrix.setToZero();
|
||||
m_inverseMassMatrix.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrix = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
// Compute the constraint error (value of the C(x) function)
|
||||
const Vector3 constraintError = (x2 + m_r2World - x1 - m_r1World);
|
||||
const vec3 constraintError = (x2 + m_r2World - x1 - m_r1World);
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
// TODO : Do not solve the system by computing the inverse each time and multiplying with the
|
||||
// right-hand side vector but instead use a method to directly solve the linear system.
|
||||
const Vector3 lambda = m_inverseMassMatrix * (-constraintError);
|
||||
const vec3 lambda = m_inverseMassMatrix * (-constraintError);
|
||||
|
||||
// Compute the impulse of body 1
|
||||
const Vector3 linearImpulseBody1 = -lambda;
|
||||
const Vector3 angularImpulseBody1 = lambda.cross(m_r1World);
|
||||
const vec3 linearImpulseBody1 = -lambda;
|
||||
const vec3 angularImpulseBody1 = lambda.cross(m_r1World);
|
||||
|
||||
// Compute the pseudo velocity of body 1
|
||||
const Vector3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
const Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
const vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body center of mass and orientation of body 1
|
||||
x1 += v1;
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse of body 2
|
||||
const Vector3 angularImpulseBody2 = -lambda.cross(m_r2World);
|
||||
const vec3 angularImpulseBody2 = -lambda.cross(m_r2World);
|
||||
|
||||
// Compute the pseudo velocity of body 2
|
||||
const Vector3 v2 = inverseMassBody2 * lambda;
|
||||
const Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 v2 = inverseMassBody2 * lambda;
|
||||
const vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
x2 += v2;
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ struct BallAndSocketJointInfo : public JointInfo {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point (in world-space coordinates)
|
||||
Vector3 m_anchorPointWorldSpace;
|
||||
vec3 m_anchorPointWorldSpace;
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
@ -33,7 +33,7 @@ struct BallAndSocketJointInfo : public JointInfo {
|
||||
* coordinates
|
||||
*/
|
||||
BallAndSocketJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace)
|
||||
const vec3& initAnchorPointWorldSpace)
|
||||
: JointInfo(rigidBody1, rigidBody2, BALLSOCKETJOINT),
|
||||
m_anchorPointWorldSpace(initAnchorPointWorldSpace) {}
|
||||
};
|
||||
@ -56,31 +56,31 @@ class BallAndSocketJoint : public Joint {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point of body 1 (in local-space coordinates of body 1)
|
||||
Vector3 m_localAnchorPointBody1;
|
||||
vec3 m_localAnchorPointBody1;
|
||||
|
||||
/// Anchor point of body 2 (in local-space coordinates of body 2)
|
||||
Vector3 m_localAnchorPointBody2;
|
||||
vec3 m_localAnchorPointBody2;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
Vector3 m_r1World;
|
||||
vec3 m_r1World;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
Vector3 m_r2World;
|
||||
vec3 m_r2World;
|
||||
|
||||
/// Inertia tensor of body 1 (in world-space coordinates)
|
||||
Matrix3x3 m_i1;
|
||||
etk::Matrix3x3 m_i1;
|
||||
|
||||
/// Inertia tensor of body 2 (in world-space coordinates)
|
||||
Matrix3x3 m_i2;
|
||||
etk::Matrix3x3 m_i2;
|
||||
|
||||
/// Bias vector for the constraint
|
||||
Vector3 m_biasVector;
|
||||
vec3 m_biasVector;
|
||||
|
||||
/// Inverse mass matrix K=JM^-1J^-t of the constraint
|
||||
Matrix3x3 m_inverseMassMatrix;
|
||||
etk::Matrix3x3 m_inverseMassMatrix;
|
||||
|
||||
/// Accumulated impulse
|
||||
Vector3 m_impulse;
|
||||
vec3 m_impulse;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
|
@ -26,8 +26,8 @@ ContactPoint::ContactPoint(const ContactPointInfo& contactInfo)
|
||||
contactInfo.localPoint2),
|
||||
mIsRestingContact(false) {
|
||||
|
||||
m_frictionVectors[0] = Vector3(0, 0, 0);
|
||||
m_frictionVectors[1] = Vector3(0, 0, 0);
|
||||
m_frictionVectors[0] = vec3(0, 0, 0);
|
||||
m_frictionVectors[1] = vec3(0, 0, 0);
|
||||
|
||||
assert(mPenetrationDepth > 0.0);
|
||||
|
||||
|
@ -45,23 +45,23 @@ struct ContactPointInfo {
|
||||
const CollisionShape* collisionShape2;
|
||||
|
||||
/// Normalized normal vector of the collision contact in world space
|
||||
Vector3 normal;
|
||||
vec3 normal;
|
||||
|
||||
/// Penetration depth of the contact
|
||||
float penetrationDepth;
|
||||
|
||||
/// Contact point of body 1 in local space of body 1
|
||||
Vector3 localPoint1;
|
||||
vec3 localPoint1;
|
||||
|
||||
/// Contact point of body 2 in local space of body 2
|
||||
Vector3 localPoint2;
|
||||
vec3 localPoint2;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
ContactPointInfo(ProxyShape* proxyShape1, ProxyShape* proxyShape2, const CollisionShape* collShape1,
|
||||
const CollisionShape* collShape2, const Vector3& normal, float penetrationDepth,
|
||||
const Vector3& localPoint1, const Vector3& localPoint2)
|
||||
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) {
|
||||
@ -87,28 +87,28 @@ class ContactPoint {
|
||||
CollisionBody* m_body2;
|
||||
|
||||
/// Normalized normal vector of the contact (from body1 toward body2) in world space
|
||||
const Vector3 mNormal;
|
||||
const vec3 mNormal;
|
||||
|
||||
/// Penetration depth
|
||||
float mPenetrationDepth;
|
||||
|
||||
/// Contact point on body 1 in local space of body 1
|
||||
const Vector3 mLocalPointOnBody1;
|
||||
const vec3 mLocalPointOnBody1;
|
||||
|
||||
/// Contact point on body 2 in local space of body 2
|
||||
const Vector3 mLocalPointOnBody2;
|
||||
const vec3 mLocalPointOnBody2;
|
||||
|
||||
/// Contact point on body 1 in world space
|
||||
Vector3 m_worldPointOnBody1;
|
||||
vec3 m_worldPointOnBody1;
|
||||
|
||||
/// Contact point on body 2 in world space
|
||||
Vector3 m_worldPointOnBody2;
|
||||
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
|
||||
Vector3 m_frictionVectors[2];
|
||||
vec3 m_frictionVectors[2];
|
||||
|
||||
/// Cached penetration impulse
|
||||
float mPenetrationImpulse;
|
||||
@ -120,7 +120,7 @@ class ContactPoint {
|
||||
float m_frictionImpulse2;
|
||||
|
||||
/// Cached rolling resistance impulse
|
||||
Vector3 m_rollingResistanceImpulse;
|
||||
vec3 m_rollingResistanceImpulse;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -147,22 +147,22 @@ class ContactPoint {
|
||||
CollisionBody* getBody2() const;
|
||||
|
||||
/// Return the normal vector of the contact
|
||||
Vector3 getNormal() const;
|
||||
vec3 getNormal() const;
|
||||
|
||||
/// Set the penetration depth of the contact
|
||||
void setPenetrationDepth(float penetrationDepth);
|
||||
|
||||
/// Return the contact local point on body 1
|
||||
Vector3 getLocalPointOnBody1() const;
|
||||
vec3 getLocalPointOnBody1() const;
|
||||
|
||||
/// Return the contact local point on body 2
|
||||
Vector3 getLocalPointOnBody2() const;
|
||||
vec3 getLocalPointOnBody2() const;
|
||||
|
||||
/// Return the contact world point on body 1
|
||||
Vector3 getWorldPointOnBody1() const;
|
||||
vec3 getWorldPointOnBody1() const;
|
||||
|
||||
/// Return the contact world point on body 2
|
||||
Vector3 getWorldPointOnBody2() const;
|
||||
vec3 getWorldPointOnBody2() const;
|
||||
|
||||
/// Return the cached penetration impulse
|
||||
float getPenetrationImpulse() const;
|
||||
@ -174,7 +174,7 @@ class ContactPoint {
|
||||
float getFrictionImpulse2() const;
|
||||
|
||||
/// Return the cached rolling resistance impulse
|
||||
Vector3 getRollingResistanceImpulse() const;
|
||||
vec3 getRollingResistanceImpulse() const;
|
||||
|
||||
/// Set the cached penetration impulse
|
||||
void setPenetrationImpulse(float impulse);
|
||||
@ -186,13 +186,13 @@ class ContactPoint {
|
||||
void setFrictionImpulse2(float impulse);
|
||||
|
||||
/// Set the cached rolling resistance impulse
|
||||
void setRollingResistanceImpulse(const Vector3& impulse);
|
||||
void setRollingResistanceImpulse(const vec3& impulse);
|
||||
|
||||
/// Set the contact world point on body 1
|
||||
void setWorldPointOnBody1(const Vector3& worldPoint);
|
||||
void setWorldPointOnBody1(const vec3& worldPoint);
|
||||
|
||||
/// Set the contact world point on body 2
|
||||
void setWorldPointOnBody2(const Vector3& worldPoint);
|
||||
void setWorldPointOnBody2(const vec3& worldPoint);
|
||||
|
||||
/// Return true if the contact is a resting contact
|
||||
bool getIsRestingContact() const;
|
||||
@ -201,16 +201,16 @@ class ContactPoint {
|
||||
void setIsRestingContact(bool isRestingContact);
|
||||
|
||||
/// Get the first friction vector
|
||||
Vector3 getFrictionVector1() const;
|
||||
vec3 getFrictionVector1() const;
|
||||
|
||||
/// Set the first friction vector
|
||||
void setFrictionVector1(const Vector3& frictionVector1);
|
||||
void setFrictionVector1(const vec3& frictionVector1);
|
||||
|
||||
/// Get the second friction vector
|
||||
Vector3 getFrictionVector2() const;
|
||||
vec3 getFrictionvec2() const;
|
||||
|
||||
/// Set the second friction vector
|
||||
void setFrictionVector2(const Vector3& frictionVector2);
|
||||
void setFrictionvec2(const vec3& frictionvec2);
|
||||
|
||||
/// Return the penetration depth
|
||||
float getPenetrationDepth() const;
|
||||
@ -230,7 +230,7 @@ inline CollisionBody* ContactPoint::getBody2() const {
|
||||
}
|
||||
|
||||
// Return the normal vector of the contact
|
||||
inline Vector3 ContactPoint::getNormal() const {
|
||||
inline vec3 ContactPoint::getNormal() const {
|
||||
return mNormal;
|
||||
}
|
||||
|
||||
@ -240,22 +240,22 @@ inline void ContactPoint::setPenetrationDepth(float penetrationDepth) {
|
||||
}
|
||||
|
||||
// Return the contact point on body 1
|
||||
inline Vector3 ContactPoint::getLocalPointOnBody1() const {
|
||||
inline vec3 ContactPoint::getLocalPointOnBody1() const {
|
||||
return mLocalPointOnBody1;
|
||||
}
|
||||
|
||||
// Return the contact point on body 2
|
||||
inline Vector3 ContactPoint::getLocalPointOnBody2() const {
|
||||
inline vec3 ContactPoint::getLocalPointOnBody2() const {
|
||||
return mLocalPointOnBody2;
|
||||
}
|
||||
|
||||
// Return the contact world point on body 1
|
||||
inline Vector3 ContactPoint::getWorldPointOnBody1() const {
|
||||
inline vec3 ContactPoint::getWorldPointOnBody1() const {
|
||||
return m_worldPointOnBody1;
|
||||
}
|
||||
|
||||
// Return the contact world point on body 2
|
||||
inline Vector3 ContactPoint::getWorldPointOnBody2() const {
|
||||
inline vec3 ContactPoint::getWorldPointOnBody2() const {
|
||||
return m_worldPointOnBody2;
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ inline float ContactPoint::getFrictionImpulse2() const {
|
||||
}
|
||||
|
||||
// Return the cached rolling resistance impulse
|
||||
inline Vector3 ContactPoint::getRollingResistanceImpulse() const {
|
||||
inline vec3 ContactPoint::getRollingResistanceImpulse() const {
|
||||
return m_rollingResistanceImpulse;
|
||||
}
|
||||
|
||||
@ -295,17 +295,17 @@ inline void ContactPoint::setFrictionImpulse2(float impulse) {
|
||||
}
|
||||
|
||||
// Set the cached rolling resistance impulse
|
||||
inline void ContactPoint::setRollingResistanceImpulse(const Vector3& impulse) {
|
||||
inline void ContactPoint::setRollingResistanceImpulse(const vec3& impulse) {
|
||||
m_rollingResistanceImpulse = impulse;
|
||||
}
|
||||
|
||||
// Set the contact world point on body 1
|
||||
inline void ContactPoint::setWorldPointOnBody1(const Vector3& worldPoint) {
|
||||
inline void ContactPoint::setWorldPointOnBody1(const vec3& worldPoint) {
|
||||
m_worldPointOnBody1 = worldPoint;
|
||||
}
|
||||
|
||||
// Set the contact world point on body 2
|
||||
inline void ContactPoint::setWorldPointOnBody2(const Vector3& worldPoint) {
|
||||
inline void ContactPoint::setWorldPointOnBody2(const vec3& worldPoint) {
|
||||
m_worldPointOnBody2 = worldPoint;
|
||||
}
|
||||
|
||||
@ -320,23 +320,23 @@ inline void ContactPoint::setIsRestingContact(bool isRestingContact) {
|
||||
}
|
||||
|
||||
// Get the first friction vector
|
||||
inline Vector3 ContactPoint::getFrictionVector1() const {
|
||||
inline vec3 ContactPoint::getFrictionVector1() const {
|
||||
return m_frictionVectors[0];
|
||||
}
|
||||
|
||||
// Set the first friction vector
|
||||
inline void ContactPoint::setFrictionVector1(const Vector3& frictionVector1) {
|
||||
inline void ContactPoint::setFrictionVector1(const vec3& frictionVector1) {
|
||||
m_frictionVectors[0] = frictionVector1;
|
||||
}
|
||||
|
||||
// Get the second friction vector
|
||||
inline Vector3 ContactPoint::getFrictionVector2() const {
|
||||
inline vec3 ContactPoint::getFrictionvec2() const {
|
||||
return m_frictionVectors[1];
|
||||
}
|
||||
|
||||
// Set the second friction vector
|
||||
inline void ContactPoint::setFrictionVector2(const Vector3& frictionVector2) {
|
||||
m_frictionVectors[1] = frictionVector2;
|
||||
inline void ContactPoint::setFrictionvec2(const vec3& frictionvec2) {
|
||||
m_frictionVectors[1] = frictionvec2;
|
||||
}
|
||||
|
||||
// Return the penetration depth of the contact
|
||||
|
@ -18,8 +18,8 @@ FixedJoint::FixedJoint(const FixedJointInfo& jointInfo)
|
||||
: Joint(jointInfo), m_impulseTranslation(0, 0, 0), m_impulseRotation(0, 0, 0) {
|
||||
|
||||
// Compute the local-space anchor point for each body
|
||||
const Transform& transform1 = m_body1->getTransform();
|
||||
const Transform& transform2 = m_body2->getTransform();
|
||||
const etk::Transform3D& transform1 = m_body1->getTransform();
|
||||
const etk::Transform3D& transform2 = m_body2->getTransform();
|
||||
m_localAnchorPointBody1 = transform1.getInverse() * jointInfo.m_anchorPointWorldSpace;
|
||||
m_localAnchorPointBody2 = transform2.getInverse() * jointInfo.m_anchorPointWorldSpace;
|
||||
|
||||
@ -43,10 +43,10 @@ void FixedJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
m_indexBody2 = constraintSolverData.mapBodyToConstrainedVelocityIndex.find(m_body2)->second;
|
||||
|
||||
// Get the bodies positions and orientations
|
||||
const Vector3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const Vector3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
const vec3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const vec3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const etk::Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const etk::Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
|
||||
// Get the inertia tensor of bodies
|
||||
m_i1 = m_body1->getInertiaTensorInverseWorld();
|
||||
@ -57,26 +57,26 @@ void FixedJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
m_r2World = orientationBody2 * m_localAnchorPointBody2;
|
||||
|
||||
// Compute the corresponding skew-symmetric matrices
|
||||
Matrix3x3 skewSymmetricMatrixU1= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
Matrix3x3 skewSymmetricMatrixU2= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU1= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU2= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix) for the 3 translation constraints
|
||||
float inverseMassBodies = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies) +
|
||||
skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose() +
|
||||
skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
etk::Matrix3x3 massMatrix = etk::Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies)
|
||||
+ skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose()
|
||||
+ skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
|
||||
// Compute the inverse mass matrix K^-1 for the 3 translation constraints
|
||||
m_inverseMassMatrixTranslation.setToZero();
|
||||
m_inverseMassMatrixTranslation.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
// Compute the bias "b" of the constraint for the 3 translation constraints
|
||||
float biasFactor = (BETA / constraintSolverData.timeStep);
|
||||
m_biasTranslation.setToZero();
|
||||
m_biasTranslation.setZero();
|
||||
if (m_positionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
m_biasTranslation = biasFactor * (x2 + m_r2World - x1 - m_r1World);
|
||||
}
|
||||
@ -89,11 +89,11 @@ void FixedJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
}
|
||||
|
||||
// Compute the bias "b" for the 3 rotation constraints
|
||||
m_biasRotation.setToZero();
|
||||
m_biasRotation.setZero();
|
||||
if (m_positionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
Quaternion currentOrientationDifference = orientationBody2 * orientationBody1.getInverse();
|
||||
etk::Quaternion currentOrientationDifference = orientationBody2 * orientationBody1.getInverse();
|
||||
currentOrientationDifference.normalize();
|
||||
const Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
const etk::Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
m_biasRotation = biasFactor * float(2.0) * qError.getVectorV();
|
||||
}
|
||||
|
||||
@ -101,8 +101,8 @@ void FixedJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
if (!constraintSolverData.isWarmStartingActive) {
|
||||
|
||||
// Reset the accumulated impulses
|
||||
m_impulseTranslation.setToZero();
|
||||
m_impulseRotation.setToZero();
|
||||
m_impulseTranslation.setZero();
|
||||
m_impulseRotation.setZero();
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,18 +110,18 @@ void FixedJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
void FixedJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Get the inverse mass of the bodies
|
||||
const float inverseMassBody1 = m_body1->m_massInverse;
|
||||
const float inverseMassBody2 = m_body2->m_massInverse;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints for body 1
|
||||
Vector3 linearImpulseBody1 = -m_impulseTranslation;
|
||||
Vector3 angularImpulseBody1 = m_impulseTranslation.cross(m_r1World);
|
||||
vec3 linearImpulseBody1 = -m_impulseTranslation;
|
||||
vec3 angularImpulseBody1 = m_impulseTranslation.cross(m_r1World);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints for body 1
|
||||
angularImpulseBody1 += -m_impulseRotation;
|
||||
@ -131,7 +131,7 @@ void FixedJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints for body 2
|
||||
Vector3 angularImpulseBody2 = -m_impulseTranslation.cross(m_r2World);
|
||||
vec3 angularImpulseBody2 = -m_impulseTranslation.cross(m_r2World);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints for body 2
|
||||
angularImpulseBody2 += m_impulseRotation;
|
||||
@ -145,10 +145,10 @@ void FixedJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
void FixedJoint::solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Get the inverse mass of the bodies
|
||||
float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -157,23 +157,23 @@ void FixedJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
||||
// --------------- Translation Constraints --------------- //
|
||||
|
||||
// Compute J*v for the 3 translation constraints
|
||||
const Vector3 JvTranslation = v2 + w2.cross(m_r2World) - v1 - w1.cross(m_r1World);
|
||||
const vec3 JvTranslation = v2 + w2.cross(m_r2World) - v1 - w1.cross(m_r1World);
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
const Vector3 deltaLambda = m_inverseMassMatrixTranslation *
|
||||
const vec3 deltaLambda = m_inverseMassMatrixTranslation *
|
||||
(-JvTranslation - m_biasTranslation);
|
||||
m_impulseTranslation += deltaLambda;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for body 1
|
||||
const Vector3 linearImpulseBody1 = -deltaLambda;
|
||||
Vector3 angularImpulseBody1 = deltaLambda.cross(m_r1World);
|
||||
const vec3 linearImpulseBody1 = -deltaLambda;
|
||||
vec3 angularImpulseBody1 = deltaLambda.cross(m_r1World);
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for body 2
|
||||
const Vector3 angularImpulseBody2 = -deltaLambda.cross(m_r2World);
|
||||
const vec3 angularImpulseBody2 = -deltaLambda.cross(m_r2World);
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
v2 += inverseMassBody2 * deltaLambda;
|
||||
@ -182,10 +182,10 @@ void FixedJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
||||
// --------------- Rotation Constraints --------------- //
|
||||
|
||||
// Compute J*v for the 3 rotation constraints
|
||||
const Vector3 JvRotation = w2 - w1;
|
||||
const vec3 JvRotation = w2 - w1;
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 3 rotation constraints
|
||||
Vector3 deltaLambda2 = m_inverseMassMatrixRotation * (-JvRotation - m_biasRotation);
|
||||
vec3 deltaLambda2 = m_inverseMassMatrixRotation * (-JvRotation - m_biasRotation);
|
||||
m_impulseRotation += deltaLambda2;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints for body 1
|
||||
@ -206,10 +206,10 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
if (m_positionCorrectionTechnique != NON_LINEAR_GAUSS_SEIDEL) return;
|
||||
|
||||
// Get the bodies positions and orientations
|
||||
Vector3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
Vector3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
vec3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
vec3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
etk::Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
etk::Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -224,52 +224,52 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
m_r2World = q2 * m_localAnchorPointBody2;
|
||||
|
||||
// Compute the corresponding skew-symmetric matrices
|
||||
Matrix3x3 skewSymmetricMatrixU1= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
Matrix3x3 skewSymmetricMatrixU2= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU1= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU2= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
|
||||
// --------------- Translation Constraints --------------- //
|
||||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix) for the 3 translation constraints
|
||||
float inverseMassBodies = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies) +
|
||||
skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose() +
|
||||
skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
m_inverseMassMatrixTranslation.setToZero();
|
||||
etk::Matrix3x3 massMatrix = etk::Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies)
|
||||
+ skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose()
|
||||
+ skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
m_inverseMassMatrixTranslation.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
// Compute position error for the 3 translation constraints
|
||||
const Vector3 errorTranslation = x2 + m_r2World - x1 - m_r1World;
|
||||
const vec3 errorTranslation = x2 + m_r2World - x1 - m_r1World;
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
const Vector3 lambdaTranslation = m_inverseMassMatrixTranslation * (-errorTranslation);
|
||||
const vec3 lambdaTranslation = m_inverseMassMatrixTranslation * (-errorTranslation);
|
||||
|
||||
// Compute the impulse of body 1
|
||||
Vector3 linearImpulseBody1 = -lambdaTranslation;
|
||||
Vector3 angularImpulseBody1 = lambdaTranslation.cross(m_r1World);
|
||||
vec3 linearImpulseBody1 = -lambdaTranslation;
|
||||
vec3 angularImpulseBody1 = lambdaTranslation.cross(m_r1World);
|
||||
|
||||
// Compute the pseudo velocity of body 1
|
||||
const Vector3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
x1 += v1;
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse of body 2
|
||||
Vector3 angularImpulseBody2 = -lambdaTranslation.cross(m_r2World);
|
||||
vec3 angularImpulseBody2 = -lambdaTranslation.cross(m_r2World);
|
||||
|
||||
// Compute the pseudo velocity of body 2
|
||||
const Vector3 v2 = inverseMassBody2 * lambdaTranslation;
|
||||
Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 v2 = inverseMassBody2 * lambdaTranslation;
|
||||
vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
x2 += v2;
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
|
||||
// --------------- Rotation Constraints --------------- //
|
||||
@ -282,13 +282,13 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
}
|
||||
|
||||
// Compute the position error for the 3 rotation constraints
|
||||
Quaternion currentOrientationDifference = q2 * q1.getInverse();
|
||||
etk::Quaternion currentOrientationDifference = q2 * q1.getInverse();
|
||||
currentOrientationDifference.normalize();
|
||||
const Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
const Vector3 errorRotation = float(2.0) * qError.getVectorV();
|
||||
const etk::Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
const vec3 errorRotation = float(2.0) * qError.getVectorV();
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 3 rotation constraints
|
||||
Vector3 lambdaRotation = m_inverseMassMatrixRotation * (-errorRotation);
|
||||
vec3 lambdaRotation = m_inverseMassMatrixRotation * (-errorRotation);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints of body 1
|
||||
angularImpulseBody1 = -lambdaRotation;
|
||||
@ -297,14 +297,14 @@ void FixedJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the pseudo velocity of body 2
|
||||
w2 = m_i2 * lambdaRotation;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ struct FixedJointInfo : public JointInfo {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point (in world-space coordinates)
|
||||
Vector3 m_anchorPointWorldSpace;
|
||||
vec3 m_anchorPointWorldSpace;
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
@ -33,7 +33,7 @@ struct FixedJointInfo : public JointInfo {
|
||||
* world-space coordinates
|
||||
*/
|
||||
FixedJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace)
|
||||
const vec3& initAnchorPointWorldSpace)
|
||||
: JointInfo(rigidBody1, rigidBody2, FIXEDJOINT),
|
||||
m_anchorPointWorldSpace(initAnchorPointWorldSpace){}
|
||||
};
|
||||
@ -55,43 +55,43 @@ class FixedJoint : public Joint {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point of body 1 (in local-space coordinates of body 1)
|
||||
Vector3 m_localAnchorPointBody1;
|
||||
vec3 m_localAnchorPointBody1;
|
||||
|
||||
/// Anchor point of body 2 (in local-space coordinates of body 2)
|
||||
Vector3 m_localAnchorPointBody2;
|
||||
vec3 m_localAnchorPointBody2;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
Vector3 m_r1World;
|
||||
vec3 m_r1World;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
Vector3 m_r2World;
|
||||
vec3 m_r2World;
|
||||
|
||||
/// Inertia tensor of body 1 (in world-space coordinates)
|
||||
Matrix3x3 m_i1;
|
||||
etk::Matrix3x3 m_i1;
|
||||
|
||||
/// Inertia tensor of body 2 (in world-space coordinates)
|
||||
Matrix3x3 m_i2;
|
||||
etk::Matrix3x3 m_i2;
|
||||
|
||||
/// Accumulated impulse for the 3 translation constraints
|
||||
Vector3 m_impulseTranslation;
|
||||
vec3 m_impulseTranslation;
|
||||
|
||||
/// Accumulate impulse for the 3 rotation constraints
|
||||
Vector3 m_impulseRotation;
|
||||
vec3 m_impulseRotation;
|
||||
|
||||
/// Inverse mass matrix K=JM^-1J^-t of the 3 translation constraints (3x3 matrix)
|
||||
Matrix3x3 m_inverseMassMatrixTranslation;
|
||||
etk::Matrix3x3 m_inverseMassMatrixTranslation;
|
||||
|
||||
/// Inverse mass matrix K=JM^-1J^-t of the 3 rotation constraints (3x3 matrix)
|
||||
Matrix3x3 m_inverseMassMatrixRotation;
|
||||
etk::Matrix3x3 m_inverseMassMatrixRotation;
|
||||
|
||||
/// Bias vector for the 3 translation constraints
|
||||
Vector3 m_biasTranslation;
|
||||
vec3 m_biasTranslation;
|
||||
|
||||
/// Bias vector for the 3 rotation constraints
|
||||
Vector3 m_biasRotation;
|
||||
vec3 m_biasRotation;
|
||||
|
||||
/// Inverse of the initial orientation difference between the two bodies
|
||||
Quaternion m_initOrientationDifferenceInv;
|
||||
etk::Quaternion m_initOrientationDifferenceInv;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
|
@ -27,8 +27,8 @@ HingeJoint::HingeJoint(const HingeJointInfo& jointInfo)
|
||||
assert(mUpperLimit >= 0 && mUpperLimit <= 2.0 * PI);
|
||||
|
||||
// Compute the local-space anchor point for each body
|
||||
Transform transform1 = m_body1->getTransform();
|
||||
Transform transform2 = m_body2->getTransform();
|
||||
etk::Transform3D transform1 = m_body1->getTransform();
|
||||
etk::Transform3D transform2 = m_body2->getTransform();
|
||||
m_localAnchorPointBody1 = transform1.getInverse() * jointInfo.m_anchorPointWorldSpace;
|
||||
m_localAnchorPointBody2 = transform2.getInverse() * jointInfo.m_anchorPointWorldSpace;
|
||||
|
||||
@ -58,10 +58,10 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
m_indexBody2 = constraintSolverData.mapBodyToConstrainedVelocityIndex.find(m_body2)->second;
|
||||
|
||||
// Get the bodies positions and orientations
|
||||
const Vector3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const Vector3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
const vec3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const vec3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const etk::Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const etk::Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
|
||||
// Get the inertia tensor of bodies
|
||||
m_i1 = m_body1->getInertiaTensorInverseWorld();
|
||||
@ -90,42 +90,42 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
|
||||
// Compute vectors needed in the Jacobian
|
||||
mA1 = orientationBody1 * mHingeLocalAxisBody1;
|
||||
Vector3 a2 = orientationBody2 * mHingeLocalAxisBody2;
|
||||
vec3 a2 = orientationBody2 * mHingeLocalAxisBody2;
|
||||
mA1.normalize();
|
||||
a2.normalize();
|
||||
const Vector3 b2 = a2.getOneUnitOrthogonalVector();
|
||||
const Vector3 c2 = a2.cross(b2);
|
||||
const vec3 b2 = a2.getOneUnitOrthogonalVector();
|
||||
const vec3 c2 = a2.cross(b2);
|
||||
mB2CrossA1 = b2.cross(mA1);
|
||||
mC2CrossA1 = c2.cross(mA1);
|
||||
|
||||
// Compute the corresponding skew-symmetric matrices
|
||||
Matrix3x3 skewSymmetricMatrixU1= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
Matrix3x3 skewSymmetricMatrixU2= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU1= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU2= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
|
||||
// Compute the inverse mass matrix K=JM^-1J^t for the 3 translation constraints (3x3 matrix)
|
||||
float inverseMassBodies = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
etk::Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies) +
|
||||
skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose() +
|
||||
skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
m_inverseMassMatrixTranslation.setToZero();
|
||||
m_inverseMassMatrixTranslation.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
// Compute the bias "b" of the translation constraints
|
||||
mBTranslation.setToZero();
|
||||
mBTranslation.setZero();
|
||||
float biasFactor = (BETA / constraintSolverData.timeStep);
|
||||
if (m_positionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
mBTranslation = biasFactor * (x2 + m_r2World - x1 - m_r1World);
|
||||
}
|
||||
|
||||
// Compute the inverse mass matrix K=JM^-1J^t for the 2 rotation constraints (2x2 matrix)
|
||||
Vector3 I1B2CrossA1 = m_i1 * mB2CrossA1;
|
||||
Vector3 I1C2CrossA1 = m_i1 * mC2CrossA1;
|
||||
Vector3 I2B2CrossA1 = m_i2 * mB2CrossA1;
|
||||
Vector3 I2C2CrossA1 = m_i2 * mC2CrossA1;
|
||||
vec3 I1B2CrossA1 = m_i1 * mB2CrossA1;
|
||||
vec3 I1C2CrossA1 = m_i1 * mC2CrossA1;
|
||||
vec3 I2B2CrossA1 = m_i2 * mB2CrossA1;
|
||||
vec3 I2C2CrossA1 = m_i2 * mC2CrossA1;
|
||||
const float el11 = mB2CrossA1.dot(I1B2CrossA1) +
|
||||
mB2CrossA1.dot(I2B2CrossA1);
|
||||
const float el12 = mB2CrossA1.dot(I1C2CrossA1) +
|
||||
@ -134,24 +134,24 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
mC2CrossA1.dot(I2B2CrossA1);
|
||||
const float el22 = mC2CrossA1.dot(I1C2CrossA1) +
|
||||
mC2CrossA1.dot(I2C2CrossA1);
|
||||
const Matrix2x2 matrixKRotation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixRotation.setToZero();
|
||||
const etk::Matrix2x2 matrixKRotation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixRotation.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixRotation = matrixKRotation.getInverse();
|
||||
}
|
||||
|
||||
// Compute the bias "b" of the rotation constraints
|
||||
mBRotation.setToZero();
|
||||
mBRotation.setZero();
|
||||
if (m_positionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
mBRotation = biasFactor * Vector2(mA1.dot(b2), mA1.dot(c2));
|
||||
mBRotation = biasFactor * vec2(mA1.dot(b2), mA1.dot(c2));
|
||||
}
|
||||
|
||||
// If warm-starting is not enabled
|
||||
if (!constraintSolverData.isWarmStartingActive) {
|
||||
|
||||
// Reset all the accumulated impulses
|
||||
m_impulseTranslation.setToZero();
|
||||
m_impulseRotation.setToZero();
|
||||
m_impulseTranslation.setZero();
|
||||
m_impulseRotation.setZero();
|
||||
m_impulseLowerLimit = 0.0;
|
||||
m_impulseUpperLimit = 0.0;
|
||||
m_impulseMotor = 0.0;
|
||||
@ -163,7 +163,7 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the limits and motor (1x1 matrix)
|
||||
m_inverseMassMatrixLimitMotor = mA1.dot(m_i1 * mA1) + mA1.dot(m_i2 * mA1);
|
||||
m_inverseMassMatrixLimitMotor = (m_inverseMassMatrixLimitMotor > 0.0) ?
|
||||
float(1.0) / m_inverseMassMatrixLimitMotor : float(0.0);
|
||||
1.0f / m_inverseMassMatrixLimitMotor : 0.0f;
|
||||
|
||||
if (mIsLimitEnabled) {
|
||||
|
||||
@ -186,27 +186,27 @@ void HingeJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDat
|
||||
void HingeJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
const float inverseMassBody1 = m_body1->m_massInverse;
|
||||
const float inverseMassBody2 = m_body2->m_massInverse;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 rotation constraints
|
||||
Vector3 rotationImpulse = -mB2CrossA1 * m_impulseRotation.x - mC2CrossA1 * m_impulseRotation.y;
|
||||
vec3 rotationImpulse = -mB2CrossA1 * m_impulseRotation.x() - mC2CrossA1 * m_impulseRotation.y();
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower and upper limits constraints
|
||||
const Vector3 limitsImpulse = (m_impulseUpperLimit - m_impulseLowerLimit) * mA1;
|
||||
const vec3 limitsImpulse = (m_impulseUpperLimit - m_impulseLowerLimit) * mA1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor constraint
|
||||
const Vector3 motorImpulse = -m_impulseMotor * mA1;
|
||||
const vec3 motorImpulse = -m_impulseMotor * mA1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints of body 1
|
||||
Vector3 linearImpulseBody1 = -m_impulseTranslation;
|
||||
Vector3 angularImpulseBody1 = m_impulseTranslation.cross(m_r1World);
|
||||
vec3 linearImpulseBody1 = -m_impulseTranslation;
|
||||
vec3 angularImpulseBody1 = m_impulseTranslation.cross(m_r1World);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 rotation constraints of body 1
|
||||
angularImpulseBody1 += rotationImpulse;
|
||||
@ -222,7 +222,7 @@ void HingeJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 translation constraints of body 2
|
||||
Vector3 angularImpulseBody2 = -m_impulseTranslation.cross(m_r2World);
|
||||
vec3 angularImpulseBody2 = -m_impulseTranslation.cross(m_r2World);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 rotation constraints of body 2
|
||||
angularImpulseBody2 += -rotationImpulse;
|
||||
@ -242,10 +242,10 @@ void HingeJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -254,23 +254,23 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
||||
// --------------- Translation Constraints --------------- //
|
||||
|
||||
// Compute J*v
|
||||
const Vector3 JvTranslation = v2 + w2.cross(m_r2World) - v1 - w1.cross(m_r1World);
|
||||
const vec3 JvTranslation = v2 + w2.cross(m_r2World) - v1 - w1.cross(m_r1World);
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
const Vector3 deltaLambdaTranslation = m_inverseMassMatrixTranslation *
|
||||
const vec3 deltaLambdaTranslation = m_inverseMassMatrixTranslation *
|
||||
(-JvTranslation - mBTranslation);
|
||||
m_impulseTranslation += deltaLambdaTranslation;
|
||||
|
||||
// Compute the impulse P=J^T * lambda of body 1
|
||||
const Vector3 linearImpulseBody1 = -deltaLambdaTranslation;
|
||||
Vector3 angularImpulseBody1 = deltaLambdaTranslation.cross(m_r1World);
|
||||
const vec3 linearImpulseBody1 = -deltaLambdaTranslation;
|
||||
vec3 angularImpulseBody1 = deltaLambdaTranslation.cross(m_r1World);
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda of body 2
|
||||
Vector3 angularImpulseBody2 = -deltaLambdaTranslation.cross(m_r2World);
|
||||
vec3 angularImpulseBody2 = -deltaLambdaTranslation.cross(m_r2World);
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
v2 += inverseMassBody2 * deltaLambdaTranslation;
|
||||
@ -279,23 +279,23 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
||||
// --------------- Rotation Constraints --------------- //
|
||||
|
||||
// Compute J*v for the 2 rotation constraints
|
||||
const Vector2 JvRotation(-mB2CrossA1.dot(w1) + mB2CrossA1.dot(w2),
|
||||
const vec2 JvRotation(-mB2CrossA1.dot(w1) + mB2CrossA1.dot(w2),
|
||||
-mC2CrossA1.dot(w1) + mC2CrossA1.dot(w2));
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 2 rotation constraints
|
||||
Vector2 deltaLambdaRotation = m_inverseMassMatrixRotation * (-JvRotation - mBRotation);
|
||||
vec2 deltaLambdaRotation = m_inverseMassMatrixRotation * (-JvRotation - mBRotation);
|
||||
m_impulseRotation += deltaLambdaRotation;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 rotation constraints of body 1
|
||||
angularImpulseBody1 = -mB2CrossA1 * deltaLambdaRotation.x -
|
||||
mC2CrossA1 * deltaLambdaRotation.y;
|
||||
angularImpulseBody1 = -mB2CrossA1 * deltaLambdaRotation.x() -
|
||||
mC2CrossA1 * deltaLambdaRotation.y();
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 rotation constraints of body 2
|
||||
angularImpulseBody2 = mB2CrossA1 * deltaLambdaRotation.x +
|
||||
mC2CrossA1 * deltaLambdaRotation.y;
|
||||
angularImpulseBody2 = mB2CrossA1 * deltaLambdaRotation.x() +
|
||||
mC2CrossA1 * deltaLambdaRotation.y();
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
w2 += m_i2 * angularImpulseBody2;
|
||||
@ -313,17 +313,17 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
||||
// Compute the Lagrange multiplier lambda for the lower limit constraint
|
||||
float deltaLambdaLower = m_inverseMassMatrixLimitMotor * (-JvLowerLimit -mBLowerLimit);
|
||||
float lambdaTemp = m_impulseLowerLimit;
|
||||
m_impulseLowerLimit = std::max(m_impulseLowerLimit + deltaLambdaLower, float(0.0));
|
||||
m_impulseLowerLimit = std::max(m_impulseLowerLimit + deltaLambdaLower, 0.0f);
|
||||
deltaLambdaLower = m_impulseLowerLimit - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint of body 1
|
||||
const Vector3 angularImpulseBody1 = -deltaLambdaLower * mA1;
|
||||
const vec3 angularImpulseBody1 = -deltaLambdaLower * mA1;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint of body 2
|
||||
const Vector3 angularImpulseBody2 = deltaLambdaLower * mA1;
|
||||
const vec3 angularImpulseBody2 = deltaLambdaLower * mA1;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
w2 += m_i2 * angularImpulseBody2;
|
||||
@ -338,17 +338,17 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
||||
// Compute the Lagrange multiplier lambda for the upper limit constraint
|
||||
float deltaLambdaUpper = m_inverseMassMatrixLimitMotor * (-JvUpperLimit -mBUpperLimit);
|
||||
float lambdaTemp = m_impulseUpperLimit;
|
||||
m_impulseUpperLimit = std::max(m_impulseUpperLimit + deltaLambdaUpper, float(0.0));
|
||||
m_impulseUpperLimit = std::max(m_impulseUpperLimit + deltaLambdaUpper, 0.0f);
|
||||
deltaLambdaUpper = m_impulseUpperLimit - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint of body 1
|
||||
const Vector3 angularImpulseBody1 = deltaLambdaUpper * mA1;
|
||||
const vec3 angularImpulseBody1 = deltaLambdaUpper * mA1;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint of body 2
|
||||
const Vector3 angularImpulseBody2 = -deltaLambdaUpper * mA1;
|
||||
const vec3 angularImpulseBody2 = -deltaLambdaUpper * mA1;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
w2 += m_i2 * angularImpulseBody2;
|
||||
@ -371,13 +371,13 @@ void HingeJoint::solveVelocityConstraint(const ConstraintSolverData& constraintS
|
||||
deltaLambdaMotor = m_impulseMotor - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor of body 1
|
||||
const Vector3 angularImpulseBody1 = -deltaLambdaMotor * mA1;
|
||||
const vec3 angularImpulseBody1 = -deltaLambdaMotor * mA1;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor of body 2
|
||||
const Vector3 angularImpulseBody2 = deltaLambdaMotor * mA1;
|
||||
const vec3 angularImpulseBody2 = deltaLambdaMotor * mA1;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
w2 += m_i2 * angularImpulseBody2;
|
||||
@ -392,10 +392,10 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
if (m_positionCorrectionTechnique != NON_LINEAR_GAUSS_SEIDEL) return;
|
||||
|
||||
// Get the bodies positions and orientations
|
||||
Vector3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
Vector3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
vec3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
vec3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
etk::Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
etk::Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -420,70 +420,70 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
|
||||
// Compute vectors needed in the Jacobian
|
||||
mA1 = q1 * mHingeLocalAxisBody1;
|
||||
Vector3 a2 = q2 * mHingeLocalAxisBody2;
|
||||
vec3 a2 = q2 * mHingeLocalAxisBody2;
|
||||
mA1.normalize();
|
||||
a2.normalize();
|
||||
const Vector3 b2 = a2.getOneUnitOrthogonalVector();
|
||||
const Vector3 c2 = a2.cross(b2);
|
||||
const vec3 b2 = a2.getOneUnitOrthogonalVector();
|
||||
const vec3 c2 = a2.cross(b2);
|
||||
mB2CrossA1 = b2.cross(mA1);
|
||||
mC2CrossA1 = c2.cross(mA1);
|
||||
|
||||
// Compute the corresponding skew-symmetric matrices
|
||||
Matrix3x3 skewSymmetricMatrixU1= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
Matrix3x3 skewSymmetricMatrixU2= Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU1= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r1World);
|
||||
etk::Matrix3x3 skewSymmetricMatrixU2= etk::Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(m_r2World);
|
||||
|
||||
// --------------- Translation Constraints --------------- //
|
||||
|
||||
// Compute the matrix K=JM^-1J^t (3x3 matrix) for the 3 translation constraints
|
||||
float inverseMassBodies = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
etk::Matrix3x3 massMatrix = Matrix3x3(inverseMassBodies, 0, 0,
|
||||
0, inverseMassBodies, 0,
|
||||
0, 0, inverseMassBodies) +
|
||||
skewSymmetricMatrixU1 * m_i1 * skewSymmetricMatrixU1.getTranspose() +
|
||||
skewSymmetricMatrixU2 * m_i2 * skewSymmetricMatrixU2.getTranspose();
|
||||
m_inverseMassMatrixTranslation.setToZero();
|
||||
m_inverseMassMatrixTranslation.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixTranslation = massMatrix.getInverse();
|
||||
}
|
||||
|
||||
// Compute position error for the 3 translation constraints
|
||||
const Vector3 errorTranslation = x2 + m_r2World - x1 - m_r1World;
|
||||
const vec3 errorTranslation = x2 + m_r2World - x1 - m_r1World;
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
const Vector3 lambdaTranslation = m_inverseMassMatrixTranslation * (-errorTranslation);
|
||||
const vec3 lambdaTranslation = m_inverseMassMatrixTranslation * (-errorTranslation);
|
||||
|
||||
// Compute the impulse of body 1
|
||||
Vector3 linearImpulseBody1 = -lambdaTranslation;
|
||||
Vector3 angularImpulseBody1 = lambdaTranslation.cross(m_r1World);
|
||||
vec3 linearImpulseBody1 = -lambdaTranslation;
|
||||
vec3 angularImpulseBody1 = lambdaTranslation.cross(m_r1World);
|
||||
|
||||
// Compute the pseudo velocity of body 1
|
||||
const Vector3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
x1 += v1;
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse of body 2
|
||||
Vector3 angularImpulseBody2 = -lambdaTranslation.cross(m_r2World);
|
||||
vec3 angularImpulseBody2 = -lambdaTranslation.cross(m_r2World);
|
||||
|
||||
// Compute the pseudo velocity of body 2
|
||||
const Vector3 v2 = inverseMassBody2 * lambdaTranslation;
|
||||
Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 v2 = inverseMassBody2 * lambdaTranslation;
|
||||
vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
x2 += v2;
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
|
||||
// --------------- Rotation Constraints --------------- //
|
||||
|
||||
// Compute the inverse mass matrix K=JM^-1J^t for the 2 rotation constraints (2x2 matrix)
|
||||
Vector3 I1B2CrossA1 = m_i1 * mB2CrossA1;
|
||||
Vector3 I1C2CrossA1 = m_i1 * mC2CrossA1;
|
||||
Vector3 I2B2CrossA1 = m_i2 * mB2CrossA1;
|
||||
Vector3 I2C2CrossA1 = m_i2 * mC2CrossA1;
|
||||
vec3 I1B2CrossA1 = m_i1 * mB2CrossA1;
|
||||
vec3 I1C2CrossA1 = m_i1 * mC2CrossA1;
|
||||
vec3 I2B2CrossA1 = m_i2 * mB2CrossA1;
|
||||
vec3 I2C2CrossA1 = m_i2 * mC2CrossA1;
|
||||
const float el11 = mB2CrossA1.dot(I1B2CrossA1) +
|
||||
mB2CrossA1.dot(I2B2CrossA1);
|
||||
const float el12 = mB2CrossA1.dot(I1C2CrossA1) +
|
||||
@ -492,36 +492,36 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
mC2CrossA1.dot(I2B2CrossA1);
|
||||
const float el22 = mC2CrossA1.dot(I1C2CrossA1) +
|
||||
mC2CrossA1.dot(I2C2CrossA1);
|
||||
const Matrix2x2 matrixKRotation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixRotation.setToZero();
|
||||
const etk::Matrix2x2 matrixKRotation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixRotation.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixRotation = matrixKRotation.getInverse();
|
||||
}
|
||||
|
||||
// Compute the position error for the 3 rotation constraints
|
||||
const Vector2 errorRotation = Vector2(mA1.dot(b2), mA1.dot(c2));
|
||||
const vec2 errorRotation = vec2(mA1.dot(b2), mA1.dot(c2));
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 3 rotation constraints
|
||||
Vector2 lambdaRotation = m_inverseMassMatrixRotation * (-errorRotation);
|
||||
vec2 lambdaRotation = m_inverseMassMatrixRotation * (-errorRotation);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints of body 1
|
||||
angularImpulseBody1 = -mB2CrossA1 * lambdaRotation.x - mC2CrossA1 * lambdaRotation.y;
|
||||
angularImpulseBody1 = -mB2CrossA1 * lambdaRotation.x() - mC2CrossA1 * lambdaRotation.y();
|
||||
|
||||
// Compute the pseudo velocity of body 1
|
||||
w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse of body 2
|
||||
angularImpulseBody2 = mB2CrossA1 * lambdaRotation.x + mC2CrossA1 * lambdaRotation.y;
|
||||
angularImpulseBody2 = mB2CrossA1 * lambdaRotation.x() + mC2CrossA1 * lambdaRotation.y();
|
||||
|
||||
// Compute the pseudo velocity of body 2
|
||||
w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
|
||||
// --------------- Limits Constraints --------------- //
|
||||
@ -533,7 +533,7 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the limits (1x1 matrix)
|
||||
m_inverseMassMatrixLimitMotor = mA1.dot(m_i1 * mA1) + mA1.dot(m_i2 * mA1);
|
||||
m_inverseMassMatrixLimitMotor = (m_inverseMassMatrixLimitMotor > 0.0) ?
|
||||
float(1.0) / m_inverseMassMatrixLimitMotor : float(0.0);
|
||||
1.0f / m_inverseMassMatrixLimitMotor : 0.0f;
|
||||
}
|
||||
|
||||
// If the lower limit is violated
|
||||
@ -543,23 +543,23 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
float lambdaLowerLimit = m_inverseMassMatrixLimitMotor * (-lowerLimitError );
|
||||
|
||||
// Compute the impulse P=J^T * lambda of body 1
|
||||
const Vector3 angularImpulseBody1 = -lambdaLowerLimit * mA1;
|
||||
const vec3 angularImpulseBody1 = -lambdaLowerLimit * mA1;
|
||||
|
||||
// Compute the pseudo velocity of body 1
|
||||
const Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse P=J^T * lambda of body 2
|
||||
const Vector3 angularImpulseBody2 = lambdaLowerLimit * mA1;
|
||||
const vec3 angularImpulseBody2 = lambdaLowerLimit * mA1;
|
||||
|
||||
// Compute the pseudo velocity of body 2
|
||||
const Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
}
|
||||
|
||||
@ -570,23 +570,23 @@ void HingeJoint::solvePositionConstraint(const ConstraintSolverData& constraintS
|
||||
float lambdaUpperLimit = m_inverseMassMatrixLimitMotor * (-upperLimitError);
|
||||
|
||||
// Compute the impulse P=J^T * lambda of body 1
|
||||
const Vector3 angularImpulseBody1 = lambdaUpperLimit * mA1;
|
||||
const vec3 angularImpulseBody1 = lambdaUpperLimit * mA1;
|
||||
|
||||
// Compute the pseudo velocity of body 1
|
||||
const Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse P=J^T * lambda of body 2
|
||||
const Vector3 angularImpulseBody2 = -lambdaUpperLimit * mA1;
|
||||
const vec3 angularImpulseBody2 = -lambdaUpperLimit * mA1;
|
||||
|
||||
// Compute the pseudo velocity of body 2
|
||||
const Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
}
|
||||
}
|
||||
@ -742,17 +742,17 @@ float HingeJoint::computeCorrespondingAngleNearLimits(float inputAngle, float lo
|
||||
}
|
||||
|
||||
// Compute the current angle around the hinge axis
|
||||
float HingeJoint::computeCurrentHingeAngle(const Quaternion& orientationBody1,
|
||||
const Quaternion& orientationBody2) {
|
||||
float HingeJoint::computeCurrentHingeAngle(const etk::Quaternion& orientationBody1,
|
||||
const etk::Quaternion& orientationBody2) {
|
||||
|
||||
float hingeAngle;
|
||||
|
||||
// Compute the current orientation difference between the two bodies
|
||||
Quaternion currentOrientationDiff = orientationBody2 * orientationBody1.getInverse();
|
||||
etk::Quaternion currentOrientationDiff = orientationBody2 * orientationBody1.getInverse();
|
||||
currentOrientationDiff.normalize();
|
||||
|
||||
// Compute the relative rotation considering the initial orientation difference
|
||||
Quaternion relativeRotation = currentOrientationDiff * m_initOrientationDifferenceInv;
|
||||
etk::Quaternion relativeRotation = currentOrientationDiff * m_initOrientationDifferenceInv;
|
||||
relativeRotation.normalize();
|
||||
|
||||
// A quaternion q = [cos(theta/2); sin(theta/2) * rotAxis] where rotAxis is a unit
|
||||
@ -769,7 +769,7 @@ float HingeJoint::computeCurrentHingeAngle(const Quaternion& orientationBody1,
|
||||
float dotProduct = relativeRotation.getVectorV().dot(mA1);
|
||||
|
||||
// If the relative rotation axis and the hinge axis are pointing the same direction
|
||||
if (dotProduct >= float(0.0)) {
|
||||
if (dotProduct >= 0.0f) {
|
||||
hingeAngle = float(2.0) * std::atan2(sinHalfAngleAbs, cosHalfAngle);
|
||||
}
|
||||
else {
|
||||
|
@ -23,10 +23,10 @@ struct HingeJointInfo : public JointInfo {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point (in world-space coordinates)
|
||||
Vector3 m_anchorPointWorldSpace;
|
||||
vec3 m_anchorPointWorldSpace;
|
||||
|
||||
/// Hinge rotation axis (in world-space coordinates)
|
||||
Vector3 rotationAxisWorld;
|
||||
vec3 rotationAxisWorld;
|
||||
|
||||
/// True if the hinge joint limits are enabled
|
||||
bool isLimitEnabled;
|
||||
@ -59,8 +59,8 @@ struct HingeJointInfo : public JointInfo {
|
||||
* coordinates
|
||||
*/
|
||||
HingeJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initRotationAxisWorld)
|
||||
const vec3& initAnchorPointWorldSpace,
|
||||
const vec3& initRotationAxisWorld)
|
||||
: JointInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
m_anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
rotationAxisWorld(initRotationAxisWorld), isLimitEnabled(false),
|
||||
@ -77,8 +77,8 @@ struct HingeJointInfo : public JointInfo {
|
||||
* @param initMaxAngleLimit The initial maximum limit angle (in radian)
|
||||
*/
|
||||
HingeJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initRotationAxisWorld,
|
||||
const vec3& initAnchorPointWorldSpace,
|
||||
const vec3& initRotationAxisWorld,
|
||||
float initMinAngleLimit, float initMaxAngleLimit)
|
||||
: JointInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
m_anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
@ -99,8 +99,8 @@ struct HingeJointInfo : public JointInfo {
|
||||
* @param initMaxMotorTorque The initial maximum motor torque (in Newtons)
|
||||
*/
|
||||
HingeJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initRotationAxisWorld,
|
||||
const vec3& initAnchorPointWorldSpace,
|
||||
const vec3& initRotationAxisWorld,
|
||||
float initMinAngleLimit, float initMaxAngleLimit,
|
||||
float initMotorSpeed, float initMaxMotorTorque)
|
||||
: JointInfo(rigidBody1, rigidBody2, HINGEJOINT),
|
||||
@ -129,43 +129,43 @@ class HingeJoint : public Joint {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point of body 1 (in local-space coordinates of body 1)
|
||||
Vector3 m_localAnchorPointBody1;
|
||||
vec3 m_localAnchorPointBody1;
|
||||
|
||||
/// Anchor point of body 2 (in local-space coordinates of body 2)
|
||||
Vector3 m_localAnchorPointBody2;
|
||||
vec3 m_localAnchorPointBody2;
|
||||
|
||||
/// Hinge rotation axis (in local-space coordinates of body 1)
|
||||
Vector3 mHingeLocalAxisBody1;
|
||||
vec3 mHingeLocalAxisBody1;
|
||||
|
||||
/// Hinge rotation axis (in local-space coordiantes of body 2)
|
||||
Vector3 mHingeLocalAxisBody2;
|
||||
vec3 mHingeLocalAxisBody2;
|
||||
|
||||
/// Inertia tensor of body 1 (in world-space coordinates)
|
||||
Matrix3x3 m_i1;
|
||||
etk::Matrix3x3 m_i1;
|
||||
|
||||
/// Inertia tensor of body 2 (in world-space coordinates)
|
||||
Matrix3x3 m_i2;
|
||||
etk::Matrix3x3 m_i2;
|
||||
|
||||
/// Hinge rotation axis (in world-space coordinates) computed from body 1
|
||||
Vector3 mA1;
|
||||
vec3 mA1;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
Vector3 m_r1World;
|
||||
vec3 m_r1World;
|
||||
|
||||
/// Vector from center of body 2 to anchor point in world-space
|
||||
Vector3 m_r2World;
|
||||
vec3 m_r2World;
|
||||
|
||||
/// Cross product of vector b2 and a1
|
||||
Vector3 mB2CrossA1;
|
||||
vec3 mB2CrossA1;
|
||||
|
||||
/// Cross product of vector c2 and a1;
|
||||
Vector3 mC2CrossA1;
|
||||
vec3 mC2CrossA1;
|
||||
|
||||
/// Impulse for the 3 translation constraints
|
||||
Vector3 m_impulseTranslation;
|
||||
vec3 m_impulseTranslation;
|
||||
|
||||
/// Impulse for the 2 rotation constraints
|
||||
Vector2 m_impulseRotation;
|
||||
vec2 m_impulseRotation;
|
||||
|
||||
/// Accumulated impulse for the lower limit constraint
|
||||
float m_impulseLowerLimit;
|
||||
@ -177,10 +177,10 @@ class HingeJoint : public Joint {
|
||||
float m_impulseMotor;
|
||||
|
||||
/// Inverse mass matrix K=JM^-1J^t for the 3 translation constraints
|
||||
Matrix3x3 m_inverseMassMatrixTranslation;
|
||||
etk::Matrix3x3 m_inverseMassMatrixTranslation;
|
||||
|
||||
/// Inverse mass matrix K=JM^-1J^t for the 2 rotation constraints
|
||||
Matrix2x2 m_inverseMassMatrixRotation;
|
||||
etk::Matrix2x2 m_inverseMassMatrixRotation;
|
||||
|
||||
/// Inverse of mass matrix K=JM^-1J^t for the limits and motor constraints (1x1 matrix)
|
||||
float m_inverseMassMatrixLimitMotor;
|
||||
@ -189,10 +189,10 @@ class HingeJoint : public Joint {
|
||||
float m_inverseMassMatrixMotor;
|
||||
|
||||
/// Bias vector for the error correction for the translation constraints
|
||||
Vector3 mBTranslation;
|
||||
vec3 mBTranslation;
|
||||
|
||||
/// Bias vector for the error correction for the rotation constraints
|
||||
Vector2 mBRotation;
|
||||
vec2 mBRotation;
|
||||
|
||||
/// Bias of the lower limit constraint
|
||||
float mBLowerLimit;
|
||||
@ -201,7 +201,7 @@ class HingeJoint : public Joint {
|
||||
float mBUpperLimit;
|
||||
|
||||
/// Inverse of the initial orientation difference between the bodies
|
||||
Quaternion m_initOrientationDifferenceInv;
|
||||
etk::Quaternion m_initOrientationDifferenceInv;
|
||||
|
||||
/// True if the joint limits are enabled
|
||||
bool mIsLimitEnabled;
|
||||
@ -249,8 +249,8 @@ class HingeJoint : public Joint {
|
||||
float upperLimitAngle) const;
|
||||
|
||||
/// Compute the current angle around the hinge axis
|
||||
float computeCurrentHingeAngle(const Quaternion& orientationBody1,
|
||||
const Quaternion& orientationBody2);
|
||||
float computeCurrentHingeAngle(const etk::Quaternion& orientationBody1,
|
||||
const etk::Quaternion& orientationBody2);
|
||||
|
||||
/// Return the number of bytes used by the joint
|
||||
virtual size_t getSizeInBytes() const;
|
||||
|
@ -27,8 +27,8 @@ SliderJoint::SliderJoint(const SliderJointInfo& jointInfo)
|
||||
assert(mMaxMotorForce >= 0.0);
|
||||
|
||||
// Compute the local-space anchor point for each body
|
||||
const Transform& transform1 = m_body1->getTransform();
|
||||
const Transform& transform2 = m_body2->getTransform();
|
||||
const etk::Transform3D& transform1 = m_body1->getTransform();
|
||||
const etk::Transform3D& transform2 = m_body2->getTransform();
|
||||
m_localAnchorPointBody1 = transform1.getInverse() * jointInfo.m_anchorPointWorldSpace;
|
||||
m_localAnchorPointBody2 = transform2.getInverse() * jointInfo.m_anchorPointWorldSpace;
|
||||
|
||||
@ -57,10 +57,10 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
m_indexBody2 = constraintSolverData.mapBodyToConstrainedVelocityIndex.find(m_body2)->second;
|
||||
|
||||
// Get the bodies positions and orientations
|
||||
const Vector3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const Vector3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
const vec3& x1 = m_body1->m_centerOfMassWorld;
|
||||
const vec3& x2 = m_body2->m_centerOfMassWorld;
|
||||
const etk::Quaternion& orientationBody1 = m_body1->getTransform().getOrientation();
|
||||
const etk::Quaternion& orientationBody2 = m_body2->getTransform().getOrientation();
|
||||
|
||||
// Get the inertia tensor of bodies
|
||||
m_i1 = m_body1->getInertiaTensorInverseWorld();
|
||||
@ -71,7 +71,7 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
mR2 = orientationBody2 * m_localAnchorPointBody2;
|
||||
|
||||
// Compute the vector u (difference between anchor points)
|
||||
const Vector3 u = x2 + mR2 - x1 - mR1;
|
||||
const vec3 u = x2 + mR2 - x1 - mR1;
|
||||
|
||||
// Compute the two orthogonal vectors to the slider axis in world-space
|
||||
mSliderAxisWorld = orientationBody1 * mSliderAxisBody1;
|
||||
@ -98,7 +98,7 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
mR2CrossN1 = mR2.cross(mN1);
|
||||
mR2CrossN2 = mR2.cross(mN2);
|
||||
mR2CrossSliderAxis = mR2.cross(mSliderAxisWorld);
|
||||
const Vector3 r1PlusU = mR1 + u;
|
||||
const vec3 r1PlusU = mR1 + u;
|
||||
mR1PlusUCrossN1 = (r1PlusU).cross(mN1);
|
||||
mR1PlusUCrossN2 = (r1PlusU).cross(mN2);
|
||||
mR1PlusUCrossSliderAxis = (r1PlusU).cross(mSliderAxisWorld);
|
||||
@ -106,10 +106,10 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
// Compute the inverse of the mass matrix K=JM^-1J^t for the 2 translation
|
||||
// constraints (2x2 matrix)
|
||||
float sumInverseMass = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
Vector3 I1R1PlusUCrossN1 = m_i1 * mR1PlusUCrossN1;
|
||||
Vector3 I1R1PlusUCrossN2 = m_i1 * mR1PlusUCrossN2;
|
||||
Vector3 I2R2CrossN1 = m_i2 * mR2CrossN1;
|
||||
Vector3 I2R2CrossN2 = m_i2 * mR2CrossN2;
|
||||
vec3 I1R1PlusUCrossN1 = m_i1 * mR1PlusUCrossN1;
|
||||
vec3 I1R1PlusUCrossN2 = m_i1 * mR1PlusUCrossN2;
|
||||
vec3 I2R2CrossN1 = m_i2 * mR2CrossN1;
|
||||
vec3 I2R2CrossN2 = m_i2 * mR2CrossN2;
|
||||
const float el11 = sumInverseMass + mR1PlusUCrossN1.dot(I1R1PlusUCrossN1) +
|
||||
mR2CrossN1.dot(I2R2CrossN1);
|
||||
const float el12 = mR1PlusUCrossN1.dot(I1R1PlusUCrossN2) +
|
||||
@ -118,18 +118,18 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
mR2CrossN2.dot(I2R2CrossN1);
|
||||
const float el22 = sumInverseMass + mR1PlusUCrossN2.dot(I1R1PlusUCrossN2) +
|
||||
mR2CrossN2.dot(I2R2CrossN2);
|
||||
Matrix2x2 matrixKTranslation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixTranslationConstraint.setToZero();
|
||||
etk::Matrix2x2 matrixKTranslation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixTranslationConstraint.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixTranslationConstraint = matrixKTranslation.getInverse();
|
||||
}
|
||||
|
||||
// Compute the bias "b" of the translation constraint
|
||||
mBTranslation.setToZero();
|
||||
mBTranslation.setZero();
|
||||
float biasFactor = (BETA / constraintSolverData.timeStep);
|
||||
if (m_positionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
mBTranslation.x = u.dot(mN1);
|
||||
mBTranslation.y = u.dot(mN2);
|
||||
mBTranslation.x() = u.dot(mN1);
|
||||
mBTranslation.y() = u.dot(mN2);
|
||||
mBTranslation *= biasFactor;
|
||||
}
|
||||
|
||||
@ -141,11 +141,11 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
}
|
||||
|
||||
// Compute the bias "b" of the rotation constraint
|
||||
mBRotation.setToZero();
|
||||
mBRotation.setZero();
|
||||
if (m_positionCorrectionTechnique == BAUMGARTE_JOINTS) {
|
||||
Quaternion currentOrientationDifference = orientationBody2 * orientationBody1.getInverse();
|
||||
etk::Quaternion currentOrientationDifference = orientationBody2 * orientationBody1.getInverse();
|
||||
currentOrientationDifference.normalize();
|
||||
const Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
const etk::Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
mBRotation = biasFactor * float(2.0) * qError.getVectorV();
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
mR1PlusUCrossSliderAxis.dot(m_i1 * mR1PlusUCrossSliderAxis) +
|
||||
mR2CrossSliderAxis.dot(m_i2 * mR2CrossSliderAxis);
|
||||
m_inverseMassMatrixLimit = (m_inverseMassMatrixLimit > 0.0) ?
|
||||
float(1.0) / m_inverseMassMatrixLimit : float(0.0);
|
||||
1.0f / m_inverseMassMatrixLimit : 0.0f;
|
||||
|
||||
// Compute the bias "b" of the lower limit constraint
|
||||
mBLowerLimit = 0.0;
|
||||
@ -178,15 +178,15 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
// Compute the inverse of mass matrix K=JM^-1J^t for the motor (1x1 matrix)
|
||||
m_inverseMassMatrixMotor = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
m_inverseMassMatrixMotor = (m_inverseMassMatrixMotor > 0.0) ?
|
||||
float(1.0) / m_inverseMassMatrixMotor : float(0.0);
|
||||
1.0f / m_inverseMassMatrixMotor : 0.0f;
|
||||
}
|
||||
|
||||
// If warm-starting is not enabled
|
||||
if (!constraintSolverData.isWarmStartingActive) {
|
||||
|
||||
// Reset all the accumulated impulses
|
||||
m_impulseTranslation.setToZero();
|
||||
m_impulseRotation.setToZero();
|
||||
m_impulseTranslation.setZero();
|
||||
m_impulseRotation.setZero();
|
||||
m_impulseLowerLimit = 0.0;
|
||||
m_impulseUpperLimit = 0.0;
|
||||
m_impulseMotor = 0.0;
|
||||
@ -197,10 +197,10 @@ void SliderJoint::initBeforeSolve(const ConstraintSolverData& constraintSolverDa
|
||||
void SliderJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
const float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -208,15 +208,15 @@ void SliderJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower and upper limits constraints of body 1
|
||||
float impulseLimits = m_impulseUpperLimit - m_impulseLowerLimit;
|
||||
Vector3 linearImpulseLimits = impulseLimits * mSliderAxisWorld;
|
||||
vec3 linearImpulseLimits = impulseLimits * mSliderAxisWorld;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor constraint of body 1
|
||||
Vector3 impulseMotor = m_impulseMotor * mSliderAxisWorld;
|
||||
vec3 impulseMotor = m_impulseMotor * mSliderAxisWorld;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints of body 1
|
||||
Vector3 linearImpulseBody1 = -mN1 * m_impulseTranslation.x - mN2 * m_impulseTranslation.y;
|
||||
Vector3 angularImpulseBody1 = -mR1PlusUCrossN1 * m_impulseTranslation.x -
|
||||
mR1PlusUCrossN2 * m_impulseTranslation.y;
|
||||
vec3 linearImpulseBody1 = -mN1 * m_impulseTranslation.x() - mN2 * m_impulseTranslation.y();
|
||||
vec3 angularImpulseBody1 = -mR1PlusUCrossN1 * m_impulseTranslation.x() -
|
||||
mR1PlusUCrossN2 * m_impulseTranslation.y();
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints of body 1
|
||||
angularImpulseBody1 += -m_impulseRotation;
|
||||
@ -233,9 +233,9 @@ void SliderJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints of body 2
|
||||
Vector3 linearImpulseBody2 = mN1 * m_impulseTranslation.x + mN2 * m_impulseTranslation.y;
|
||||
Vector3 angularImpulseBody2 = mR2CrossN1 * m_impulseTranslation.x +
|
||||
mR2CrossN2 * m_impulseTranslation.y;
|
||||
vec3 linearImpulseBody2 = mN1 * m_impulseTranslation.x() + mN2 * m_impulseTranslation.y();
|
||||
vec3 angularImpulseBody2 = mR2CrossN1 * m_impulseTranslation.x() +
|
||||
mR2CrossN2 * m_impulseTranslation.y();
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints of body 2
|
||||
angularImpulseBody2 += m_impulseRotation;
|
||||
@ -256,10 +256,10 @@ void SliderJoint::warmstart(const ConstraintSolverData& constraintSolverData) {
|
||||
void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraintSolverData) {
|
||||
|
||||
// Get the velocities
|
||||
Vector3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
Vector3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
Vector3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
Vector3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
vec3& v1 = constraintSolverData.linearVelocities[m_indexBody1];
|
||||
vec3& v2 = constraintSolverData.linearVelocities[m_indexBody2];
|
||||
vec3& w1 = constraintSolverData.angularVelocities[m_indexBody1];
|
||||
vec3& w2 = constraintSolverData.angularVelocities[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -272,24 +272,24 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
||||
mN1.dot(v2) + w2.dot(mR2CrossN1);
|
||||
const float el2 = -mN2.dot(v1) - w1.dot(mR1PlusUCrossN2) +
|
||||
mN2.dot(v2) + w2.dot(mR2CrossN2);
|
||||
const Vector2 JvTranslation(el1, el2);
|
||||
const vec2 JvTranslation(el1, el2);
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 2 translation constraints
|
||||
Vector2 deltaLambda = m_inverseMassMatrixTranslationConstraint * (-JvTranslation -mBTranslation);
|
||||
vec2 deltaLambda = m_inverseMassMatrixTranslationConstraint * (-JvTranslation -mBTranslation);
|
||||
m_impulseTranslation += deltaLambda;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints of body 1
|
||||
const Vector3 linearImpulseBody1 = -mN1 * deltaLambda.x - mN2 * deltaLambda.y;
|
||||
Vector3 angularImpulseBody1 = -mR1PlusUCrossN1 * deltaLambda.x -
|
||||
mR1PlusUCrossN2 * deltaLambda.y;
|
||||
const vec3 linearImpulseBody1 = -mN1 * deltaLambda.x() - mN2 * deltaLambda.y();
|
||||
vec3 angularImpulseBody1 = -mR1PlusUCrossN1 * deltaLambda.x() -
|
||||
mR1PlusUCrossN2 * deltaLambda.y();
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints of body 2
|
||||
const Vector3 linearImpulseBody2 = mN1 * deltaLambda.x + mN2 * deltaLambda.y;
|
||||
Vector3 angularImpulseBody2 = mR2CrossN1 * deltaLambda.x + mR2CrossN2 * deltaLambda.y;
|
||||
const vec3 linearImpulseBody2 = mN1 * deltaLambda.x() + mN2 * deltaLambda.y();
|
||||
vec3 angularImpulseBody2 = mR2CrossN1 * deltaLambda.x() + mR2CrossN2 * deltaLambda.y();
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
v2 += inverseMassBody2 * linearImpulseBody2;
|
||||
@ -298,10 +298,10 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
||||
// --------------- Rotation Constraints --------------- //
|
||||
|
||||
// Compute J*v for the 3 rotation constraints
|
||||
const Vector3 JvRotation = w2 - w1;
|
||||
const vec3 JvRotation = w2 - w1;
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 3 rotation constraints
|
||||
Vector3 deltaLambda2 = m_inverseMassMatrixRotationConstraint * (-JvRotation - mBRotation);
|
||||
vec3 deltaLambda2 = m_inverseMassMatrixRotationConstraint * (-JvRotation - mBRotation);
|
||||
m_impulseRotation += deltaLambda2;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints of body 1
|
||||
@ -330,20 +330,20 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
||||
// Compute the Lagrange multiplier lambda for the lower limit constraint
|
||||
float deltaLambdaLower = m_inverseMassMatrixLimit * (-JvLowerLimit -mBLowerLimit);
|
||||
float lambdaTemp = m_impulseLowerLimit;
|
||||
m_impulseLowerLimit = std::max(m_impulseLowerLimit + deltaLambdaLower, float(0.0));
|
||||
m_impulseLowerLimit = std::max(m_impulseLowerLimit + deltaLambdaLower, 0.0f);
|
||||
deltaLambdaLower = m_impulseLowerLimit - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint of body 1
|
||||
const Vector3 linearImpulseBody1 = -deltaLambdaLower * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody1 = -deltaLambdaLower * mR1PlusUCrossSliderAxis;
|
||||
const vec3 linearImpulseBody1 = -deltaLambdaLower * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody1 = -deltaLambdaLower * mR1PlusUCrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint of body 2
|
||||
const Vector3 linearImpulseBody2 = deltaLambdaLower * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody2 = deltaLambdaLower * mR2CrossSliderAxis;
|
||||
const vec3 linearImpulseBody2 = deltaLambdaLower * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody2 = deltaLambdaLower * mR2CrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
v2 += inverseMassBody2 * linearImpulseBody2;
|
||||
@ -360,20 +360,20 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
||||
// Compute the Lagrange multiplier lambda for the upper limit constraint
|
||||
float deltaLambdaUpper = m_inverseMassMatrixLimit * (-JvUpperLimit -mBUpperLimit);
|
||||
float lambdaTemp = m_impulseUpperLimit;
|
||||
m_impulseUpperLimit = std::max(m_impulseUpperLimit + deltaLambdaUpper, float(0.0));
|
||||
m_impulseUpperLimit = std::max(m_impulseUpperLimit + deltaLambdaUpper, 0.0f);
|
||||
deltaLambdaUpper = m_impulseUpperLimit - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint of body 1
|
||||
const Vector3 linearImpulseBody1 = deltaLambdaUpper * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody1 = deltaLambdaUpper * mR1PlusUCrossSliderAxis;
|
||||
const vec3 linearImpulseBody1 = deltaLambdaUpper * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody1 = deltaLambdaUpper * mR1PlusUCrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
w1 += m_i1 * angularImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint of body 2
|
||||
const Vector3 linearImpulseBody2 = -deltaLambdaUpper * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody2 = -deltaLambdaUpper * mR2CrossSliderAxis;
|
||||
const vec3 linearImpulseBody2 = -deltaLambdaUpper * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody2 = -deltaLambdaUpper * mR2CrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
v2 += inverseMassBody2 * linearImpulseBody2;
|
||||
@ -396,13 +396,13 @@ void SliderJoint::solveVelocityConstraint(const ConstraintSolverData& constraint
|
||||
deltaLambdaMotor = m_impulseMotor - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor of body 1
|
||||
const Vector3 linearImpulseBody1 = deltaLambdaMotor * mSliderAxisWorld;
|
||||
const vec3 linearImpulseBody1 = deltaLambdaMotor * mSliderAxisWorld;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
v1 += inverseMassBody1 * linearImpulseBody1;
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the motor of body 2
|
||||
const Vector3 linearImpulseBody2 = -deltaLambdaMotor * mSliderAxisWorld;
|
||||
const vec3 linearImpulseBody2 = -deltaLambdaMotor * mSliderAxisWorld;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
v2 += inverseMassBody2 * linearImpulseBody2;
|
||||
@ -417,10 +417,10 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
if (m_positionCorrectionTechnique != NON_LINEAR_GAUSS_SEIDEL) return;
|
||||
|
||||
// Get the bodies positions and orientations
|
||||
Vector3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
Vector3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
vec3& x1 = constraintSolverData.positions[m_indexBody1];
|
||||
vec3& x2 = constraintSolverData.positions[m_indexBody2];
|
||||
etk::Quaternion& q1 = constraintSolverData.orientations[m_indexBody1];
|
||||
etk::Quaternion& q2 = constraintSolverData.orientations[m_indexBody2];
|
||||
|
||||
// Get the inverse mass and inverse inertia tensors of the bodies
|
||||
float inverseMassBody1 = m_body1->m_massInverse;
|
||||
@ -435,7 +435,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
mR2 = q2 * m_localAnchorPointBody2;
|
||||
|
||||
// Compute the vector u (difference between anchor points)
|
||||
const Vector3 u = x2 + mR2 - x1 - mR1;
|
||||
const vec3 u = x2 + mR2 - x1 - mR1;
|
||||
|
||||
// Compute the two orthogonal vectors to the slider axis in world-space
|
||||
mSliderAxisWorld = q1 * mSliderAxisBody1;
|
||||
@ -454,7 +454,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
mR2CrossN1 = mR2.cross(mN1);
|
||||
mR2CrossN2 = mR2.cross(mN2);
|
||||
mR2CrossSliderAxis = mR2.cross(mSliderAxisWorld);
|
||||
const Vector3 r1PlusU = mR1 + u;
|
||||
const vec3 r1PlusU = mR1 + u;
|
||||
mR1PlusUCrossN1 = (r1PlusU).cross(mN1);
|
||||
mR1PlusUCrossN2 = (r1PlusU).cross(mN2);
|
||||
mR1PlusUCrossSliderAxis = (r1PlusU).cross(mSliderAxisWorld);
|
||||
@ -464,10 +464,10 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
// Recompute the inverse of the mass matrix K=JM^-1J^t for the 2 translation
|
||||
// constraints (2x2 matrix)
|
||||
float sumInverseMass = m_body1->m_massInverse + m_body2->m_massInverse;
|
||||
Vector3 I1R1PlusUCrossN1 = m_i1 * mR1PlusUCrossN1;
|
||||
Vector3 I1R1PlusUCrossN2 = m_i1 * mR1PlusUCrossN2;
|
||||
Vector3 I2R2CrossN1 = m_i2 * mR2CrossN1;
|
||||
Vector3 I2R2CrossN2 = m_i2 * mR2CrossN2;
|
||||
vec3 I1R1PlusUCrossN1 = m_i1 * mR1PlusUCrossN1;
|
||||
vec3 I1R1PlusUCrossN2 = m_i1 * mR1PlusUCrossN2;
|
||||
vec3 I2R2CrossN1 = m_i2 * mR2CrossN1;
|
||||
vec3 I2R2CrossN2 = m_i2 * mR2CrossN2;
|
||||
const float el11 = sumInverseMass + mR1PlusUCrossN1.dot(I1R1PlusUCrossN1) +
|
||||
mR2CrossN1.dot(I2R2CrossN1);
|
||||
const float el12 = mR1PlusUCrossN1.dot(I1R1PlusUCrossN2) +
|
||||
@ -476,44 +476,44 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
mR2CrossN2.dot(I2R2CrossN1);
|
||||
const float el22 = sumInverseMass + mR1PlusUCrossN2.dot(I1R1PlusUCrossN2) +
|
||||
mR2CrossN2.dot(I2R2CrossN2);
|
||||
Matrix2x2 matrixKTranslation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixTranslationConstraint.setToZero();
|
||||
etk::Matrix2x2 matrixKTranslation(el11, el12, el21, el22);
|
||||
m_inverseMassMatrixTranslationConstraint.setZero();
|
||||
if (m_body1->getType() == DYNAMIC || m_body2->getType() == DYNAMIC) {
|
||||
m_inverseMassMatrixTranslationConstraint = matrixKTranslation.getInverse();
|
||||
}
|
||||
|
||||
// Compute the position error for the 2 translation constraints
|
||||
const Vector2 translationError(u.dot(mN1), u.dot(mN2));
|
||||
const vec2 translationError(u.dot(mN1), u.dot(mN2));
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 2 translation constraints
|
||||
Vector2 lambdaTranslation = m_inverseMassMatrixTranslationConstraint * (-translationError);
|
||||
vec2 lambdaTranslation = m_inverseMassMatrixTranslationConstraint * (-translationError);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints of body 1
|
||||
const Vector3 linearImpulseBody1 = -mN1 * lambdaTranslation.x - mN2 * lambdaTranslation.y;
|
||||
Vector3 angularImpulseBody1 = -mR1PlusUCrossN1 * lambdaTranslation.x -
|
||||
mR1PlusUCrossN2 * lambdaTranslation.y;
|
||||
const vec3 linearImpulseBody1 = -mN1 * lambdaTranslation.x() - mN2 * lambdaTranslation.y();
|
||||
vec3 angularImpulseBody1 = -mR1PlusUCrossN1 * lambdaTranslation.x() -
|
||||
mR1PlusUCrossN2 * lambdaTranslation.y();
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
const Vector3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
x1 += v1;
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 2 translation constraints of body 2
|
||||
const Vector3 linearImpulseBody2 = mN1 * lambdaTranslation.x + mN2 * lambdaTranslation.y;
|
||||
Vector3 angularImpulseBody2 = mR2CrossN1 * lambdaTranslation.x +
|
||||
mR2CrossN2 * lambdaTranslation.y;
|
||||
const vec3 linearImpulseBody2 = mN1 * lambdaTranslation.x() + mN2 * lambdaTranslation.y();
|
||||
vec3 angularImpulseBody2 = mR2CrossN1 * lambdaTranslation.x() +
|
||||
mR2CrossN2 * lambdaTranslation.y();
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
const Vector3 v2 = inverseMassBody2 * linearImpulseBody2;
|
||||
Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 v2 = inverseMassBody2 * linearImpulseBody2;
|
||||
vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
x2 += v2;
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
|
||||
// --------------- Rotation Constraints --------------- //
|
||||
@ -526,13 +526,13 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
}
|
||||
|
||||
// Compute the position error for the 3 rotation constraints
|
||||
Quaternion currentOrientationDifference = q2 * q1.getInverse();
|
||||
etk::Quaternion currentOrientationDifference = q2 * q1.getInverse();
|
||||
currentOrientationDifference.normalize();
|
||||
const Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
const Vector3 errorRotation = float(2.0) * qError.getVectorV();
|
||||
const etk::Quaternion qError = currentOrientationDifference * m_initOrientationDifferenceInv;
|
||||
const vec3 errorRotation = float(2.0) * qError.getVectorV();
|
||||
|
||||
// Compute the Lagrange multiplier lambda for the 3 rotation constraints
|
||||
Vector3 lambdaRotation = m_inverseMassMatrixRotationConstraint * (-errorRotation);
|
||||
vec3 lambdaRotation = m_inverseMassMatrixRotationConstraint * (-errorRotation);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints of body 1
|
||||
angularImpulseBody1 = -lambdaRotation;
|
||||
@ -541,7 +541,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the 3 rotation constraints of body 2
|
||||
@ -551,7 +551,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
|
||||
// --------------- Limits Constraints --------------- //
|
||||
@ -565,7 +565,7 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
mR1PlusUCrossSliderAxis.dot(m_i1 * mR1PlusUCrossSliderAxis) +
|
||||
mR2CrossSliderAxis.dot(m_i2 * mR2CrossSliderAxis);
|
||||
m_inverseMassMatrixLimit = (m_inverseMassMatrixLimit > 0.0) ?
|
||||
float(1.0) / m_inverseMassMatrixLimit : float(0.0);
|
||||
1.0f / m_inverseMassMatrixLimit : 0.0f;
|
||||
}
|
||||
|
||||
// If the lower limit is violated
|
||||
@ -575,29 +575,29 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
float lambdaLowerLimit = m_inverseMassMatrixLimit * (-lowerLimitError);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint of body 1
|
||||
const Vector3 linearImpulseBody1 = -lambdaLowerLimit * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody1 = -lambdaLowerLimit * mR1PlusUCrossSliderAxis;
|
||||
const vec3 linearImpulseBody1 = -lambdaLowerLimit * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody1 = -lambdaLowerLimit * mR1PlusUCrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
const Vector3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
const Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
const vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
x1 += v1;
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the lower limit constraint of body 2
|
||||
const Vector3 linearImpulseBody2 = lambdaLowerLimit * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody2 = lambdaLowerLimit * mR2CrossSliderAxis;
|
||||
const vec3 linearImpulseBody2 = lambdaLowerLimit * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody2 = lambdaLowerLimit * mR2CrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
const Vector3 v2 = inverseMassBody2 * linearImpulseBody2;
|
||||
const Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 v2 = inverseMassBody2 * linearImpulseBody2;
|
||||
const vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
x2 += v2;
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
}
|
||||
|
||||
@ -608,29 +608,29 @@ void SliderJoint::solvePositionConstraint(const ConstraintSolverData& constraint
|
||||
float lambdaUpperLimit = m_inverseMassMatrixLimit * (-upperLimitError);
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint of body 1
|
||||
const Vector3 linearImpulseBody1 = lambdaUpperLimit * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody1 = lambdaUpperLimit * mR1PlusUCrossSliderAxis;
|
||||
const vec3 linearImpulseBody1 = lambdaUpperLimit * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody1 = lambdaUpperLimit * mR1PlusUCrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 1
|
||||
const Vector3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
const Vector3 w1 = m_i1 * angularImpulseBody1;
|
||||
const vec3 v1 = inverseMassBody1 * linearImpulseBody1;
|
||||
const vec3 w1 = m_i1 * angularImpulseBody1;
|
||||
|
||||
// Update the body position/orientation of body 1
|
||||
x1 += v1;
|
||||
q1 += Quaternion(0, w1) * q1 * float(0.5);
|
||||
q1 += etk::Quaternion(0, w1) * q1 * 0.5f;
|
||||
q1.normalize();
|
||||
|
||||
// Compute the impulse P=J^T * lambda for the upper limit constraint of body 2
|
||||
const Vector3 linearImpulseBody2 = -lambdaUpperLimit * mSliderAxisWorld;
|
||||
const Vector3 angularImpulseBody2 = -lambdaUpperLimit * mR2CrossSliderAxis;
|
||||
const vec3 linearImpulseBody2 = -lambdaUpperLimit * mSliderAxisWorld;
|
||||
const vec3 angularImpulseBody2 = -lambdaUpperLimit * mR2CrossSliderAxis;
|
||||
|
||||
// Apply the impulse to the body 2
|
||||
const Vector3 v2 = inverseMassBody2 * linearImpulseBody2;
|
||||
const Vector3 w2 = m_i2 * angularImpulseBody2;
|
||||
const vec3 v2 = inverseMassBody2 * linearImpulseBody2;
|
||||
const vec3 w2 = m_i2 * angularImpulseBody2;
|
||||
|
||||
// Update the body position/orientation of body 2
|
||||
x2 += v2;
|
||||
q2 += Quaternion(0, w2) * q2 * float(0.5);
|
||||
q2 += etk::Quaternion(0, w2) * q2 * 0.5f;
|
||||
q2.normalize();
|
||||
}
|
||||
}
|
||||
@ -676,20 +676,20 @@ float SliderJoint::getTranslation() const {
|
||||
// TODO : Check if we need to compare rigid body position or center of mass here
|
||||
|
||||
// Get the bodies positions and orientations
|
||||
const Vector3& x1 = m_body1->getTransform().getPosition();
|
||||
const Vector3& x2 = m_body2->getTransform().getPosition();
|
||||
const Quaternion& q1 = m_body1->getTransform().getOrientation();
|
||||
const Quaternion& q2 = m_body2->getTransform().getOrientation();
|
||||
const vec3& x1 = m_body1->getTransform().getPosition();
|
||||
const vec3& x2 = m_body2->getTransform().getPosition();
|
||||
const etk::Quaternion& q1 = m_body1->getTransform().getOrientation();
|
||||
const etk::Quaternion& q2 = m_body2->getTransform().getOrientation();
|
||||
|
||||
// Compute the two anchor points in world-space coordinates
|
||||
const Vector3 anchorBody1 = x1 + q1 * m_localAnchorPointBody1;
|
||||
const Vector3 anchorBody2 = x2 + q2 * m_localAnchorPointBody2;
|
||||
const vec3 anchorBody1 = x1 + q1 * m_localAnchorPointBody1;
|
||||
const vec3 anchorBody2 = x2 + q2 * m_localAnchorPointBody2;
|
||||
|
||||
// Compute the vector u (difference between anchor points)
|
||||
const Vector3 u = anchorBody2 - anchorBody1;
|
||||
const vec3 u = anchorBody2 - anchorBody1;
|
||||
|
||||
// Compute the slider axis in world-space
|
||||
Vector3 sliderAxisWorld = q1 * mSliderAxisBody1;
|
||||
vec3 sliderAxisWorld = q1 * mSliderAxisBody1;
|
||||
sliderAxisWorld.normalize();
|
||||
|
||||
// Compute and return the translation value
|
||||
|
@ -23,10 +23,10 @@ struct SliderJointInfo : public JointInfo {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point (in world-space coordinates)
|
||||
Vector3 m_anchorPointWorldSpace;
|
||||
vec3 m_anchorPointWorldSpace;
|
||||
|
||||
/// Slider axis (in world-space coordinates)
|
||||
Vector3 sliderAxisWorldSpace;
|
||||
vec3 sliderAxisWorldSpace;
|
||||
|
||||
/// True if the slider limits are enabled
|
||||
bool isLimitEnabled;
|
||||
@ -54,8 +54,8 @@ struct SliderJointInfo : public JointInfo {
|
||||
* @param initSliderAxisWorldSpace The initial slider axis in world-space
|
||||
*/
|
||||
SliderJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initSliderAxisWorldSpace)
|
||||
const vec3& initAnchorPointWorldSpace,
|
||||
const vec3& initSliderAxisWorldSpace)
|
||||
: JointInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
m_anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
sliderAxisWorldSpace(initSliderAxisWorldSpace),
|
||||
@ -72,8 +72,8 @@ struct SliderJointInfo : public JointInfo {
|
||||
* @param initMaxTranslationLimit The initial maximum translation limit (in meters)
|
||||
*/
|
||||
SliderJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initSliderAxisWorldSpace,
|
||||
const vec3& initAnchorPointWorldSpace,
|
||||
const vec3& initSliderAxisWorldSpace,
|
||||
float initMinTranslationLimit, float initMaxTranslationLimit)
|
||||
: JointInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
m_anchorPointWorldSpace(initAnchorPointWorldSpace),
|
||||
@ -95,8 +95,8 @@ struct SliderJointInfo : public JointInfo {
|
||||
* @param initMaxMotorForce The initial maximum motor force of the joint (in Newtons x meters)
|
||||
*/
|
||||
SliderJointInfo(RigidBody* rigidBody1, RigidBody* rigidBody2,
|
||||
const Vector3& initAnchorPointWorldSpace,
|
||||
const Vector3& initSliderAxisWorldSpace,
|
||||
const vec3& initAnchorPointWorldSpace,
|
||||
const vec3& initSliderAxisWorldSpace,
|
||||
float initMinTranslationLimit, float initMaxTranslationLimit,
|
||||
float initMotorSpeed, float initMaxMotorForce)
|
||||
: JointInfo(rigidBody1, rigidBody2, SLIDERJOINT),
|
||||
@ -126,58 +126,58 @@ class SliderJoint : public Joint {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Anchor point of body 1 (in local-space coordinates of body 1)
|
||||
Vector3 m_localAnchorPointBody1;
|
||||
vec3 m_localAnchorPointBody1;
|
||||
|
||||
/// Anchor point of body 2 (in local-space coordinates of body 2)
|
||||
Vector3 m_localAnchorPointBody2;
|
||||
vec3 m_localAnchorPointBody2;
|
||||
|
||||
/// Slider axis (in local-space coordinates of body 1)
|
||||
Vector3 mSliderAxisBody1;
|
||||
vec3 mSliderAxisBody1;
|
||||
|
||||
/// Inertia tensor of body 1 (in world-space coordinates)
|
||||
Matrix3x3 m_i1;
|
||||
etk::Matrix3x3 m_i1;
|
||||
|
||||
/// Inertia tensor of body 2 (in world-space coordinates)
|
||||
Matrix3x3 m_i2;
|
||||
etk::Matrix3x3 m_i2;
|
||||
|
||||
/// Inverse of the initial orientation difference between the two bodies
|
||||
Quaternion m_initOrientationDifferenceInv;
|
||||
etk::Quaternion m_initOrientationDifferenceInv;
|
||||
|
||||
/// First vector orthogonal to the slider axis local-space of body 1
|
||||
Vector3 mN1;
|
||||
vec3 mN1;
|
||||
|
||||
/// Second vector orthogonal to the slider axis and mN1 in local-space of body 1
|
||||
Vector3 mN2;
|
||||
vec3 mN2;
|
||||
|
||||
/// Vector r1 in world-space coordinates
|
||||
Vector3 mR1;
|
||||
vec3 mR1;
|
||||
|
||||
/// Vector r2 in world-space coordinates
|
||||
Vector3 mR2;
|
||||
vec3 mR2;
|
||||
|
||||
/// Cross product of r2 and n1
|
||||
Vector3 mR2CrossN1;
|
||||
vec3 mR2CrossN1;
|
||||
|
||||
/// Cross product of r2 and n2
|
||||
Vector3 mR2CrossN2;
|
||||
vec3 mR2CrossN2;
|
||||
|
||||
/// Cross product of r2 and the slider axis
|
||||
Vector3 mR2CrossSliderAxis;
|
||||
vec3 mR2CrossSliderAxis;
|
||||
|
||||
/// Cross product of vector (r1 + u) and n1
|
||||
Vector3 mR1PlusUCrossN1;
|
||||
vec3 mR1PlusUCrossN1;
|
||||
|
||||
/// Cross product of vector (r1 + u) and n2
|
||||
Vector3 mR1PlusUCrossN2;
|
||||
vec3 mR1PlusUCrossN2;
|
||||
|
||||
/// Cross product of vector (r1 + u) and the slider axis
|
||||
Vector3 mR1PlusUCrossSliderAxis;
|
||||
vec3 mR1PlusUCrossSliderAxis;
|
||||
|
||||
/// Bias of the 2 translation constraints
|
||||
Vector2 mBTranslation;
|
||||
vec2 mBTranslation;
|
||||
|
||||
/// Bias of the 3 rotation constraints
|
||||
Vector3 mBRotation;
|
||||
vec3 mBRotation;
|
||||
|
||||
/// Bias of the lower limit constraint
|
||||
float mBLowerLimit;
|
||||
@ -186,10 +186,10 @@ class SliderJoint : public Joint {
|
||||
float mBUpperLimit;
|
||||
|
||||
/// Inverse of mass matrix K=JM^-1J^t for the translation constraint (2x2 matrix)
|
||||
Matrix2x2 m_inverseMassMatrixTranslationConstraint;
|
||||
etk::Matrix2x2 m_inverseMassMatrixTranslationConstraint;
|
||||
|
||||
/// Inverse of mass matrix K=JM^-1J^t for the rotation constraint (3x3 matrix)
|
||||
Matrix3x3 m_inverseMassMatrixRotationConstraint;
|
||||
etk::Matrix3x3 m_inverseMassMatrixRotationConstraint;
|
||||
|
||||
/// Inverse of mass matrix K=JM^-1J^t for the upper and lower limit constraints (1x1 matrix)
|
||||
float m_inverseMassMatrixLimit;
|
||||
@ -198,10 +198,10 @@ class SliderJoint : public Joint {
|
||||
float m_inverseMassMatrixMotor;
|
||||
|
||||
/// Accumulated impulse for the 2 translation constraints
|
||||
Vector2 m_impulseTranslation;
|
||||
vec2 m_impulseTranslation;
|
||||
|
||||
/// Accumulated impulse for the 3 rotation constraints
|
||||
Vector3 m_impulseRotation;
|
||||
vec3 m_impulseRotation;
|
||||
|
||||
/// Accumulated impulse for the lower limit constraint
|
||||
float m_impulseLowerLimit;
|
||||
@ -219,7 +219,7 @@ class SliderJoint : public Joint {
|
||||
bool mIsMotorEnabled;
|
||||
|
||||
/// Slider axis in world-space coordinates
|
||||
Vector3 mSliderAxisWorld;
|
||||
vec3 mSliderAxisWorld;
|
||||
|
||||
/// Lower limit (minimum translation distance)
|
||||
float mLowerLimit;
|
||||
|
@ -35,10 +35,10 @@ CollisionWorld::~CollisionWorld() {
|
||||
|
||||
// Create a collision body and add it to the world
|
||||
/**
|
||||
* @param transform Transformation mapping the local-space of the body to world-space
|
||||
* @param transform etk::Transform3Dation mapping the local-space of the body to world-space
|
||||
* @return A pointer to the body that has been created in the world
|
||||
*/
|
||||
CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
|
||||
CollisionBody* CollisionWorld::createCollisionBody(const etk::Transform3D& transform) {
|
||||
|
||||
// Get the next available body ID
|
||||
bodyindex bodyID = computeNextAvailableBodyID();
|
||||
|
@ -88,7 +88,7 @@ class CollisionWorld {
|
||||
std::set<CollisionBody*>::iterator getBodiesEndIterator();
|
||||
|
||||
/// Create a collision body
|
||||
CollisionBody* createCollisionBody(const Transform& transform);
|
||||
CollisionBody* createCollisionBody(const etk::Transform3D& transform);
|
||||
|
||||
/// Destroy a collision body
|
||||
void destroyCollisionBody(CollisionBody* collisionBody);
|
||||
|
@ -28,16 +28,16 @@ struct ConstraintSolverData {
|
||||
float timeStep;
|
||||
|
||||
/// Array with the bodies linear velocities
|
||||
Vector3* linearVelocities;
|
||||
vec3* linearVelocities;
|
||||
|
||||
/// Array with the bodies angular velocities
|
||||
Vector3* angularVelocities;
|
||||
vec3* angularVelocities;
|
||||
|
||||
/// Reference to the bodies positions
|
||||
Vector3* positions;
|
||||
vec3* positions;
|
||||
|
||||
/// Reference to the bodies orientations
|
||||
Quaternion* orientations;
|
||||
etk::Quaternion* orientations;
|
||||
|
||||
/// Reference to the map that associates rigid body to their index
|
||||
/// in the constrained velocities array
|
||||
@ -170,17 +170,17 @@ class ConstraintSolver {
|
||||
void setIsNonLinearGaussSeidelPositionCorrectionActive(bool isActive);
|
||||
|
||||
/// Set the constrained velocities arrays
|
||||
void setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
|
||||
Vector3* constrainedAngularVelocities);
|
||||
void setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
vec3* constrainedAngularVelocities);
|
||||
|
||||
/// Set the constrained positions/orientations arrays
|
||||
void setConstrainedPositionsArrays(Vector3* constrainedPositions,
|
||||
Quaternion* constrainedOrientations);
|
||||
void setConstrainedPositionsArrays(vec3* constrainedPositions,
|
||||
etk::Quaternion* constrainedOrientations);
|
||||
};
|
||||
|
||||
// Set the constrained velocities arrays
|
||||
inline void ConstraintSolver::setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
|
||||
Vector3* constrainedAngularVelocities) {
|
||||
inline void ConstraintSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
vec3* constrainedAngularVelocities) {
|
||||
assert(constrainedLinearVelocities != NULL);
|
||||
assert(constrainedAngularVelocities != NULL);
|
||||
m_constraintSolverData.linearVelocities = constrainedLinearVelocities;
|
||||
@ -188,8 +188,8 @@ inline void ConstraintSolver::setConstrainedVelocitiesArrays(Vector3* constraine
|
||||
}
|
||||
|
||||
// Set the constrained positions/orientations arrays
|
||||
inline void ConstraintSolver::setConstrainedPositionsArrays(Vector3* constrainedPositions,
|
||||
Quaternion* constrainedOrientations) {
|
||||
inline void ConstraintSolver::setConstrainedPositionsArrays(vec3* constrainedPositions,
|
||||
etk::Quaternion* constrainedOrientations) {
|
||||
assert(constrainedPositions != NULL);
|
||||
assert(constrainedOrientations != NULL);
|
||||
m_constraintSolverData.positions = constrainedPositions;
|
||||
|
@ -70,8 +70,8 @@ void ContactSolver::initializeForIsland(float dt, Island* island) {
|
||||
assert(body2 != NULL);
|
||||
|
||||
// Get the position of the two bodies
|
||||
const Vector3& x1 = body1->m_centerOfMassWorld;
|
||||
const Vector3& x2 = body2->m_centerOfMassWorld;
|
||||
const vec3& x1 = body1->m_centerOfMassWorld;
|
||||
const vec3& x2 = body2->m_centerOfMassWorld;
|
||||
|
||||
// Initialize the int32_ternal contact manifold structure using the external
|
||||
// contact manifold
|
||||
@ -91,8 +91,8 @@ void ContactSolver::initializeForIsland(float dt, Island* island) {
|
||||
|
||||
// If we solve the friction constraints at the center of the contact manifold
|
||||
if (mIsSolveFrictionAtContactManifoldCenterActive) {
|
||||
int32_ternalManifold.frictionPointBody1 = Vector3::zero();
|
||||
int32_ternalManifold.frictionPointBody2 = Vector3::zero();
|
||||
int32_ternalManifold.frictionPointBody1 = vec3::zero();
|
||||
int32_ternalManifold.frictionPointBody2 = vec3::zero();
|
||||
}
|
||||
|
||||
// For each contact point of the contact manifold
|
||||
@ -104,8 +104,8 @@ void ContactSolver::initializeForIsland(float dt, Island* island) {
|
||||
ContactPoint* externalContact = externalManifold->getContactPoint(c);
|
||||
|
||||
// Get the contact point on the two bodies
|
||||
Vector3 p1 = externalContact->getWorldPointOnBody1();
|
||||
Vector3 p2 = externalContact->getWorldPointOnBody2();
|
||||
vec3 p1 = externalContact->getWorldPointOnBody1();
|
||||
vec3 p2 = externalContact->getWorldPointOnBody2();
|
||||
|
||||
contactPoint.externalContact = externalContact;
|
||||
contactPoint.normal = externalContact->getNormal();
|
||||
@ -115,11 +115,11 @@ void ContactSolver::initializeForIsland(float dt, Island* island) {
|
||||
contactPoint.isRestingContact = externalContact->getIsRestingContact();
|
||||
externalContact->setIsRestingContact(true);
|
||||
contactPoint.oldFrictionVector1 = externalContact->getFrictionVector1();
|
||||
contactPoint.oldFrictionVector2 = externalContact->getFrictionVector2();
|
||||
contactPoint.oldFrictionvec2 = externalContact->getFrictionvec2();
|
||||
contactPoint.penetrationImpulse = 0.0;
|
||||
contactPoint.friction1Impulse = 0.0;
|
||||
contactPoint.friction2Impulse = 0.0;
|
||||
contactPoint.rollingResistanceImpulse = Vector3::zero();
|
||||
contactPoint.rollingResistanceImpulse = vec3::zero();
|
||||
|
||||
// If we solve the friction constraints at the center of the contact manifold
|
||||
if (mIsSolveFrictionAtContactManifoldCenterActive) {
|
||||
@ -136,7 +136,7 @@ void ContactSolver::initializeForIsland(float dt, Island* island) {
|
||||
int32_ternalManifold.r1Friction = int32_ternalManifold.frictionPointBody1 - x1;
|
||||
int32_ternalManifold.r2Friction = int32_ternalManifold.frictionPointBody2 - x2;
|
||||
int32_ternalManifold.oldFrictionVector1 = externalManifold->getFrictionVector1();
|
||||
int32_ternalManifold.oldFrictionVector2 = externalManifold->getFrictionVector2();
|
||||
int32_ternalManifold.oldFrictionvec2 = externalManifold->getFrictionvec2();
|
||||
|
||||
// If warm starting is active
|
||||
if (mIsWarmStartingActive) {
|
||||
@ -152,7 +152,7 @@ void ContactSolver::initializeForIsland(float dt, Island* island) {
|
||||
int32_ternalManifold.friction1Impulse = 0.0;
|
||||
int32_ternalManifold.friction2Impulse = 0.0;
|
||||
int32_ternalManifold.frictionTwistImpulse = 0.0;
|
||||
int32_ternalManifold.rollingResistanceImpulse = Vector3(0, 0, 0);
|
||||
int32_ternalManifold.rollingResistanceImpulse = vec3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,19 +170,19 @@ void ContactSolver::initializeContactConstraints() {
|
||||
ContactManifoldSolver& manifold = mContactConstraints[c];
|
||||
|
||||
// Get the inertia tensors of both bodies
|
||||
Matrix3x3& I1 = manifold.inverseInertiaTensorBody1;
|
||||
Matrix3x3& I2 = manifold.inverseInertiaTensorBody2;
|
||||
etk::Matrix3x3& I1 = manifold.inverseInertiaTensorBody1;
|
||||
etk::Matrix3x3& I2 = manifold.inverseInertiaTensorBody2;
|
||||
|
||||
// If we solve the friction constraints at the center of the contact manifold
|
||||
if (mIsSolveFrictionAtContactManifoldCenterActive) {
|
||||
manifold.normal = Vector3(0.0, 0.0, 0.0);
|
||||
manifold.normal = vec3(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// Get the velocities of the bodies
|
||||
const Vector3& v1 = mLinearVelocities[manifold.indexBody1];
|
||||
const Vector3& w1 = mAngularVelocities[manifold.indexBody1];
|
||||
const Vector3& v2 = mLinearVelocities[manifold.indexBody2];
|
||||
const Vector3& w2 = mAngularVelocities[manifold.indexBody2];
|
||||
const vec3& v1 = mLinearVelocities[manifold.indexBody1];
|
||||
const vec3& w1 = mAngularVelocities[manifold.indexBody1];
|
||||
const vec3& v2 = mLinearVelocities[manifold.indexBody2];
|
||||
const vec3& w2 = mAngularVelocities[manifold.indexBody2];
|
||||
|
||||
// For each contact point constraint
|
||||
for (uint32_t i=0; i<manifold.nbContacts; i++) {
|
||||
@ -191,7 +191,7 @@ void ContactSolver::initializeContactConstraints() {
|
||||
ContactPoint* externalContact = contactPoint.externalContact;
|
||||
|
||||
// Compute the velocity difference
|
||||
Vector3 deltaV = v2 + w2.cross(contactPoint.r2) - v1 - w1.cross(contactPoint.r1);
|
||||
vec3 deltaV = v2 + w2.cross(contactPoint.r2) - v1 - w1.cross(contactPoint.r1);
|
||||
|
||||
contactPoint.r1CrossN = contactPoint.r1.cross(contactPoint.normal);
|
||||
contactPoint.r2CrossN = contactPoint.r2.cross(contactPoint.normal);
|
||||
@ -200,9 +200,9 @@ void ContactSolver::initializeContactConstraints() {
|
||||
float massPenetration = manifold.massInverseBody1 + manifold.massInverseBody2 +
|
||||
((I1 * contactPoint.r1CrossN).cross(contactPoint.r1)).dot(contactPoint.normal) +
|
||||
((I2 * contactPoint.r2CrossN).cross(contactPoint.r2)).dot(contactPoint.normal);
|
||||
massPenetration > 0.0 ? contactPoint.inversePenetrationMass = float(1.0) /
|
||||
massPenetration > 0.0 ? contactPoint.inversePenetrationMass = 1.0f /
|
||||
massPenetration :
|
||||
float(0.0);
|
||||
0.0f;
|
||||
|
||||
// If we do not solve the friction constraints at the center of the contact manifold
|
||||
if (!mIsSolveFrictionAtContactManifoldCenterActive) {
|
||||
@ -211,9 +211,9 @@ void ContactSolver::initializeContactConstraints() {
|
||||
computeFrictionVectors(deltaV, contactPoint);
|
||||
|
||||
contactPoint.r1CrossT1 = contactPoint.r1.cross(contactPoint.frictionVector1);
|
||||
contactPoint.r1CrossT2 = contactPoint.r1.cross(contactPoint.frictionVector2);
|
||||
contactPoint.r1CrossT2 = contactPoint.r1.cross(contactPoint.frictionvec2);
|
||||
contactPoint.r2CrossT1 = contactPoint.r2.cross(contactPoint.frictionVector1);
|
||||
contactPoint.r2CrossT2 = contactPoint.r2.cross(contactPoint.frictionVector2);
|
||||
contactPoint.r2CrossT2 = contactPoint.r2.cross(contactPoint.frictionvec2);
|
||||
|
||||
// Compute the inverse mass matrix K for the friction
|
||||
// constraints at each contact point
|
||||
@ -224,15 +224,15 @@ void ContactSolver::initializeContactConstraints() {
|
||||
contactPoint.frictionVector1);
|
||||
float friction2Mass = manifold.massInverseBody1 + manifold.massInverseBody2 +
|
||||
((I1 * contactPoint.r1CrossT2).cross(contactPoint.r1)).dot(
|
||||
contactPoint.frictionVector2) +
|
||||
contactPoint.frictionvec2) +
|
||||
((I2 * contactPoint.r2CrossT2).cross(contactPoint.r2)).dot(
|
||||
contactPoint.frictionVector2);
|
||||
friction1Mass > 0.0 ? contactPoint.inverseFriction1Mass = float(1.0) /
|
||||
contactPoint.frictionvec2);
|
||||
friction1Mass > 0.0 ? contactPoint.inverseFriction1Mass = 1.0f /
|
||||
friction1Mass :
|
||||
float(0.0);
|
||||
friction2Mass > 0.0 ? contactPoint.inverseFriction2Mass = float(1.0) /
|
||||
0.0f;
|
||||
friction2Mass > 0.0 ? contactPoint.inverseFriction2Mass = 1.0f /
|
||||
friction2Mass :
|
||||
float(0.0);
|
||||
0.0f;
|
||||
}
|
||||
|
||||
// Compute the restitution velocity bias "b". We compute this here instead
|
||||
@ -265,7 +265,7 @@ void ContactSolver::initializeContactConstraints() {
|
||||
}
|
||||
|
||||
// Compute the inverse K matrix for the rolling resistance constraint
|
||||
manifold.inverseRollingResistance.setToZero();
|
||||
manifold.inverseRollingResistance.setZero();
|
||||
if (manifold.rollingResistanceFactor > 0 && (manifold.isBody1DynamicType || manifold.isBody2DynamicType)) {
|
||||
manifold.inverseRollingResistance = manifold.inverseInertiaTensorBody1 + manifold.inverseInertiaTensorBody2;
|
||||
manifold.inverseRollingResistance = manifold.inverseRollingResistance.getInverse();
|
||||
@ -276,7 +276,7 @@ void ContactSolver::initializeContactConstraints() {
|
||||
|
||||
manifold.normal.normalize();
|
||||
|
||||
Vector3 deltaVFrictionPoint = v2 + w2.cross(manifold.r2Friction) -
|
||||
vec3 deltaVFrictionPoint = v2 + w2.cross(manifold.r2Friction) -
|
||||
v1 - w1.cross(manifold.r1Friction);
|
||||
|
||||
// Compute the friction vectors
|
||||
@ -285,9 +285,9 @@ void ContactSolver::initializeContactConstraints() {
|
||||
// Compute the inverse mass matrix K for the friction constraints at the center of
|
||||
// the contact manifold
|
||||
manifold.r1CrossT1 = manifold.r1Friction.cross(manifold.frictionVector1);
|
||||
manifold.r1CrossT2 = manifold.r1Friction.cross(manifold.frictionVector2);
|
||||
manifold.r1CrossT2 = manifold.r1Friction.cross(manifold.frictionvec2);
|
||||
manifold.r2CrossT1 = manifold.r2Friction.cross(manifold.frictionVector1);
|
||||
manifold.r2CrossT2 = manifold.r2Friction.cross(manifold.frictionVector2);
|
||||
manifold.r2CrossT2 = manifold.r2Friction.cross(manifold.frictionvec2);
|
||||
float friction1Mass = manifold.massInverseBody1 + manifold.massInverseBody2 +
|
||||
((I1 * manifold.r1CrossT1).cross(manifold.r1Friction)).dot(
|
||||
manifold.frictionVector1) +
|
||||
@ -295,20 +295,20 @@ void ContactSolver::initializeContactConstraints() {
|
||||
manifold.frictionVector1);
|
||||
float friction2Mass = manifold.massInverseBody1 + manifold.massInverseBody2 +
|
||||
((I1 * manifold.r1CrossT2).cross(manifold.r1Friction)).dot(
|
||||
manifold.frictionVector2) +
|
||||
manifold.frictionvec2) +
|
||||
((I2 * manifold.r2CrossT2).cross(manifold.r2Friction)).dot(
|
||||
manifold.frictionVector2);
|
||||
manifold.frictionvec2);
|
||||
float frictionTwistMass = manifold.normal.dot(manifold.inverseInertiaTensorBody1 *
|
||||
manifold.normal) +
|
||||
manifold.normal.dot(manifold.inverseInertiaTensorBody2 *
|
||||
manifold.normal);
|
||||
friction1Mass > 0.0 ? manifold.inverseFriction1Mass = float(1.0)/friction1Mass
|
||||
: float(0.0);
|
||||
friction2Mass > 0.0 ? manifold.inverseFriction2Mass = float(1.0)/friction2Mass
|
||||
: float(0.0);
|
||||
frictionTwistMass > 0.0 ? manifold.inverseTwistFrictionMass = float(1.0) /
|
||||
friction1Mass > 0.0 ? manifold.inverseFriction1Mass = 1.0f/friction1Mass
|
||||
: 0.0f;
|
||||
friction2Mass > 0.0 ? manifold.inverseFriction2Mass = 1.0f/friction2Mass
|
||||
: 0.0f;
|
||||
frictionTwistMass > 0.0 ? manifold.inverseTwistFrictionMass = 1.0f /
|
||||
frictionTwistMass :
|
||||
float(0.0);
|
||||
0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -352,14 +352,14 @@ void ContactSolver::warmStart() {
|
||||
|
||||
// Project the old friction impulses (with old friction vectors) int32_to
|
||||
// the new friction vectors to get the new friction impulses
|
||||
Vector3 oldFrictionImpulse = contactPoint.friction1Impulse *
|
||||
vec3 oldFrictionImpulse = contactPoint.friction1Impulse *
|
||||
contactPoint.oldFrictionVector1 +
|
||||
contactPoint.friction2Impulse *
|
||||
contactPoint.oldFrictionVector2;
|
||||
contactPoint.oldFrictionvec2;
|
||||
contactPoint.friction1Impulse = oldFrictionImpulse.dot(
|
||||
contactPoint.frictionVector1);
|
||||
contactPoint.friction2Impulse = oldFrictionImpulse.dot(
|
||||
contactPoint.frictionVector2);
|
||||
contactPoint.frictionvec2);
|
||||
|
||||
// --------- Friction 1 --------- //
|
||||
|
||||
@ -384,8 +384,8 @@ void ContactSolver::warmStart() {
|
||||
if (contactManifold.rollingResistanceFactor > 0) {
|
||||
|
||||
// Compute the impulse P = J^T * lambda
|
||||
const Impulse impulseRollingResistance(Vector3::zero(), -contactPoint.rollingResistanceImpulse,
|
||||
Vector3::zero(), contactPoint.rollingResistanceImpulse);
|
||||
const Impulse impulseRollingResistance(vec3::zero(), -contactPoint.rollingResistanceImpulse,
|
||||
vec3::zero(), contactPoint.rollingResistanceImpulse);
|
||||
|
||||
// Apply the impulses to the bodies of the constraint
|
||||
applyImpulse(impulseRollingResistance, contactManifold);
|
||||
@ -398,7 +398,7 @@ void ContactSolver::warmStart() {
|
||||
contactPoint.penetrationImpulse = 0.0;
|
||||
contactPoint.friction1Impulse = 0.0;
|
||||
contactPoint.friction2Impulse = 0.0;
|
||||
contactPoint.rollingResistanceImpulse = Vector3::zero();
|
||||
contactPoint.rollingResistanceImpulse = vec3::zero();
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,25 +408,25 @@ void ContactSolver::warmStart() {
|
||||
|
||||
// Project the old friction impulses (with old friction vectors) int32_to the new friction
|
||||
// vectors to get the new friction impulses
|
||||
Vector3 oldFrictionImpulse = contactManifold.friction1Impulse *
|
||||
vec3 oldFrictionImpulse = contactManifold.friction1Impulse *
|
||||
contactManifold.oldFrictionVector1 +
|
||||
contactManifold.friction2Impulse *
|
||||
contactManifold.oldFrictionVector2;
|
||||
contactManifold.oldFrictionvec2;
|
||||
contactManifold.friction1Impulse = oldFrictionImpulse.dot(
|
||||
contactManifold.frictionVector1);
|
||||
contactManifold.friction2Impulse = oldFrictionImpulse.dot(
|
||||
contactManifold.frictionVector2);
|
||||
contactManifold.frictionvec2);
|
||||
|
||||
// ------ First friction constraint at the center of the contact manifold ------ //
|
||||
|
||||
// Compute the impulse P = J^T * lambda
|
||||
Vector3 linearImpulseBody1 = -contactManifold.frictionVector1 *
|
||||
vec3 linearImpulseBody1 = -contactManifold.frictionVector1 *
|
||||
contactManifold.friction1Impulse;
|
||||
Vector3 angularImpulseBody1 = -contactManifold.r1CrossT1 *
|
||||
vec3 angularImpulseBody1 = -contactManifold.r1CrossT1 *
|
||||
contactManifold.friction1Impulse;
|
||||
Vector3 linearImpulseBody2 = contactManifold.frictionVector1 *
|
||||
vec3 linearImpulseBody2 = contactManifold.frictionVector1 *
|
||||
contactManifold.friction1Impulse;
|
||||
Vector3 angularImpulseBody2 = contactManifold.r2CrossT1 *
|
||||
vec3 angularImpulseBody2 = contactManifold.r2CrossT1 *
|
||||
contactManifold.friction1Impulse;
|
||||
const Impulse impulseFriction1(linearImpulseBody1, angularImpulseBody1,
|
||||
linearImpulseBody2, angularImpulseBody2);
|
||||
@ -437,11 +437,11 @@ void ContactSolver::warmStart() {
|
||||
// ------ Second friction constraint at the center of the contact manifold ----- //
|
||||
|
||||
// Compute the impulse P = J^T * lambda
|
||||
linearImpulseBody1 = -contactManifold.frictionVector2 *
|
||||
linearImpulseBody1 = -contactManifold.frictionvec2 *
|
||||
contactManifold.friction2Impulse;
|
||||
angularImpulseBody1 = -contactManifold.r1CrossT2 *
|
||||
contactManifold.friction2Impulse;
|
||||
linearImpulseBody2 = contactManifold.frictionVector2 *
|
||||
linearImpulseBody2 = contactManifold.frictionvec2 *
|
||||
contactManifold.friction2Impulse;
|
||||
angularImpulseBody2 = contactManifold.r2CrossT2 *
|
||||
contactManifold.friction2Impulse;
|
||||
@ -454,9 +454,9 @@ void ContactSolver::warmStart() {
|
||||
// ------ Twist friction constraint at the center of the contact manifold ------ //
|
||||
|
||||
// Compute the impulse P = J^T * lambda
|
||||
linearImpulseBody1 = Vector3(0.0, 0.0, 0.0);
|
||||
linearImpulseBody1 = vec3(0.0, 0.0, 0.0);
|
||||
angularImpulseBody1 = -contactManifold.normal * contactManifold.frictionTwistImpulse;
|
||||
linearImpulseBody2 = Vector3(0.0, 0.0, 0.0);
|
||||
linearImpulseBody2 = vec3(0.0, 0.0, 0.0);
|
||||
angularImpulseBody2 = contactManifold.normal * contactManifold.frictionTwistImpulse;
|
||||
const Impulse impulseTwistFriction(linearImpulseBody1, angularImpulseBody1,
|
||||
linearImpulseBody2, angularImpulseBody2);
|
||||
@ -469,8 +469,8 @@ void ContactSolver::warmStart() {
|
||||
// Compute the impulse P = J^T * lambda
|
||||
angularImpulseBody1 = -contactManifold.rollingResistanceImpulse;
|
||||
angularImpulseBody2 = contactManifold.rollingResistanceImpulse;
|
||||
const Impulse impulseRollingResistance(Vector3::zero(), angularImpulseBody1,
|
||||
Vector3::zero(), angularImpulseBody2);
|
||||
const Impulse impulseRollingResistance(vec3::zero(), angularImpulseBody1,
|
||||
vec3::zero(), angularImpulseBody2);
|
||||
|
||||
// Apply the impulses to the bodies of the constraint
|
||||
applyImpulse(impulseRollingResistance, contactManifold);
|
||||
@ -481,7 +481,7 @@ void ContactSolver::warmStart() {
|
||||
contactManifold.friction1Impulse = 0.0;
|
||||
contactManifold.friction2Impulse = 0.0;
|
||||
contactManifold.frictionTwistImpulse = 0.0;
|
||||
contactManifold.rollingResistanceImpulse = Vector3::zero();
|
||||
contactManifold.rollingResistanceImpulse = vec3::zero();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -502,10 +502,10 @@ void ContactSolver::solve() {
|
||||
float sumPenetrationImpulse = 0.0;
|
||||
|
||||
// Get the constrained velocities
|
||||
const Vector3& v1 = mLinearVelocities[contactManifold.indexBody1];
|
||||
const Vector3& w1 = mAngularVelocities[contactManifold.indexBody1];
|
||||
const Vector3& v2 = mLinearVelocities[contactManifold.indexBody2];
|
||||
const Vector3& w2 = mAngularVelocities[contactManifold.indexBody2];
|
||||
const vec3& v1 = mLinearVelocities[contactManifold.indexBody1];
|
||||
const vec3& w1 = mAngularVelocities[contactManifold.indexBody1];
|
||||
const vec3& v2 = mLinearVelocities[contactManifold.indexBody2];
|
||||
const vec3& w2 = mAngularVelocities[contactManifold.indexBody2];
|
||||
|
||||
for (uint32_t i=0; i<contactManifold.nbContacts; i++) {
|
||||
|
||||
@ -514,7 +514,7 @@ void ContactSolver::solve() {
|
||||
// --------- Penetration --------- //
|
||||
|
||||
// Compute J*v
|
||||
Vector3 deltaV = v2 + w2.cross(contactPoint.r2) - v1 - w1.cross(contactPoint.r1);
|
||||
vec3 deltaV = v2 + w2.cross(contactPoint.r2) - v1 - w1.cross(contactPoint.r1);
|
||||
float deltaVDotN = deltaV.dot(contactPoint.normal);
|
||||
float Jv = deltaVDotN;
|
||||
|
||||
@ -535,7 +535,7 @@ void ContactSolver::solve() {
|
||||
}
|
||||
lambdaTemp = contactPoint.penetrationImpulse;
|
||||
contactPoint.penetrationImpulse = std::max(contactPoint.penetrationImpulse +
|
||||
deltaLambda, float(0.0));
|
||||
deltaLambda, 0.0f);
|
||||
deltaLambda = contactPoint.penetrationImpulse - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
@ -551,11 +551,11 @@ void ContactSolver::solve() {
|
||||
if (mIsSplitImpulseActive) {
|
||||
|
||||
// Split impulse (position correction)
|
||||
const Vector3& v1Split = m_splitLinearVelocities[contactManifold.indexBody1];
|
||||
const Vector3& w1Split = m_splitAngularVelocities[contactManifold.indexBody1];
|
||||
const Vector3& v2Split = m_splitLinearVelocities[contactManifold.indexBody2];
|
||||
const Vector3& w2Split = m_splitAngularVelocities[contactManifold.indexBody2];
|
||||
Vector3 deltaVSplit = v2Split + w2Split.cross(contactPoint.r2) -
|
||||
const vec3& v1Split = m_splitLinearVelocities[contactManifold.indexBody1];
|
||||
const vec3& w1Split = m_splitAngularVelocities[contactManifold.indexBody1];
|
||||
const vec3& v2Split = m_splitLinearVelocities[contactManifold.indexBody2];
|
||||
const vec3& w2Split = m_splitAngularVelocities[contactManifold.indexBody2];
|
||||
vec3 deltaVSplit = v2Split + w2Split.cross(contactPoint.r2) -
|
||||
v1Split - w1Split.cross(contactPoint.r1);
|
||||
float JvSplit = deltaVSplit.dot(contactPoint.normal);
|
||||
float deltaLambdaSplit = - (JvSplit + biasPenetrationDepth) *
|
||||
@ -563,7 +563,7 @@ void ContactSolver::solve() {
|
||||
float lambdaTempSplit = contactPoint.penetrationSplitImpulse;
|
||||
contactPoint.penetrationSplitImpulse = std::max(
|
||||
contactPoint.penetrationSplitImpulse +
|
||||
deltaLambdaSplit, float(0.0));
|
||||
deltaLambdaSplit, 0.0f);
|
||||
deltaLambda = contactPoint.penetrationSplitImpulse - lambdaTempSplit;
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
@ -604,7 +604,7 @@ void ContactSolver::solve() {
|
||||
|
||||
// Compute J*v
|
||||
deltaV = v2 + w2.cross(contactPoint.r2) - v1 - w1.cross(contactPoint.r1);
|
||||
Jv = deltaV.dot(contactPoint.frictionVector2);
|
||||
Jv = deltaV.dot(contactPoint.frictionvec2);
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
deltaLambda = -Jv;
|
||||
@ -629,19 +629,19 @@ void ContactSolver::solve() {
|
||||
if (contactManifold.rollingResistanceFactor > 0) {
|
||||
|
||||
// Compute J*v
|
||||
const Vector3 JvRolling = w2 - w1;
|
||||
const vec3 JvRolling = w2 - w1;
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
Vector3 deltaLambdaRolling = contactManifold.inverseRollingResistance * (-JvRolling);
|
||||
vec3 deltaLambdaRolling = contactManifold.inverseRollingResistance * (-JvRolling);
|
||||
float rollingLimit = contactManifold.rollingResistanceFactor * contactPoint.penetrationImpulse;
|
||||
Vector3 lambdaTempRolling = contactPoint.rollingResistanceImpulse;
|
||||
vec3 lambdaTempRolling = contactPoint.rollingResistanceImpulse;
|
||||
contactPoint.rollingResistanceImpulse = clamp(contactPoint.rollingResistanceImpulse +
|
||||
deltaLambdaRolling, rollingLimit);
|
||||
deltaLambdaRolling = contactPoint.rollingResistanceImpulse - lambdaTempRolling;
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
const Impulse impulseRolling(Vector3::zero(), -deltaLambdaRolling,
|
||||
Vector3::zero(), deltaLambdaRolling);
|
||||
const Impulse impulseRolling(vec3::zero(), -deltaLambdaRolling,
|
||||
vec3::zero(), deltaLambdaRolling);
|
||||
|
||||
// Apply the impulses to the bodies of the constraint
|
||||
applyImpulse(impulseRolling, contactManifold);
|
||||
@ -655,7 +655,7 @@ void ContactSolver::solve() {
|
||||
// ------ First friction constraint at the center of the contact manifol ------ //
|
||||
|
||||
// Compute J*v
|
||||
Vector3 deltaV = v2 + w2.cross(contactManifold.r2Friction)
|
||||
vec3 deltaV = v2 + w2.cross(contactManifold.r2Friction)
|
||||
- v1 - w1.cross(contactManifold.r1Friction);
|
||||
float Jv = deltaV.dot(contactManifold.frictionVector1);
|
||||
|
||||
@ -669,10 +669,10 @@ void ContactSolver::solve() {
|
||||
deltaLambda = contactManifold.friction1Impulse - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
Vector3 linearImpulseBody1 = -contactManifold.frictionVector1 * deltaLambda;
|
||||
Vector3 angularImpulseBody1 = -contactManifold.r1CrossT1 * deltaLambda;
|
||||
Vector3 linearImpulseBody2 = contactManifold.frictionVector1 * deltaLambda;
|
||||
Vector3 angularImpulseBody2 = contactManifold.r2CrossT1 * deltaLambda;
|
||||
vec3 linearImpulseBody1 = -contactManifold.frictionVector1 * deltaLambda;
|
||||
vec3 angularImpulseBody1 = -contactManifold.r1CrossT1 * deltaLambda;
|
||||
vec3 linearImpulseBody2 = contactManifold.frictionVector1 * deltaLambda;
|
||||
vec3 angularImpulseBody2 = contactManifold.r2CrossT1 * deltaLambda;
|
||||
const Impulse impulseFriction1(linearImpulseBody1, angularImpulseBody1,
|
||||
linearImpulseBody2, angularImpulseBody2);
|
||||
|
||||
@ -684,7 +684,7 @@ void ContactSolver::solve() {
|
||||
// Compute J*v
|
||||
deltaV = v2 + w2.cross(contactManifold.r2Friction)
|
||||
- v1 - w1.cross(contactManifold.r1Friction);
|
||||
Jv = deltaV.dot(contactManifold.frictionVector2);
|
||||
Jv = deltaV.dot(contactManifold.frictionvec2);
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
deltaLambda = -Jv * contactManifold.inverseFriction2Mass;
|
||||
@ -696,9 +696,9 @@ void ContactSolver::solve() {
|
||||
deltaLambda = contactManifold.friction2Impulse - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
linearImpulseBody1 = -contactManifold.frictionVector2 * deltaLambda;
|
||||
linearImpulseBody1 = -contactManifold.frictionvec2 * deltaLambda;
|
||||
angularImpulseBody1 = -contactManifold.r1CrossT2 * deltaLambda;
|
||||
linearImpulseBody2 = contactManifold.frictionVector2 * deltaLambda;
|
||||
linearImpulseBody2 = contactManifold.frictionvec2 * deltaLambda;
|
||||
angularImpulseBody2 = contactManifold.r2CrossT2 * deltaLambda;
|
||||
const Impulse impulseFriction2(linearImpulseBody1, angularImpulseBody1,
|
||||
linearImpulseBody2, angularImpulseBody2);
|
||||
@ -721,9 +721,9 @@ void ContactSolver::solve() {
|
||||
deltaLambda = contactManifold.frictionTwistImpulse - lambdaTemp;
|
||||
|
||||
// Compute the impulse P=J^T * lambda
|
||||
linearImpulseBody1 = Vector3(0.0, 0.0, 0.0);
|
||||
linearImpulseBody1 = vec3(0.0, 0.0, 0.0);
|
||||
angularImpulseBody1 = -contactManifold.normal * deltaLambda;
|
||||
linearImpulseBody2 = Vector3(0.0, 0.0, 0.0);;
|
||||
linearImpulseBody2 = vec3(0.0, 0.0, 0.0);;
|
||||
angularImpulseBody2 = contactManifold.normal * deltaLambda;
|
||||
const Impulse impulseTwistFriction(linearImpulseBody1, angularImpulseBody1,
|
||||
linearImpulseBody2, angularImpulseBody2);
|
||||
@ -736,12 +736,12 @@ void ContactSolver::solve() {
|
||||
if (contactManifold.rollingResistanceFactor > 0) {
|
||||
|
||||
// Compute J*v
|
||||
const Vector3 JvRolling = w2 - w1;
|
||||
const vec3 JvRolling = w2 - w1;
|
||||
|
||||
// Compute the Lagrange multiplier lambda
|
||||
Vector3 deltaLambdaRolling = contactManifold.inverseRollingResistance * (-JvRolling);
|
||||
vec3 deltaLambdaRolling = contactManifold.inverseRollingResistance * (-JvRolling);
|
||||
float rollingLimit = contactManifold.rollingResistanceFactor * sumPenetrationImpulse;
|
||||
Vector3 lambdaTempRolling = contactManifold.rollingResistanceImpulse;
|
||||
vec3 lambdaTempRolling = contactManifold.rollingResistanceImpulse;
|
||||
contactManifold.rollingResistanceImpulse = clamp(contactManifold.rollingResistanceImpulse +
|
||||
deltaLambdaRolling, rollingLimit);
|
||||
deltaLambdaRolling = contactManifold.rollingResistanceImpulse - lambdaTempRolling;
|
||||
@ -749,8 +749,8 @@ void ContactSolver::solve() {
|
||||
// Compute the impulse P=J^T * lambda
|
||||
angularImpulseBody1 = -deltaLambdaRolling;
|
||||
angularImpulseBody2 = deltaLambdaRolling;
|
||||
const Impulse impulseRolling(Vector3::zero(), angularImpulseBody1,
|
||||
Vector3::zero(), angularImpulseBody2);
|
||||
const Impulse impulseRolling(vec3::zero(), angularImpulseBody1,
|
||||
vec3::zero(), angularImpulseBody2);
|
||||
|
||||
// Apply the impulses to the bodies of the constraint
|
||||
applyImpulse(impulseRolling, contactManifold);
|
||||
@ -778,7 +778,7 @@ void ContactSolver::storeImpulses() {
|
||||
contactPoint.externalContact->setRollingResistanceImpulse(contactPoint.rollingResistanceImpulse);
|
||||
|
||||
contactPoint.externalContact->setFrictionVector1(contactPoint.frictionVector1);
|
||||
contactPoint.externalContact->setFrictionVector2(contactPoint.frictionVector2);
|
||||
contactPoint.externalContact->setFrictionvec2(contactPoint.frictionvec2);
|
||||
}
|
||||
|
||||
manifold.externalContactManifold->setFrictionImpulse1(manifold.friction1Impulse);
|
||||
@ -786,7 +786,7 @@ void ContactSolver::storeImpulses() {
|
||||
manifold.externalContactManifold->setFrictionTwistImpulse(manifold.frictionTwistImpulse);
|
||||
manifold.externalContactManifold->setRollingResistanceImpulse(manifold.rollingResistanceImpulse);
|
||||
manifold.externalContactManifold->setFrictionVector1(manifold.frictionVector1);
|
||||
manifold.externalContactManifold->setFrictionVector2(manifold.frictionVector2);
|
||||
manifold.externalContactManifold->setFrictionvec2(manifold.frictionvec2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -826,14 +826,14 @@ void ContactSolver::applySplitImpulse(const Impulse& impulse,
|
||||
|
||||
// Compute the two unit orthogonal vectors "t1" and "t2" that span the tangential friction plane
|
||||
// for a contact point. The two vectors have to be such that : t1 x t2 = contactNormal.
|
||||
void ContactSolver::computeFrictionVectors(const Vector3& deltaVelocity,
|
||||
void ContactSolver::computeFrictionVectors(const vec3& deltaVelocity,
|
||||
ContactPointSolver& contactPoint) const {
|
||||
|
||||
assert(contactPoint.normal.length() > 0.0);
|
||||
|
||||
// Compute the velocity difference vector in the tangential plane
|
||||
Vector3 normalVelocity = deltaVelocity.dot(contactPoint.normal) * contactPoint.normal;
|
||||
Vector3 tangentVelocity = deltaVelocity - normalVelocity;
|
||||
vec3 normalVelocity = deltaVelocity.dot(contactPoint.normal) * contactPoint.normal;
|
||||
vec3 tangentVelocity = deltaVelocity - normalVelocity;
|
||||
|
||||
// If the velocty difference in the tangential plane is not zero
|
||||
float lengthTangenVelocity = tangentVelocity.length();
|
||||
@ -851,19 +851,19 @@ void ContactSolver::computeFrictionVectors(const Vector3& deltaVelocity,
|
||||
|
||||
// The second friction vector is computed by the cross product of the firs
|
||||
// friction vector and the contact normal
|
||||
contactPoint.frictionVector2 =contactPoint.normal.cross(contactPoint.frictionVector1).getUnit();
|
||||
contactPoint.frictionvec2 =contactPoint.normal.cross(contactPoint.frictionVector1).safeNormalized();
|
||||
}
|
||||
|
||||
// Compute the two unit orthogonal vectors "t1" and "t2" that span the tangential friction plane
|
||||
// for a contact manifold. The two vectors have to be such that : t1 x t2 = contactNormal.
|
||||
void ContactSolver::computeFrictionVectors(const Vector3& deltaVelocity,
|
||||
void ContactSolver::computeFrictionVectors(const vec3& deltaVelocity,
|
||||
ContactManifoldSolver& contact) const {
|
||||
|
||||
assert(contact.normal.length() > 0.0);
|
||||
|
||||
// Compute the velocity difference vector in the tangential plane
|
||||
Vector3 normalVelocity = deltaVelocity.dot(contact.normal) * contact.normal;
|
||||
Vector3 tangentVelocity = deltaVelocity - normalVelocity;
|
||||
vec3 normalVelocity = deltaVelocity.dot(contact.normal) * contact.normal;
|
||||
vec3 tangentVelocity = deltaVelocity - normalVelocity;
|
||||
|
||||
// If the velocty difference in the tangential plane is not zero
|
||||
float lengthTangenVelocity = tangentVelocity.length();
|
||||
@ -881,7 +881,7 @@ void ContactSolver::computeFrictionVectors(const Vector3& deltaVelocity,
|
||||
|
||||
// The second friction vector is computed by the cross product of the firs
|
||||
// friction vector and the contact normal
|
||||
contact.frictionVector2 = contact.normal.cross(contact.frictionVector1).getUnit();
|
||||
contact.frictionvec2 = contact.normal.cross(contact.frictionVector1).safeNormalized();
|
||||
}
|
||||
|
||||
// Clean up the constraint solver
|
||||
|
@ -112,46 +112,46 @@ class ContactSolver {
|
||||
float penetrationSplitImpulse;
|
||||
|
||||
/// Accumulated rolling resistance impulse
|
||||
Vector3 rollingResistanceImpulse;
|
||||
vec3 rollingResistanceImpulse;
|
||||
|
||||
/// Normal vector of the contact
|
||||
Vector3 normal;
|
||||
vec3 normal;
|
||||
|
||||
/// First friction vector in the tangent plane
|
||||
Vector3 frictionVector1;
|
||||
vec3 frictionVector1;
|
||||
|
||||
/// Second friction vector in the tangent plane
|
||||
Vector3 frictionVector2;
|
||||
vec3 frictionvec2;
|
||||
|
||||
/// Old first friction vector in the tangent plane
|
||||
Vector3 oldFrictionVector1;
|
||||
vec3 oldFrictionVector1;
|
||||
|
||||
/// Old second friction vector in the tangent plane
|
||||
Vector3 oldFrictionVector2;
|
||||
vec3 oldFrictionvec2;
|
||||
|
||||
/// Vector from the body 1 center to the contact point
|
||||
Vector3 r1;
|
||||
vec3 r1;
|
||||
|
||||
/// Vector from the body 2 center to the contact point
|
||||
Vector3 r2;
|
||||
vec3 r2;
|
||||
|
||||
/// Cross product of r1 with 1st friction vector
|
||||
Vector3 r1CrossT1;
|
||||
vec3 r1CrossT1;
|
||||
|
||||
/// Cross product of r1 with 2nd friction vector
|
||||
Vector3 r1CrossT2;
|
||||
vec3 r1CrossT2;
|
||||
|
||||
/// Cross product of r2 with 1st friction vector
|
||||
Vector3 r2CrossT1;
|
||||
vec3 r2CrossT1;
|
||||
|
||||
/// Cross product of r2 with 2nd friction vector
|
||||
Vector3 r2CrossT2;
|
||||
vec3 r2CrossT2;
|
||||
|
||||
/// Cross product of r1 with the contact normal
|
||||
Vector3 r1CrossN;
|
||||
vec3 r1CrossN;
|
||||
|
||||
/// Cross product of r2 with the contact normal
|
||||
Vector3 r2CrossN;
|
||||
vec3 r2CrossN;
|
||||
|
||||
/// Penetration depth
|
||||
float penetrationDepth;
|
||||
@ -195,10 +195,10 @@ class ContactSolver {
|
||||
float massInverseBody2;
|
||||
|
||||
/// Inverse inertia tensor of body 1
|
||||
Matrix3x3 inverseInertiaTensorBody1;
|
||||
etk::Matrix3x3 inverseInertiaTensorBody1;
|
||||
|
||||
/// Inverse inertia tensor of body 2
|
||||
Matrix3x3 inverseInertiaTensorBody2;
|
||||
etk::Matrix3x3 inverseInertiaTensorBody2;
|
||||
|
||||
/// Contact point constraints
|
||||
ContactPointSolver contacts[MAX_CONTACT_POINTS_IN_MANIFOLD];
|
||||
@ -227,31 +227,31 @@ class ContactSolver {
|
||||
// - Variables used when friction constraints are apply at the center of the manifold-//
|
||||
|
||||
/// Average normal vector of the contact manifold
|
||||
Vector3 normal;
|
||||
vec3 normal;
|
||||
|
||||
/// Point on body 1 where to apply the friction constraints
|
||||
Vector3 frictionPointBody1;
|
||||
vec3 frictionPointBody1;
|
||||
|
||||
/// Point on body 2 where to apply the friction constraints
|
||||
Vector3 frictionPointBody2;
|
||||
vec3 frictionPointBody2;
|
||||
|
||||
/// R1 vector for the friction constraints
|
||||
Vector3 r1Friction;
|
||||
vec3 r1Friction;
|
||||
|
||||
/// R2 vector for the friction constraints
|
||||
Vector3 r2Friction;
|
||||
vec3 r2Friction;
|
||||
|
||||
/// Cross product of r1 with 1st friction vector
|
||||
Vector3 r1CrossT1;
|
||||
vec3 r1CrossT1;
|
||||
|
||||
/// Cross product of r1 with 2nd friction vector
|
||||
Vector3 r1CrossT2;
|
||||
vec3 r1CrossT2;
|
||||
|
||||
/// Cross product of r2 with 1st friction vector
|
||||
Vector3 r2CrossT1;
|
||||
vec3 r2CrossT1;
|
||||
|
||||
/// Cross product of r2 with 2nd friction vector
|
||||
Vector3 r2CrossT2;
|
||||
vec3 r2CrossT2;
|
||||
|
||||
/// Matrix K for the first friction constraint
|
||||
float inverseFriction1Mass;
|
||||
@ -263,19 +263,19 @@ class ContactSolver {
|
||||
float inverseTwistFrictionMass;
|
||||
|
||||
/// Matrix K for the rolling resistance constraint
|
||||
Matrix3x3 inverseRollingResistance;
|
||||
etk::Matrix3x3 inverseRollingResistance;
|
||||
|
||||
/// First friction direction at contact manifold center
|
||||
Vector3 frictionVector1;
|
||||
vec3 frictionVector1;
|
||||
|
||||
/// Second friction direction at contact manifold center
|
||||
Vector3 frictionVector2;
|
||||
vec3 frictionvec2;
|
||||
|
||||
/// Old 1st friction direction at contact manifold center
|
||||
Vector3 oldFrictionVector1;
|
||||
vec3 oldFrictionVector1;
|
||||
|
||||
/// Old 2nd friction direction at contact manifold center
|
||||
Vector3 oldFrictionVector2;
|
||||
vec3 oldFrictionvec2;
|
||||
|
||||
/// First friction direction impulse at manifold center
|
||||
float friction1Impulse;
|
||||
@ -287,7 +287,7 @@ class ContactSolver {
|
||||
float frictionTwistImpulse;
|
||||
|
||||
/// Rolling resistance impulse
|
||||
Vector3 rollingResistanceImpulse;
|
||||
vec3 rollingResistanceImpulse;
|
||||
};
|
||||
|
||||
// -------------------- Constants --------------------- //
|
||||
@ -304,10 +304,10 @@ class ContactSolver {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Split linear velocities for the position contact solver (split impulse)
|
||||
Vector3* m_splitLinearVelocities;
|
||||
vec3* m_splitLinearVelocities;
|
||||
|
||||
/// Split angular velocities for the position contact solver (split impulse)
|
||||
Vector3* m_splitAngularVelocities;
|
||||
vec3* m_splitAngularVelocities;
|
||||
|
||||
/// Current time step
|
||||
float m_timeStep;
|
||||
@ -319,10 +319,10 @@ class ContactSolver {
|
||||
uint32_t m_numberContactManifolds;
|
||||
|
||||
/// Array of linear velocities
|
||||
Vector3* mLinearVelocities;
|
||||
vec3* mLinearVelocities;
|
||||
|
||||
/// Array of angular velocities
|
||||
Vector3* mAngularVelocities;
|
||||
vec3* mAngularVelocities;
|
||||
|
||||
/// Reference to the map of rigid body to their index in the constrained velocities array
|
||||
const std::map<RigidBody*, uint32_t>& m_mapBodyToConstrainedVelocityIndex;
|
||||
@ -363,13 +363,13 @@ class ContactSolver {
|
||||
/// Compute the two unit orthogonal vectors "t1" and "t2" that span the tangential friction
|
||||
/// plane for a contact point. The two vectors have to be
|
||||
/// such that : t1 x t2 = contactNormal.
|
||||
void computeFrictionVectors(const Vector3& deltaVelocity,
|
||||
void computeFrictionVectors(const vec3& deltaVelocity,
|
||||
ContactPointSolver &contactPoint) const;
|
||||
|
||||
/// Compute the two unit orthogonal vectors "t1" and "t2" that span the tangential friction
|
||||
/// plane for a contact manifold. The two vectors have to be
|
||||
/// such that : t1 x t2 = contactNormal.
|
||||
void computeFrictionVectors(const Vector3& deltaVelocity,
|
||||
void computeFrictionVectors(const vec3& deltaVelocity,
|
||||
ContactManifoldSolver& contactPoint) const;
|
||||
|
||||
/// Compute a penetration constraint impulse
|
||||
@ -398,12 +398,12 @@ class ContactSolver {
|
||||
void initializeForIsland(float dt, Island* island);
|
||||
|
||||
/// Set the split velocities arrays
|
||||
void setSplitVelocitiesArrays(Vector3* splitLinearVelocities,
|
||||
Vector3* splitAngularVelocities);
|
||||
void setSplitVelocitiesArrays(vec3* splitLinearVelocities,
|
||||
vec3* splitAngularVelocities);
|
||||
|
||||
/// Set the constrained velocities arrays
|
||||
void setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
|
||||
Vector3* constrainedAngularVelocities);
|
||||
void setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
vec3* constrainedAngularVelocities);
|
||||
|
||||
/// Warm start the solver.
|
||||
void warmStart();
|
||||
@ -430,8 +430,8 @@ class ContactSolver {
|
||||
};
|
||||
|
||||
// Set the split velocities arrays
|
||||
inline void ContactSolver::setSplitVelocitiesArrays(Vector3* splitLinearVelocities,
|
||||
Vector3* splitAngularVelocities) {
|
||||
inline void ContactSolver::setSplitVelocitiesArrays(vec3* splitLinearVelocities,
|
||||
vec3* splitAngularVelocities) {
|
||||
assert(splitLinearVelocities != NULL);
|
||||
assert(splitAngularVelocities != NULL);
|
||||
m_splitLinearVelocities = splitLinearVelocities;
|
||||
@ -439,8 +439,8 @@ inline void ContactSolver::setSplitVelocitiesArrays(Vector3* splitLinearVelociti
|
||||
}
|
||||
|
||||
// Set the constrained velocities arrays
|
||||
inline void ContactSolver::setConstrainedVelocitiesArrays(Vector3* constrainedLinearVelocities,
|
||||
Vector3* constrainedAngularVelocities) {
|
||||
inline void ContactSolver::setConstrainedVelocitiesArrays(vec3* constrainedLinearVelocities,
|
||||
vec3* constrainedAngularVelocities) {
|
||||
assert(constrainedLinearVelocities != NULL);
|
||||
assert(constrainedAngularVelocities != NULL);
|
||||
mLinearVelocities = constrainedLinearVelocities;
|
||||
@ -509,9 +509,9 @@ inline const Impulse ContactSolver::computeFriction1Impulse(float deltaLambda,
|
||||
inline const Impulse ContactSolver::computeFriction2Impulse(float deltaLambda,
|
||||
const ContactPointSolver& contactPoint)
|
||||
const {
|
||||
return Impulse(-contactPoint.frictionVector2 * deltaLambda,
|
||||
return Impulse(-contactPoint.frictionvec2 * deltaLambda,
|
||||
-contactPoint.r1CrossT2 * deltaLambda,
|
||||
contactPoint.frictionVector2 * deltaLambda,
|
||||
contactPoint.frictionvec2 * deltaLambda,
|
||||
contactPoint.r2CrossT2 * deltaLambda);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ using namespace std;
|
||||
/**
|
||||
* @param gravity Gravity vector in the world (in meters per second squared)
|
||||
*/
|
||||
DynamicsWorld::DynamicsWorld(const Vector3 &gravity)
|
||||
DynamicsWorld::DynamicsWorld(const vec3 &gravity)
|
||||
: CollisionWorld(),
|
||||
m_contactSolver(m_mapBodyToConstrainedVelocityIndex),
|
||||
m_constraintSolver(m_mapBodyToConstrainedVelocityIndex),
|
||||
@ -168,8 +168,8 @@ void DynamicsWorld::int32_tegrateRigidBodiesPositions() {
|
||||
|
||||
// Get the constrained velocity
|
||||
uint32_t indexArray = m_mapBodyToConstrainedVelocityIndex.find(bodies[b])->second;
|
||||
Vector3 newLinVelocity = m_constrainedLinearVelocities[indexArray];
|
||||
Vector3 newAngVelocity = m_constrainedAngularVelocities[indexArray];
|
||||
vec3 newLinVelocity = m_constrainedLinearVelocities[indexArray];
|
||||
vec3 newAngVelocity = m_constrainedAngularVelocities[indexArray];
|
||||
|
||||
// Add the split impulse velocity from Contact Solver (only used
|
||||
// to update the position)
|
||||
@ -180,14 +180,14 @@ void DynamicsWorld::int32_tegrateRigidBodiesPositions() {
|
||||
}
|
||||
|
||||
// Get current position and orientation of the body
|
||||
const Vector3& currentPosition = bodies[b]->m_centerOfMassWorld;
|
||||
const Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation();
|
||||
const vec3& currentPosition = bodies[b]->m_centerOfMassWorld;
|
||||
const etk::Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation();
|
||||
|
||||
// Update the new constrained position and orientation of the body
|
||||
m_constrainedPositions[indexArray] = currentPosition + newLinVelocity * m_timeStep;
|
||||
m_constrainedOrientations[indexArray] = currentOrientation +
|
||||
Quaternion(0, newAngVelocity) *
|
||||
currentOrientation * float(0.5) * m_timeStep;
|
||||
etk::Quaternion(0, newAngVelocity) *
|
||||
currentOrientation * 0.5f * m_timeStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,7 +215,7 @@ void DynamicsWorld::updateBodiesState() {
|
||||
bodies[b]->m_centerOfMassWorld = m_constrainedPositions[index];
|
||||
|
||||
// Update the orientation of the body
|
||||
bodies[b]->m_transform.setOrientation(m_constrainedOrientations[index].getUnit());
|
||||
bodies[b]->m_transform.setOrientation(m_constrainedOrientations[index].safeNormalized());
|
||||
|
||||
// Update the transform of the body (using the new center of mass and new orientation)
|
||||
bodies[b]->updateTransformWithCenterOfMass();
|
||||
@ -238,12 +238,12 @@ void DynamicsWorld::initVelocityArrays() {
|
||||
}
|
||||
m_numberBodiesCapacity = nbBodies;
|
||||
// TODO : Use better memory allocation here
|
||||
m_splitLinearVelocities = new Vector3[m_numberBodiesCapacity];
|
||||
m_splitAngularVelocities = new Vector3[m_numberBodiesCapacity];
|
||||
m_constrainedLinearVelocities = new Vector3[m_numberBodiesCapacity];
|
||||
m_constrainedAngularVelocities = new Vector3[m_numberBodiesCapacity];
|
||||
m_constrainedPositions = new Vector3[m_numberBodiesCapacity];
|
||||
m_constrainedOrientations = new Quaternion[m_numberBodiesCapacity];
|
||||
m_splitLinearVelocities = new vec3[m_numberBodiesCapacity];
|
||||
m_splitAngularVelocities = new vec3[m_numberBodiesCapacity];
|
||||
m_constrainedLinearVelocities = new vec3[m_numberBodiesCapacity];
|
||||
m_constrainedAngularVelocities = new vec3[m_numberBodiesCapacity];
|
||||
m_constrainedPositions = new vec3[m_numberBodiesCapacity];
|
||||
m_constrainedOrientations = new etk::Quaternion[m_numberBodiesCapacity];
|
||||
assert(m_splitLinearVelocities != NULL);
|
||||
assert(m_splitAngularVelocities != NULL);
|
||||
assert(m_constrainedLinearVelocities != NULL);
|
||||
@ -254,8 +254,8 @@ void DynamicsWorld::initVelocityArrays() {
|
||||
|
||||
// Reset the velocities arrays
|
||||
for (uint32_t i=0; i<m_numberBodiesCapacity; i++) {
|
||||
m_splitLinearVelocities[i].setToZero();
|
||||
m_splitAngularVelocities[i].setToZero();
|
||||
m_splitLinearVelocities[i].setZero();
|
||||
m_splitAngularVelocities[i].setZero();
|
||||
}
|
||||
|
||||
// Initialize the map of body indexes in the velocity arrays
|
||||
@ -293,8 +293,8 @@ void DynamicsWorld::int32_tegrateRigidBodiesVelocities() {
|
||||
// Insert the body int32_to the map of constrained velocities
|
||||
uint32_t indexBody = m_mapBodyToConstrainedVelocityIndex.find(bodies[b])->second;
|
||||
|
||||
assert(m_splitLinearVelocities[indexBody] == Vector3(0, 0, 0));
|
||||
assert(m_splitAngularVelocities[indexBody] == Vector3(0, 0, 0));
|
||||
assert(m_splitLinearVelocities[indexBody] == vec3(0, 0, 0));
|
||||
assert(m_splitAngularVelocities[indexBody] == vec3(0, 0, 0));
|
||||
|
||||
// Integrate the external force to get the new velocity of the body
|
||||
m_constrainedLinearVelocities[indexBody] = bodies[b]->getLinearVelocity() +
|
||||
@ -326,8 +326,8 @@ void DynamicsWorld::int32_tegrateRigidBodiesVelocities() {
|
||||
// => v2 = v1 * (1 - c * dt)
|
||||
float linDampingFactor = bodies[b]->getLinearDamping();
|
||||
float angDampingFactor = bodies[b]->getAngularDamping();
|
||||
float linearDamping = pow(float(1.0) - linDampingFactor, m_timeStep);
|
||||
float angularDamping = pow(float(1.0) - angDampingFactor, m_timeStep);
|
||||
float linearDamping = pow(1.0f - linDampingFactor, m_timeStep);
|
||||
float angularDamping = pow(1.0f - angDampingFactor, m_timeStep);
|
||||
m_constrainedLinearVelocities[indexBody] *= linearDamping;
|
||||
m_constrainedAngularVelocities[indexBody] *= angularDamping;
|
||||
|
||||
@ -422,10 +422,10 @@ void DynamicsWorld::solvePositionCorrection() {
|
||||
|
||||
// Create a rigid body int32_to the physics world
|
||||
/**
|
||||
* @param transform Transformation from body local-space to world-space
|
||||
* @param transform etk::Transform3Dation from body local-space to world-space
|
||||
* @return A pointer to the body that has been created in the world
|
||||
*/
|
||||
RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
|
||||
RigidBody* DynamicsWorld::createRigidBody(const etk::Transform3D& transform) {
|
||||
|
||||
// Compute the body ID
|
||||
bodyindex bodyID = computeNextAvailableBodyID();
|
||||
@ -794,13 +794,13 @@ void DynamicsWorld::updateSleepingBodies() {
|
||||
if (bodies[b]->getType() == STATIC) continue;
|
||||
|
||||
// If the body is velocity is large enough to stay awake
|
||||
if (bodies[b]->getLinearVelocity().lengthSquare() > sleepLinearVelocitySquare ||
|
||||
bodies[b]->getAngularVelocity().lengthSquare() > sleepAngularVelocitySquare ||
|
||||
if (bodies[b]->getLinearVelocity().length2() > sleepLinearVelocitySquare ||
|
||||
bodies[b]->getAngularVelocity().length2() > sleepAngularVelocitySquare ||
|
||||
!bodies[b]->isAllowedToSleep()) {
|
||||
|
||||
// Reset the sleep time of the body
|
||||
bodies[b]->m_sleepTime = float(0.0);
|
||||
minSleepTime = float(0.0);
|
||||
bodies[b]->m_sleepTime = 0.0f;
|
||||
minSleepTime = 0.0f;
|
||||
}
|
||||
else { // If the body velocity is bellow the sleeping velocity threshold
|
||||
|
||||
|
@ -51,7 +51,7 @@ class DynamicsWorld : public CollisionWorld {
|
||||
std::set<Joint*> m_joints;
|
||||
|
||||
/// Gravity vector of the world
|
||||
Vector3 m_gravity;
|
||||
vec3 m_gravity;
|
||||
|
||||
/// Current frame time step (in seconds)
|
||||
float m_timeStep;
|
||||
@ -61,23 +61,23 @@ class DynamicsWorld : public CollisionWorld {
|
||||
|
||||
/// Array of constrained linear velocities (state of the linear velocities
|
||||
/// after solving the constraints)
|
||||
Vector3* m_constrainedLinearVelocities;
|
||||
vec3* m_constrainedLinearVelocities;
|
||||
|
||||
/// Array of constrained angular velocities (state of the angular velocities
|
||||
/// after solving the constraints)
|
||||
Vector3* m_constrainedAngularVelocities;
|
||||
vec3* m_constrainedAngularVelocities;
|
||||
|
||||
/// Split linear velocities for the position contact solver (split impulse)
|
||||
Vector3* m_splitLinearVelocities;
|
||||
vec3* m_splitLinearVelocities;
|
||||
|
||||
/// Split angular velocities for the position contact solver (split impulse)
|
||||
Vector3* m_splitAngularVelocities;
|
||||
vec3* m_splitAngularVelocities;
|
||||
|
||||
/// Array of constrained rigid bodies position (for position error correction)
|
||||
Vector3* m_constrainedPositions;
|
||||
vec3* m_constrainedPositions;
|
||||
|
||||
/// Array of constrained rigid bodies orientation (for position error correction)
|
||||
Quaternion* m_constrainedOrientations;
|
||||
etk::Quaternion* m_constrainedOrientations;
|
||||
|
||||
/// Map body to their index in the constrained velocities array
|
||||
std::map<RigidBody*, uint32_t> m_mapBodyToConstrainedVelocityIndex;
|
||||
@ -122,8 +122,8 @@ class DynamicsWorld : public CollisionWorld {
|
||||
void resetBodiesForceAndTorque();
|
||||
|
||||
/// Update the position and orientation of a body
|
||||
void updatePositionAndOrientationOfBody(RigidBody* body, Vector3 newLinVelocity,
|
||||
Vector3 newAngVelocity);
|
||||
void updatePositionAndOrientationOfBody(RigidBody* body, vec3 newLinVelocity,
|
||||
vec3 newAngVelocity);
|
||||
|
||||
/// Compute and set the int32_terpolation factor to all bodies
|
||||
void setInterpolationFactorToAllBodies();
|
||||
@ -160,7 +160,7 @@ class DynamicsWorld : public CollisionWorld {
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
DynamicsWorld(const Vector3& m_gravity);
|
||||
DynamicsWorld(const vec3& m_gravity);
|
||||
|
||||
/// Destructor
|
||||
virtual ~DynamicsWorld();
|
||||
@ -191,7 +191,7 @@ class DynamicsWorld : public CollisionWorld {
|
||||
void setIsSolveFrictionAtContactManifoldCenterActive(bool isActive);
|
||||
|
||||
/// Create a rigid body int32_to the physics world.
|
||||
RigidBody* createRigidBody(const Transform& transform);
|
||||
RigidBody* createRigidBody(const etk::Transform3D& transform);
|
||||
|
||||
/// Destroy a rigid body and all the joints which it belongs
|
||||
void destroyRigidBody(RigidBody* rigidBody);
|
||||
@ -203,10 +203,10 @@ class DynamicsWorld : public CollisionWorld {
|
||||
void destroyJoint(Joint* joint);
|
||||
|
||||
/// Return the gravity vector of the world
|
||||
Vector3 getGravity() const;
|
||||
vec3 getGravity() const;
|
||||
|
||||
/// Set the gravity vector of the world
|
||||
void setGravity(Vector3& gravity);
|
||||
void setGravity(vec3& gravity);
|
||||
|
||||
/// Return if the gravity is on
|
||||
bool isGravityEnabled() const;
|
||||
@ -290,8 +290,8 @@ inline void DynamicsWorld::resetBodiesForceAndTorque() {
|
||||
// For each body of the world
|
||||
std::set<RigidBody*>::iterator it;
|
||||
for (it = m_rigidBodies.begin(); it != m_rigidBodies.end(); ++it) {
|
||||
(*it)->m_externalForce.setToZero();
|
||||
(*it)->m_externalTorque.setToZero();
|
||||
(*it)->m_externalForce.setZero();
|
||||
(*it)->m_externalTorque.setZero();
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,7 +363,7 @@ inline void DynamicsWorld::setIsSolveFrictionAtContactManifoldCenterActive(bool
|
||||
/**
|
||||
* @return The current gravity vector (in meter per seconds squared)
|
||||
*/
|
||||
inline Vector3 DynamicsWorld::getGravity() const {
|
||||
inline vec3 DynamicsWorld::getGravity() const {
|
||||
return m_gravity;
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ inline Vector3 DynamicsWorld::getGravity() const {
|
||||
/**
|
||||
* @param gravity The gravity vector (in meter per seconds squared)
|
||||
*/
|
||||
inline void DynamicsWorld::setGravity(Vector3& gravity) {
|
||||
inline void DynamicsWorld::setGravity(vec3& gravity) {
|
||||
m_gravity = gravity;
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ inline float DynamicsWorld::getSleepLinearVelocity() const {
|
||||
* @param sleepLinearVelocity The sleep linear velocity (in meters per second)
|
||||
*/
|
||||
inline void DynamicsWorld::setSleepLinearVelocity(float sleepLinearVelocity) {
|
||||
assert(sleepLinearVelocity >= float(0.0));
|
||||
assert(sleepLinearVelocity >= 0.0f);
|
||||
m_sleepLinearVelocity = sleepLinearVelocity;
|
||||
}
|
||||
|
||||
@ -468,7 +468,7 @@ inline float DynamicsWorld::getSleepAngularVelocity() const {
|
||||
* @param sleepAngularVelocity The sleep angular velocity (in radian per second)
|
||||
*/
|
||||
inline void DynamicsWorld::setSleepAngularVelocity(float sleepAngularVelocity) {
|
||||
assert(sleepAngularVelocity >= float(0.0));
|
||||
assert(sleepAngularVelocity >= 0.0f);
|
||||
m_sleepAngularVelocity = sleepAngularVelocity;
|
||||
}
|
||||
|
||||
@ -486,7 +486,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) {
|
||||
assert(timeBeforeSleep >= float(0.0));
|
||||
assert(timeBeforeSleep >= 0.0f);
|
||||
m_timeBeforeSleep = timeBeforeSleep;
|
||||
}
|
||||
|
||||
|
@ -28,22 +28,22 @@ struct Impulse {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Linear impulse applied to the first body
|
||||
const Vector3 linearImpulseBody1;
|
||||
const vec3 linearImpulseBody1;
|
||||
|
||||
/// Angular impulse applied to the first body
|
||||
const Vector3 angularImpulseBody1;
|
||||
const vec3 angularImpulseBody1;
|
||||
|
||||
/// Linear impulse applied to the second body
|
||||
const Vector3 linearImpulseBody2;
|
||||
const vec3 linearImpulseBody2;
|
||||
|
||||
/// Angular impulse applied to the second body
|
||||
const Vector3 angularImpulseBody2;
|
||||
const vec3 angularImpulseBody2;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Impulse(const Vector3& initLinearImpulseBody1, const Vector3& initAngularImpulseBody1,
|
||||
const Vector3& initLinearImpulseBody2, const Vector3& initAngularImpulseBody2)
|
||||
Impulse(const vec3& initLinearImpulseBody1, const vec3& initAngularImpulseBody1,
|
||||
const vec3& initLinearImpulseBody2, const vec3& initAngularImpulseBody2)
|
||||
: linearImpulseBody1(initLinearImpulseBody1),
|
||||
angularImpulseBody1(initAngularImpulseBody1),
|
||||
linearImpulseBody2(initLinearImpulseBody2),
|
||||
|
@ -82,7 +82,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) {
|
||||
assert(bounciness >= float(0.0) && bounciness <= float(1.0));
|
||||
assert(bounciness >= 0.0f && bounciness <= 1.0f);
|
||||
m_bounciness = bounciness;
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ inline float Material::getFrictionCoefficient() const {
|
||||
* @param frictionCoefficient Friction coefficient (positive value)
|
||||
*/
|
||||
inline void Material::setFrictionCoefficient(float frictionCoefficient) {
|
||||
assert(frictionCoefficient >= float(0.0));
|
||||
assert(frictionCoefficient >= 0.0f);
|
||||
m_frictionCoefficient = frictionCoefficient;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ class OverlappingPair {
|
||||
ContactManifoldSet m_contactManifoldSet;
|
||||
|
||||
/// Cached previous separating axis
|
||||
Vector3 m_cachedSeparatingAxis;
|
||||
vec3 m_cachedSeparatingAxis;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
@ -68,10 +68,10 @@ class OverlappingPair {
|
||||
void update();
|
||||
|
||||
/// Return the cached separating axis
|
||||
Vector3 getCachedSeparatingAxis() const;
|
||||
vec3 getCachedSeparatingAxis() const;
|
||||
|
||||
/// Set the cached separating axis
|
||||
void setCachedSeparatingAxis(const Vector3& axis);
|
||||
void setCachedSeparatingAxis(const vec3& axis);
|
||||
|
||||
/// Return the number of contacts in the cache
|
||||
uint32_t getNbContactPoints() const;
|
||||
@ -114,12 +114,12 @@ inline void OverlappingPair::update() {
|
||||
}
|
||||
|
||||
// Return the cached separating axis
|
||||
inline Vector3 OverlappingPair::getCachedSeparatingAxis() const {
|
||||
inline vec3 OverlappingPair::getCachedSeparatingAxis() const {
|
||||
return m_cachedSeparatingAxis;
|
||||
}
|
||||
|
||||
// Set the cached separating axis
|
||||
inline void OverlappingPair::setCachedSeparatingAxis(const Vector3& axis) {
|
||||
inline void OverlappingPair::setCachedSeparatingAxis(const vec3& axis) {
|
||||
m_cachedSeparatingAxis = axis;
|
||||
}
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Matrix2x2.h>
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor of the class Matrix2x2
|
||||
Matrix2x2::Matrix2x2() {
|
||||
|
||||
// Initialize all values in the matrix to zero
|
||||
setAllValues(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// Constructor
|
||||
Matrix2x2::Matrix2x2(float value) {
|
||||
setAllValues(value, value, value, value);
|
||||
}
|
||||
|
||||
// Constructor with arguments
|
||||
Matrix2x2::Matrix2x2(float a1, float a2, float b1, float b2) {
|
||||
|
||||
// Initialize the matrix with the values
|
||||
setAllValues(a1, a2, b1, b2);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Matrix2x2::~Matrix2x2() {
|
||||
|
||||
}
|
||||
|
||||
// Copy-constructor
|
||||
Matrix2x2::Matrix2x2(const Matrix2x2& matrix) {
|
||||
setAllValues(matrix.mRows[0][0], matrix.mRows[0][1],
|
||||
matrix.mRows[1][0], matrix.mRows[1][1]);
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
Matrix2x2& Matrix2x2::operator=(const Matrix2x2& matrix) {
|
||||
|
||||
// Check for self-assignment
|
||||
if (&matrix != this) {
|
||||
setAllValues(matrix.mRows[0][0], matrix.mRows[0][1],
|
||||
matrix.mRows[1][0], matrix.mRows[1][1]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return the inverse matrix
|
||||
Matrix2x2 Matrix2x2::getInverse() const {
|
||||
|
||||
// Compute the determinant of the matrix
|
||||
float determinant = getDeterminant();
|
||||
|
||||
// Check if the determinant is equal to zero
|
||||
assert(std::abs(determinant) > MACHINE_EPSILON);
|
||||
|
||||
float invDeterminant = float(1.0) / determinant;
|
||||
|
||||
Matrix2x2 tempMatrix(mRows[1][1], -mRows[0][1], -mRows[1][0], mRows[0][0]);
|
||||
|
||||
// Return the inverse matrix
|
||||
return (invDeterminant * tempMatrix);
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cassert>
|
||||
#include <ephysics/mathematics/Vector2.h>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class Matrix2x2
|
||||
/**
|
||||
* This class represents a 2x2 matrix.
|
||||
*/
|
||||
class Matrix2x2 {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Rows of the matrix;
|
||||
Vector2 mRows[2];
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Matrix2x2();
|
||||
|
||||
/// Constructor
|
||||
Matrix2x2(float value);
|
||||
|
||||
/// Constructor
|
||||
Matrix2x2(float a1, float a2, float b1, float b2);
|
||||
|
||||
/// Destructor
|
||||
~Matrix2x2();
|
||||
|
||||
/// Copy-constructor
|
||||
Matrix2x2(const Matrix2x2& matrix);
|
||||
|
||||
/// Assignment operator
|
||||
Matrix2x2& operator=(const Matrix2x2& matrix);
|
||||
|
||||
/// Set all the values in the matrix
|
||||
void setAllValues(float a1, float a2, float b1, float b2);
|
||||
|
||||
/// Set the matrix to zero
|
||||
void setToZero();
|
||||
|
||||
/// Return a column
|
||||
Vector2 getColumn(int32_t i) const;
|
||||
|
||||
/// Return a row
|
||||
Vector2 getRow(int32_t i) const;
|
||||
|
||||
/// Return the transpose matrix
|
||||
Matrix2x2 getTranspose() const;
|
||||
|
||||
/// Return the determinant of the matrix
|
||||
float getDeterminant() const;
|
||||
|
||||
/// Return the trace of the matrix
|
||||
float getTrace() const;
|
||||
|
||||
/// Return the inverse matrix
|
||||
Matrix2x2 getInverse() const;
|
||||
|
||||
/// Return the matrix with absolute values
|
||||
Matrix2x2 getAbsoluteMatrix() const;
|
||||
|
||||
/// Set the matrix to the identity matrix
|
||||
void setToIdentity();
|
||||
|
||||
/// Return the 2x2 identity matrix
|
||||
static Matrix2x2 identity();
|
||||
|
||||
/// Return the 2x2 zero matrix
|
||||
static Matrix2x2 zero();
|
||||
|
||||
/// Overloaded operator for addition
|
||||
friend Matrix2x2 operator+(const Matrix2x2& matrix1, const Matrix2x2& matrix2);
|
||||
|
||||
/// Overloaded operator for substraction
|
||||
friend Matrix2x2 operator-(const Matrix2x2& matrix1, const Matrix2x2& matrix2);
|
||||
|
||||
/// Overloaded operator for the negative of the matrix
|
||||
friend Matrix2x2 operator-(const Matrix2x2& matrix);
|
||||
|
||||
/// Overloaded operator for multiplication with a number
|
||||
friend Matrix2x2 operator*(float nb, const Matrix2x2& matrix);
|
||||
|
||||
/// Overloaded operator for multiplication with a matrix
|
||||
friend Matrix2x2 operator*(const Matrix2x2& matrix, float nb);
|
||||
|
||||
/// Overloaded operator for matrix multiplication
|
||||
friend Matrix2x2 operator*(const Matrix2x2& matrix1, const Matrix2x2& matrix2);
|
||||
|
||||
/// Overloaded operator for multiplication with a vector
|
||||
friend Vector2 operator*(const Matrix2x2& matrix, const Vector2& vector);
|
||||
|
||||
/// Overloaded operator for equality condition
|
||||
bool operator==(const Matrix2x2& matrix) const;
|
||||
|
||||
/// Overloaded operator for the is different condition
|
||||
bool operator!= (const Matrix2x2& matrix) const;
|
||||
|
||||
/// Overloaded operator for addition with assignment
|
||||
Matrix2x2& operator+=(const Matrix2x2& matrix);
|
||||
|
||||
/// Overloaded operator for substraction with assignment
|
||||
Matrix2x2& operator-=(const Matrix2x2& matrix);
|
||||
|
||||
/// Overloaded operator for multiplication with a number with assignment
|
||||
Matrix2x2& operator*=(float nb);
|
||||
|
||||
/// Overloaded operator to read element of the matrix.
|
||||
const Vector2& operator[](int32_t row) const;
|
||||
|
||||
/// Overloaded operator to read/write element of the matrix.
|
||||
Vector2& operator[](int32_t row);
|
||||
};
|
||||
|
||||
// Method to set all the values in the matrix
|
||||
inline void Matrix2x2::setAllValues(float a1, float a2,
|
||||
float b1, float b2) {
|
||||
mRows[0][0] = a1; mRows[0][1] = a2;
|
||||
mRows[1][0] = b1; mRows[1][1] = b2;
|
||||
}
|
||||
|
||||
// Set the matrix to zero
|
||||
inline void Matrix2x2::setToZero() {
|
||||
mRows[0].setToZero();
|
||||
mRows[1].setToZero();
|
||||
}
|
||||
|
||||
// Return a column
|
||||
inline Vector2 Matrix2x2::getColumn(int32_t i) const {
|
||||
assert(i>= 0 && i<2);
|
||||
return Vector2(mRows[0][i], mRows[1][i]);
|
||||
}
|
||||
|
||||
// Return a row
|
||||
inline Vector2 Matrix2x2::getRow(int32_t i) const {
|
||||
assert(i>= 0 && i<2);
|
||||
return mRows[i];
|
||||
}
|
||||
|
||||
// Return the transpose matrix
|
||||
inline Matrix2x2 Matrix2x2::getTranspose() const {
|
||||
|
||||
// Return the transpose matrix
|
||||
return Matrix2x2(mRows[0][0], mRows[1][0],
|
||||
mRows[0][1], mRows[1][1]);
|
||||
}
|
||||
|
||||
// Return the determinant of the matrix
|
||||
inline float Matrix2x2::getDeterminant() const {
|
||||
|
||||
// Compute and return the determinant of the matrix
|
||||
return mRows[0][0] * mRows[1][1] - mRows[1][0] * mRows[0][1];
|
||||
}
|
||||
|
||||
// Return the trace of the matrix
|
||||
inline float Matrix2x2::getTrace() const {
|
||||
|
||||
// Compute and return the trace
|
||||
return (mRows[0][0] + mRows[1][1]);
|
||||
}
|
||||
|
||||
// Set the matrix to the identity matrix
|
||||
inline void Matrix2x2::setToIdentity() {
|
||||
mRows[0][0] = 1.0; mRows[0][1] = 0.0;
|
||||
mRows[1][0] = 0.0; mRows[1][1] = 1.0;
|
||||
}
|
||||
|
||||
// Return the 2x2 identity matrix
|
||||
inline Matrix2x2 Matrix2x2::identity() {
|
||||
|
||||
// Return the isdentity matrix
|
||||
return Matrix2x2(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Return the 2x2 zero matrix
|
||||
inline Matrix2x2 Matrix2x2::zero() {
|
||||
return Matrix2x2(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// Return the matrix with absolute values
|
||||
inline Matrix2x2 Matrix2x2::getAbsoluteMatrix() const {
|
||||
return Matrix2x2(fabs(mRows[0][0]), fabs(mRows[0][1]),
|
||||
fabs(mRows[1][0]), fabs(mRows[1][1]));
|
||||
}
|
||||
|
||||
// Overloaded operator for addition
|
||||
inline Matrix2x2 operator+(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
|
||||
return Matrix2x2(matrix1.mRows[0][0] + matrix2.mRows[0][0],
|
||||
matrix1.mRows[0][1] + matrix2.mRows[0][1],
|
||||
matrix1.mRows[1][0] + matrix2.mRows[1][0],
|
||||
matrix1.mRows[1][1] + matrix2.mRows[1][1]);
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction
|
||||
inline Matrix2x2 operator-(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
|
||||
return Matrix2x2(matrix1.mRows[0][0] - matrix2.mRows[0][0],
|
||||
matrix1.mRows[0][1] - matrix2.mRows[0][1],
|
||||
matrix1.mRows[1][0] - matrix2.mRows[1][0],
|
||||
matrix1.mRows[1][1] - matrix2.mRows[1][1]);
|
||||
}
|
||||
|
||||
// Overloaded operator for the negative of the matrix
|
||||
inline Matrix2x2 operator-(const Matrix2x2& matrix) {
|
||||
return Matrix2x2(-matrix.mRows[0][0], -matrix.mRows[0][1],
|
||||
-matrix.mRows[1][0], -matrix.mRows[1][1]);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number
|
||||
inline Matrix2x2 operator*(float nb, const Matrix2x2& matrix) {
|
||||
return Matrix2x2(matrix.mRows[0][0] * nb, matrix.mRows[0][1] * nb,
|
||||
matrix.mRows[1][0] * nb, matrix.mRows[1][1] * nb);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a matrix
|
||||
inline Matrix2x2 operator*(const Matrix2x2& matrix, float nb) {
|
||||
return nb * matrix;
|
||||
}
|
||||
|
||||
// Overloaded operator for matrix multiplication
|
||||
inline Matrix2x2 operator*(const Matrix2x2& matrix1, const Matrix2x2& matrix2) {
|
||||
return Matrix2x2(matrix1.mRows[0][0] * matrix2.mRows[0][0] + matrix1.mRows[0][1] *
|
||||
matrix2.mRows[1][0],
|
||||
matrix1.mRows[0][0] * matrix2.mRows[0][1] + matrix1.mRows[0][1] *
|
||||
matrix2.mRows[1][1],
|
||||
matrix1.mRows[1][0] * matrix2.mRows[0][0] + matrix1.mRows[1][1] *
|
||||
matrix2.mRows[1][0],
|
||||
matrix1.mRows[1][0] * matrix2.mRows[0][1] + matrix1.mRows[1][1] *
|
||||
matrix2.mRows[1][1]);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a vector
|
||||
inline Vector2 operator*(const Matrix2x2& matrix, const Vector2& vector) {
|
||||
return Vector2(matrix.mRows[0][0]*vector.x + matrix.mRows[0][1]*vector.y,
|
||||
matrix.mRows[1][0]*vector.x + matrix.mRows[1][1]*vector.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for equality condition
|
||||
inline bool Matrix2x2::operator==(const Matrix2x2& matrix) const {
|
||||
return (mRows[0][0] == matrix.mRows[0][0] && mRows[0][1] == matrix.mRows[0][1] &&
|
||||
mRows[1][0] == matrix.mRows[1][0] && mRows[1][1] == matrix.mRows[1][1]);
|
||||
}
|
||||
|
||||
// Overloaded operator for the is different condition
|
||||
inline bool Matrix2x2::operator!= (const Matrix2x2& matrix) const {
|
||||
return !(*this == matrix);
|
||||
}
|
||||
|
||||
// Overloaded operator for addition with assignment
|
||||
inline Matrix2x2& Matrix2x2::operator+=(const Matrix2x2& matrix) {
|
||||
mRows[0][0] += matrix.mRows[0][0]; mRows[0][1] += matrix.mRows[0][1];
|
||||
mRows[1][0] += matrix.mRows[1][0]; mRows[1][1] += matrix.mRows[1][1];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction with assignment
|
||||
inline Matrix2x2& Matrix2x2::operator-=(const Matrix2x2& matrix) {
|
||||
mRows[0][0] -= matrix.mRows[0][0]; mRows[0][1] -= matrix.mRows[0][1];
|
||||
mRows[1][0] -= matrix.mRows[1][0]; mRows[1][1] -= matrix.mRows[1][1];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number with assignment
|
||||
inline Matrix2x2& Matrix2x2::operator*=(float nb) {
|
||||
mRows[0][0] *= nb; mRows[0][1] *= nb;
|
||||
mRows[1][0] *= nb; mRows[1][1] *= nb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator to return a row of the matrix.
|
||||
/// This operator is also used to access a matrix value using the syntax
|
||||
/// matrix[row][col].
|
||||
inline const Vector2& Matrix2x2::operator[](int32_t row) const {
|
||||
return mRows[row];
|
||||
}
|
||||
|
||||
// Overloaded operator to return a row of the matrix.
|
||||
/// This operator is also used to access a matrix value using the syntax
|
||||
/// matrix[row][col].
|
||||
inline Vector2& Matrix2x2::operator[](int32_t row) {
|
||||
return mRows[row];
|
||||
}
|
||||
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <iostream>
|
||||
#include <ephysics/mathematics/Matrix3x3.h>
|
||||
|
||||
// Namespaces
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor of the class Matrix3x3
|
||||
Matrix3x3::Matrix3x3() {
|
||||
// Initialize all values in the matrix to zero
|
||||
setAllValues(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// Constructor
|
||||
Matrix3x3::Matrix3x3(float value) {
|
||||
setAllValues(value, value, value, value, value, value, value, value, value);
|
||||
}
|
||||
|
||||
// Constructor with arguments
|
||||
Matrix3x3::Matrix3x3(float a1, float a2, float a3,
|
||||
float b1, float b2, float b3,
|
||||
float c1, float c2, float c3) {
|
||||
// Initialize the matrix with the values
|
||||
setAllValues(a1, a2, a3, b1, b2, b3, c1, c2, c3);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Matrix3x3::~Matrix3x3() {
|
||||
|
||||
}
|
||||
|
||||
// Copy-constructor
|
||||
Matrix3x3::Matrix3x3(const Matrix3x3& matrix) {
|
||||
setAllValues(matrix.mRows[0][0], matrix.mRows[0][1], matrix.mRows[0][2],
|
||||
matrix.mRows[1][0], matrix.mRows[1][1], matrix.mRows[1][2],
|
||||
matrix.mRows[2][0], matrix.mRows[2][1], matrix.mRows[2][2]);
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
Matrix3x3& Matrix3x3::operator=(const Matrix3x3& matrix) {
|
||||
|
||||
// Check for self-assignment
|
||||
if (&matrix != this) {
|
||||
setAllValues(matrix.mRows[0][0], matrix.mRows[0][1], matrix.mRows[0][2],
|
||||
matrix.mRows[1][0], matrix.mRows[1][1], matrix.mRows[1][2],
|
||||
matrix.mRows[2][0], matrix.mRows[2][1], matrix.mRows[2][2]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return the inverse matrix
|
||||
Matrix3x3 Matrix3x3::getInverse() const {
|
||||
|
||||
// Compute the determinant of the matrix
|
||||
float determinant = getDeterminant();
|
||||
|
||||
// Check if the determinant is equal to zero
|
||||
assert(std::abs(determinant) > MACHINE_EPSILON);
|
||||
|
||||
float invDeterminant = float(1.0) / determinant;
|
||||
|
||||
Matrix3x3 tempMatrix((mRows[1][1]*mRows[2][2]-mRows[2][1]*mRows[1][2]),
|
||||
-(mRows[0][1]*mRows[2][2]-mRows[2][1]*mRows[0][2]),
|
||||
(mRows[0][1]*mRows[1][2]-mRows[0][2]*mRows[1][1]),
|
||||
-(mRows[1][0]*mRows[2][2]-mRows[2][0]*mRows[1][2]),
|
||||
(mRows[0][0]*mRows[2][2]-mRows[2][0]*mRows[0][2]),
|
||||
-(mRows[0][0]*mRows[1][2]-mRows[1][0]*mRows[0][2]),
|
||||
(mRows[1][0]*mRows[2][1]-mRows[2][0]*mRows[1][1]),
|
||||
-(mRows[0][0]*mRows[2][1]-mRows[2][0]*mRows[0][1]),
|
||||
(mRows[0][0]*mRows[1][1]-mRows[0][1]*mRows[1][0]));
|
||||
|
||||
// Return the inverse matrix
|
||||
return (invDeterminant * tempMatrix);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,347 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cassert>
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
|
||||
// Class Matrix3x3
|
||||
/**
|
||||
* This class represents a 3x3 matrix.
|
||||
*/
|
||||
class Matrix3x3 {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Rows of the matrix;
|
||||
Vector3 mRows[3];
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Matrix3x3();
|
||||
|
||||
/// Constructor
|
||||
Matrix3x3(float value);
|
||||
|
||||
/// Constructor
|
||||
Matrix3x3(float a1, float a2, float a3, float b1, float b2, float b3,
|
||||
float c1, float c2, float c3);
|
||||
|
||||
/// Destructor
|
||||
virtual ~Matrix3x3();
|
||||
|
||||
/// Copy-constructor
|
||||
Matrix3x3(const Matrix3x3& matrix);
|
||||
|
||||
/// Assignment operator
|
||||
Matrix3x3& operator=(const Matrix3x3& matrix);
|
||||
|
||||
/// Set all the values in the matrix
|
||||
void setAllValues(float a1, float a2, float a3, float b1, float b2, float b3,
|
||||
float c1, float c2, float c3);
|
||||
|
||||
/// Set the matrix to zero
|
||||
void setToZero();
|
||||
|
||||
/// Return a column
|
||||
Vector3 getColumn(int32_t i) const;
|
||||
|
||||
/// Return a row
|
||||
Vector3 getRow(int32_t i) const;
|
||||
|
||||
/// Return the transpose matrix
|
||||
Matrix3x3 getTranspose() const;
|
||||
|
||||
/// Return the determinant of the matrix
|
||||
float getDeterminant() const;
|
||||
|
||||
/// Return the trace of the matrix
|
||||
float getTrace() const;
|
||||
|
||||
/// Return the inverse matrix
|
||||
Matrix3x3 getInverse() const;
|
||||
|
||||
/// Return the matrix with absolute values
|
||||
Matrix3x3 getAbsoluteMatrix() const;
|
||||
|
||||
/// Set the matrix to the identity matrix
|
||||
void setToIdentity();
|
||||
|
||||
/// Return the 3x3 identity matrix
|
||||
static Matrix3x3 identity();
|
||||
|
||||
/// Return the 3x3 zero matrix
|
||||
static Matrix3x3 zero();
|
||||
|
||||
/// Return a skew-symmetric matrix using a given vector that can be used
|
||||
/// to compute cross product with another vector using matrix multiplication
|
||||
static Matrix3x3 computeSkewSymmetricMatrixForCrossProduct(const Vector3& vector);
|
||||
|
||||
/// Overloaded operator for addition
|
||||
friend Matrix3x3 operator+(const Matrix3x3& matrix1, const Matrix3x3& matrix2);
|
||||
|
||||
/// Overloaded operator for substraction
|
||||
friend Matrix3x3 operator-(const Matrix3x3& matrix1, const Matrix3x3& matrix2);
|
||||
|
||||
/// Overloaded operator for the negative of the matrix
|
||||
friend Matrix3x3 operator-(const Matrix3x3& matrix);
|
||||
|
||||
/// Overloaded operator for multiplication with a number
|
||||
friend Matrix3x3 operator*(float nb, const Matrix3x3& matrix);
|
||||
|
||||
/// Overloaded operator for multiplication with a matrix
|
||||
friend Matrix3x3 operator*(const Matrix3x3& matrix, float nb);
|
||||
|
||||
/// Overloaded operator for matrix multiplication
|
||||
friend Matrix3x3 operator*(const Matrix3x3& matrix1, const Matrix3x3& matrix2);
|
||||
|
||||
/// Overloaded operator for multiplication with a vector
|
||||
friend Vector3 operator*(const Matrix3x3& matrix, const Vector3& vector);
|
||||
|
||||
/// Overloaded operator for equality condition
|
||||
bool operator==(const Matrix3x3& matrix) const;
|
||||
|
||||
/// Overloaded operator for the is different condition
|
||||
bool operator!= (const Matrix3x3& matrix) const;
|
||||
|
||||
/// Overloaded operator for addition with assignment
|
||||
Matrix3x3& operator+=(const Matrix3x3& matrix);
|
||||
|
||||
/// Overloaded operator for substraction with assignment
|
||||
Matrix3x3& operator-=(const Matrix3x3& matrix);
|
||||
|
||||
/// Overloaded operator for multiplication with a number with assignment
|
||||
Matrix3x3& operator*=(float nb);
|
||||
|
||||
/// Overloaded operator to read element of the matrix.
|
||||
const Vector3& operator[](int32_t row) const;
|
||||
|
||||
/// Overloaded operator to read/write element of the matrix.
|
||||
Vector3& operator[](int32_t row);
|
||||
};
|
||||
|
||||
// Method to set all the values in the matrix
|
||||
inline void Matrix3x3::setAllValues(float a1, float a2, float a3,
|
||||
float b1, float b2, float b3,
|
||||
float c1, float c2, float c3) {
|
||||
mRows[0][0] = a1; mRows[0][1] = a2; mRows[0][2] = a3;
|
||||
mRows[1][0] = b1; mRows[1][1] = b2; mRows[1][2] = b3;
|
||||
mRows[2][0] = c1; mRows[2][1] = c2; mRows[2][2] = c3;
|
||||
}
|
||||
|
||||
// Set the matrix to zero
|
||||
inline void Matrix3x3::setToZero() {
|
||||
mRows[0].setToZero();
|
||||
mRows[1].setToZero();
|
||||
mRows[2].setToZero();
|
||||
}
|
||||
|
||||
// Return a column
|
||||
inline Vector3 Matrix3x3::getColumn(int32_t i) const {
|
||||
assert(i>= 0 && i<3);
|
||||
return Vector3(mRows[0][i], mRows[1][i], mRows[2][i]);
|
||||
}
|
||||
|
||||
// Return a row
|
||||
inline Vector3 Matrix3x3::getRow(int32_t i) const {
|
||||
assert(i>= 0 && i<3);
|
||||
return mRows[i];
|
||||
}
|
||||
|
||||
// Return the transpose matrix
|
||||
inline Matrix3x3 Matrix3x3::getTranspose() const {
|
||||
|
||||
// Return the transpose matrix
|
||||
return Matrix3x3(mRows[0][0], mRows[1][0], mRows[2][0],
|
||||
mRows[0][1], mRows[1][1], mRows[2][1],
|
||||
mRows[0][2], mRows[1][2], mRows[2][2]);
|
||||
}
|
||||
|
||||
// Return the determinant of the matrix
|
||||
inline float Matrix3x3::getDeterminant() const {
|
||||
|
||||
// Compute and return the determinant of the matrix
|
||||
return (mRows[0][0]*(mRows[1][1]*mRows[2][2]-mRows[2][1]*mRows[1][2]) -
|
||||
mRows[0][1]*(mRows[1][0]*mRows[2][2]-mRows[2][0]*mRows[1][2]) +
|
||||
mRows[0][2]*(mRows[1][0]*mRows[2][1]-mRows[2][0]*mRows[1][1]));
|
||||
}
|
||||
|
||||
// Return the trace of the matrix
|
||||
inline float Matrix3x3::getTrace() const {
|
||||
|
||||
// Compute and return the trace
|
||||
return (mRows[0][0] + mRows[1][1] + mRows[2][2]);
|
||||
}
|
||||
|
||||
// Set the matrix to the identity matrix
|
||||
inline void Matrix3x3::setToIdentity() {
|
||||
mRows[0][0] = 1.0; mRows[0][1] = 0.0; mRows[0][2] = 0.0;
|
||||
mRows[1][0] = 0.0; mRows[1][1] = 1.0; mRows[1][2] = 0.0;
|
||||
mRows[2][0] = 0.0; mRows[2][1] = 0.0; mRows[2][2] = 1.0;
|
||||
}
|
||||
|
||||
// Return the 3x3 identity matrix
|
||||
inline Matrix3x3 Matrix3x3::identity() {
|
||||
return Matrix3x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Return the 3x3 zero matrix
|
||||
inline Matrix3x3 Matrix3x3::zero() {
|
||||
return Matrix3x3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
// Return a skew-symmetric matrix using a given vector that can be used
|
||||
// to compute cross product with another vector using matrix multiplication
|
||||
inline Matrix3x3 Matrix3x3::computeSkewSymmetricMatrixForCrossProduct(const Vector3& vector) {
|
||||
return Matrix3x3(0, -vector.z, vector.y, vector.z, 0, -vector.x, -vector.y, vector.x, 0);
|
||||
}
|
||||
|
||||
// Return the matrix with absolute values
|
||||
inline Matrix3x3 Matrix3x3::getAbsoluteMatrix() const {
|
||||
return Matrix3x3(fabs(mRows[0][0]), fabs(mRows[0][1]), fabs(mRows[0][2]),
|
||||
fabs(mRows[1][0]), fabs(mRows[1][1]), fabs(mRows[1][2]),
|
||||
fabs(mRows[2][0]), fabs(mRows[2][1]), fabs(mRows[2][2]));
|
||||
}
|
||||
|
||||
// Overloaded operator for addition
|
||||
inline Matrix3x3 operator+(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
|
||||
return Matrix3x3(matrix1.mRows[0][0] + matrix2.mRows[0][0], matrix1.mRows[0][1] +
|
||||
matrix2.mRows[0][1], matrix1.mRows[0][2] + matrix2.mRows[0][2],
|
||||
matrix1.mRows[1][0] + matrix2.mRows[1][0], matrix1.mRows[1][1] +
|
||||
matrix2.mRows[1][1], matrix1.mRows[1][2] + matrix2.mRows[1][2],
|
||||
matrix1.mRows[2][0] + matrix2.mRows[2][0], matrix1.mRows[2][1] +
|
||||
matrix2.mRows[2][1], matrix1.mRows[2][2] + matrix2.mRows[2][2]);
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction
|
||||
inline Matrix3x3 operator-(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
|
||||
return Matrix3x3(matrix1.mRows[0][0] - matrix2.mRows[0][0], matrix1.mRows[0][1] -
|
||||
matrix2.mRows[0][1], matrix1.mRows[0][2] - matrix2.mRows[0][2],
|
||||
matrix1.mRows[1][0] - matrix2.mRows[1][0], matrix1.mRows[1][1] -
|
||||
matrix2.mRows[1][1], matrix1.mRows[1][2] - matrix2.mRows[1][2],
|
||||
matrix1.mRows[2][0] - matrix2.mRows[2][0], matrix1.mRows[2][1] -
|
||||
matrix2.mRows[2][1], matrix1.mRows[2][2] - matrix2.mRows[2][2]);
|
||||
}
|
||||
|
||||
// Overloaded operator for the negative of the matrix
|
||||
inline Matrix3x3 operator-(const Matrix3x3& matrix) {
|
||||
return Matrix3x3(-matrix.mRows[0][0], -matrix.mRows[0][1], -matrix.mRows[0][2],
|
||||
-matrix.mRows[1][0], -matrix.mRows[1][1], -matrix.mRows[1][2],
|
||||
-matrix.mRows[2][0], -matrix.mRows[2][1], -matrix.mRows[2][2]);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number
|
||||
inline Matrix3x3 operator*(float nb, const Matrix3x3& matrix) {
|
||||
return Matrix3x3(matrix.mRows[0][0] * nb, matrix.mRows[0][1] * nb, matrix.mRows[0][2] * nb,
|
||||
matrix.mRows[1][0] * nb, matrix.mRows[1][1] * nb, matrix.mRows[1][2] * nb,
|
||||
matrix.mRows[2][0] * nb, matrix.mRows[2][1] * nb, matrix.mRows[2][2] * nb);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a matrix
|
||||
inline Matrix3x3 operator*(const Matrix3x3& matrix, float nb) {
|
||||
return nb * matrix;
|
||||
}
|
||||
|
||||
// Overloaded operator for matrix multiplication
|
||||
inline Matrix3x3 operator*(const Matrix3x3& matrix1, const Matrix3x3& matrix2) {
|
||||
return Matrix3x3(matrix1.mRows[0][0]*matrix2.mRows[0][0] + matrix1.mRows[0][1] *
|
||||
matrix2.mRows[1][0] + matrix1.mRows[0][2]*matrix2.mRows[2][0],
|
||||
matrix1.mRows[0][0]*matrix2.mRows[0][1] + matrix1.mRows[0][1] *
|
||||
matrix2.mRows[1][1] + matrix1.mRows[0][2]*matrix2.mRows[2][1],
|
||||
matrix1.mRows[0][0]*matrix2.mRows[0][2] + matrix1.mRows[0][1] *
|
||||
matrix2.mRows[1][2] + matrix1.mRows[0][2]*matrix2.mRows[2][2],
|
||||
matrix1.mRows[1][0]*matrix2.mRows[0][0] + matrix1.mRows[1][1] *
|
||||
matrix2.mRows[1][0] + matrix1.mRows[1][2]*matrix2.mRows[2][0],
|
||||
matrix1.mRows[1][0]*matrix2.mRows[0][1] + matrix1.mRows[1][1] *
|
||||
matrix2.mRows[1][1] + matrix1.mRows[1][2]*matrix2.mRows[2][1],
|
||||
matrix1.mRows[1][0]*matrix2.mRows[0][2] + matrix1.mRows[1][1] *
|
||||
matrix2.mRows[1][2] + matrix1.mRows[1][2]*matrix2.mRows[2][2],
|
||||
matrix1.mRows[2][0]*matrix2.mRows[0][0] + matrix1.mRows[2][1] *
|
||||
matrix2.mRows[1][0] + matrix1.mRows[2][2]*matrix2.mRows[2][0],
|
||||
matrix1.mRows[2][0]*matrix2.mRows[0][1] + matrix1.mRows[2][1] *
|
||||
matrix2.mRows[1][1] + matrix1.mRows[2][2]*matrix2.mRows[2][1],
|
||||
matrix1.mRows[2][0]*matrix2.mRows[0][2] + matrix1.mRows[2][1] *
|
||||
matrix2.mRows[1][2] + matrix1.mRows[2][2]*matrix2.mRows[2][2]);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a vector
|
||||
inline Vector3 operator*(const Matrix3x3& matrix, const Vector3& vector) {
|
||||
return Vector3(matrix.mRows[0][0]*vector.x + matrix.mRows[0][1]*vector.y +
|
||||
matrix.mRows[0][2]*vector.z,
|
||||
matrix.mRows[1][0]*vector.x + matrix.mRows[1][1]*vector.y +
|
||||
matrix.mRows[1][2]*vector.z,
|
||||
matrix.mRows[2][0]*vector.x + matrix.mRows[2][1]*vector.y +
|
||||
matrix.mRows[2][2]*vector.z);
|
||||
}
|
||||
|
||||
// Overloaded operator for equality condition
|
||||
inline bool Matrix3x3::operator==(const Matrix3x3& matrix) const {
|
||||
return (mRows[0][0] == matrix.mRows[0][0] && mRows[0][1] == matrix.mRows[0][1] &&
|
||||
mRows[0][2] == matrix.mRows[0][2] &&
|
||||
mRows[1][0] == matrix.mRows[1][0] && mRows[1][1] == matrix.mRows[1][1] &&
|
||||
mRows[1][2] == matrix.mRows[1][2] &&
|
||||
mRows[2][0] == matrix.mRows[2][0] && mRows[2][1] == matrix.mRows[2][1] &&
|
||||
mRows[2][2] == matrix.mRows[2][2]);
|
||||
}
|
||||
|
||||
// Overloaded operator for the is different condition
|
||||
inline bool Matrix3x3::operator!= (const Matrix3x3& matrix) const {
|
||||
return !(*this == matrix);
|
||||
}
|
||||
|
||||
// Overloaded operator for addition with assignment
|
||||
inline Matrix3x3& Matrix3x3::operator+=(const Matrix3x3& matrix) {
|
||||
mRows[0][0] += matrix.mRows[0][0]; mRows[0][1] += matrix.mRows[0][1];
|
||||
mRows[0][2] += matrix.mRows[0][2]; mRows[1][0] += matrix.mRows[1][0];
|
||||
mRows[1][1] += matrix.mRows[1][1]; mRows[1][2] += matrix.mRows[1][2];
|
||||
mRows[2][0] += matrix.mRows[2][0]; mRows[2][1] += matrix.mRows[2][1];
|
||||
mRows[2][2] += matrix.mRows[2][2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction with assignment
|
||||
inline Matrix3x3& Matrix3x3::operator-=(const Matrix3x3& matrix) {
|
||||
mRows[0][0] -= matrix.mRows[0][0]; mRows[0][1] -= matrix.mRows[0][1];
|
||||
mRows[0][2] -= matrix.mRows[0][2]; mRows[1][0] -= matrix.mRows[1][0];
|
||||
mRows[1][1] -= matrix.mRows[1][1]; mRows[1][2] -= matrix.mRows[1][2];
|
||||
mRows[2][0] -= matrix.mRows[2][0]; mRows[2][1] -= matrix.mRows[2][1];
|
||||
mRows[2][2] -= matrix.mRows[2][2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number with assignment
|
||||
inline Matrix3x3& Matrix3x3::operator*=(float nb) {
|
||||
mRows[0][0] *= nb; mRows[0][1] *= nb; mRows[0][2] *= nb;
|
||||
mRows[1][0] *= nb; mRows[1][1] *= nb; mRows[1][2] *= nb;
|
||||
mRows[2][0] *= nb; mRows[2][1] *= nb; mRows[2][2] *= nb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator to return a row of the matrix.
|
||||
/// This operator is also used to access a matrix value using the syntax
|
||||
/// matrix[row][col].
|
||||
inline const Vector3& Matrix3x3::operator[](int32_t row) const {
|
||||
return mRows[row];
|
||||
}
|
||||
|
||||
// Overloaded operator to return a row of the matrix.
|
||||
/// This operator is also used to access a matrix value using the syntax
|
||||
/// matrix[row][col].
|
||||
inline Vector3& Matrix3x3::operator[](int32_t row) {
|
||||
return mRows[row];
|
||||
}
|
||||
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Quaternion.h>
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <cassert>
|
||||
|
||||
// Namespace
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor of the class
|
||||
Quaternion::Quaternion() : x(0.0), y(0.0), z(0.0), w(0.0) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor with arguments
|
||||
Quaternion::Quaternion(float newX, float newY, float newZ, float newW)
|
||||
:x(newX), y(newY), z(newZ), w(newW) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor with the component w and the vector v=(x y z)
|
||||
Quaternion::Quaternion(float newW, const Vector3& v) : x(v.x), y(v.y), z(v.z), w(newW) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor which convert Euler angles (in radians) to a quaternion
|
||||
Quaternion::Quaternion(float angleX, float angleY, float angleZ) {
|
||||
initWithEulerAngles(angleX, angleY, angleZ);
|
||||
}
|
||||
|
||||
// Constructor which convert Euler angles (in radians) to a quaternion
|
||||
Quaternion::Quaternion(const Vector3& eulerAngles) {
|
||||
initWithEulerAngles(eulerAngles.x, eulerAngles.y, eulerAngles.z);
|
||||
}
|
||||
|
||||
// Copy-constructor
|
||||
Quaternion::Quaternion(const Quaternion& quaternion)
|
||||
:x(quaternion.x), y(quaternion.y), z(quaternion.z), w(quaternion.w) {
|
||||
|
||||
}
|
||||
|
||||
// Create a unit quaternion from a rotation matrix
|
||||
Quaternion::Quaternion(const Matrix3x3& matrix) {
|
||||
|
||||
// Get the trace of the matrix
|
||||
float trace = matrix.getTrace();
|
||||
|
||||
float r;
|
||||
float s;
|
||||
|
||||
if (trace < 0.0) {
|
||||
if (matrix[1][1] > matrix[0][0]) {
|
||||
if(matrix[2][2] > matrix[1][1]) {
|
||||
r = sqrt(matrix[2][2] - matrix[0][0] - matrix[1][1] + float(1.0));
|
||||
s = float(0.5) / r;
|
||||
|
||||
// Compute the quaternion
|
||||
x = (matrix[2][0] + matrix[0][2]) * s;
|
||||
y = (matrix[1][2] + matrix[2][1]) * s;
|
||||
z = float(0.5) * r;
|
||||
w = (matrix[1][0] - matrix[0][1]) * s;
|
||||
}
|
||||
else {
|
||||
r = sqrt(matrix[1][1] - matrix[2][2] - matrix[0][0] + float(1.0));
|
||||
s = float(0.5) / r;
|
||||
|
||||
// Compute the quaternion
|
||||
x = (matrix[0][1] + matrix[1][0]) * s;
|
||||
y = float(0.5) * r;
|
||||
z = (matrix[1][2] + matrix[2][1]) * s;
|
||||
w = (matrix[0][2] - matrix[2][0]) * s;
|
||||
}
|
||||
}
|
||||
else if (matrix[2][2] > matrix[0][0]) {
|
||||
r = sqrt(matrix[2][2] - matrix[0][0] - matrix[1][1] + float(1.0));
|
||||
s = float(0.5) / r;
|
||||
|
||||
// Compute the quaternion
|
||||
x = (matrix[2][0] + matrix[0][2]) * s;
|
||||
y = (matrix[1][2] + matrix[2][1]) * s;
|
||||
z = float(0.5) * r;
|
||||
w = (matrix[1][0] - matrix[0][1]) * s;
|
||||
}
|
||||
else {
|
||||
r = sqrt(matrix[0][0] - matrix[1][1] - matrix[2][2] + float(1.0));
|
||||
s = float(0.5) / r;
|
||||
|
||||
// Compute the quaternion
|
||||
x = float(0.5) * r;
|
||||
y = (matrix[0][1] + matrix[1][0]) * s;
|
||||
z = (matrix[2][0] - matrix[0][2]) * s;
|
||||
w = (matrix[2][1] - matrix[1][2]) * s;
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = sqrt(trace + float(1.0));
|
||||
s = float(0.5) / r;
|
||||
|
||||
// Compute the quaternion
|
||||
x = (matrix[2][1] - matrix[1][2]) * s;
|
||||
y = (matrix[0][2] - matrix[2][0]) * s;
|
||||
z = (matrix[1][0] - matrix[0][1]) * s;
|
||||
w = float(0.5) * r;
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Quaternion::~Quaternion() {
|
||||
|
||||
}
|
||||
|
||||
// Compute the rotation angle (in radians) and the rotation axis
|
||||
/// This method is used to get the rotation angle (in radian) and the unit
|
||||
/// rotation axis of an orientation quaternion.
|
||||
void Quaternion::getRotationAngleAxis(float& angle, Vector3& axis) const {
|
||||
Quaternion quaternion;
|
||||
|
||||
// If the quaternion is unit
|
||||
if (length() == 1.0) {
|
||||
quaternion = *this;
|
||||
}
|
||||
else {
|
||||
// We compute the unit quaternion
|
||||
quaternion = getUnit();
|
||||
}
|
||||
|
||||
// Compute the roation angle
|
||||
angle = acos(quaternion.w) * float(2.0);
|
||||
|
||||
// Compute the 3D rotation axis
|
||||
Vector3 rotationAxis(quaternion.x, quaternion.y, quaternion.z);
|
||||
|
||||
// Normalize the rotation axis
|
||||
rotationAxis = rotationAxis.getUnit();
|
||||
|
||||
// Set the rotation axis values
|
||||
axis.setAllValues(rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
}
|
||||
|
||||
// Return the orientation matrix corresponding to this quaternion
|
||||
Matrix3x3 Quaternion::getMatrix() const {
|
||||
|
||||
float nQ = x*x + y*y + z*z + w*w;
|
||||
float s = 0.0;
|
||||
|
||||
if (nQ > 0.0) {
|
||||
s = float(2.0) / nQ;
|
||||
}
|
||||
|
||||
// Computations used for optimization (less multiplications)
|
||||
float xs = x*s;
|
||||
float ys = y*s;
|
||||
float zs = z*s;
|
||||
float wxs = w*xs;
|
||||
float wys = w*ys;
|
||||
float wzs = w*zs;
|
||||
float xxs = x*xs;
|
||||
float xys = x*ys;
|
||||
float xzs = x*zs;
|
||||
float yys = y*ys;
|
||||
float yzs = y*zs;
|
||||
float zzs = z*zs;
|
||||
|
||||
// Create the matrix corresponding to the quaternion
|
||||
return Matrix3x3(float(1.0) - yys - zzs, xys-wzs, xzs + wys,
|
||||
xys + wzs, float(1.0) - xxs - zzs, yzs-wxs,
|
||||
xzs-wys, yzs + wxs, float(1.0) - xxs - yys);
|
||||
}
|
||||
|
||||
// Compute the spherical linear int32_terpolation between two quaternions.
|
||||
/// The t argument has to be such that 0 <= t <= 1. This method is static.
|
||||
Quaternion Quaternion::slerp(const Quaternion& quaternion1,
|
||||
const Quaternion& quaternion2, float t) {
|
||||
assert(t >= 0.0 && t <= 1.0);
|
||||
|
||||
float invert = 1.0;
|
||||
|
||||
// Compute cos(theta) using the quaternion scalar product
|
||||
float cosineTheta = quaternion1.dot(quaternion2);
|
||||
|
||||
// Take care of the sign of cosineTheta
|
||||
if (cosineTheta < 0.0) {
|
||||
cosineTheta = -cosineTheta;
|
||||
invert = -1.0;
|
||||
}
|
||||
|
||||
// Because of precision, if cos(theta) is nearly 1,
|
||||
// therefore theta is nearly 0 and we can write
|
||||
// sin((1-t)*theta) as (1-t) and sin(t*theta) as t
|
||||
const float epsilon = float(0.00001);
|
||||
if(1-cosineTheta < epsilon) {
|
||||
return quaternion1 * (float(1.0)-t) + quaternion2 * (t * invert);
|
||||
}
|
||||
|
||||
// Compute the theta angle
|
||||
float theta = acos(cosineTheta);
|
||||
|
||||
// Compute sin(theta)
|
||||
float sineTheta = sin(theta);
|
||||
|
||||
// Compute the two coefficients that are in the spherical linear int32_terpolation formula
|
||||
float coeff1 = sin((float(1.0)-t)*theta) / sineTheta;
|
||||
float coeff2 = sin(t*theta) / sineTheta * invert;
|
||||
|
||||
// Compute and return the int32_terpolated quaternion
|
||||
return quaternion1 * coeff1 + quaternion2 * coeff2;
|
||||
}
|
||||
|
||||
// Initialize the quaternion using Euler angles
|
||||
void Quaternion::initWithEulerAngles(float angleX, float angleY, float angleZ) {
|
||||
|
||||
float angle = angleX * float(0.5);
|
||||
const float sinX = std::sin(angle);
|
||||
const float cosX = std::cos(angle);
|
||||
|
||||
angle = angleY * float(0.5);
|
||||
const float sinY = std::sin(angle);
|
||||
const float cosY = std::cos(angle);
|
||||
|
||||
angle = angleZ * float(0.5);
|
||||
const float sinZ = std::sin(angle);
|
||||
const float cosZ = std::cos(angle);
|
||||
|
||||
const float cosYcosZ = cosY * cosZ;
|
||||
const float sinYcosZ = sinY * cosZ;
|
||||
const float cosYsinZ = cosY * sinZ;
|
||||
const float sinYsinZ = sinY * sinZ;
|
||||
|
||||
x = sinX * cosYcosZ - cosX * sinYsinZ;
|
||||
y = cosX * sinYcosZ + sinX * cosYsinZ;
|
||||
z = cosX * cosYsinZ - sinX * sinYcosZ;
|
||||
w = cosX * cosYcosZ + sinX * sinYsinZ;
|
||||
|
||||
// Normalize the quaternion
|
||||
normalize();
|
||||
}
|
@ -1,330 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cmath>
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <ephysics/mathematics/Matrix3x3.h>
|
||||
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class Quaternion
|
||||
/**
|
||||
* This class represents a quaternion. We use the notation :
|
||||
* q = (x*i, y*j, z*k, w) to represent a quaternion.
|
||||
*/
|
||||
struct Quaternion {
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Component x
|
||||
float x;
|
||||
|
||||
/// Component y
|
||||
float y;
|
||||
|
||||
/// Component z
|
||||
float z;
|
||||
|
||||
/// Component w
|
||||
float w;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Quaternion();
|
||||
|
||||
/// Constructor with arguments
|
||||
Quaternion(float newX, float newY, float newZ, float newW);
|
||||
|
||||
/// Constructor with the component w and the vector v=(x y z)
|
||||
Quaternion(float newW, const Vector3& v);
|
||||
|
||||
/// Constructor which convert Euler angles (in radians) to a quaternion
|
||||
Quaternion(float angleX, float angleY, float angleZ);
|
||||
|
||||
/// Constructor which convert Euler angles (in radians) to a quaternion
|
||||
Quaternion(const Vector3& eulerAngles);
|
||||
|
||||
/// Copy-constructor
|
||||
Quaternion(const Quaternion& quaternion);
|
||||
|
||||
/// Create a unit quaternion from a rotation matrix
|
||||
Quaternion(const Matrix3x3& matrix);
|
||||
|
||||
/// Destructor
|
||||
~Quaternion();
|
||||
|
||||
/// Set all the values
|
||||
void setAllValues(float newX, float newY, float newZ, float newW);
|
||||
|
||||
/// Set the quaternion to zero
|
||||
void setToZero();
|
||||
|
||||
/// Set to the identity quaternion
|
||||
void setToIdentity();
|
||||
|
||||
/// Return the vector v=(x y z) of the quaternion
|
||||
Vector3 getVectorV() const;
|
||||
|
||||
/// Return the length of the quaternion
|
||||
float length() const;
|
||||
|
||||
/// Return the square of the length of the quaternion
|
||||
float lengthSquare() const;
|
||||
|
||||
/// Normalize the quaternion
|
||||
void normalize();
|
||||
|
||||
/// Inverse the quaternion
|
||||
void inverse();
|
||||
|
||||
/// Return the unit quaternion
|
||||
Quaternion getUnit() const;
|
||||
|
||||
/// Return the conjugate quaternion
|
||||
Quaternion getConjugate() const;
|
||||
|
||||
/// Return the inverse of the quaternion
|
||||
Quaternion getInverse() const;
|
||||
|
||||
/// Return the orientation matrix corresponding to this quaternion
|
||||
Matrix3x3 getMatrix() const;
|
||||
|
||||
/// Return the identity quaternion
|
||||
static Quaternion identity();
|
||||
|
||||
/// Dot product between two quaternions
|
||||
float dot(const Quaternion& quaternion) const;
|
||||
|
||||
/// Compute the rotation angle (in radians) and the rotation axis
|
||||
void getRotationAngleAxis(float& angle, Vector3& axis) const;
|
||||
|
||||
/// Compute the spherical linear int32_terpolation between two quaternions
|
||||
static Quaternion slerp(const Quaternion& quaternion1, const Quaternion& quaternion2,
|
||||
float t);
|
||||
|
||||
/// Overloaded operator for the addition
|
||||
Quaternion operator+(const Quaternion& quaternion) const;
|
||||
|
||||
/// Overloaded operator for the substraction
|
||||
Quaternion operator-(const Quaternion& quaternion) const;
|
||||
|
||||
/// Overloaded operator for addition with assignment
|
||||
Quaternion& operator+=(const Quaternion& quaternion);
|
||||
|
||||
/// Overloaded operator for substraction with assignment
|
||||
Quaternion& operator-=(const Quaternion& quaternion);
|
||||
|
||||
/// Overloaded operator for the multiplication with a constant
|
||||
Quaternion operator*(float nb) const;
|
||||
|
||||
/// Overloaded operator for the multiplication
|
||||
Quaternion operator*(const Quaternion& quaternion) const;
|
||||
|
||||
/// Overloaded operator for the multiplication with a vector
|
||||
Vector3 operator*(const Vector3& point) const;
|
||||
|
||||
/// Overloaded operator for assignment
|
||||
Quaternion& operator=(const Quaternion& quaternion);
|
||||
|
||||
/// Overloaded operator for equality condition
|
||||
bool operator==(const Quaternion& quaternion) const;
|
||||
|
||||
private:
|
||||
|
||||
/// Initialize the quaternion using Euler angles
|
||||
void initWithEulerAngles(float angleX, float angleY, float angleZ);
|
||||
};
|
||||
|
||||
/// Set all the values
|
||||
inline void Quaternion::setAllValues(float newX, float newY, float newZ, float newW) {
|
||||
x = newX;
|
||||
y = newY;
|
||||
z = newZ;
|
||||
w = newW;
|
||||
}
|
||||
|
||||
/// Set the quaternion to zero
|
||||
inline void Quaternion::setToZero() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
w = 0;
|
||||
}
|
||||
|
||||
// Set to the identity quaternion
|
||||
inline void Quaternion::setToIdentity() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
w = 1;
|
||||
}
|
||||
|
||||
// Return the vector v=(x y z) of the quaternion
|
||||
inline Vector3 Quaternion::getVectorV() const {
|
||||
|
||||
// Return the vector v
|
||||
return Vector3(x, y, z);
|
||||
}
|
||||
|
||||
// Return the length of the quaternion (inline)
|
||||
inline float Quaternion::length() const {
|
||||
return sqrt(x*x + y*y + z*z + w*w);
|
||||
}
|
||||
|
||||
// Return the square of the length of the quaternion
|
||||
inline float Quaternion::lengthSquare() const {
|
||||
return x*x + y*y + z*z + w*w;
|
||||
}
|
||||
|
||||
// Normalize the quaternion
|
||||
inline void Quaternion::normalize() {
|
||||
|
||||
float l = length();
|
||||
|
||||
// Check if the length is not equal to zero
|
||||
assert (l > MACHINE_EPSILON);
|
||||
|
||||
x /= l;
|
||||
y /= l;
|
||||
z /= l;
|
||||
w /= l;
|
||||
}
|
||||
|
||||
// Inverse the quaternion
|
||||
inline void Quaternion::inverse() {
|
||||
|
||||
// Get the square length of the quaternion
|
||||
float lengthSquareQuaternion = lengthSquare();
|
||||
|
||||
assert (lengthSquareQuaternion > MACHINE_EPSILON);
|
||||
|
||||
// Compute and return the inverse quaternion
|
||||
x /= -lengthSquareQuaternion;
|
||||
y /= -lengthSquareQuaternion;
|
||||
z /= -lengthSquareQuaternion;
|
||||
w /= lengthSquareQuaternion;
|
||||
}
|
||||
|
||||
// Return the unit quaternion
|
||||
inline Quaternion Quaternion::getUnit() const {
|
||||
float lengthQuaternion = length();
|
||||
|
||||
// Check if the length is not equal to zero
|
||||
assert (lengthQuaternion > MACHINE_EPSILON);
|
||||
|
||||
// Compute and return the unit quaternion
|
||||
return Quaternion(x / lengthQuaternion, y / lengthQuaternion,
|
||||
z / lengthQuaternion, w / lengthQuaternion);
|
||||
}
|
||||
|
||||
// Return the identity quaternion
|
||||
inline Quaternion Quaternion::identity() {
|
||||
return Quaternion(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Return the conjugate of the quaternion (inline)
|
||||
inline Quaternion Quaternion::getConjugate() const {
|
||||
return Quaternion(-x, -y, -z, w);
|
||||
}
|
||||
|
||||
// Return the inverse of the quaternion (inline)
|
||||
inline Quaternion Quaternion::getInverse() const {
|
||||
|
||||
float lengthSquareQuaternion = lengthSquare();
|
||||
|
||||
assert (lengthSquareQuaternion > MACHINE_EPSILON);
|
||||
|
||||
// Compute and return the inverse quaternion
|
||||
return Quaternion(-x / lengthSquareQuaternion, -y / lengthSquareQuaternion,
|
||||
-z / lengthSquareQuaternion, w / lengthSquareQuaternion);
|
||||
}
|
||||
|
||||
// Scalar product between two quaternions
|
||||
inline float Quaternion::dot(const Quaternion& quaternion) const {
|
||||
return (x*quaternion.x + y*quaternion.y + z*quaternion.z + w*quaternion.w);
|
||||
}
|
||||
|
||||
// Overloaded operator for the addition of two quaternions
|
||||
inline Quaternion Quaternion::operator+(const Quaternion& quaternion) const {
|
||||
|
||||
// Return the result quaternion
|
||||
return Quaternion(x + quaternion.x, y + quaternion.y, z + quaternion.z, w + quaternion.w);
|
||||
}
|
||||
|
||||
// Overloaded operator for the substraction of two quaternions
|
||||
inline Quaternion Quaternion::operator-(const Quaternion& quaternion) const {
|
||||
|
||||
// Return the result of the substraction
|
||||
return Quaternion(x - quaternion.x, y - quaternion.y, z - quaternion.z, w - quaternion.w);
|
||||
}
|
||||
|
||||
// Overloaded operator for addition with assignment
|
||||
inline Quaternion& Quaternion::operator+=(const Quaternion& quaternion) {
|
||||
x += quaternion.x;
|
||||
y += quaternion.y;
|
||||
z += quaternion.z;
|
||||
w += quaternion.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction with assignment
|
||||
inline Quaternion& Quaternion::operator-=(const Quaternion& quaternion) {
|
||||
x -= quaternion.x;
|
||||
y -= quaternion.y;
|
||||
z -= quaternion.z;
|
||||
w -= quaternion.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for the multiplication with a constant
|
||||
inline Quaternion Quaternion::operator*(float nb) const {
|
||||
return Quaternion(nb * x, nb * y, nb * z, nb * w);
|
||||
}
|
||||
|
||||
// Overloaded operator for the multiplication of two quaternions
|
||||
inline Quaternion Quaternion::operator*(const Quaternion& quaternion) const {
|
||||
return Quaternion(w * quaternion.w - getVectorV().dot(quaternion.getVectorV()),
|
||||
w * quaternion.getVectorV() + quaternion.w * getVectorV() +
|
||||
getVectorV().cross(quaternion.getVectorV()));
|
||||
}
|
||||
|
||||
// Overloaded operator for the multiplication with a vector.
|
||||
/// This methods rotates a point given the rotation of a quaternion.
|
||||
inline Vector3 Quaternion::operator*(const Vector3& point) const {
|
||||
Quaternion p(point.x, point.y, point.z, 0.0);
|
||||
return (((*this) * p) * getConjugate()).getVectorV();
|
||||
}
|
||||
|
||||
// Overloaded operator for the assignment
|
||||
inline Quaternion& Quaternion::operator=(const Quaternion& quaternion) {
|
||||
|
||||
// Check for self-assignment
|
||||
if (this != &quaternion) {
|
||||
x = quaternion.x;
|
||||
y = quaternion.y;
|
||||
z = quaternion.z;
|
||||
w = quaternion.w;
|
||||
}
|
||||
|
||||
// Return this quaternion
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for equality condition
|
||||
inline bool Quaternion::operator==(const Quaternion& quaternion) const {
|
||||
return (x == quaternion.x && y == quaternion.y &&
|
||||
z == quaternion.z && w == quaternion.w);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <etk/math/Vector3D.hpp>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
@ -24,10 +24,10 @@ struct Ray {
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// First point of the ray (origin)
|
||||
Vector3 point1;
|
||||
vec3 point1;
|
||||
|
||||
/// Second point of the ray
|
||||
Vector3 point2;
|
||||
vec3 point2;
|
||||
|
||||
/// Maximum fraction value
|
||||
float maxFraction;
|
||||
@ -35,7 +35,7 @@ struct Ray {
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor with arguments
|
||||
Ray(const Vector3& p1, const Vector3& p2, float maxFrac = float(1.0))
|
||||
Ray(const vec3& p1, const vec3& p2, float maxFrac = 1.0f)
|
||||
: point1(p1), point2(p2), maxFraction(maxFrac) {
|
||||
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Transform.h>
|
||||
|
||||
// Namespaces
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
Transform::Transform() : m_position(Vector3(0.0, 0.0, 0.0)), m_orientation(Quaternion::identity()) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor
|
||||
Transform::Transform(const Vector3& position, const Matrix3x3& orientation)
|
||||
: m_position(position), m_orientation(Quaternion(orientation)) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor
|
||||
Transform::Transform(const Vector3& position, const Quaternion& orientation)
|
||||
: m_position(position), m_orientation(orientation) {
|
||||
|
||||
}
|
||||
|
||||
// Copy-constructor
|
||||
Transform::Transform(const Transform& transform)
|
||||
: m_position(transform.m_position), m_orientation(transform.m_orientation) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Transform::~Transform() {
|
||||
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Matrix3x3.h>
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <ephysics/mathematics/Quaternion.h>
|
||||
|
||||
// ReactPhysiscs3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class Transform
|
||||
/**
|
||||
* This class represents a position and an orientation in 3D. It can
|
||||
* also be seen as representing a translation and a rotation.
|
||||
*/
|
||||
class Transform {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Position
|
||||
Vector3 m_position;
|
||||
|
||||
/// Orientation
|
||||
Quaternion m_orientation;
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
Transform();
|
||||
|
||||
/// Constructor
|
||||
Transform(const Vector3& position, const Matrix3x3& orientation);
|
||||
|
||||
/// Constructor
|
||||
Transform(const Vector3& position, const Quaternion& orientation);
|
||||
|
||||
/// Destructor
|
||||
~Transform();
|
||||
|
||||
/// Copy-constructor
|
||||
Transform(const Transform& transform);
|
||||
|
||||
/// Return the origin of the transform
|
||||
const Vector3& getPosition() const;
|
||||
|
||||
/// Set the origin of the transform
|
||||
void setPosition(const Vector3& position);
|
||||
|
||||
/// Return the orientation quaternion
|
||||
const Quaternion& getOrientation() const;
|
||||
|
||||
/// Set the rotation quaternion
|
||||
void setOrientation(const Quaternion& orientation);
|
||||
|
||||
/// Set the transform to the identity transform
|
||||
void setToIdentity();
|
||||
|
||||
/// Set the transform from an OpenGL transform matrix
|
||||
void setFromOpenGL(float* openglMatrix);
|
||||
|
||||
/// Get the OpenGL matrix of the transform
|
||||
void getOpenGLMatrix(float* openglMatrix) const;
|
||||
|
||||
/// Return the inverse of the transform
|
||||
Transform getInverse() const;
|
||||
|
||||
/// Return an int32_terpolated transform
|
||||
static Transform int32_terpolateTransforms(const Transform& oldTransform,
|
||||
const Transform& newTransform,
|
||||
float int32_terpolationFactor);
|
||||
|
||||
/// Return the identity transform
|
||||
static Transform identity();
|
||||
|
||||
/// Return the transformed vector
|
||||
Vector3 operator*(const Vector3& vector) const;
|
||||
|
||||
/// Operator of multiplication of a transform with another one
|
||||
Transform operator*(const Transform& transform2) const;
|
||||
|
||||
/// Return true if the two transforms are equal
|
||||
bool operator==(const Transform& transform2) const;
|
||||
|
||||
/// Return true if the two transforms are different
|
||||
bool operator!=(const Transform& transform2) const;
|
||||
|
||||
/// Assignment operator
|
||||
Transform& operator=(const Transform& transform);
|
||||
};
|
||||
|
||||
// Return the position of the transform
|
||||
inline const Vector3& Transform::getPosition() const {
|
||||
return m_position;
|
||||
}
|
||||
|
||||
// Set the origin of the transform
|
||||
inline void Transform::setPosition(const Vector3& position) {
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
// Return the rotation matrix
|
||||
inline const Quaternion& Transform::getOrientation() const {
|
||||
return m_orientation;
|
||||
}
|
||||
|
||||
// Set the rotation matrix of the transform
|
||||
inline void Transform::setOrientation(const Quaternion& orientation) {
|
||||
m_orientation = orientation;
|
||||
}
|
||||
|
||||
// Set the transform to the identity transform
|
||||
inline void Transform::setToIdentity() {
|
||||
m_position = Vector3(0.0, 0.0, 0.0);
|
||||
m_orientation = Quaternion::identity();
|
||||
}
|
||||
|
||||
// Set the transform from an OpenGL transform matrix
|
||||
inline void Transform::setFromOpenGL(float* openglMatrix) {
|
||||
Matrix3x3 matrix(openglMatrix[0], openglMatrix[4], openglMatrix[8],
|
||||
openglMatrix[1], openglMatrix[5], openglMatrix[9],
|
||||
openglMatrix[2], openglMatrix[6], openglMatrix[10]);
|
||||
m_orientation = Quaternion(matrix);
|
||||
m_position.setAllValues(openglMatrix[12], openglMatrix[13], openglMatrix[14]);
|
||||
}
|
||||
|
||||
// Get the OpenGL matrix of the transform
|
||||
inline void Transform::getOpenGLMatrix(float* openglMatrix) const {
|
||||
const Matrix3x3& matrix = m_orientation.getMatrix();
|
||||
openglMatrix[0] = matrix[0][0]; openglMatrix[1] = matrix[1][0];
|
||||
openglMatrix[2] = matrix[2][0]; openglMatrix[3] = 0.0;
|
||||
openglMatrix[4] = matrix[0][1]; openglMatrix[5] = matrix[1][1];
|
||||
openglMatrix[6] = matrix[2][1]; openglMatrix[7] = 0.0;
|
||||
openglMatrix[8] = matrix[0][2]; openglMatrix[9] = matrix[1][2];
|
||||
openglMatrix[10] = matrix[2][2]; openglMatrix[11] = 0.0;
|
||||
openglMatrix[12] = m_position.x; openglMatrix[13] = m_position.y;
|
||||
openglMatrix[14] = m_position.z; openglMatrix[15] = 1.0;
|
||||
}
|
||||
|
||||
// Return the inverse of the transform
|
||||
inline Transform Transform::getInverse() const {
|
||||
const Quaternion& invQuaternion = m_orientation.getInverse();
|
||||
Matrix3x3 invMatrix = invQuaternion.getMatrix();
|
||||
return Transform(invMatrix * (-m_position), invQuaternion);
|
||||
}
|
||||
|
||||
// Return an int32_terpolated transform
|
||||
inline Transform Transform::int32_terpolateTransforms(const Transform& oldTransform,
|
||||
const Transform& newTransform,
|
||||
float int32_terpolationFactor) {
|
||||
|
||||
Vector3 int32_terPosition = oldTransform.m_position * (float(1.0) - int32_terpolationFactor) +
|
||||
newTransform.m_position * int32_terpolationFactor;
|
||||
|
||||
Quaternion int32_terOrientation = Quaternion::slerp(oldTransform.m_orientation,
|
||||
newTransform.m_orientation,
|
||||
int32_terpolationFactor);
|
||||
|
||||
return Transform(int32_terPosition, int32_terOrientation);
|
||||
}
|
||||
|
||||
// Return the identity transform
|
||||
inline Transform Transform::identity() {
|
||||
return Transform(Vector3(0, 0, 0), Quaternion::identity());
|
||||
}
|
||||
|
||||
// Return the transformed vector
|
||||
inline Vector3 Transform::operator*(const Vector3& vector) const {
|
||||
return (m_orientation.getMatrix() * vector) + m_position;
|
||||
}
|
||||
|
||||
// Operator of multiplication of a transform with another one
|
||||
inline Transform Transform::operator*(const Transform& transform2) const {
|
||||
return Transform(m_position + m_orientation.getMatrix() * transform2.m_position,
|
||||
m_orientation * transform2.m_orientation);
|
||||
}
|
||||
|
||||
// Return true if the two transforms are equal
|
||||
inline bool Transform::operator==(const Transform& transform2) const {
|
||||
return (m_position == transform2.m_position) && (m_orientation == transform2.m_orientation);
|
||||
}
|
||||
|
||||
// Return true if the two transforms are different
|
||||
inline bool Transform::operator!=(const Transform& transform2) const {
|
||||
return !(*this == transform2);
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
inline Transform& Transform::operator=(const Transform& transform) {
|
||||
if (&transform != this) {
|
||||
m_position = transform.m_position;
|
||||
m_orientation = transform.m_orientation;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Vector2.h>
|
||||
#include <vector>
|
||||
|
||||
// Namespaces
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor
|
||||
Vector2::Vector2() : x(0.0), y(0.0) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor with arguments
|
||||
Vector2::Vector2(float newX, float newY) : x(newX), y(newY) {
|
||||
|
||||
}
|
||||
|
||||
// Copy-constructor
|
||||
Vector2::Vector2(const Vector2& vector) : x(vector.x), y(vector.y) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Vector2::~Vector2() {
|
||||
|
||||
}
|
||||
|
||||
// Return the corresponding unit vector
|
||||
Vector2 Vector2::getUnit() const {
|
||||
float lengthVector = length();
|
||||
|
||||
if (lengthVector < MACHINE_EPSILON) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compute and return the unit vector
|
||||
float lengthInv = float(1.0) / lengthVector;
|
||||
return Vector2(x * lengthInv, y * lengthInv);
|
||||
}
|
||||
|
||||
// Return one unit orthogonal vector of the current vector
|
||||
Vector2 Vector2::getOneUnitOrthogonalVector() const {
|
||||
|
||||
float l = length();
|
||||
assert(l > MACHINE_EPSILON);
|
||||
|
||||
return Vector2(-y / l, x / l);
|
||||
}
|
@ -1,323 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <ephysics/mathematics/mathematics_functions.h>
|
||||
|
||||
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class Vector2
|
||||
/**
|
||||
* This class represents a 2D vector.
|
||||
*/
|
||||
struct Vector2 {
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Component x
|
||||
float x;
|
||||
|
||||
/// Component y
|
||||
float y;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor of the class Vector3D
|
||||
Vector2();
|
||||
|
||||
/// Constructor with arguments
|
||||
Vector2(float newX, float newY);
|
||||
|
||||
/// Copy-constructor
|
||||
Vector2(const Vector2& vector);
|
||||
|
||||
/// Destructor
|
||||
~Vector2();
|
||||
|
||||
/// Set all the values of the vector
|
||||
void setAllValues(float newX, float newY);
|
||||
|
||||
/// Set the vector to zero
|
||||
void setToZero();
|
||||
|
||||
/// Return the length of the vector
|
||||
float length() const;
|
||||
|
||||
/// Return the square of the length of the vector
|
||||
float lengthSquare() const;
|
||||
|
||||
/// Return the corresponding unit vector
|
||||
Vector2 getUnit() const;
|
||||
|
||||
/// Return one unit orthogonal vector of the current vector
|
||||
Vector2 getOneUnitOrthogonalVector() const;
|
||||
|
||||
/// Return true if the vector is unit and false otherwise
|
||||
bool isUnit() const;
|
||||
|
||||
/// Return true if the current vector is the zero vector
|
||||
bool isZero() const;
|
||||
|
||||
/// Dot product of two vectors
|
||||
float dot(const Vector2& vector) const;
|
||||
|
||||
/// Normalize the vector
|
||||
void normalize();
|
||||
|
||||
/// Return the corresponding absolute value vector
|
||||
Vector2 getAbsoluteVector() const;
|
||||
|
||||
/// Return the axis with the minimal value
|
||||
int32_t getMinAxis() const;
|
||||
|
||||
/// Return the axis with the maximal value
|
||||
int32_t getMaxAxis() const;
|
||||
|
||||
/// Overloaded operator for the equality condition
|
||||
bool operator== (const Vector2& vector) const;
|
||||
|
||||
/// Overloaded operator for the is different condition
|
||||
bool operator!= (const Vector2& vector) const;
|
||||
|
||||
/// Overloaded operator for addition with assignment
|
||||
Vector2& operator+=(const Vector2& vector);
|
||||
|
||||
/// Overloaded operator for substraction with assignment
|
||||
Vector2& operator-=(const Vector2& vector);
|
||||
|
||||
/// Overloaded operator for multiplication with a number with assignment
|
||||
Vector2& operator*=(float number);
|
||||
|
||||
/// Overloaded operator for division by a number with assignment
|
||||
Vector2& operator/=(float number);
|
||||
|
||||
/// Overloaded operator for value access
|
||||
float& operator[] (int32_t index);
|
||||
|
||||
/// Overloaded operator for value access
|
||||
const float& operator[] (int32_t index) const;
|
||||
|
||||
/// Overloaded operator
|
||||
Vector2& operator=(const Vector2& vector);
|
||||
|
||||
/// Overloaded less than operator for ordering to be used inside std::set for instance
|
||||
bool operator<(const Vector2& vector) const;
|
||||
|
||||
/// Return a vector taking the minimum components of two vectors
|
||||
static Vector2 min(const Vector2& vector1, const Vector2& vector2);
|
||||
|
||||
/// Return a vector taking the maximum components of two vectors
|
||||
static Vector2 max(const Vector2& vector1, const Vector2& vector2);
|
||||
|
||||
/// Return the zero vector
|
||||
static Vector2 zero();
|
||||
|
||||
// -------------------- Friends -------------------- //
|
||||
|
||||
friend Vector2 operator+(const Vector2& vector1, const Vector2& vector2);
|
||||
friend Vector2 operator-(const Vector2& vector1, const Vector2& vector2);
|
||||
friend Vector2 operator-(const Vector2& vector);
|
||||
friend Vector2 operator*(const Vector2& vector, float number);
|
||||
friend Vector2 operator*(float number, const Vector2& vector);
|
||||
friend Vector2 operator*(const Vector2& vector1, const Vector2& vector2);
|
||||
friend Vector2 operator/(const Vector2& vector, float number);
|
||||
friend Vector2 operator/(const Vector2& vector1, const Vector2& vector2);
|
||||
};
|
||||
|
||||
// Set the vector to zero
|
||||
inline void Vector2::setToZero() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
// Set all the values of the vector
|
||||
inline void Vector2::setAllValues(float newX, float newY) {
|
||||
x = newX;
|
||||
y = newY;
|
||||
}
|
||||
|
||||
// Return the length of the vector
|
||||
inline float Vector2::length() const {
|
||||
return sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
// Return the square of the length of the vector
|
||||
inline float Vector2::lengthSquare() const {
|
||||
return x*x + y*y;
|
||||
}
|
||||
|
||||
// Scalar product of two vectors (inline)
|
||||
inline float Vector2::dot(const Vector2& vector) const {
|
||||
return (x*vector.x + y*vector.y);
|
||||
}
|
||||
|
||||
// Normalize the vector
|
||||
inline void Vector2::normalize() {
|
||||
float l = length();
|
||||
if (l < MACHINE_EPSILON) {
|
||||
return;
|
||||
}
|
||||
x /= l;
|
||||
y /= l;
|
||||
}
|
||||
|
||||
// Return the corresponding absolute value vector
|
||||
inline Vector2 Vector2::getAbsoluteVector() const {
|
||||
return Vector2(std::abs(x), std::abs(y));
|
||||
}
|
||||
|
||||
// Return the axis with the minimal value
|
||||
inline int32_t Vector2::getMinAxis() const {
|
||||
return (x < y ? 0 : 1);
|
||||
}
|
||||
|
||||
// Return the axis with the maximal value
|
||||
inline int32_t Vector2::getMaxAxis() const {
|
||||
return (x < y ? 1 : 0);
|
||||
}
|
||||
|
||||
// Return true if the vector is unit and false otherwise
|
||||
inline bool Vector2::isUnit() const {
|
||||
return approxEqual(lengthSquare(), 1.0);
|
||||
}
|
||||
|
||||
// Return true if the vector is the zero vector
|
||||
inline bool Vector2::isZero() const {
|
||||
return approxEqual(lengthSquare(), 0.0);
|
||||
}
|
||||
|
||||
// Overloaded operator for the equality condition
|
||||
inline bool Vector2::operator== (const Vector2& vector) const {
|
||||
return (x == vector.x && y == vector.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for the is different condition
|
||||
inline bool Vector2::operator!= (const Vector2& vector) const {
|
||||
return !(*this == vector);
|
||||
}
|
||||
|
||||
// Overloaded operator for addition with assignment
|
||||
inline Vector2& Vector2::operator+=(const Vector2& vector) {
|
||||
x += vector.x;
|
||||
y += vector.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction with assignment
|
||||
inline Vector2& Vector2::operator-=(const Vector2& vector) {
|
||||
x -= vector.x;
|
||||
y -= vector.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number with assignment
|
||||
inline Vector2& Vector2::operator*=(float number) {
|
||||
x *= number;
|
||||
y *= number;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for division by a number with assignment
|
||||
inline Vector2& Vector2::operator/=(float number) {
|
||||
assert(number > std::numeric_limits<float>::epsilon());
|
||||
x /= number;
|
||||
y /= number;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for value access
|
||||
inline float& Vector2::operator[] (int32_t index) {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// Overloaded operator for value access
|
||||
inline const float& Vector2::operator[] (int32_t index) const {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// Overloaded operator for addition
|
||||
inline Vector2 operator+(const Vector2& vector1, const Vector2& vector2) {
|
||||
return Vector2(vector1.x + vector2.x, vector1.y + vector2.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction
|
||||
inline Vector2 operator-(const Vector2& vector1, const Vector2& vector2) {
|
||||
return Vector2(vector1.x - vector2.x, vector1.y - vector2.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for the negative of a vector
|
||||
inline Vector2 operator-(const Vector2& vector) {
|
||||
return Vector2(-vector.x, -vector.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number
|
||||
inline Vector2 operator*(const Vector2& vector, float number) {
|
||||
return Vector2(number * vector.x, number * vector.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication of two vectors
|
||||
inline Vector2 operator*(const Vector2& vector1, const Vector2& vector2) {
|
||||
return Vector2(vector1.x * vector2.x, vector1.y * vector2.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for division by a number
|
||||
inline Vector2 operator/(const Vector2& vector, float number) {
|
||||
assert(number > MACHINE_EPSILON);
|
||||
return Vector2(vector.x / number, vector.y / number);
|
||||
}
|
||||
|
||||
// Overload operator for division between two vectors
|
||||
inline Vector2 operator/(const Vector2& vector1, const Vector2& vector2) {
|
||||
assert(vector2.x > MACHINE_EPSILON);
|
||||
assert(vector2.y > MACHINE_EPSILON);
|
||||
return Vector2(vector1.x / vector2.x, vector1.y / vector2.y);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number
|
||||
inline Vector2 operator*(float number, const Vector2& vector) {
|
||||
return vector * number;
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
inline Vector2& Vector2::operator=(const Vector2& vector) {
|
||||
if (&vector != this) {
|
||||
x = vector.x;
|
||||
y = vector.y;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded less than operator for ordering to be used inside std::set for instance
|
||||
inline bool Vector2::operator<(const Vector2& vector) const {
|
||||
return (x == vector.x ? y < vector.y : x < vector.x);
|
||||
}
|
||||
|
||||
// Return a vector taking the minimum components of two vectors
|
||||
inline Vector2 Vector2::min(const Vector2& vector1, const Vector2& vector2) {
|
||||
return Vector2(std::min(vector1.x, vector2.x),
|
||||
std::min(vector1.y, vector2.y));
|
||||
}
|
||||
|
||||
// Return a vector taking the maximum components of two vectors
|
||||
inline Vector2 Vector2::max(const Vector2& vector1, const Vector2& vector2) {
|
||||
return Vector2(std::max(vector1.x, vector2.x),
|
||||
std::max(vector1.y, vector2.y));
|
||||
}
|
||||
|
||||
// Return the zero vector
|
||||
inline Vector2 Vector2::zero() {
|
||||
return Vector2(0, 0);
|
||||
}
|
||||
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
// Namespaces
|
||||
using namespace reactphysics3d;
|
||||
|
||||
// Constructor of the class Vector3D
|
||||
Vector3::Vector3() : x(0.0), y(0.0), z(0.0) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor with arguments
|
||||
Vector3::Vector3(float newX, float newY, float newZ) : x(newX), y(newY), z(newZ) {
|
||||
|
||||
}
|
||||
|
||||
// Copy-constructor
|
||||
Vector3::Vector3(const Vector3& vector) : x(vector.x), y(vector.y), z(vector.z) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Vector3::~Vector3() {
|
||||
|
||||
}
|
||||
|
||||
// Return the corresponding unit vector
|
||||
Vector3 Vector3::getUnit() const {
|
||||
float lengthVector = length();
|
||||
|
||||
if (lengthVector < MACHINE_EPSILON) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compute and return the unit vector
|
||||
float lengthInv = float(1.0) / lengthVector;
|
||||
return Vector3(x * lengthInv, y * lengthInv, z * lengthInv);
|
||||
}
|
||||
|
||||
// Return one unit orthogonal vector of the current vector
|
||||
Vector3 Vector3::getOneUnitOrthogonalVector() const {
|
||||
|
||||
assert(length() > MACHINE_EPSILON);
|
||||
|
||||
// Get the minimum element of the vector
|
||||
Vector3 vectorAbs(fabs(x), fabs(y), fabs(z));
|
||||
int32_t minElement = vectorAbs.getMinAxis();
|
||||
|
||||
if (minElement == 0) {
|
||||
return Vector3(0.0, -z, y) / sqrt(y*y + z*z);
|
||||
}
|
||||
else if (minElement == 1) {
|
||||
return Vector3(-z, 0.0, x) / sqrt(x*x + z*z);
|
||||
}
|
||||
else {
|
||||
return Vector3(-y, x, 0.0) / sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
}
|
@ -1,363 +0,0 @@
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include <ephysics/mathematics/mathematics_functions.h>
|
||||
|
||||
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
// Class Vector3
|
||||
/**
|
||||
* This class represents a 3D vector.
|
||||
*/
|
||||
struct Vector3 {
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Component x
|
||||
float x;
|
||||
|
||||
/// Component y
|
||||
float y;
|
||||
|
||||
/// Component z
|
||||
float z;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor of the class Vector3D
|
||||
Vector3();
|
||||
|
||||
/// Constructor with arguments
|
||||
Vector3(float newX, float newY, float newZ);
|
||||
|
||||
/// Copy-constructor
|
||||
Vector3(const Vector3& vector);
|
||||
|
||||
/// Destructor
|
||||
~Vector3();
|
||||
|
||||
/// Set all the values of the vector
|
||||
void setAllValues(float newX, float newY, float newZ);
|
||||
|
||||
/// Set the vector to zero
|
||||
void setToZero();
|
||||
|
||||
/// Return the length of the vector
|
||||
float length() const;
|
||||
|
||||
/// Return the square of the length of the vector
|
||||
float lengthSquare() const;
|
||||
|
||||
/// Return the corresponding unit vector
|
||||
Vector3 getUnit() const;
|
||||
|
||||
/// Return one unit orthogonal vector of the current vector
|
||||
Vector3 getOneUnitOrthogonalVector() const;
|
||||
|
||||
/// Return true if the vector is unit and false otherwise
|
||||
bool isUnit() const;
|
||||
|
||||
/// Return true if the current vector is the zero vector
|
||||
bool isZero() const;
|
||||
|
||||
/// Dot product of two vectors
|
||||
float dot(const Vector3& vector) const;
|
||||
|
||||
/// Cross product of two vectors
|
||||
Vector3 cross(const Vector3& vector) const;
|
||||
|
||||
/// Normalize the vector
|
||||
void normalize();
|
||||
|
||||
/// Return the corresponding absolute value vector
|
||||
Vector3 getAbsoluteVector() const;
|
||||
|
||||
/// Return the axis with the minimal value
|
||||
int32_t getMinAxis() const;
|
||||
|
||||
/// Return the axis with the maximal value
|
||||
int32_t getMaxAxis() const;
|
||||
|
||||
/// Return the minimum value among the three components of a vector
|
||||
float getMinValue() const;
|
||||
|
||||
/// Return the maximum value among the three components of a vector
|
||||
float getMaxValue() const;
|
||||
|
||||
/// Overloaded operator for the equality condition
|
||||
bool operator== (const Vector3& vector) const;
|
||||
|
||||
/// Overloaded operator for the is different condition
|
||||
bool operator!= (const Vector3& vector) const;
|
||||
|
||||
/// Overloaded operator for addition with assignment
|
||||
Vector3& operator+=(const Vector3& vector);
|
||||
|
||||
/// Overloaded operator for substraction with assignment
|
||||
Vector3& operator-=(const Vector3& vector);
|
||||
|
||||
/// Overloaded operator for multiplication with a number with assignment
|
||||
Vector3& operator*=(float number);
|
||||
|
||||
/// Overloaded operator for division by a number with assignment
|
||||
Vector3& operator/=(float number);
|
||||
|
||||
/// Overloaded operator for value access
|
||||
float& operator[] (int32_t index);
|
||||
|
||||
/// Overloaded operator for value access
|
||||
const float& operator[] (int32_t index) const;
|
||||
|
||||
/// Overloaded operator
|
||||
Vector3& operator=(const Vector3& vector);
|
||||
|
||||
/// Overloaded less than operator for ordering to be used inside std::set for instance
|
||||
bool operator<(const Vector3& vector) const;
|
||||
|
||||
/// Return a vector taking the minimum components of two vectors
|
||||
static Vector3 min(const Vector3& vector1, const Vector3& vector2);
|
||||
|
||||
/// Return a vector taking the maximum components of two vectors
|
||||
static Vector3 max(const Vector3& vector1, const Vector3& vector2);
|
||||
|
||||
/// Return the zero vector
|
||||
static Vector3 zero();
|
||||
|
||||
// -------------------- Friends -------------------- //
|
||||
|
||||
friend Vector3 operator+(const Vector3& vector1, const Vector3& vector2);
|
||||
friend Vector3 operator-(const Vector3& vector1, const Vector3& vector2);
|
||||
friend Vector3 operator-(const Vector3& vector);
|
||||
friend Vector3 operator*(const Vector3& vector, float number);
|
||||
friend Vector3 operator*(float number, const Vector3& vector);
|
||||
friend Vector3 operator*(const Vector3& vector1, const Vector3& vector2);
|
||||
friend Vector3 operator/(const Vector3& vector, float number);
|
||||
friend Vector3 operator/(const Vector3& vector1, const Vector3& vector2);
|
||||
};
|
||||
|
||||
// Set the vector to zero
|
||||
inline void Vector3::setToZero() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
// Set all the values of the vector
|
||||
inline void Vector3::setAllValues(float newX, float newY, float newZ) {
|
||||
x = newX;
|
||||
y = newY;
|
||||
z = newZ;
|
||||
}
|
||||
|
||||
// Return the length of the vector
|
||||
inline float Vector3::length() const {
|
||||
return sqrt(x*x + y*y + z*z);
|
||||
}
|
||||
|
||||
// Return the square of the length of the vector
|
||||
inline float Vector3::lengthSquare() const {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
// Scalar product of two vectors (inline)
|
||||
inline float Vector3::dot(const Vector3& vector) const {
|
||||
return (x*vector.x + y*vector.y + z*vector.z);
|
||||
}
|
||||
|
||||
// Cross product of two vectors (inline)
|
||||
inline Vector3 Vector3::cross(const Vector3& vector) const {
|
||||
return Vector3(y * vector.z - z * vector.y,
|
||||
z * vector.x - x * vector.z,
|
||||
x * vector.y - y * vector.x);
|
||||
}
|
||||
|
||||
// Normalize the vector
|
||||
inline void Vector3::normalize() {
|
||||
float l = length();
|
||||
if (l < MACHINE_EPSILON) {
|
||||
return;
|
||||
}
|
||||
x /= l;
|
||||
y /= l;
|
||||
z /= l;
|
||||
}
|
||||
|
||||
// Return the corresponding absolute value vector
|
||||
inline Vector3 Vector3::getAbsoluteVector() const {
|
||||
return Vector3(std::abs(x), std::abs(y), std::abs(z));
|
||||
}
|
||||
|
||||
// Return the axis with the minimal value
|
||||
inline int32_t Vector3::getMinAxis() const {
|
||||
return (x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2));
|
||||
}
|
||||
|
||||
// Return the axis with the maximal value
|
||||
inline int32_t Vector3::getMaxAxis() const {
|
||||
return (x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0));
|
||||
}
|
||||
|
||||
// Return true if the vector is unit and false otherwise
|
||||
inline bool Vector3::isUnit() const {
|
||||
return approxEqual(lengthSquare(), 1.0);
|
||||
}
|
||||
|
||||
// Return true if the vector is the zero vector
|
||||
inline bool Vector3::isZero() const {
|
||||
return approxEqual(lengthSquare(), 0.0);
|
||||
}
|
||||
|
||||
// Overloaded operator for the equality condition
|
||||
inline bool Vector3::operator== (const Vector3& vector) const {
|
||||
return (x == vector.x && y == vector.y && z == vector.z);
|
||||
}
|
||||
|
||||
// Overloaded operator for the is different condition
|
||||
inline bool Vector3::operator!= (const Vector3& vector) const {
|
||||
return !(*this == vector);
|
||||
}
|
||||
|
||||
// Overloaded operator for addition with assignment
|
||||
inline Vector3& Vector3::operator+=(const Vector3& vector) {
|
||||
x += vector.x;
|
||||
y += vector.y;
|
||||
z += vector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction with assignment
|
||||
inline Vector3& Vector3::operator-=(const Vector3& vector) {
|
||||
x -= vector.x;
|
||||
y -= vector.y;
|
||||
z -= vector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number with assignment
|
||||
inline Vector3& Vector3::operator*=(float number) {
|
||||
x *= number;
|
||||
y *= number;
|
||||
z *= number;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for division by a number with assignment
|
||||
inline Vector3& Vector3::operator/=(float number) {
|
||||
assert(number > std::numeric_limits<float>::epsilon());
|
||||
x /= number;
|
||||
y /= number;
|
||||
z /= number;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded operator for value access
|
||||
inline float& Vector3::operator[] (int32_t index) {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// Overloaded operator for value access
|
||||
inline const float& Vector3::operator[] (int32_t index) const {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
// Overloaded operator for addition
|
||||
inline Vector3 operator+(const Vector3& vector1, const Vector3& vector2) {
|
||||
return Vector3(vector1.x + vector2.x, vector1.y + vector2.y, vector1.z + vector2.z);
|
||||
}
|
||||
|
||||
// Overloaded operator for substraction
|
||||
inline Vector3 operator-(const Vector3& vector1, const Vector3& vector2) {
|
||||
return Vector3(vector1.x - vector2.x, vector1.y - vector2.y, vector1.z - vector2.z);
|
||||
}
|
||||
|
||||
// Overloaded operator for the negative of a vector
|
||||
inline Vector3 operator-(const Vector3& vector) {
|
||||
return Vector3(-vector.x, -vector.y, -vector.z);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number
|
||||
inline Vector3 operator*(const Vector3& vector, float number) {
|
||||
return Vector3(number * vector.x, number * vector.y, number * vector.z);
|
||||
}
|
||||
|
||||
// Overloaded operator for division by a number
|
||||
inline Vector3 operator/(const Vector3& vector, float number) {
|
||||
assert(number > MACHINE_EPSILON);
|
||||
return Vector3(vector.x / number, vector.y / number, vector.z / number);
|
||||
}
|
||||
|
||||
// Overload operator for division between two vectors
|
||||
inline Vector3 operator/(const Vector3& vector1, const Vector3& vector2) {
|
||||
assert(vector2.x > MACHINE_EPSILON);
|
||||
assert(vector2.y > MACHINE_EPSILON);
|
||||
assert(vector2.z > MACHINE_EPSILON);
|
||||
return Vector3(vector1.x / vector2.x, vector1.y / vector2.y, vector1.z / vector2.z);
|
||||
}
|
||||
|
||||
// Overloaded operator for multiplication with a number
|
||||
inline Vector3 operator*(float number, const Vector3& vector) {
|
||||
return vector * number;
|
||||
}
|
||||
|
||||
// Overload operator for multiplication between two vectors
|
||||
inline Vector3 operator*(const Vector3& vector1, const Vector3& vector2) {
|
||||
return Vector3(vector1.x * vector2.x, vector1.y * vector2.y, vector1.z * vector2.z);
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
inline Vector3& Vector3::operator=(const Vector3& vector) {
|
||||
if (&vector != this) {
|
||||
x = vector.x;
|
||||
y = vector.y;
|
||||
z = vector.z;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overloaded less than operator for ordering to be used inside std::set for instance
|
||||
inline bool Vector3::operator<(const Vector3& vector) const {
|
||||
return (x == vector.x ? (y == vector.y ? z < vector.z : y < vector.y) : x < vector.x);
|
||||
}
|
||||
|
||||
// Return a vector taking the minimum components of two vectors
|
||||
inline Vector3 Vector3::min(const Vector3& vector1, const Vector3& vector2) {
|
||||
return Vector3(std::min(vector1.x, vector2.x),
|
||||
std::min(vector1.y, vector2.y),
|
||||
std::min(vector1.z, vector2.z));
|
||||
}
|
||||
|
||||
// Return a vector taking the maximum components of two vectors
|
||||
inline Vector3 Vector3::max(const Vector3& vector1, const Vector3& vector2) {
|
||||
return Vector3(std::max(vector1.x, vector2.x),
|
||||
std::max(vector1.y, vector2.y),
|
||||
std::max(vector1.z, vector2.z));
|
||||
}
|
||||
|
||||
// Return the minimum value among the three components of a vector
|
||||
inline float Vector3::getMinValue() const {
|
||||
return std::min(std::min(x, y), z);
|
||||
}
|
||||
|
||||
// Return the maximum value among the three components of a vector
|
||||
inline float Vector3::getMaxValue() const {
|
||||
return std::max(std::max(x, y), z);
|
||||
}
|
||||
|
||||
// Return the zero vector
|
||||
inline Vector3 Vector3::zero() {
|
||||
return Vector3(0, 0, 0);
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +1,17 @@
|
||||
/********************************************************************************
|
||||
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
||||
* Copyright (c) 2010-2016 Daniel Chappuis *
|
||||
*********************************************************************************
|
||||
* *
|
||||
* This software is provided 'as-is', without any express or implied warranty. *
|
||||
* In no event will the authors be held liable for any damages arising from the *
|
||||
* use of this software. *
|
||||
* *
|
||||
* Permission is granted to anyone to use this software for any purpose, *
|
||||
* including commercial applications, and to alter it and redistribute it *
|
||||
* freely, subject to the following restrictions: *
|
||||
* *
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim *
|
||||
* that you wrote the original software. If you use this software in a *
|
||||
* product, an acknowledgment in the product documentation would be *
|
||||
* appreciated but is not required. *
|
||||
* *
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be *
|
||||
* misrepresented as being the original software. *
|
||||
* *
|
||||
* 3. This notice may not be removed or altered from any source distribution. *
|
||||
* *
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef REACTPHYSICS3D_MATHEMATICS_H
|
||||
#define REACTPHYSICS3D_MATHEMATICS_H
|
||||
/** @file
|
||||
* @author Daniel Chappuis
|
||||
* @copyright 2010-2016 Daniel Chappuis
|
||||
* @license BSD 3 clauses (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/Matrix3x3.h>
|
||||
#include <ephysics/mathematics/Matrix2x2.h>
|
||||
#include <ephysics/mathematics/Quaternion.h>
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <ephysics/mathematics/Vector2.h>
|
||||
#include <ephysics/mathematics/Transform.h>
|
||||
#include <etk/math/Matrix3x3.hpp>
|
||||
#include <etk/math/Matrix2x2.hpp>
|
||||
#include <etk/math/Quaternion.hpp>
|
||||
#include <etk/math/Vector3D.hpp>
|
||||
#include <etk/math/Vector2D.hpp>
|
||||
#include <etk/math/Transform3D.hpp>
|
||||
#include <ephysics/mathematics/Ray.h>
|
||||
#include <ephysics/configuration.h>
|
||||
#include <ephysics/mathematics/mathematics_functions.h>
|
||||
@ -40,5 +19,3 @@
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#endif
|
||||
|
@ -6,18 +6,18 @@
|
||||
|
||||
// Libraries
|
||||
#include <ephysics/mathematics/mathematics_functions.h>
|
||||
#include <ephysics/mathematics/Vector3.h>
|
||||
#include <etk/math/Vector3D.hpp>
|
||||
|
||||
using namespace reactphysics3d;
|
||||
|
||||
/// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
|
||||
/// This method uses the technique described in the book Real-Time collision detection by
|
||||
/// Christer Ericson.
|
||||
void reactphysics3d::computeBarycentricCoordinatesInTriangle(const Vector3& a, const Vector3& b, const Vector3& c,
|
||||
const Vector3& p, float& u, float& v, float& w) {
|
||||
const Vector3 v0 = b - a;
|
||||
const Vector3 v1 = c - a;
|
||||
const Vector3 v2 = p - a;
|
||||
void reactphysics3d::computeBarycentricCoordinatesInTriangle(const vec3& a, const vec3& b, const vec3& c,
|
||||
const vec3& p, float& u, float& v, float& w) {
|
||||
const vec3 v0 = b - a;
|
||||
const vec3 v1 = c - a;
|
||||
const vec3 v2 = p - a;
|
||||
|
||||
float d00 = v0.dot(v0);
|
||||
float d01 = v0.dot(v1);
|
||||
@ -28,13 +28,13 @@ void reactphysics3d::computeBarycentricCoordinatesInTriangle(const Vector3& a, c
|
||||
float denom = d00 * d11 - d01 * d01;
|
||||
v = (d11 * d20 - d01 * d21) / denom;
|
||||
w = (d00 * d21 - d01 * d20) / denom;
|
||||
u = float(1.0) - v - w;
|
||||
u = 1.0f - v - w;
|
||||
}
|
||||
|
||||
// Clamp a vector such that it is no longer than a given maximum length
|
||||
Vector3 reactphysics3d::clamp(const Vector3& vector, float maxLength) {
|
||||
if (vector.lengthSquare() > maxLength * maxLength) {
|
||||
return vector.getUnit() * maxLength;
|
||||
vec3 reactphysics3d::clamp(const vec3& vector, float maxLength) {
|
||||
if (vector.length2() > maxLength * maxLength) {
|
||||
return vector.safeNormalized() * maxLength;
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
@ -15,8 +15,6 @@
|
||||
/// ReactPhysics3D namespace
|
||||
namespace reactphysics3d {
|
||||
|
||||
struct Vector3;
|
||||
|
||||
// ---------- Mathematics functions ---------- //
|
||||
|
||||
/// Function to test if two real numbers are (almost) equal
|
||||
@ -51,14 +49,14 @@ inline float max3(float a, float b, float c) {
|
||||
|
||||
/// Return true if two values have the same sign
|
||||
inline bool sameSign(float a, float b) {
|
||||
return a * b >= float(0.0);
|
||||
return a * b >= 0.0f;
|
||||
}
|
||||
|
||||
/// Clamp a vector such that it is no longer than a given maximum length
|
||||
Vector3 clamp(const Vector3& vector, float maxLength);
|
||||
vec3 clamp(const vec3& vector, float maxLength);
|
||||
|
||||
/// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
|
||||
void computeBarycentricCoordinatesInTriangle(const Vector3& a, const Vector3& b, const Vector3& c,
|
||||
const Vector3& p, float& u, float& v, float& w);
|
||||
void computeBarycentricCoordinatesInTriangle(const vec3& a, const vec3& b, const vec3& c,
|
||||
const vec3& p, float& u, float& v, float& w);
|
||||
|
||||
}
|
||||
|
@ -70,13 +70,7 @@ def configure(target, my_module):
|
||||
'ephysics/body/RigidBody.cpp',
|
||||
'ephysics/body/Body.cpp',
|
||||
'ephysics/body/CollisionBody.cpp',
|
||||
'ephysics/mathematics/Vector2.cpp',
|
||||
'ephysics/mathematics/Vector3.cpp',
|
||||
'ephysics/mathematics/Transform.cpp',
|
||||
'ephysics/mathematics/Matrix2x2.cpp',
|
||||
'ephysics/mathematics/mathematics_functions.cpp',
|
||||
'ephysics/mathematics/Matrix3x3.cpp',
|
||||
'ephysics/mathematics/Quaternion.cpp',
|
||||
'ephysics/engine/CollisionWorld.cpp',
|
||||
'ephysics/engine/OverlappingPair.cpp',
|
||||
'ephysics/engine/Material.cpp',
|
||||
@ -138,13 +132,7 @@ def configure(target, my_module):
|
||||
'ephysics/body/CollisionBody.h',
|
||||
'ephysics/mathematics/mathematics.h',
|
||||
'ephysics/mathematics/Ray.h',
|
||||
'ephysics/mathematics/Matrix2x2.h',
|
||||
'ephysics/mathematics/Vector2.h',
|
||||
'ephysics/mathematics/mathematics_functions.h',
|
||||
'ephysics/mathematics/Vector3.h',
|
||||
'ephysics/mathematics/Quaternion.h',
|
||||
'ephysics/mathematics/Transform.h',
|
||||
'ephysics/mathematics/Matrix3x3.h',
|
||||
'ephysics/engine/CollisionWorld.h',
|
||||
'ephysics/engine/DynamicsWorld.h',
|
||||
'ephysics/engine/ConstraintSolver.h',
|
||||
|
@ -25,12 +25,12 @@
|
||||
|
||||
// Libraries
|
||||
#include <test/TestSuite.h>
|
||||
#include <test/tests/mathematics/TestVector2.h>
|
||||
#include <test/tests/mathematics/TestVector3.h>
|
||||
#include <test/tests/mathematics/TestTransform.h>
|
||||
#include <test/tests/mathematics/TestQuaternion.h>
|
||||
#include <test/tests/mathematics/TestMatrix2x2.h>
|
||||
#include <test/tests/mathematics/TestMatrix3x3.h>
|
||||
#include <test/tests/mathematics/Testvec2.h>
|
||||
#include <test/tests/mathematics/Testvec3.h>
|
||||
#include <test/tests/mathematics/Testetk::Transform3D.h>
|
||||
#include <test/tests/mathematics/Testetk::Quaternion.h>
|
||||
#include <test/tests/mathematics/Testetk::Matrix2x2.h>
|
||||
#include <test/tests/mathematics/Testetk::Matrix3x3.h>
|
||||
#include <test/tests/mathematics/TestMathematicsFunctions.h>
|
||||
#include <test/tests/collision/TestPointInside.h>
|
||||
#include <test/tests/collision/TestRaycast.h>
|
||||
@ -46,12 +46,12 @@ int32_t main() {
|
||||
|
||||
// ---------- Mathematics tests ---------- //
|
||||
|
||||
testSuite.addTest(new TestVector2("Vector2"));
|
||||
testSuite.addTest(new TestVector3("Vector3"));
|
||||
testSuite.addTest(new TestTransform("Transform"));
|
||||
testSuite.addTest(new TestQuaternion("Quaternion"));
|
||||
testSuite.addTest(new TestMatrix3x3("Matrix3x3"));
|
||||
testSuite.addTest(new TestMatrix2x2("Matrix2x2"));
|
||||
testSuite.addTest(new Testvec2("vec2"));
|
||||
testSuite.addTest(new Testvec3("vec3"));
|
||||
testSuite.addTest(new Testetk::Transform3D("Transform"));
|
||||
testSuite.addTest(new Testetk::Quaternion("Quaternion"));
|
||||
testSuite.addTest(new Testetk::Matrix3x3("Matrix3x3"));
|
||||
testSuite.addTest(new Testetk::Matrix2x2("Matrix2x2"));
|
||||
testSuite.addTest(new TestMathematicsFunctions("Maths Functions"));
|
||||
|
||||
// ---------- Collision Detection tests ---------- //
|
||||
|
@ -43,10 +43,10 @@ class TestAABB : public Test {
|
||||
|
||||
// ---------- Atributes ---------- //
|
||||
|
||||
AABB mAABB1;
|
||||
AABB mAABB2;
|
||||
AABB mAABB3;
|
||||
AABB mAABB4;
|
||||
AABB m_AABB1;
|
||||
AABB m_AABB2;
|
||||
AABB m_AABB3;
|
||||
AABB m_AABB4;
|
||||
|
||||
public :
|
||||
|
||||
@ -55,20 +55,20 @@ class TestAABB : public Test {
|
||||
/// Constructor
|
||||
TestAABB(const std::string& name) : Test(name) {
|
||||
|
||||
mAABB1.setMin(Vector3(-10, -10, -10));
|
||||
mAABB1.setMax(Vector3(10, 10, 10));
|
||||
m_AABB1.setMin(vec3(-10, -10, -10));
|
||||
m_AABB1.setMax(vec3(10, 10, 10));
|
||||
|
||||
// AABB2 int32_tersect with AABB1
|
||||
mAABB2.setMin(Vector3(-5, 4, -30));
|
||||
mAABB2.setMax(Vector3(-2, 20, 30));
|
||||
m_AABB2.setMin(vec3(-5, 4, -30));
|
||||
m_AABB2.setMax(vec3(-2, 20, 30));
|
||||
|
||||
// AABB3 contains AABB1
|
||||
mAABB3.setMin(Vector3(-25, -25, -25));
|
||||
mAABB3.setMax(Vector3(25, 25, 25));
|
||||
m_AABB3.setMin(vec3(-25, -25, -25));
|
||||
m_AABB3.setMax(vec3(25, 25, 25));
|
||||
|
||||
// AABB4 does not collide with AABB1
|
||||
mAABB4.setMin(Vector3(-40, -40, -40));
|
||||
mAABB4.setMax(Vector3(-15, -25, -12));
|
||||
m_AABB4.setMin(vec3(-40, -40, -40));
|
||||
m_AABB4.setMax(vec3(-15, -25, -12));
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
@ -87,201 +87,201 @@ class TestAABB : public Test {
|
||||
|
||||
// -------- Test constructors -------- //
|
||||
AABB aabb1;
|
||||
AABB aabb2(Vector3(-3, -5, -8), Vector3(65, -1, 56));
|
||||
Vector3 trianglePoints[] = {
|
||||
Vector3(-5, 7, 23), Vector3(45, -34, -73), Vector3(-12, 98, 76)
|
||||
AABB aabb2(vec3(-3, -5, -8), vec3(65, -1, 56));
|
||||
vec3 trianglePoints[] = {
|
||||
vec3(-5, 7, 23), vec3(45, -34, -73), vec3(-12, 98, 76)
|
||||
};
|
||||
AABB aabb3 = AABB::createAABBForTriangle(trianglePoints);
|
||||
|
||||
test(aabb1.getMin().x == 0);
|
||||
test(aabb1.getMin().y == 0);
|
||||
test(aabb1.getMin().z == 0);
|
||||
test(aabb1.getMax().x == 0);
|
||||
test(aabb1.getMax().y == 0);
|
||||
test(aabb1.getMax().z == 0);
|
||||
test(aabb1.getMin().x() == 0);
|
||||
test(aabb1.getMin().y() == 0);
|
||||
test(aabb1.getMin().z() == 0);
|
||||
test(aabb1.getMax().x() == 0);
|
||||
test(aabb1.getMax().y() == 0);
|
||||
test(aabb1.getMax().z() == 0);
|
||||
|
||||
test(aabb2.getMin().x == -3);
|
||||
test(aabb2.getMin().y == -5);
|
||||
test(aabb2.getMin().z == -8);
|
||||
test(aabb2.getMax().x == 65);
|
||||
test(aabb2.getMax().y == -1);
|
||||
test(aabb2.getMax().z == 56);
|
||||
test(aabb2.getMin().x() == -3);
|
||||
test(aabb2.getMin().y() == -5);
|
||||
test(aabb2.getMin().z() == -8);
|
||||
test(aabb2.getMax().x() == 65);
|
||||
test(aabb2.getMax().y() == -1);
|
||||
test(aabb2.getMax().z() == 56);
|
||||
|
||||
test(aabb3.getMin().x == -12);
|
||||
test(aabb3.getMin().y == -34);
|
||||
test(aabb3.getMin().z == -73);
|
||||
test(aabb3.getMax().x == 45);
|
||||
test(aabb3.getMax().y == 98);
|
||||
test(aabb3.getMax().z == 76);
|
||||
test(aabb3.getMin().x() == -12);
|
||||
test(aabb3.getMin().y() == -34);
|
||||
test(aabb3.getMin().z() == -73);
|
||||
test(aabb3.getMax().x() == 45);
|
||||
test(aabb3.getMax().y() == 98);
|
||||
test(aabb3.getMax().z() == 76);
|
||||
|
||||
// -------- Test inflate() -------- //
|
||||
AABB aabbInflate(Vector3(-3, 4, 8), Vector3(-1, 6, 32));
|
||||
AABB aabbInflate(vec3(-3, 4, 8), vec3(-1, 6, 32));
|
||||
aabbInflate.inflate(1, 2, 3);
|
||||
test(approxEqual(aabbInflate.getMin().x, -4, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMin().y, 2, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMin().z, 5, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMax().x, 0, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMax().y, 8, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMax().z, 35, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMin().x(), -4, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMin().y(), 2, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMin().z(), 5, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMax().x(), 0, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMax().y(), 8, 0.00001));
|
||||
test(approxEqual(aabbInflate.getMax().z(), 35, 0.00001));
|
||||
|
||||
// -------- Test getExtent() --------- //
|
||||
|
||||
test(approxEqual(mAABB1.getExtent().x, 20));
|
||||
test(approxEqual(mAABB1.getExtent().y, 20));
|
||||
test(approxEqual(mAABB1.getExtent().z, 20));
|
||||
test(approxEqual(m_AABB1.getExtent().x(), 20));
|
||||
test(approxEqual(m_AABB1.getExtent().y(), 20));
|
||||
test(approxEqual(m_AABB1.getExtent().z(), 20));
|
||||
|
||||
test(approxEqual(mAABB2.getExtent().x, 3));
|
||||
test(approxEqual(mAABB2.getExtent().y, 16));
|
||||
test(approxEqual(mAABB2.getExtent().z, 60));
|
||||
test(approxEqual(m_AABB2.getExtent().x(), 3));
|
||||
test(approxEqual(m_AABB2.getExtent().y(), 16));
|
||||
test(approxEqual(m_AABB2.getExtent().z(), 60));
|
||||
|
||||
test(approxEqual(mAABB3.getExtent().x, 50));
|
||||
test(approxEqual(mAABB3.getExtent().y, 50));
|
||||
test(approxEqual(mAABB3.getExtent().z, 50));
|
||||
test(approxEqual(m_AABB3.getExtent().x(), 50));
|
||||
test(approxEqual(m_AABB3.getExtent().y(), 50));
|
||||
test(approxEqual(m_AABB3.getExtent().z(), 50));
|
||||
|
||||
// -------- Test getCenter() -------- //
|
||||
|
||||
test(mAABB1.getCenter().x == 0);
|
||||
test(mAABB1.getCenter().y == 0);
|
||||
test(mAABB1.getCenter().z == 0);
|
||||
test(m_AABB1.getCenter().x() == 0);
|
||||
test(m_AABB1.getCenter().y() == 0);
|
||||
test(m_AABB1.getCenter().z() == 0);
|
||||
|
||||
test(approxEqual(mAABB2.getCenter().x, -3.5));
|
||||
test(approxEqual(mAABB2.getCenter().y, 12));
|
||||
test(approxEqual(mAABB2.getCenter().z, 0));
|
||||
test(approxEqual(m_AABB2.getCenter().x(), -3.5));
|
||||
test(approxEqual(m_AABB2.getCenter().y(), 12));
|
||||
test(approxEqual(m_AABB2.getCenter().z(), 0));
|
||||
|
||||
// -------- Test setMin(), setMax(), getMin(), getMax() -------- //
|
||||
|
||||
AABB aabb5;
|
||||
aabb5.setMin(Vector3(-12, 34, 6));
|
||||
aabb5.setMax(Vector3(-3, 56, 20));
|
||||
aabb5.setMin(vec3(-12, 34, 6));
|
||||
aabb5.setMax(vec3(-3, 56, 20));
|
||||
|
||||
test(aabb5.getMin().x == -12);
|
||||
test(aabb5.getMin().y == 34);
|
||||
test(aabb5.getMin().z == 6);
|
||||
test(aabb5.getMax().x == -3);
|
||||
test(aabb5.getMax().y == 56);
|
||||
test(aabb5.getMax().z == 20);
|
||||
test(aabb5.getMin().x() == -12);
|
||||
test(aabb5.getMin().y() == 34);
|
||||
test(aabb5.getMin().z() == 6);
|
||||
test(aabb5.getMax().x() == -3);
|
||||
test(aabb5.getMax().y() == 56);
|
||||
test(aabb5.getMax().z() == 20);
|
||||
|
||||
// -------- Test assignment operator -------- //
|
||||
|
||||
AABB aabb6;
|
||||
aabb6 = aabb2;
|
||||
|
||||
test(aabb6.getMin().x == -3);
|
||||
test(aabb6.getMin().y == -5);
|
||||
test(aabb6.getMin().z == -8);
|
||||
test(aabb6.getMax().x == 65);
|
||||
test(aabb6.getMax().y == -1);
|
||||
test(aabb6.getMax().z == 56);
|
||||
test(aabb6.getMin().x() == -3);
|
||||
test(aabb6.getMin().y() == -5);
|
||||
test(aabb6.getMin().z() == -8);
|
||||
test(aabb6.getMax().x() == 65);
|
||||
test(aabb6.getMax().y() == -1);
|
||||
test(aabb6.getMax().z() == 56);
|
||||
|
||||
// -------- Test getVolume() -------- //
|
||||
|
||||
test(approxEqual(mAABB1.getVolume(), 8000));
|
||||
test(approxEqual(mAABB2.getVolume(), 2880));
|
||||
test(approxEqual(m_AABB1.getVolume(), 8000));
|
||||
test(approxEqual(m_AABB2.getVolume(), 2880));
|
||||
}
|
||||
|
||||
void testMergeMethods() {
|
||||
|
||||
AABB aabb1(Vector3(-45, 7, -2), Vector3(23, 8, 1));
|
||||
AABB aabb2(Vector3(-15, 6, 23), Vector3(-5, 9, 45));
|
||||
AABB aabb1(vec3(-45, 7, -2), vec3(23, 8, 1));
|
||||
AABB aabb2(vec3(-15, 6, 23), vec3(-5, 9, 45));
|
||||
|
||||
// -------- Test mergeTwoAABBs() -------- //
|
||||
|
||||
AABB aabb3;
|
||||
aabb3.mergeTwoAABBs(aabb1, mAABB1);
|
||||
aabb3.mergeTwoAABBs(aabb1, m_AABB1);
|
||||
|
||||
test(aabb3.getMin().x == -45);
|
||||
test(aabb3.getMin().y == -10);
|
||||
test(aabb3.getMin().z == -10);
|
||||
test(aabb3.getMax().x == 23);
|
||||
test(aabb3.getMax().y == 10);
|
||||
test(aabb3.getMax().z == 10);
|
||||
test(aabb3.getMin().x() == -45);
|
||||
test(aabb3.getMin().y() == -10);
|
||||
test(aabb3.getMin().z() == -10);
|
||||
test(aabb3.getMax().x() == 23);
|
||||
test(aabb3.getMax().y() == 10);
|
||||
test(aabb3.getMax().z() == 10);
|
||||
|
||||
AABB aabb4;
|
||||
aabb4.mergeTwoAABBs(aabb1, aabb2);
|
||||
|
||||
test(aabb4.getMin().x == -45);
|
||||
test(aabb4.getMin().y == 6);
|
||||
test(aabb4.getMin().z == -2);
|
||||
test(aabb4.getMax().x == 23);
|
||||
test(aabb4.getMax().y == 9);
|
||||
test(aabb4.getMax().z == 45);
|
||||
test(aabb4.getMin().x() == -45);
|
||||
test(aabb4.getMin().y() == 6);
|
||||
test(aabb4.getMin().z() == -2);
|
||||
test(aabb4.getMax().x() == 23);
|
||||
test(aabb4.getMax().y() == 9);
|
||||
test(aabb4.getMax().z() == 45);
|
||||
|
||||
// -------- Test mergeWithAABB() -------- //
|
||||
|
||||
aabb1.mergeWithAABB(mAABB1);
|
||||
aabb1.mergeWithAABB(m_AABB1);
|
||||
|
||||
test(aabb1.getMin().x == -45);
|
||||
test(aabb1.getMin().y == -10);
|
||||
test(aabb1.getMin().z == -10);
|
||||
test(aabb1.getMax().x == 23);
|
||||
test(aabb1.getMax().y == 10);
|
||||
test(aabb1.getMax().z == 10);
|
||||
test(aabb1.getMin().x() == -45);
|
||||
test(aabb1.getMin().y() == -10);
|
||||
test(aabb1.getMin().z() == -10);
|
||||
test(aabb1.getMax().x() == 23);
|
||||
test(aabb1.getMax().y() == 10);
|
||||
test(aabb1.getMax().z() == 10);
|
||||
|
||||
aabb2.mergeWithAABB(mAABB1);
|
||||
aabb2.mergeWithAABB(m_AABB1);
|
||||
|
||||
test(aabb2.getMin().x == -15);
|
||||
test(aabb2.getMin().y == -10);
|
||||
test(aabb2.getMin().z == -10);
|
||||
test(aabb2.getMax().x == 10);
|
||||
test(aabb2.getMax().y == 10);
|
||||
test(aabb2.getMax().z == 45);
|
||||
test(aabb2.getMin().x() == -15);
|
||||
test(aabb2.getMin().y() == -10);
|
||||
test(aabb2.getMin().z() == -10);
|
||||
test(aabb2.getMax().x() == 10);
|
||||
test(aabb2.getMax().y() == 10);
|
||||
test(aabb2.getMax().z() == 45);
|
||||
}
|
||||
|
||||
void testIntersection() {
|
||||
|
||||
// -------- Test contains(AABB) -------- //
|
||||
test(!mAABB1.contains(mAABB2));
|
||||
test(mAABB3.contains(mAABB1));
|
||||
test(!mAABB1.contains(mAABB3));
|
||||
test(!mAABB1.contains(mAABB4));
|
||||
test(!mAABB4.contains(mAABB1));
|
||||
test(!m_AABB1.contains(m_AABB2));
|
||||
test(m_AABB3.contains(m_AABB1));
|
||||
test(!m_AABB1.contains(m_AABB3));
|
||||
test(!m_AABB1.contains(m_AABB4));
|
||||
test(!m_AABB4.contains(m_AABB1));
|
||||
|
||||
// -------- Test contains(Vector3) -------- //
|
||||
test(mAABB1.contains(Vector3(0, 0, 0)));
|
||||
test(mAABB1.contains(Vector3(-5, 6, 9)));
|
||||
test(mAABB1.contains(Vector3(-9, -4, -9)));
|
||||
test(mAABB1.contains(Vector3(9, 4, 7)));
|
||||
test(!mAABB1.contains(Vector3(-11, -4, -9)));
|
||||
test(!mAABB1.contains(Vector3(1, 12, -9)));
|
||||
test(!mAABB1.contains(Vector3(1, 8, -13)));
|
||||
test(!mAABB1.contains(Vector3(-14, 82, -13)));
|
||||
// -------- Test contains(vec3) -------- //
|
||||
test(m_AABB1.contains(vec3(0, 0, 0)));
|
||||
test(m_AABB1.contains(vec3(-5, 6, 9)));
|
||||
test(m_AABB1.contains(vec3(-9, -4, -9)));
|
||||
test(m_AABB1.contains(vec3(9, 4, 7)));
|
||||
test(!m_AABB1.contains(vec3(-11, -4, -9)));
|
||||
test(!m_AABB1.contains(vec3(1, 12, -9)));
|
||||
test(!m_AABB1.contains(vec3(1, 8, -13)));
|
||||
test(!m_AABB1.contains(vec3(-14, 82, -13)));
|
||||
|
||||
// -------- Test testCollision() -------- //
|
||||
test(mAABB1.testCollision(mAABB2));
|
||||
test(mAABB2.testCollision(mAABB1));
|
||||
test(mAABB1.testCollision(mAABB3));
|
||||
test(mAABB3.testCollision(mAABB1));
|
||||
test(!mAABB1.testCollision(mAABB4));
|
||||
test(!mAABB4.testCollision(mAABB1));
|
||||
test(m_AABB1.testCollision(m_AABB2));
|
||||
test(m_AABB2.testCollision(m_AABB1));
|
||||
test(m_AABB1.testCollision(m_AABB3));
|
||||
test(m_AABB3.testCollision(m_AABB1));
|
||||
test(!m_AABB1.testCollision(m_AABB4));
|
||||
test(!m_AABB4.testCollision(m_AABB1));
|
||||
|
||||
// -------- Test testCollisionTriangleAABB() -------- //
|
||||
|
||||
AABB aabb(Vector3(100, 100, 100), Vector3(200, 200, 200));
|
||||
Vector3 trianglePoints[] = {
|
||||
Vector3(-2, 4, 6), Vector3(20, -34, -73), Vector3(-12, 98, 76)
|
||||
AABB aabb(vec3(100, 100, 100), vec3(200, 200, 200));
|
||||
vec3 trianglePoints[] = {
|
||||
vec3(-2, 4, 6), vec3(20, -34, -73), vec3(-12, 98, 76)
|
||||
};
|
||||
test(mAABB1.testCollisionTriangleAABB(trianglePoints));
|
||||
test(m_AABB1.testCollisionTriangleAABB(trianglePoints));
|
||||
test(!aabb.testCollisionTriangleAABB(trianglePoints));
|
||||
|
||||
// -------- Test testRayIntersect() -------- //
|
||||
|
||||
Ray ray1(Vector3(-20, 4, -7), Vector3(20, 4, -7));
|
||||
Ray ray2(Vector3(-20, 11, -7), Vector3(20, 11, -7));
|
||||
Ray ray3(Vector3(0, 15, 0), Vector3(0, -15, 0));
|
||||
Ray ray4(Vector3(0, -15, 0), Vector3(0, 15, 0));
|
||||
Ray ray5(Vector3(-3, 4, 8), Vector3(-7, 9, 4));
|
||||
Ray ray6(Vector3(-4, 6, -100), Vector3(-4, 6, -9));
|
||||
Ray ray7(Vector3(-4, 6, -100), Vector3(-4, 6, -11), 0.6);
|
||||
Ray ray8(Vector3(-403, -432, -100), Vector3(134, 643, 23));
|
||||
Ray ray1(vec3(-20, 4, -7), vec3(20, 4, -7));
|
||||
Ray ray2(vec3(-20, 11, -7), vec3(20, 11, -7));
|
||||
Ray ray3(vec3(0, 15, 0), vec3(0, -15, 0));
|
||||
Ray ray4(vec3(0, -15, 0), vec3(0, 15, 0));
|
||||
Ray ray5(vec3(-3, 4, 8), vec3(-7, 9, 4));
|
||||
Ray ray6(vec3(-4, 6, -100), vec3(-4, 6, -9));
|
||||
Ray ray7(vec3(-4, 6, -100), vec3(-4, 6, -11), 0.6);
|
||||
Ray ray8(vec3(-403, -432, -100), vec3(134, 643, 23));
|
||||
|
||||
test(mAABB1.testRayIntersect(ray1));
|
||||
test(!mAABB1.testRayIntersect(ray2));
|
||||
test(mAABB1.testRayIntersect(ray3));
|
||||
test(mAABB1.testRayIntersect(ray4));
|
||||
test(mAABB1.testRayIntersect(ray5));
|
||||
test(mAABB1.testRayIntersect(ray6));
|
||||
test(!mAABB1.testRayIntersect(ray7));
|
||||
test(!mAABB1.testRayIntersect(ray8));
|
||||
test(m_AABB1.testRayIntersect(ray1));
|
||||
test(!m_AABB1.testRayIntersect(ray2));
|
||||
test(m_AABB1.testRayIntersect(ray3));
|
||||
test(m_AABB1.testRayIntersect(ray4));
|
||||
test(m_AABB1.testRayIntersect(ray5));
|
||||
test(m_AABB1.testRayIntersect(ray6));
|
||||
test(!m_AABB1.testRayIntersect(ray7));
|
||||
test(!m_AABB1.testRayIntersect(ray8));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -139,24 +139,24 @@ class TestCollisionWorld : public Test {
|
||||
m_world = new CollisionWorld();
|
||||
|
||||
// Create the bodies
|
||||
Transform boxTransform(Vector3(10, 0, 0), Quaternion::identity());
|
||||
mBoxBody = m_world->createCollisionBody(boxTransform);
|
||||
mBoxShape = new BoxShape(Vector3(3, 3, 3));
|
||||
mBoxProxyShape = mBoxBody->addCollisionShape(mBoxShape, Transform::identity());
|
||||
etk::Transform3D boxTransform(vec3(10, 0, 0), etk::Quaternion::identity());
|
||||
mBoxBody = m_world->createCollisionBody(boxetk::Transform3D);
|
||||
mBoxShape = new BoxShape(vec3(3, 3, 3));
|
||||
mBoxProxyShape = mBoxBody->addCollisionShape(mBoxShape, etk::Transform3D::identity());
|
||||
|
||||
mSphereShape = new SphereShape(3.0);
|
||||
Transform sphere1Transform(Vector3(10,5, 0), Quaternion::identity());
|
||||
mSphere1Body = m_world->createCollisionBody(sphere1Transform);
|
||||
mSphere1ProxyShape = mSphere1Body->addCollisionShape(mSphereShape, Transform::identity());
|
||||
etk::Transform3D sphere1Transform(vec3(10,5, 0), etk::Quaternion::identity());
|
||||
mSphere1Body = m_world->createCollisionBody(sphere1etk::Transform3D);
|
||||
mSphere1ProxyShape = mSphere1Body->addCollisionShape(mSphereShape, etk::Transform3D::identity());
|
||||
|
||||
Transform sphere2Transform(Vector3(30, 10, 10), Quaternion::identity());
|
||||
mSphere2Body = m_world->createCollisionBody(sphere2Transform);
|
||||
mSphere2ProxyShape = mSphere2Body->addCollisionShape(mSphereShape, Transform::identity());
|
||||
etk::Transform3D sphere2Transform(vec3(30, 10, 10), etk::Quaternion::identity());
|
||||
mSphere2Body = m_world->createCollisionBody(sphere2etk::Transform3D);
|
||||
mSphere2ProxyShape = mSphere2Body->addCollisionShape(mSphereShape, etk::Transform3D::identity());
|
||||
|
||||
Transform cylinderTransform(Vector3(10, -5, 0), Quaternion::identity());
|
||||
mCylinderBody = m_world->createCollisionBody(cylinderTransform);
|
||||
etk::Transform3D cylinderTransform(vec3(10, -5, 0), etk::Quaternion::identity());
|
||||
mCylinderBody = m_world->createCollisionBody(cylinderetk::Transform3D);
|
||||
mCylinderShape = new CylinderShape(2, 5);
|
||||
mCylinderProxyShape = mCylinderBody->addCollisionShape(mCylinderShape, Transform::identity());
|
||||
mCylinderProxyShape = mCylinderBody->addCollisionShape(mCylinderShape, etk::Transform3D::identity());
|
||||
|
||||
// Assign collision categories to proxy shapes
|
||||
mBoxProxyShape->setCollisionCategoryBits(CATEGORY_1);
|
||||
@ -238,7 +238,7 @@ class TestCollisionWorld : public Test {
|
||||
test(!m_collisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
// Move sphere 1 to collide with sphere 2
|
||||
mSphere1Body->setTransform(Transform(Vector3(30, 15, 10), Quaternion::identity()));
|
||||
mSphere1Body->setTransform(Transform(vec3(30, 15, 10), etk::Quaternion::identity()));
|
||||
|
||||
m_collisionCallback.reset();
|
||||
m_world->testCollision(&m_collisionCallback);
|
||||
@ -262,7 +262,7 @@ class TestCollisionWorld : public Test {
|
||||
test(!m_collisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
// Move sphere 1 to collide with box
|
||||
mSphere1Body->setTransform(Transform(Vector3(10, 5, 0), Quaternion::identity()));
|
||||
mSphere1Body->setTransform(Transform(vec3(10, 5, 0), etk::Quaternion::identity()));
|
||||
|
||||
// --------- Test collision with inactive bodies --------- //
|
||||
|
||||
@ -307,7 +307,7 @@ class TestCollisionWorld : public Test {
|
||||
test(!m_collisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
// Move sphere 1 to collide with sphere 2
|
||||
mSphere1Body->setTransform(Transform(Vector3(30, 15, 10), Quaternion::identity()));
|
||||
mSphere1Body->setTransform(Transform(vec3(30, 15, 10), etk::Quaternion::identity()));
|
||||
|
||||
m_collisionCallback.reset();
|
||||
m_world->testCollision(&m_collisionCallback);
|
||||
@ -329,7 +329,7 @@ class TestCollisionWorld : public Test {
|
||||
test(!m_collisionCallback.sphere1CollideWithSphere2);
|
||||
|
||||
// Move sphere 1 to collide with box
|
||||
mSphere1Body->setTransform(Transform(Vector3(10, 5, 0), Quaternion::identity()));
|
||||
mSphere1Body->setTransform(Transform(vec3(10, 5, 0), etk::Quaternion::identity()));
|
||||
|
||||
mBoxProxyShape->setCollideWithMaskBits(0xFFFF);
|
||||
mSphere1ProxyShape->setCollideWithMaskBits(0xFFFF);
|
||||
|
@ -123,31 +123,31 @@ class TestDynamicAABBTree : public Test {
|
||||
int32_t object4Data = 7;
|
||||
|
||||
// First object
|
||||
AABB aabb1 = AABB(Vector3(-6, 4, -3), Vector3(4, 8, 3));
|
||||
AABB aabb1 = AABB(vec3(-6, 4, -3), vec3(4, 8, 3));
|
||||
int32_t object1Id = tree.addObject(aabb1, &object1Data);
|
||||
|
||||
// Second object
|
||||
AABB aabb2 = AABB(Vector3(5, 2, -3), Vector3(10, 7, 3));
|
||||
AABB aabb2 = AABB(vec3(5, 2, -3), vec3(10, 7, 3));
|
||||
int32_t object2Id = tree.addObject(aabb2, &object2Data);
|
||||
|
||||
// Third object
|
||||
AABB aabb3 = AABB(Vector3(-5, 1, -3), Vector3(-2, 3, 3));
|
||||
AABB aabb3 = AABB(vec3(-5, 1, -3), vec3(-2, 3, 3));
|
||||
int32_t object3Id = tree.addObject(aabb3, &object3Data);
|
||||
|
||||
// Fourth object
|
||||
AABB aabb4 = AABB(Vector3(0, -4, -3), Vector3(3, -2, 3));
|
||||
AABB aabb4 = AABB(vec3(0, -4, -3), vec3(3, -2, 3));
|
||||
int32_t object4Id = tree.addObject(aabb4, &object4Data);
|
||||
|
||||
// ----------- Tests ----------- //
|
||||
|
||||
// Test root AABB
|
||||
AABB rootAABB = tree.getRootAABB();
|
||||
test(rootAABB.getMin().x == -6);
|
||||
test(rootAABB.getMin().y == -4);
|
||||
test(rootAABB.getMin().z == -3);
|
||||
test(rootAABB.getMax().x == 10);
|
||||
test(rootAABB.getMax().y == 8);
|
||||
test(rootAABB.getMax().z == 3);
|
||||
test(rootAABB.getMin().x() == -6);
|
||||
test(rootAABB.getMin().y() == -4);
|
||||
test(rootAABB.getMin().z() == -3);
|
||||
test(rootAABB.getMax().x() == 10);
|
||||
test(rootAABB.getMax().y() == 8);
|
||||
test(rootAABB.getMax().z() == 3);
|
||||
|
||||
// Test data stored at the nodes of the tree
|
||||
test(*(int32_t*)(tree.getNodeDataPointer(object1Id)) == object1Data);
|
||||
@ -169,26 +169,26 @@ class TestDynamicAABBTree : public Test {
|
||||
int32_t object4Data = 7;
|
||||
|
||||
// First object
|
||||
AABB aabb1 = AABB(Vector3(-6, 4, -3), Vector3(4, 8, 3));
|
||||
AABB aabb1 = AABB(vec3(-6, 4, -3), vec3(4, 8, 3));
|
||||
int32_t object1Id = tree.addObject(aabb1, &object1Data);
|
||||
|
||||
// Second object
|
||||
AABB aabb2 = AABB(Vector3(5, 2, -3), Vector3(10, 7, 3));
|
||||
AABB aabb2 = AABB(vec3(5, 2, -3), vec3(10, 7, 3));
|
||||
int32_t object2Id = tree.addObject(aabb2, &object2Data);
|
||||
|
||||
// Third object
|
||||
AABB aabb3 = AABB(Vector3(-5, 1, -3), Vector3(-2, 3, 3));
|
||||
AABB aabb3 = AABB(vec3(-5, 1, -3), vec3(-2, 3, 3));
|
||||
int32_t object3Id = tree.addObject(aabb3, &object3Data);
|
||||
|
||||
// Fourth object
|
||||
AABB aabb4 = AABB(Vector3(0, -4, -3), Vector3(3, -2, 3));
|
||||
AABB aabb4 = AABB(vec3(0, -4, -3), vec3(3, -2, 3));
|
||||
int32_t object4Id = tree.addObject(aabb4, &object4Data);
|
||||
|
||||
// ---------- Tests ---------- //
|
||||
|
||||
// AABB overlapping nothing
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-10, 12, -4), vec3(10, 50, 4)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(!mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -196,7 +196,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping everything
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-15, -15, -4), vec3(15, 15, 4)), mOverlapCallback);
|
||||
test(mOverlapCallback.isOverlapping(object1Id));
|
||||
test(mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -204,7 +204,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 1 and 3
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-4, 2, -4), vec3(-1, 7, 4)), mOverlapCallback);
|
||||
test(mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -212,7 +212,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 3 and 4
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-6, -5, -2), vec3(2, 2, 0)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -220,7 +220,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 2
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(5, -10, -2), vec3(7, 10, 9)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(mOverlapCallback.isOverlapping(object2Id));
|
||||
test(!mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -228,14 +228,14 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// ---- Update the object AABBs with the initial AABBs (no reinsertion) ----- //
|
||||
|
||||
tree.updateObject(object1Id, aabb1, Vector3::zero(), false);
|
||||
tree.updateObject(object2Id, aabb2, Vector3::zero(), false);
|
||||
tree.updateObject(object3Id, aabb3, Vector3::zero(), false);
|
||||
tree.updateObject(object4Id, aabb4, Vector3::zero(), false);
|
||||
tree.updateObject(object1Id, aabb1, vec3::zero(), false);
|
||||
tree.updateObject(object2Id, aabb2, vec3::zero(), false);
|
||||
tree.updateObject(object3Id, aabb3, vec3::zero(), false);
|
||||
tree.updateObject(object4Id, aabb4, vec3::zero(), false);
|
||||
|
||||
// AABB overlapping nothing
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-10, 12, -4), vec3(10, 50, 4)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(!mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -243,7 +243,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping everything
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-15, -15, -4), vec3(15, 15, 4)), mOverlapCallback);
|
||||
test(mOverlapCallback.isOverlapping(object1Id));
|
||||
test(mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -251,7 +251,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 1 and 3
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-4, 2, -4), vec3(-1, 7, 4)), mOverlapCallback);
|
||||
test(mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -259,7 +259,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 3 and 4
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-6, -5, -2), vec3(2, 2, 0)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -267,7 +267,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 2
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(5, -10, -2), vec3(7, 10, 9)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(mOverlapCallback.isOverlapping(object2Id));
|
||||
test(!mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -275,14 +275,14 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// ---- Update the object AABBs with the initial AABBs (with reinsertion) ----- //
|
||||
|
||||
tree.updateObject(object1Id, aabb1, Vector3::zero(), true);
|
||||
tree.updateObject(object2Id, aabb2, Vector3::zero(), true);
|
||||
tree.updateObject(object3Id, aabb3, Vector3::zero(), true);
|
||||
tree.updateObject(object4Id, aabb4, Vector3::zero(), true);
|
||||
tree.updateObject(object1Id, aabb1, vec3::zero(), true);
|
||||
tree.updateObject(object2Id, aabb2, vec3::zero(), true);
|
||||
tree.updateObject(object3Id, aabb3, vec3::zero(), true);
|
||||
tree.updateObject(object4Id, aabb4, vec3::zero(), true);
|
||||
|
||||
// AABB overlapping nothing
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-10, 12, -4), Vector3(10, 50, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-10, 12, -4), vec3(10, 50, 4)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(!mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -290,7 +290,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping everything
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-15, -15, -4), Vector3(15, 15, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-15, -15, -4), vec3(15, 15, 4)), mOverlapCallback);
|
||||
test(mOverlapCallback.isOverlapping(object1Id));
|
||||
test(mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -298,7 +298,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 1 and 3
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-4, 2, -4), Vector3(-1, 7, 4)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-4, 2, -4), vec3(-1, 7, 4)), mOverlapCallback);
|
||||
test(mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -306,7 +306,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 3 and 4
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-6, -5, -2), Vector3(2, 2, 0)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-6, -5, -2), vec3(2, 2, 0)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -314,7 +314,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping object 2
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(5, -10, -2), Vector3(7, 10, 9)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(5, -10, -2), vec3(7, 10, 9)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(mOverlapCallback.isOverlapping(object2Id));
|
||||
test(!mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -322,15 +322,15 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// ---- Move objects 2 and 3 ----- //
|
||||
|
||||
AABB newAABB2(Vector3(-7, 10, -3), Vector3(1, 13, 3));
|
||||
tree.updateObject(object2Id, newAABB2, Vector3::zero());
|
||||
AABB newAABB2(vec3(-7, 10, -3), vec3(1, 13, 3));
|
||||
tree.updateObject(object2Id, newAABB2, vec3::zero());
|
||||
|
||||
AABB newAABB3(Vector3(7, -6, -3), Vector3(9, 1, 3));
|
||||
tree.updateObject(object3Id, newAABB3, Vector3::zero());
|
||||
AABB newAABB3(vec3(7, -6, -3), vec3(9, 1, 3));
|
||||
tree.updateObject(object3Id, newAABB3, vec3::zero());
|
||||
|
||||
// AABB overlapping object 3
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(6, -10, -2), Vector3(8, 5, 3)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(6, -10, -2), vec3(8, 5, 3)), mOverlapCallback);
|
||||
test(!mOverlapCallback.isOverlapping(object1Id));
|
||||
test(!mOverlapCallback.isOverlapping(object2Id));
|
||||
test(mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -338,7 +338,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// AABB overlapping objects 1, 2
|
||||
mOverlapCallback.reset();
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(Vector3(-8, 5, -3), Vector3(-2, 11, 3)), mOverlapCallback);
|
||||
tree.reportAllShapesOverlappingWithAABB(AABB(vec3(-8, 5, -3), vec3(-2, 11, 3)), mOverlapCallback);
|
||||
test(mOverlapCallback.isOverlapping(object1Id));
|
||||
test(mOverlapCallback.isOverlapping(object2Id));
|
||||
test(!mOverlapCallback.isOverlapping(object3Id));
|
||||
@ -359,26 +359,26 @@ class TestDynamicAABBTree : public Test {
|
||||
int32_t object4Data = 7;
|
||||
|
||||
// First object
|
||||
AABB aabb1 = AABB(Vector3(-6, 4, -3), Vector3(4, 8, 3));
|
||||
AABB aabb1 = AABB(vec3(-6, 4, -3), vec3(4, 8, 3));
|
||||
int32_t object1Id = tree.addObject(aabb1, &object1Data);
|
||||
|
||||
// Second object
|
||||
AABB aabb2 = AABB(Vector3(5, 2, -3), Vector3(10, 7, 3));
|
||||
AABB aabb2 = AABB(vec3(5, 2, -3), vec3(10, 7, 3));
|
||||
int32_t object2Id = tree.addObject(aabb2, &object2Data);
|
||||
|
||||
// Third object
|
||||
AABB aabb3 = AABB(Vector3(-5, 1, -3), Vector3(-2, 3, 3));
|
||||
AABB aabb3 = AABB(vec3(-5, 1, -3), vec3(-2, 3, 3));
|
||||
int32_t object3Id = tree.addObject(aabb3, &object3Data);
|
||||
|
||||
// Fourth object
|
||||
AABB aabb4 = AABB(Vector3(0, -4, -3), Vector3(3, -2, 3));
|
||||
AABB aabb4 = AABB(vec3(0, -4, -3), vec3(3, -2, 3));
|
||||
int32_t object4Id = tree.addObject(aabb4, &object4Data);
|
||||
|
||||
// ---------- Tests ---------- //
|
||||
|
||||
// Ray with no hits
|
||||
m_raycastCallback.reset();
|
||||
Ray ray1(Vector3(4.5, -10, -5), Vector3(4.5, 10, -5));
|
||||
Ray ray1(vec3(4.5, -10, -5), vec3(4.5, 10, -5));
|
||||
tree.raycast(ray1, m_raycastCallback);
|
||||
test(!m_raycastCallback.isHit(object1Id));
|
||||
test(!m_raycastCallback.isHit(object2Id));
|
||||
@ -387,7 +387,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// Ray that hits object 1
|
||||
m_raycastCallback.reset();
|
||||
Ray ray2(Vector3(-1, -20, -2), Vector3(-1, 20, -2));
|
||||
Ray ray2(vec3(-1, -20, -2), vec3(-1, 20, -2));
|
||||
tree.raycast(ray2, m_raycastCallback);
|
||||
test(m_raycastCallback.isHit(object1Id));
|
||||
test(!m_raycastCallback.isHit(object2Id));
|
||||
@ -396,7 +396,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// Ray that hits object 1 and 2
|
||||
m_raycastCallback.reset();
|
||||
Ray ray3(Vector3(-7, 6, -2), Vector3(8, 6, -2));
|
||||
Ray ray3(vec3(-7, 6, -2), vec3(8, 6, -2));
|
||||
tree.raycast(ray3, m_raycastCallback);
|
||||
test(m_raycastCallback.isHit(object1Id));
|
||||
test(m_raycastCallback.isHit(object2Id));
|
||||
@ -405,7 +405,7 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// Ray that hits object 3
|
||||
m_raycastCallback.reset();
|
||||
Ray ray4(Vector3(-7, 2, 0), Vector3(-1, 2, 0));
|
||||
Ray ray4(vec3(-7, 2, 0), vec3(-1, 2, 0));
|
||||
tree.raycast(ray4, m_raycastCallback);
|
||||
test(!m_raycastCallback.isHit(object1Id));
|
||||
test(!m_raycastCallback.isHit(object2Id));
|
||||
@ -414,10 +414,10 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// ---- Update the object AABBs with the initial AABBs (no reinsertion) ----- //
|
||||
|
||||
tree.updateObject(object1Id, aabb1, Vector3::zero(), false);
|
||||
tree.updateObject(object2Id, aabb2, Vector3::zero(), false);
|
||||
tree.updateObject(object3Id, aabb3, Vector3::zero(), false);
|
||||
tree.updateObject(object4Id, aabb4, Vector3::zero(), false);
|
||||
tree.updateObject(object1Id, aabb1, vec3::zero(), false);
|
||||
tree.updateObject(object2Id, aabb2, vec3::zero(), false);
|
||||
tree.updateObject(object3Id, aabb3, vec3::zero(), false);
|
||||
tree.updateObject(object4Id, aabb4, vec3::zero(), false);
|
||||
|
||||
// Ray with no hits
|
||||
m_raycastCallback.reset();
|
||||
@ -453,10 +453,10 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// ---- Update the object AABBs with the initial AABBs (with reinsertion) ----- //
|
||||
|
||||
tree.updateObject(object1Id, aabb1, Vector3::zero(), true);
|
||||
tree.updateObject(object2Id, aabb2, Vector3::zero(), true);
|
||||
tree.updateObject(object3Id, aabb3, Vector3::zero(), true);
|
||||
tree.updateObject(object4Id, aabb4, Vector3::zero(), true);
|
||||
tree.updateObject(object1Id, aabb1, vec3::zero(), true);
|
||||
tree.updateObject(object2Id, aabb2, vec3::zero(), true);
|
||||
tree.updateObject(object3Id, aabb3, vec3::zero(), true);
|
||||
tree.updateObject(object4Id, aabb4, vec3::zero(), true);
|
||||
|
||||
// Ray with no hits
|
||||
m_raycastCallback.reset();
|
||||
@ -492,14 +492,14 @@ class TestDynamicAABBTree : public Test {
|
||||
|
||||
// ---- Move objects 2 and 3 ----- //
|
||||
|
||||
AABB newAABB2(Vector3(-7, 10, -3), Vector3(1, 13, 3));
|
||||
tree.updateObject(object2Id, newAABB2, Vector3::zero());
|
||||
AABB newAABB2(vec3(-7, 10, -3), vec3(1, 13, 3));
|
||||
tree.updateObject(object2Id, newAABB2, vec3::zero());
|
||||
|
||||
AABB newAABB3(Vector3(7, -6, -3), Vector3(9, 1, 3));
|
||||
tree.updateObject(object3Id, newAABB3, Vector3::zero());
|
||||
AABB newAABB3(vec3(7, -6, -3), vec3(9, 1, 3));
|
||||
tree.updateObject(object3Id, newAABB3, vec3::zero());
|
||||
|
||||
// Ray that hits object 1, 2
|
||||
Ray ray5(Vector3(-4, -5, 0), Vector3(-4, 12, 0));
|
||||
Ray ray5(vec3(-4, -5, 0), vec3(-4, 12, 0));
|
||||
m_raycastCallback.reset();
|
||||
tree.raycast(ray5, m_raycastCallback);
|
||||
test(m_raycastCallback.isHit(object1Id));
|
||||
@ -508,7 +508,7 @@ class TestDynamicAABBTree : public Test {
|
||||
test(!m_raycastCallback.isHit(object4Id));
|
||||
|
||||
// Ray that hits object 3 and 4
|
||||
Ray ray6(Vector3(11, -3, 1), Vector3(-2, -3, 1));
|
||||
Ray ray6(vec3(11, -3, 1), vec3(-2, -3, 1));
|
||||
m_raycastCallback.reset();
|
||||
tree.raycast(ray6, m_raycastCallback);
|
||||
test(!m_raycastCallback.isHit(object1Id));
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user