|
- //
- // Lol Engine
- //
- // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the Do What The Fuck You Want To
- // Public License, Version 2, as published by Sam Hocevar. See
- // http://www.wtfpl.net/ for more details.
- //
-
- #if defined HAVE_CONFIG_H
- # include "config.h"
- #endif
-
- #include "core.h"
- #include "lol/unit.h"
-
- namespace lol
- {
-
- LOLUNIT_FIXTURE(QuaternionTest)
- {
- void SetUp()
- {
- /* Generate identity quaternions */
- m_vectorpairs.Push(vec3::axis_x, vec3::axis_x);
- m_vectorpairs.Push(2.f * vec3::axis_x, 3.f * vec3::axis_x);
-
- /* Generate 90-degree rotations */
- m_vectorpairs.Push(vec3::axis_x, vec3::axis_y);
- m_vectorpairs.Push(2.f * vec3::axis_x, 3.f * vec3::axis_y);
-
- /* Generate 180-degree rotations */
- m_vectorpairs.Push(vec3::axis_x, -vec3::axis_x);
- m_vectorpairs.Push(2.f * vec3::axis_x, -3.f * vec3::axis_x);
-
- /* Fill array with random test values */
- for (int i = 0; i < 10000; ++i)
- {
- vec3 v1 = lol::pow(10.f, rand(-5.f, 5.f))
- * vec3(rand(-1.f, 1.f), rand(-1.f, 1.f), rand(-1.f, 1.f));
- vec3 v2 = lol::pow(10.f, rand(-5.f, 5.f))
- * vec3(rand(-1.f, 1.f), rand(-1.f, 1.f), rand(-1.f, 1.f));
- m_vectorpairs.Push(v1, v2);
- }
- }
-
- void TearDown() {}
-
- LOLUNIT_TEST(Equality)
- {
- quat a4(1.f, 2.f, 3.f, 4.f);
- quat b4(0.f, 2.f, 3.f, 4.f);
- quat c4(1.f, 0.f, 3.f, 4.f);
- quat d4(1.f, 2.f, 0.f, 4.f);
- quat e4(1.f, 2.f, 3.f, 0.f);
-
- LOLUNIT_ASSERT_EQUAL(a4, a4);
- LOLUNIT_ASSERT_NOT_DIFFERENT(a4, a4);
-
- LOLUNIT_ASSERT_DIFFERENT(a4, b4);
- LOLUNIT_ASSERT_NOT_EQUAL(a4, b4);
- LOLUNIT_ASSERT_DIFFERENT(a4, c4);
- LOLUNIT_ASSERT_NOT_EQUAL(a4, c4);
- LOLUNIT_ASSERT_DIFFERENT(a4, d4);
- LOLUNIT_ASSERT_NOT_EQUAL(a4, d4);
- LOLUNIT_ASSERT_DIFFERENT(a4, e4);
- LOLUNIT_ASSERT_NOT_EQUAL(a4, e4);
- }
-
- LOLUNIT_TEST(UnaryMinus)
- {
- quat a(1.f, 3.f, 2.f, 4.f);
- quat b(-1.f, -3.f, -2.f, -4.f);
-
- LOLUNIT_ASSERT_EQUAL(a, -b);
- LOLUNIT_ASSERT_EQUAL(-a, b);
- }
-
- LOLUNIT_TEST(Conjugate)
- {
- quat a(1.f, 3.f, 2.f, 4.f);
- quat b(1.f, -3.f, -2.f, -4.f);
-
- LOLUNIT_ASSERT_EQUAL(a, ~b);
- LOLUNIT_ASSERT_EQUAL(~a, b);
- }
-
- LOLUNIT_TEST(Norm)
- {
- quat a(2.f, -2.f, -8.f, 3.f);
-
- LOLUNIT_ASSERT_EQUAL(norm(a), 9.f);
-
- quat b = a * ~a;
- quat c(norm(a) * norm(a), 0.f, 0.f, 0.f);
-
- LOLUNIT_ASSERT_EQUAL(b, c);
-
- quat d(2.f, 5.f, -4.f, -2.f);
-
- LOLUNIT_ASSERT_EQUAL(norm(a * d), norm(a) * norm(d));
- }
-
- LOLUNIT_TEST(Dot)
- {
- quat a(-1.f, 2.f, -3.f, 4.f);
- quat b(8.f, 7.f, 6.f, 5.f);
-
- LOLUNIT_ASSERT_EQUAL(dot(a, b), 8.f);
- }
-
- LOLUNIT_TEST(Base)
- {
- quat one(1.f, 0.f, 0.f, 0.f);
- quat i(0.f, 1.f, 0.f, 0.f);
- quat j(0.f, 0.f, 1.f, 0.f);
- quat k(0.f, 0.f, 0.f, 1.f);
-
- LOLUNIT_ASSERT_EQUAL(norm(one), 1.f);
- LOLUNIT_ASSERT_EQUAL(norm(i), 1.f);
- LOLUNIT_ASSERT_EQUAL(norm(j), 1.f);
- LOLUNIT_ASSERT_EQUAL(norm(k), 1.f);
-
- LOLUNIT_ASSERT_EQUAL(i * i, -one);
- LOLUNIT_ASSERT_EQUAL(j * j, -one);
- LOLUNIT_ASSERT_EQUAL(k * k, -one);
- LOLUNIT_ASSERT_EQUAL(i * j * k, -one);
-
- LOLUNIT_ASSERT_EQUAL(i * j, k);
- LOLUNIT_ASSERT_EQUAL(j * i, -k);
- LOLUNIT_ASSERT_EQUAL(j * k, i);
- LOLUNIT_ASSERT_EQUAL(k * j, -i);
- LOLUNIT_ASSERT_EQUAL(k * i, j);
- LOLUNIT_ASSERT_EQUAL(i * k, -j);
- }
-
- LOLUNIT_TEST(Normalize)
- {
- quat a(2.f, -2.f, -8.f, 3.f);
- quat b = normalize(a);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(b), 1.0, 1e-5);
- }
-
- LOLUNIT_TEST(Reciprocal)
- {
- quat a(2.f, -2.f, -8.f, 3.f);
- quat b = re(a);
- quat c = 1.f / a;
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(b.w, c.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(b.x, c.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(b.y, c.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(b.z, c.z, 1e-5);
-
- quat m1 = a * b;
- quat m2 = b * a;
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.w, m2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.x, m2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.y, m2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.z, m2.z, 1e-5);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.w, 1.0, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.x, 0.0, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.y, 0.0, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(m1.z, 0.0, 1e-5);
- }
-
- LOLUNIT_TEST(Rotation)
- {
- /* Check that rotating 10 degrees twice means rotating 20 degrees */
- quat a = quat::rotate(10.f, vec3::axis_x);
- quat b = quat::rotate(20.f, vec3::axis_x);
- quat c = a * a;
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(c.w, b.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(c.x, b.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(c.y, b.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(c.z, b.z, 1e-5);
-
- /* Check that rotating 10 degrees then 20 is the same as 20 then 10 */
- quat d = a * b;
- quat e = b * a;
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(e.w, d.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(e.x, d.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(e.y, d.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(e.z, d.z, 1e-5);
- }
-
- LOLUNIT_TEST(ToAxisAngle)
- {
- quat q = quat::rotate(10.f, vec3::axis_x);
- vec3 axis = q.axis();
- float angle = q.angle();
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(1.0, axis.x, 1e-6);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(0.0, axis.y, 1e-6);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(0.0, axis.z, 1e-6);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(10.0, (double)degrees(angle), 1e-6);
- }
-
- LOLUNIT_TEST(FromTwoVectors)
- {
- for (auto pair : m_vectorpairs)
- {
- vec3 a = pair.m1;
- vec3 b = pair.m2;
- vec3 da = normalize(a);
- vec3 db = normalize(b);
-
- quat q = quat::rotate(a, b);
-
- /* Check that q is a unit quaternion */
- LOLUNIT_ASSERT_DOUBLES_EQUAL(1.0, (double)norm(q), 1e-5);
-
- /* Check that q transforms da into db */
- vec3 c = q.transform(da);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(c.x, db.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(c.y, db.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(c.z, db.z, 1e-5);
-
- /* Check that ~q transforms db into da */
- vec3 d = (~q).transform(db);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(d.x, da.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(d.y, da.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(d.z, da.z, 1e-5);
-
- if (distance(da, db) > 1e-6f)
- {
- /* If da and db differ, check that the rotation axis is normal to both
- * vectors, which is only true if the rotation uses the shortest path. */
- vec3 axis = q.axis();
- LOLUNIT_ASSERT_DOUBLES_EQUAL(0.0, (double)dot(axis, da), 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(0.0, (double)dot(axis, db), 1e-5);
- }
- else
- {
- /* If da and db are roughly the same, check that the rotation angle
- * is zero. */
- LOLUNIT_ASSERT_DOUBLES_EQUAL(0.0, (double)q.angle(), 1e-5);
- }
- }
- }
-
- LOLUNIT_TEST(FromEulerNorm)
- {
- for (int i = 0; i < 100; ++i)
- {
- vec3 angles(rand(360.f), rand(360.f), rand(360.f));
-
- /* Tait-Bryan */
- quat q1 = quat::fromeuler_xyz(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q1), 1.f, 1e-5);
-
- quat q2 = quat::fromeuler_yzx(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q2), 1.f, 1e-5);
-
- quat q3 = quat::fromeuler_zxy(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q3), 1.f, 1e-5);
-
- quat q4 = quat::fromeuler_xzy(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q4), 1.f, 1e-5);
-
- quat q5 = quat::fromeuler_zyx(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q5), 1.f, 1e-5);
-
- quat q6 = quat::fromeuler_yxz(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q6), 1.f, 1e-5);
-
- /* Euler */
- quat q7 = quat::fromeuler_xyx(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q7), 1.f, 1e-5);
-
- quat q8 = quat::fromeuler_yzy(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q8), 1.f, 1e-5);
-
- quat q9 = quat::fromeuler_zxz(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q9), 1.f, 1e-5);
-
- quat q10 = quat::fromeuler_xzx(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q10), 1.f, 1e-5);
-
- quat q11 = quat::fromeuler_zyz(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q11), 1.f, 1e-5);
-
- quat q12 = quat::fromeuler_yxy(angles);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(q12), 1.f, 1e-5);
- }
- }
-
- LOLUNIT_TEST(FirstTwoEulerAngles)
- {
- for (int i = 0; i < 100; ++i)
- {
- /* We check that fromeuler_xyx and fromeuler_xyz give the
- * same result if the 3rd angle is zero. */
- vec3 angles(rand(360.f), rand(360.f), 0.f);
- quat q1, q2;
-
- q1 = quat::fromeuler_xyz(angles);
- q2 = quat::fromeuler_xyx(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_yzx(angles);
- q2 = quat::fromeuler_yzy(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_zxy(angles);
- q2 = quat::fromeuler_zxz(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_xzy(angles);
- q2 = quat::fromeuler_xzx(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_zyx(angles);
- q2 = quat::fromeuler_zyz(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_yxz(angles);
- q2 = quat::fromeuler_yxy(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
- }
- }
-
- LOLUNIT_TEST(LastTwoEulerAngles)
- {
- for (int i = 0; i < 100; ++i)
- {
- /* We check that fromeuler_zyz and fromeuler_xyz give the
- * same result if the 1st angle is zero. */
- vec3 angles(0.f, rand(360.f), rand(360.f));
- quat q1, q2;
-
- q1 = quat::fromeuler_xyz(angles);
- q2 = quat::fromeuler_zyz(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_yzx(angles);
- q2 = quat::fromeuler_xzx(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_zxy(angles);
- q2 = quat::fromeuler_yxy(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_xzy(angles);
- q2 = quat::fromeuler_yzy(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_zyx(angles);
- q2 = quat::fromeuler_xyx(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
-
- q1 = quat::fromeuler_yxz(angles);
- q2 = quat::fromeuler_zxz(angles);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.w, q2.w, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.x, q2.x, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.y, q2.y, 1e-5);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(q1.z, q2.z, 1e-5);
- }
- }
-
- LOLUNIT_TEST(TaitBryanAngles)
- {
- for (int i = 0; i < 100; ++i)
- {
- /* Pick a random point and a random quaternion. We want
- * to check whether going to Tait-Bryan angles and back to
- * quaternion creates the same transform. */
- vec3 p(rand(1.f, 2.f), rand(1.f, 2.f), rand(1.f, 2.f));
- quat q0 = normalize(quat(rand(-1.f, 1.f), rand(-1.f, 1.f),
- rand(-1.f, 1.f), rand(-1.f, 1.f)));
- vec3 p0 = q0.transform(p);
-
- /* x-y-z */
- quat q1 = quat::fromeuler_xyz(vec3::toeuler_xyz(q0));
- vec3 p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* y-z-x */
- q1 = quat::fromeuler_yzx(vec3::toeuler_yzx(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* z-x-y */
- q1 = quat::fromeuler_zxy(vec3::toeuler_zxy(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* x-z-y */
- q1 = quat::fromeuler_xzy(vec3::toeuler_xzy(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* z-y-x */
- q1 = quat::fromeuler_zyx(vec3::toeuler_zyx(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* y-x-z */
- q1 = quat::fromeuler_yxz(vec3::toeuler_yxz(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
- }
- }
-
- LOLUNIT_TEST(EulerAngles)
- {
- for (int i = 0; i < 100; ++i)
- {
- /* Pick a random point and a random quaternion. We want
- * to check whether going to Euler angles and back to
- * quaternion creates the same transform. */
- vec3 p(rand(1.f, 2.f), rand(1.f, 2.f), rand(1.f, 2.f));
- quat q0 = normalize(quat(rand(-1.f, 1.f), rand(-1.f, 1.f),
- rand(-1.f, 1.f), rand(-1.f, 1.f)));
- vec3 p0 = q0.transform(p);
-
- /* x-y-x */
- quat q1 = quat::fromeuler_xyx(vec3::toeuler_xyx(q0));
- vec3 p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* y-z-y */
- q1 = quat::fromeuler_yzy(vec3::toeuler_yzy(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* z-x-z */
- q1 = quat::fromeuler_zxz(vec3::toeuler_zxz(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* x-z-x */
- q1 = quat::fromeuler_xzx(vec3::toeuler_xzx(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* z-y-z */
- q1 = quat::fromeuler_zyz(vec3::toeuler_zyz(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
-
- /* y-x-y */
- q1 = quat::fromeuler_yxy(vec3::toeuler_yxy(q0));
- p1 = q1.transform(p);
-
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.x, p0.x, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.y, p0.y, 1e-4);
- LOLUNIT_ASSERT_DOUBLES_EQUAL(p1.z, p0.z, 1e-4);
- }
- }
-
- private:
- Array<vec3, vec3> m_vectorpairs;
- };
-
- } /* namespace lol */
|