Fix issues and add conversion from Euler angles to Quaternion
This commit is contained in:
parent
bc4de62e75
commit
3aa05ef61a
|
@ -40,13 +40,13 @@
|
||||||
#include "../common/Viewer.h"
|
#include "../common/Viewer.h"
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const int NB_BOXES = 4;
|
const int NB_BOXES = 2;
|
||||||
const int NB_SPHERES = 2;
|
const int NB_SPHERES = 3;
|
||||||
const int NB_CONES = 3;
|
const int NB_CONES = 1;
|
||||||
const int NB_CYLINDERS = 1;
|
const int NB_CYLINDERS = 2;
|
||||||
const int NB_CAPSULES = 1;
|
const int NB_CAPSULES = 1;
|
||||||
const int NB_MESHES = 2;
|
const int NB_MESHES = 3;
|
||||||
const int NB_COMPOUND_SHAPES = 3;
|
const int NB_COMPOUND_SHAPES = 1;
|
||||||
const openglframework::Vector3 BOX_SIZE(2, 2, 2);
|
const openglframework::Vector3 BOX_SIZE(2, 2, 2);
|
||||||
const float SPHERE_RADIUS = 1.5f;
|
const float SPHERE_RADIUS = 1.5f;
|
||||||
const float CONE_RADIUS = 2.0f;
|
const float CONE_RADIUS = 2.0f;
|
||||||
|
|
|
@ -61,7 +61,8 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
|
||||||
|
|
||||||
// Initial position and orientation of the rigid body
|
// Initial position and orientation of the rigid body
|
||||||
rp3d::Vector3 initPosition(position.x, position.y, position.z);
|
rp3d::Vector3 initPosition(position.x, position.y, position.z);
|
||||||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
rp3d::decimal angleAroundX = rp3d::PI / 4;
|
||||||
|
rp3d::Quaternion initOrientation(angleAroundX, 0, 0);
|
||||||
rp3d::Transform transformBody(initPosition, initOrientation);
|
rp3d::Transform transformBody(initPosition, initOrientation);
|
||||||
|
|
||||||
// Initial transform of the first sphere collision shape of the dumbbell (in local-space)
|
// Initial transform of the first sphere collision shape of the dumbbell (in local-space)
|
||||||
|
@ -77,8 +78,8 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
|
||||||
mRigidBody = dynamicsWorld->createRigidBody(transformBody);
|
mRigidBody = dynamicsWorld->createRigidBody(transformBody);
|
||||||
|
|
||||||
// Add the three collision shapes to the body and specify the mass and transform of the shapes
|
// Add the three collision shapes to the body and specify the mass and transform of the shapes
|
||||||
mRigidBody->addCollisionShape(sphereCollisionShape, massSphere, transformSphereShape1);
|
mRigidBody->addCollisionShape(sphereCollisionShape, 1, transformSphereShape1);
|
||||||
mRigidBody->addCollisionShape(sphereCollisionShape, massSphere, transformSphereShape2);
|
mRigidBody->addCollisionShape(sphereCollisionShape, 4, transformSphereShape2);
|
||||||
mRigidBody->addCollisionShape(cylinderCollisionShape, massCylinder, transformCylinderShape);
|
mRigidBody->addCollisionShape(cylinderCollisionShape, massCylinder, transformCylinderShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ void CollisionBody::removeAllCollisionShapes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the contact manifold lists
|
// Reset the contact manifold lists
|
||||||
void CollisionBody::resetContactManifoldsList(MemoryAllocator& memoryAllocator) {
|
void CollisionBody::resetContactManifoldsList() {
|
||||||
|
|
||||||
// Delete the linked list of contact manifolds of that body
|
// Delete the linked list of contact manifolds of that body
|
||||||
ContactManifoldListElement* currentElement = mContactManifoldsList;
|
ContactManifoldListElement* currentElement = mContactManifoldsList;
|
||||||
|
@ -167,13 +167,11 @@ void CollisionBody::resetContactManifoldsList(MemoryAllocator& memoryAllocator)
|
||||||
|
|
||||||
// Delete the current element
|
// Delete the current element
|
||||||
currentElement->ContactManifoldListElement::~ContactManifoldListElement();
|
currentElement->ContactManifoldListElement::~ContactManifoldListElement();
|
||||||
memoryAllocator.release(currentElement, sizeof(ContactManifoldListElement));
|
mWorld.mMemoryAllocator.release(currentElement, sizeof(ContactManifoldListElement));
|
||||||
|
|
||||||
currentElement = nextElement;
|
currentElement = nextElement;
|
||||||
}
|
}
|
||||||
mContactManifoldsList = NULL;
|
mContactManifoldsList = NULL;
|
||||||
|
|
||||||
assert(mContactManifoldsList == NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the broad-phase state for this body (because it has moved for instance)
|
// Update the broad-phase state for this body (because it has moved for instance)
|
||||||
|
@ -190,3 +188,14 @@ void CollisionBody::updateBroadPhaseState() const {
|
||||||
mWorld.mCollisionDetection.updateProxyCollisionShape(shape, aabb);
|
mWorld.mCollisionDetection.updateProxyCollisionShape(shape, aabb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ask the broad-phase to test again the collision shapes of the body for collision
|
||||||
|
// (as if the body has moved).
|
||||||
|
void CollisionBody::askForBroadPhaseCollisionCheck() const {
|
||||||
|
|
||||||
|
// For all the proxy collision shapes of the body
|
||||||
|
for (ProxyShape* shape = mProxyCollisionShapes; shape != NULL; shape = shape->mNext) {
|
||||||
|
|
||||||
|
mWorld.mCollisionDetection.askForBroadPhaseCollisionCheck(shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ class CollisionBody : public Body {
|
||||||
CollisionBody& operator=(const CollisionBody& body);
|
CollisionBody& operator=(const CollisionBody& body);
|
||||||
|
|
||||||
/// Reset the contact manifold lists
|
/// Reset the contact manifold lists
|
||||||
void resetContactManifoldsList(MemoryAllocator& memoryAllocator);
|
void resetContactManifoldsList();
|
||||||
|
|
||||||
/// Remove all the collision shapes
|
/// Remove all the collision shapes
|
||||||
void removeAllCollisionShapes();
|
void removeAllCollisionShapes();
|
||||||
|
@ -113,6 +113,10 @@ class CollisionBody : public Body {
|
||||||
/// Update the broad-phase state for this body (because it has moved for instance)
|
/// Update the broad-phase state for this body (because it has moved for instance)
|
||||||
void updateBroadPhaseState() const;
|
void updateBroadPhaseState() const;
|
||||||
|
|
||||||
|
/// Ask the broad-phase to test again the collision shapes of the body for collision
|
||||||
|
/// (as if the body has moved).
|
||||||
|
void askForBroadPhaseCollisionCheck() const;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
|
@ -82,6 +82,17 @@ void RigidBody::setType(BodyType type) {
|
||||||
|
|
||||||
// Awake the body
|
// Awake the body
|
||||||
setIsSleeping(false);
|
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)
|
||||||
|
askForBroadPhaseCollisionCheck();
|
||||||
|
|
||||||
|
// Reset the force and torque on the body
|
||||||
|
mExternalForce.setToZero();
|
||||||
|
mExternalTorque.setToZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the local inertia tensor of the body (in body coordinates)
|
// Set the local inertia tensor of the body (in body coordinates)
|
||||||
|
|
|
@ -135,6 +135,9 @@ class CollisionDetection {
|
||||||
/// Remove a pair of bodies that cannot collide with each other
|
/// Remove a pair of bodies that cannot collide with each other
|
||||||
void removeNoCollisionPair(CollisionBody* body1, CollisionBody* body2);
|
void removeNoCollisionPair(CollisionBody* body1, CollisionBody* body2);
|
||||||
|
|
||||||
|
/// Ask for a collision shape to be tested again during broad-phase.
|
||||||
|
void askForBroadPhaseCollisionCheck(ProxyShape* shape);
|
||||||
|
|
||||||
/// Compute the collision detection
|
/// Compute the collision detection
|
||||||
void computeCollisionDetection();
|
void computeCollisionDetection();
|
||||||
|
|
||||||
|
@ -183,6 +186,13 @@ inline void CollisionDetection::removeNoCollisionPair(CollisionBody* body1,
|
||||||
mNoCollisionPairs.erase(OverlappingPair::computeBodiesIndexPair(body1, body2));
|
mNoCollisionPairs.erase(OverlappingPair::computeBodiesIndexPair(body1, body2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ask for a collision shape to be tested again during broad-phase.
|
||||||
|
/// We simply put the shape in the list of collision shape that have moved in the
|
||||||
|
/// previous frame so that it is tested for collision again in the broad-phase.
|
||||||
|
inline void CollisionDetection::askForBroadPhaseCollisionCheck(ProxyShape* shape) {
|
||||||
|
mBroadPhaseAlgorithm.addMovedCollisionShape(shape->mBroadPhaseID);
|
||||||
|
}
|
||||||
|
|
||||||
// Update a proxy collision shape (that has moved for instance)
|
// Update a proxy collision shape (that has moved for instance)
|
||||||
inline void CollisionDetection::updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb) {
|
inline void CollisionDetection::updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb) {
|
||||||
mBroadPhaseAlgorithm.updateProxyCollisionShape(shape, aabb);
|
mBroadPhaseAlgorithm.updateProxyCollisionShape(shape, aabb);
|
||||||
|
|
|
@ -36,12 +36,6 @@ using namespace std;
|
||||||
|
|
||||||
// TODO : Check if we really need to store the contact manifolds also in mContactManifolds.
|
// TODO : Check if we really need to store the contact manifolds also in mContactManifolds.
|
||||||
|
|
||||||
// TODO : Check how to compute the initial inertia tensor now (especially when a body has multiple
|
|
||||||
// collision shapes.
|
|
||||||
|
|
||||||
// TODO : Check the Body::setType() function in Box2D to be sure we are not missing any update
|
|
||||||
// of the collision shapes and broad-phase modification.
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
DynamicsWorld::DynamicsWorld(const Vector3 &gravity, decimal timeStep = DEFAULT_TIMESTEP)
|
DynamicsWorld::DynamicsWorld(const Vector3 &gravity, decimal timeStep = DEFAULT_TIMESTEP)
|
||||||
: CollisionWorld(), mTimer(timeStep), mGravity(gravity), mIsGravityEnabled(true),
|
: CollisionWorld(), mTimer(timeStep), mGravity(gravity), mIsGravityEnabled(true),
|
||||||
|
@ -194,7 +188,7 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current position and orientation of the body
|
// Get current position and orientation of the body
|
||||||
const Vector3& currentPosition = bodies[b]->getTransform().getPosition();
|
const Vector3& currentPosition = bodies[b]->mCenterOfMassWorld;
|
||||||
const Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation();
|
const Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation();
|
||||||
|
|
||||||
// Update the new constrained position and orientation of the body
|
// Update the new constrained position and orientation of the body
|
||||||
|
@ -202,6 +196,10 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
|
||||||
mConstrainedOrientations[indexArray] = currentOrientation +
|
mConstrainedOrientations[indexArray] = currentOrientation +
|
||||||
Quaternion(0, newAngVelocity) *
|
Quaternion(0, newAngVelocity) *
|
||||||
currentOrientation * decimal(0.5) * dt;
|
currentOrientation * decimal(0.5) * dt;
|
||||||
|
|
||||||
|
// TODO : DELETE THIS
|
||||||
|
Vector3 newPos = mConstrainedPositions[indexArray];
|
||||||
|
Quaternion newOrientation = mConstrainedOrientations[indexArray];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,6 +219,10 @@ void DynamicsWorld::updateBodiesState() {
|
||||||
|
|
||||||
uint index = mMapBodyToConstrainedVelocityIndex.find(bodies[b])->second;
|
uint index = mMapBodyToConstrainedVelocityIndex.find(bodies[b])->second;
|
||||||
|
|
||||||
|
// TODO : Delete this
|
||||||
|
Vector3 linVel = mConstrainedLinearVelocities[index];
|
||||||
|
Vector3 angVel = mConstrainedAngularVelocities[index];
|
||||||
|
|
||||||
// Update the linear and angular velocity of the body
|
// Update the linear and angular velocity of the body
|
||||||
bodies[b]->mLinearVelocity = mConstrainedLinearVelocities[index];
|
bodies[b]->mLinearVelocity = mConstrainedLinearVelocities[index];
|
||||||
bodies[b]->mAngularVelocity = mConstrainedAngularVelocities[index];
|
bodies[b]->mAngularVelocity = mConstrainedAngularVelocities[index];
|
||||||
|
@ -228,6 +230,9 @@ void DynamicsWorld::updateBodiesState() {
|
||||||
// Update the position of the center of mass of the body
|
// Update the position of the center of mass of the body
|
||||||
bodies[b]->mCenterOfMassWorld = mConstrainedPositions[index];
|
bodies[b]->mCenterOfMassWorld = mConstrainedPositions[index];
|
||||||
|
|
||||||
|
// TODO : DELETE THIS
|
||||||
|
Quaternion newOrient = mConstrainedOrientations[index];
|
||||||
|
|
||||||
// Update the orientation of the body
|
// Update the orientation of the body
|
||||||
bodies[b]->mTransform.setOrientation(mConstrainedOrientations[index].getUnit());
|
bodies[b]->mTransform.setOrientation(mConstrainedOrientations[index].getUnit());
|
||||||
|
|
||||||
|
@ -450,23 +455,9 @@ void DynamicsWorld::solvePositionCorrection() {
|
||||||
// Do not continue if there is no constraints
|
// Do not continue if there is no constraints
|
||||||
if (mJoints.empty()) return;
|
if (mJoints.empty()) return;
|
||||||
|
|
||||||
// ---------- Get the position/orientation of the rigid bodies ---------- //
|
|
||||||
|
|
||||||
// For each island of the world
|
// For each island of the world
|
||||||
for (uint islandIndex = 0; islandIndex < mNbIslands; islandIndex++) {
|
for (uint islandIndex = 0; islandIndex < mNbIslands; islandIndex++) {
|
||||||
|
|
||||||
// For each body of the island
|
|
||||||
RigidBody** bodies = mIslands[islandIndex]->getBodies();
|
|
||||||
for (uint b=0; b < mIslands[islandIndex]->getNbBodies(); b++) {
|
|
||||||
|
|
||||||
uint index = mMapBodyToConstrainedVelocityIndex.find(bodies[b])->second;
|
|
||||||
|
|
||||||
// Get the position/orientation of the rigid body
|
|
||||||
const Transform& transform = bodies[b]->getTransform();
|
|
||||||
mConstrainedPositions[index] = bodies[b]->mCenterOfMassWorld;
|
|
||||||
mConstrainedOrientations[index]= transform.getOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- Solve the position error correction for the constraints ---------- //
|
// ---------- Solve the position error correction for the constraints ---------- //
|
||||||
|
|
||||||
// For each iteration of the position (error correction) solver
|
// For each iteration of the position (error correction) solver
|
||||||
|
@ -516,7 +507,7 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the contact manifold list of the body
|
// Reset the contact manifold list of the body
|
||||||
rigidBody->resetContactManifoldsList(mMemoryAllocator);
|
rigidBody->resetContactManifoldsList();
|
||||||
|
|
||||||
// Call the destructor of the rigid body
|
// Call the destructor of the rigid body
|
||||||
rigidBody->RigidBody::~RigidBody();
|
rigidBody->RigidBody::~RigidBody();
|
||||||
|
@ -655,7 +646,7 @@ void DynamicsWorld::resetContactManifoldListsOfBodies() {
|
||||||
for (std::set<RigidBody*>::iterator it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) {
|
for (std::set<RigidBody*>::iterator it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) {
|
||||||
|
|
||||||
// Reset the contact manifold list of the body
|
// Reset the contact manifold list of the body
|
||||||
(*it)->resetContactManifoldsList(mMemoryAllocator);
|
(*it)->resetContactManifoldsList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,16 @@ Quaternion::Quaternion(decimal newW, const Vector3& v) : x(v.x), y(v.y), z(v.z),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructor which convert Euler angles (in radians) to a quaternion
|
||||||
|
Quaternion::Quaternion(decimal angleX, decimal angleY, decimal 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
|
// Copy-constructor
|
||||||
Quaternion::Quaternion(const Quaternion& quaternion)
|
Quaternion::Quaternion(const Quaternion& quaternion)
|
||||||
:x(quaternion.x), y(quaternion.y), z(quaternion.z), w(quaternion.w) {
|
:x(quaternion.x), y(quaternion.y), z(quaternion.z), w(quaternion.w) {
|
||||||
|
@ -219,3 +229,32 @@ Quaternion Quaternion::slerp(const Quaternion& quaternion1,
|
||||||
// Compute and return the interpolated quaternion
|
// Compute and return the interpolated quaternion
|
||||||
return quaternion1 * coeff1 + quaternion2 * coeff2;
|
return quaternion1 * coeff1 + quaternion2 * coeff2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the quaternion using Euler angles
|
||||||
|
void Quaternion::initWithEulerAngles(decimal angleX, decimal angleY, decimal angleZ) {
|
||||||
|
|
||||||
|
decimal angle = angleX * decimal(0.5);
|
||||||
|
const decimal sinX = std::sin(angle);
|
||||||
|
const decimal cosX = std::cos(angle);
|
||||||
|
|
||||||
|
angle = angleY * decimal(0.5);
|
||||||
|
const decimal sinY = std::sin(angle);
|
||||||
|
const decimal cosY = std::cos(angle);
|
||||||
|
|
||||||
|
angle = angleZ * decimal(0.5);
|
||||||
|
const decimal sinZ = std::sin(angle);
|
||||||
|
const decimal cosZ = std::cos(angle);
|
||||||
|
|
||||||
|
const decimal cosYcosZ = cosY * cosZ;
|
||||||
|
const decimal sinYcosZ = sinY * cosZ;
|
||||||
|
const decimal cosYsinZ = cosY * sinZ;
|
||||||
|
const decimal 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();
|
||||||
|
}
|
||||||
|
|
|
@ -69,6 +69,12 @@ struct Quaternion {
|
||||||
/// Constructor with the component w and the vector v=(x y z)
|
/// Constructor with the component w and the vector v=(x y z)
|
||||||
Quaternion(decimal newW, const Vector3& v);
|
Quaternion(decimal newW, const Vector3& v);
|
||||||
|
|
||||||
|
/// Constructor which convert Euler angles (in radians) to a quaternion
|
||||||
|
Quaternion(decimal angleX, decimal angleY, decimal angleZ);
|
||||||
|
|
||||||
|
/// Constructor which convert Euler angles (in radians) to a quaternion
|
||||||
|
Quaternion(const Vector3& eulerAngles);
|
||||||
|
|
||||||
/// Copy-constructor
|
/// Copy-constructor
|
||||||
Quaternion(const Quaternion& quaternion);
|
Quaternion(const Quaternion& quaternion);
|
||||||
|
|
||||||
|
@ -153,6 +159,11 @@ struct Quaternion {
|
||||||
|
|
||||||
/// Overloaded operator for equality condition
|
/// Overloaded operator for equality condition
|
||||||
bool operator==(const Quaternion& quaternion) const;
|
bool operator==(const Quaternion& quaternion) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/// Initialize the quaternion using Euler angles
|
||||||
|
void initWithEulerAngles(decimal angleX, decimal angleY, decimal angleZ);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Set all the values
|
/// Set all the values
|
||||||
|
|
|
@ -90,7 +90,7 @@ class Test {
|
||||||
Test(std::ostream* stream = &std::cout);
|
Test(std::ostream* stream = &std::cout);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~Test();
|
virtual ~Test();
|
||||||
|
|
||||||
/// Return the number of passed tests
|
/// Return the number of passed tests
|
||||||
long getNbPassedTests() const;
|
long getNbPassedTests() const;
|
||||||
|
|
|
@ -77,7 +77,7 @@ class TestQuaternion : public Test {
|
||||||
void testConstructors() {
|
void testConstructors() {
|
||||||
|
|
||||||
Quaternion quaternion1(mQuaternion1);
|
Quaternion quaternion1(mQuaternion1);
|
||||||
test(mQuaternion1== quaternion1);
|
test(mQuaternion1 == quaternion1);
|
||||||
|
|
||||||
Quaternion quaternion2(4, 5, 6, 7);
|
Quaternion quaternion2(4, 5, 6, 7);
|
||||||
test(quaternion2 == Quaternion(4, 5, 6, 7));
|
test(quaternion2 == Quaternion(4, 5, 6, 7));
|
||||||
|
@ -90,6 +90,34 @@ class TestQuaternion : public Test {
|
||||||
test(approxEqual(quaternion4.y, mQuaternion1.y));
|
test(approxEqual(quaternion4.y, mQuaternion1.y));
|
||||||
test(approxEqual(quaternion4.z, mQuaternion1.z));
|
test(approxEqual(quaternion4.z, mQuaternion1.z));
|
||||||
test(approxEqual(quaternion4.w, mQuaternion1.w));
|
test(approxEqual(quaternion4.w, mQuaternion1.w));
|
||||||
|
|
||||||
|
// Test conversion from Euler angles to quaternion
|
||||||
|
|
||||||
|
const decimal PI_OVER_2 = PI * decimal(0.5);
|
||||||
|
const decimal PI_OVER_4 = PI_OVER_2 * decimal(0.5);
|
||||||
|
Quaternion quaternion5(PI_OVER_2, 0, 0);
|
||||||
|
Quaternion quaternionTest5(std::sin(PI_OVER_4), 0, 0, std::cos(PI_OVER_4));
|
||||||
|
quaternionTest5.normalize();
|
||||||
|
test(approxEqual(quaternion5.x, quaternionTest5.x));
|
||||||
|
test(approxEqual(quaternion5.y, quaternionTest5.y));
|
||||||
|
test(approxEqual(quaternion5.z, quaternionTest5.z));
|
||||||
|
test(approxEqual(quaternion5.w, quaternionTest5.w));
|
||||||
|
|
||||||
|
Quaternion quaternion6(0, PI_OVER_2, 0);
|
||||||
|
Quaternion quaternionTest6(0, std::sin(PI_OVER_4), 0, std::cos(PI_OVER_4));
|
||||||
|
quaternionTest6.normalize();
|
||||||
|
test(approxEqual(quaternion6.x, quaternionTest6.x));
|
||||||
|
test(approxEqual(quaternion6.y, quaternionTest6.y));
|
||||||
|
test(approxEqual(quaternion6.z, quaternionTest6.z));
|
||||||
|
test(approxEqual(quaternion6.w, quaternionTest6.w));
|
||||||
|
|
||||||
|
Quaternion quaternion7(Vector3(0, 0, PI_OVER_2));
|
||||||
|
Quaternion quaternionTest7(0, 0, std::sin(PI_OVER_4), std::cos(PI_OVER_4));
|
||||||
|
quaternionTest7.normalize();
|
||||||
|
test(approxEqual(quaternion7.x, quaternionTest7.x));
|
||||||
|
test(approxEqual(quaternion7.y, quaternionTest7.y));
|
||||||
|
test(approxEqual(quaternion7.z, quaternionTest7.z));
|
||||||
|
test(approxEqual(quaternion7.w, quaternionTest7.w));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test unit, length, normalize methods
|
/// Test unit, length, normalize methods
|
||||||
|
|
Loading…
Reference in New Issue
Block a user