470 lines
19 KiB
C++
470 lines
19 KiB
C++
//----------------------------------------------------------------------------//
|
|
// //
|
|
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
|
// and distributed under the MIT License (MIT). //
|
|
// //
|
|
// Copyright (c) Guillaume Blanc //
|
|
// //
|
|
// Permission is hereby granted, free of charge, to any person obtaining a //
|
|
// copy of this software and associated documentation files (the "Software"), //
|
|
// to deal in the Software without restriction, including without limitation //
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
|
// and/or sell copies of the Software, and to permit persons to whom the //
|
|
// Software is furnished to do so, subject to the following conditions: //
|
|
// //
|
|
// The above copyright notice and this permission notice shall be included in //
|
|
// all copies or substantial portions of the Software. //
|
|
// //
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
|
// DEALINGS IN THE SOFTWARE. //
|
|
// //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
#include "ozz/base/maths/quaternion.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "ozz/base/gtest_helper.h"
|
|
#include "ozz/base/maths/gtest_math_helper.h"
|
|
|
|
using ozz::math::Float3;
|
|
using ozz::math::Float4;
|
|
using ozz::math::Quaternion;
|
|
|
|
TEST(QuaternionConstant, ozz_math) {
|
|
EXPECT_QUATERNION_EQ(Quaternion::identity(), 0.f, 0.f, 0.f, 1.f);
|
|
}
|
|
|
|
TEST(QuaternionAxisAngle, ozz_math) {
|
|
// Expect assertions from invalid inputs
|
|
EXPECT_ASSERTION(Quaternion::FromAxisAngle(Float3::zero(), 0.f),
|
|
"axis is not normalized");
|
|
EXPECT_ASSERTION(ToAxisAngle(Quaternion(0.f, 0.f, 0.f, 2.f)), "IsNormalized");
|
|
|
|
// Identity
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromAxisAngle(Float3::y_axis(), 0.f), 0.f,
|
|
0.f, 0.f, 1.f);
|
|
EXPECT_FLOAT4_EQ(ToAxisAngle(Quaternion::identity()), 1.f, 0.f, 0.f, 0.f);
|
|
|
|
// Other axis angles
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromAxisAngle(Float3::y_axis(), ozz::math::kPi_2), 0.f,
|
|
.70710677f, 0.f, .70710677f);
|
|
EXPECT_FLOAT4_EQ(ToAxisAngle(Quaternion(0.f, .70710677f, 0.f, .70710677f)),
|
|
0.f, 1.f, 0.f, ozz::math::kPi_2);
|
|
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromAxisAngle(Float3::y_axis(), -ozz::math::kPi_2), 0.f,
|
|
-.70710677f, 0.f, .70710677f);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromAxisAngle(-Float3::y_axis(), ozz::math::kPi_2), 0.f,
|
|
-.70710677f, 0.f, .70710677f);
|
|
EXPECT_FLOAT4_EQ(ToAxisAngle(Quaternion(0.f, -.70710677f, 0.f, .70710677f)),
|
|
0.f, -1.f, 0.f, ozz::math::kPi_2);
|
|
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromAxisAngle(Float3::y_axis(), 3.f * ozz::math::kPi_4), 0.f,
|
|
0.923879504f, 0.f, 0.382683426f);
|
|
EXPECT_FLOAT4_EQ(
|
|
ToAxisAngle(Quaternion(0.f, 0.923879504f, 0.f, 0.382683426f)), 0.f, 1.f,
|
|
0.f, 3.f * ozz::math::kPi_4);
|
|
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromAxisAngle(Float3(.819865f, .033034f, -.571604f), 1.123f),
|
|
.4365425f, .017589169f, -.30435428f, .84645736f);
|
|
EXPECT_FLOAT4_EQ(
|
|
ToAxisAngle(Quaternion(.4365425f, .017589169f, -.30435428f, .84645736f)),
|
|
.819865f, .033034f, -.571604f, 1.123f);
|
|
}
|
|
|
|
TEST(QuaternionAxisCosAngle, ozz_math) {
|
|
// Expect assertions from invalid inputs
|
|
EXPECT_ASSERTION(Quaternion::FromAxisCosAngle(Float3::zero(), 0.f),
|
|
"axis is not normalized");
|
|
EXPECT_ASSERTION(Quaternion::FromAxisCosAngle(Float3::y_axis(), -1.0000001f),
|
|
"cos is not in \\[-1,1\\] range.");
|
|
EXPECT_ASSERTION(Quaternion::FromAxisCosAngle(Float3::y_axis(), 1.0000001f),
|
|
"cos is not in \\[-1,1\\] range.");
|
|
|
|
// Identity
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(Float3::y_axis(), 1.f), 0.f,
|
|
0.f, 0.f, 1.f);
|
|
|
|
// Other axis angles
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(Float3::y_axis(),
|
|
std::cos(ozz::math::kPi_2)),
|
|
0.f, .70710677f, 0.f, .70710677f);
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(-Float3::y_axis(),
|
|
std::cos(ozz::math::kPi_2)),
|
|
0.f, -.70710677f, 0.f, .70710677f);
|
|
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromAxisCosAngle(
|
|
Float3::y_axis(), std::cos(3.f * ozz::math::kPi_4)),
|
|
0.f, 0.923879504f, 0.f, 0.382683426f);
|
|
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromAxisCosAngle(Float3(.819865f, .033034f, -.571604f),
|
|
std::cos(1.123f)),
|
|
.4365425f, .017589169f, -.30435428f, .84645736f);
|
|
}
|
|
|
|
TEST(QuaternionQuaternionEuler, ozz_math) {
|
|
// Identity
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(0.f, 0.f, 0.f), 0.f, 0.f, 0.f,
|
|
1.f);
|
|
EXPECT_FLOAT3_EQ(ToEuler(Quaternion::identity()), 0.f, 0.f, 0.f);
|
|
|
|
// Heading
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(ozz::math::kPi_2, 0.f, 0.f), 0.f,
|
|
.70710677f, 0.f, .70710677f);
|
|
EXPECT_FLOAT3_EQ(ToEuler(Quaternion(0.f, .70710677f, 0.f, .70710677f)),
|
|
ozz::math::kPi_2, 0.f, 0.f);
|
|
|
|
// Elevation
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(0.f, ozz::math::kPi_2, 0.f), 0.f,
|
|
0.f, .70710677f, .70710677f);
|
|
EXPECT_FLOAT3_EQ(ToEuler(Quaternion(0.f, 0.f, .70710677f, .70710677f)), 0.f,
|
|
ozz::math::kPi_2, 0.f);
|
|
|
|
// Bank
|
|
EXPECT_QUATERNION_EQ(Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi_2),
|
|
.70710677f, 0.f, 0.f, .70710677f);
|
|
EXPECT_FLOAT3_EQ(ToEuler(Quaternion(.70710677f, 0.f, 0.f, .70710677f)), 0.f,
|
|
0.f, ozz::math::kPi_2);
|
|
|
|
// Any rotation
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromEuler(ozz::math::kPi / 4.f, -ozz::math::kPi / 6.f,
|
|
ozz::math::kPi_2),
|
|
.56098551f, .092295974f, -0.43045932f, .70105737f);
|
|
EXPECT_FLOAT3_EQ(
|
|
ToEuler(Quaternion(.56098551f, .092295974f, -0.43045932f, .70105737f)),
|
|
ozz::math::kPi / 4.f, -ozz::math::kPi / 6.f, ozz::math::kPi_2);
|
|
}
|
|
|
|
TEST(QuaternionFromVectors, ozz_math) {
|
|
// Returns identity for a 0 length vector
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::zero(), Float3::x_axis()), 0.f, 0.f, 0.f,
|
|
1.f);
|
|
|
|
// pi/2 around y
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::z_axis(), Float3::x_axis()), 0.f,
|
|
0.707106769f, 0.f, 0.707106769f);
|
|
|
|
// Non unit pi/2 around y
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::z_axis() * 7.f, Float3::x_axis()), 0.f,
|
|
0.707106769f, 0.f, 0.707106769f);
|
|
|
|
// Minus pi/2 around y
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::x_axis(), Float3::z_axis()), 0.f,
|
|
-0.707106769f, 0.f, 0.707106769f);
|
|
|
|
// pi/2 around x
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::y_axis(), Float3::z_axis()), 0.707106769f,
|
|
0.f, 0.f, 0.707106769f);
|
|
|
|
// Non unit pi/2 around x
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::y_axis() * 9.f, Float3::z_axis() * 13.f),
|
|
0.707106769f, 0.f, 0.f, 0.707106769f);
|
|
|
|
// pi/2 around z
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::x_axis(), Float3::y_axis()), 0.f, 0.f,
|
|
0.707106769f, 0.707106769f);
|
|
|
|
// pi/2 around z also
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3(0.707106769f, 0.707106769f, 0.f),
|
|
Float3(-0.707106769f, 0.707106769f, 0.f)),
|
|
0.f, 0.f, 0.707106769f, 0.707106769f);
|
|
|
|
// Aligned vectors
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::x_axis(), Float3::x_axis()), 0.f, 0.f,
|
|
0.f, 1.f);
|
|
|
|
// Non-unit aligned vectors
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::x_axis(), Float3::x_axis() * 2.f), 0.f,
|
|
0.f, 0.f, 1.f);
|
|
|
|
// Opposed vectors
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::x_axis(), -Float3::x_axis()), 0.f, 1.f,
|
|
0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(-Float3::x_axis(), Float3::x_axis()), 0.f, -1.f,
|
|
0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::y_axis(), -Float3::y_axis()), 0.f, 0.f,
|
|
1.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(-Float3::y_axis(), Float3::y_axis()), 0.f, 0.f,
|
|
-1.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3::z_axis(), -Float3::z_axis()), 0.f, -1.f,
|
|
0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(-Float3::z_axis(), Float3::z_axis()), 0.f, 1.f,
|
|
0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3(0.707106769f, 0.707106769f, 0.f),
|
|
-Float3(0.707106769f, 0.707106769f, 0.f)),
|
|
-0.707106769f, 0.707106769f, 0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3(0.f, 0.707106769f, 0.707106769f),
|
|
-Float3(0.f, 0.707106769f, 0.707106769f)),
|
|
0.f, -0.707106769f, 0.707106769f, 0);
|
|
|
|
// Non-unit opposed vectors
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromVectors(Float3(2.f, 2.f, 2.f), -Float3(2.f, 2.f, 2.f)),
|
|
0.f, -0.707106769f, 0.707106769f, 0);
|
|
}
|
|
|
|
TEST(QuaternionFromUnitVectors, ozz_math) {
|
|
// assert 0 length vectors
|
|
EXPECT_ASSERTION(
|
|
Quaternion::FromUnitVectors(Float3::zero(), Float3::x_axis()),
|
|
"Input vectors must be normalized.");
|
|
EXPECT_ASSERTION(
|
|
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::zero()),
|
|
"Input vectors must be normalized.");
|
|
// assert non unit vectors
|
|
EXPECT_ASSERTION(
|
|
Quaternion::FromUnitVectors(Float3::x_axis() * 2.f, Float3::x_axis()),
|
|
"Input vectors must be normalized.");
|
|
EXPECT_ASSERTION(
|
|
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::x_axis() * .5f),
|
|
"Input vectors must be normalized.");
|
|
|
|
// pi/2 around y
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::z_axis(), Float3::x_axis()), 0.f,
|
|
0.707106769f, 0.f, 0.707106769f);
|
|
|
|
// Minus pi/2 around y
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::z_axis()), 0.f,
|
|
-0.707106769f, 0.f, 0.707106769f);
|
|
|
|
// pi/2 around x
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::y_axis(), Float3::z_axis()),
|
|
0.707106769f, 0.f, 0.f, 0.707106769f);
|
|
|
|
// pi/2 around z
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::y_axis()), 0.f, 0.f,
|
|
0.707106769f, 0.707106769f);
|
|
|
|
// pi/2 around z also
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3(0.707106769f, 0.707106769f, 0.f),
|
|
Float3(-0.707106769f, 0.707106769f, 0.f)),
|
|
0.f, 0.f, 0.707106769f, 0.707106769f);
|
|
|
|
// Aligned vectors
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::x_axis(), Float3::x_axis()), 0.f, 0.f,
|
|
0.f, 1.f);
|
|
|
|
// Opposed vectors
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::x_axis(), -Float3::x_axis()), 0.f,
|
|
1.f, 0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(-Float3::x_axis(), Float3::x_axis()), 0.f,
|
|
-1.f, 0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::y_axis(), -Float3::y_axis()), 0.f,
|
|
0.f, 1.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(-Float3::y_axis(), Float3::y_axis()), 0.f,
|
|
0.f, -1.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3::z_axis(), -Float3::z_axis()), 0.f,
|
|
-1.f, 0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(-Float3::z_axis(), Float3::z_axis()), 0.f,
|
|
1.f, 0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3(0.707106769f, 0.707106769f, 0.f),
|
|
-Float3(0.707106769f, 0.707106769f, 0.f)),
|
|
-0.707106769f, 0.707106769f, 0.f, 0);
|
|
EXPECT_QUATERNION_EQ(
|
|
Quaternion::FromUnitVectors(Float3(0.f, 0.707106769f, 0.707106769f),
|
|
-Float3(0.f, 0.707106769f, 0.707106769f)),
|
|
0.f, -0.707106769f, 0.707106769f, 0);
|
|
}
|
|
|
|
TEST(QuaternionCompare, ozz_math) {
|
|
EXPECT_TRUE(Quaternion::identity() == Quaternion(0.f, 0.f, 0.f, 1.f));
|
|
EXPECT_TRUE(Quaternion::identity() != Quaternion(1.f, 0.f, 0.f, 0.f));
|
|
EXPECT_TRUE(Compare(Quaternion::identity(), Quaternion::identity(), std::cos(.5f * 0.f)));
|
|
EXPECT_TRUE(Compare(Quaternion::identity(),
|
|
Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi / 100.f),
|
|
std::cos(.5f * ozz::math::kPi / 50.f)));
|
|
EXPECT_TRUE(Compare(Quaternion::identity(),
|
|
-Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi / 100.f),
|
|
std::cos(.5f * ozz::math::kPi / 50.f)));
|
|
EXPECT_FALSE(Compare(Quaternion::identity(),
|
|
Quaternion::FromEuler(0.f, 0.f, ozz::math::kPi / 100.f),
|
|
std::cos(.5f * ozz::math::kPi / 200.f)));
|
|
}
|
|
|
|
TEST(QuaternionArithmetic, ozz_math) {
|
|
const Quaternion a(.70710677f, 0.f, 0.f, .70710677f);
|
|
const Quaternion b(0.f, .70710677f, 0.f, .70710677f);
|
|
const Quaternion c(0.f, .70710677f, 0.f, -.70710677f);
|
|
const Quaternion denorm(1.414212f, 0.f, 0.f, 1.414212f);
|
|
|
|
EXPECT_TRUE(IsNormalized(a));
|
|
EXPECT_TRUE(IsNormalized(b));
|
|
EXPECT_TRUE(IsNormalized(c));
|
|
EXPECT_FALSE(IsNormalized(denorm));
|
|
|
|
const Quaternion conjugate = Conjugate(a);
|
|
EXPECT_QUATERNION_EQ(conjugate, -a.x, -a.y, -a.z, a.w);
|
|
EXPECT_TRUE(IsNormalized(conjugate));
|
|
|
|
const Quaternion negate = -a;
|
|
EXPECT_QUATERNION_EQ(negate, -a.x, -a.y, -a.z, -a.w);
|
|
EXPECT_TRUE(IsNormalized(negate));
|
|
|
|
const Quaternion add = a + b;
|
|
EXPECT_QUATERNION_EQ(add, .70710677f, .70710677f, 0.f, 1.41421354f);
|
|
|
|
const Quaternion mul0 = a * conjugate;
|
|
EXPECT_QUATERNION_EQ(mul0, 0.f, 0.f, 0.f, 1.f);
|
|
EXPECT_TRUE(IsNormalized(mul0));
|
|
|
|
const Quaternion muls = a * 2.f;
|
|
EXPECT_QUATERNION_EQ(muls, 1.41421354f, 0.f, 0.f, 1.41421354f);
|
|
|
|
const Quaternion mul1 = conjugate * a;
|
|
EXPECT_QUATERNION_EQ(mul1, 0.f, 0.f, 0.f, 1.f);
|
|
EXPECT_TRUE(IsNormalized(mul1));
|
|
|
|
const Quaternion q1234(1.f, 2.f, 3.f, 4.f);
|
|
const Quaternion q5678(5.f, 6.f, 7.f, 8.f);
|
|
const Quaternion mul12345678 = q1234 * q5678;
|
|
EXPECT_QUATERNION_EQ(mul12345678, 24.f, 48.f, 48.f, -6.f);
|
|
|
|
EXPECT_ASSERTION(Normalize(Quaternion(0.f, 0.f, 0.f, 0.f)),
|
|
"is not normalizable");
|
|
const Quaternion normalize = Normalize(denorm);
|
|
EXPECT_TRUE(IsNormalized(normalize));
|
|
EXPECT_QUATERNION_EQ(normalize, .7071068f, 0.f, 0.f, .7071068f);
|
|
|
|
EXPECT_ASSERTION(NormalizeSafe(denorm, Quaternion(0.f, 0.f, 0.f, 0.f)),
|
|
"_safer is not normalized");
|
|
const Quaternion normalize_safe =
|
|
NormalizeSafe(denorm, Quaternion::identity());
|
|
EXPECT_TRUE(IsNormalized(normalize_safe));
|
|
EXPECT_QUATERNION_EQ(normalize_safe, .7071068f, 0.f, 0.f, .7071068f);
|
|
|
|
const Quaternion normalize_safer =
|
|
NormalizeSafe(Quaternion(0.f, 0.f, 0.f, 0.f), Quaternion::identity());
|
|
EXPECT_TRUE(IsNormalized(normalize_safer));
|
|
EXPECT_QUATERNION_EQ(normalize_safer, 0.f, 0.f, 0.f, 1.f);
|
|
|
|
const Quaternion lerp_0 = Lerp(a, b, 0.f);
|
|
EXPECT_QUATERNION_EQ(lerp_0, a.x, a.y, a.z, a.w);
|
|
|
|
const Quaternion lerp_1 = Lerp(a, b, 1.f);
|
|
EXPECT_QUATERNION_EQ(lerp_1, b.x, b.y, b.z, b.w);
|
|
|
|
const Quaternion lerp_0_2 = Lerp(a, b, .2f);
|
|
EXPECT_QUATERNION_EQ(lerp_0_2, .5656853f, .1414213f, 0.f, .7071068f);
|
|
|
|
const Quaternion nlerp_0 = NLerp(a, b, 0.f);
|
|
EXPECT_TRUE(IsNormalized(nlerp_0));
|
|
EXPECT_QUATERNION_EQ(nlerp_0, a.x, a.y, a.z, a.w);
|
|
|
|
const Quaternion nlerp_1 = NLerp(a, b, 1.f);
|
|
EXPECT_TRUE(IsNormalized(nlerp_1));
|
|
EXPECT_QUATERNION_EQ(nlerp_1, b.x, b.y, b.z, b.w);
|
|
|
|
const Quaternion nlerp_0_2 = NLerp(a, b, .2f);
|
|
EXPECT_TRUE(IsNormalized(nlerp_0_2));
|
|
EXPECT_QUATERNION_EQ(nlerp_0_2, .6172133f, .1543033f, 0.f, .7715167f);
|
|
|
|
EXPECT_ASSERTION(SLerp(denorm, b, 0.f), "IsNormalized\\(_a\\)");
|
|
EXPECT_ASSERTION(SLerp(a, denorm, 0.f), "IsNormalized\\(_b\\)");
|
|
|
|
const Quaternion slerp_0 = SLerp(a, b, 0.f);
|
|
EXPECT_TRUE(IsNormalized(slerp_0));
|
|
EXPECT_QUATERNION_EQ(slerp_0, a.x, a.y, a.z, a.w);
|
|
|
|
const Quaternion slerp_c_0 = SLerp(a, c, 0.f);
|
|
EXPECT_TRUE(IsNormalized(slerp_c_0));
|
|
EXPECT_QUATERNION_EQ(slerp_c_0, a.x, a.y, a.z, a.w);
|
|
|
|
const Quaternion slerp_c_1 = SLerp(a, c, 1.f);
|
|
EXPECT_TRUE(IsNormalized(slerp_c_1));
|
|
EXPECT_QUATERNION_EQ(slerp_c_1, c.x, c.y, c.z, c.w);
|
|
|
|
const Quaternion slerp_c_0_6 = SLerp(a, c, .6f);
|
|
EXPECT_TRUE(IsNormalized(slerp_c_0_6));
|
|
EXPECT_QUATERNION_EQ(slerp_c_0_6, .6067752f, .7765344f, 0.f, -.1697592f);
|
|
|
|
const Quaternion slerp_1 = SLerp(a, b, 1.f);
|
|
EXPECT_TRUE(IsNormalized(slerp_1));
|
|
EXPECT_QUATERNION_EQ(slerp_1, b.x, b.y, b.z, b.w);
|
|
|
|
const Quaternion slerp_0_2 = SLerp(a, b, .2f);
|
|
EXPECT_TRUE(IsNormalized(slerp_0_2));
|
|
EXPECT_QUATERNION_EQ(slerp_0_2, .6067752f, .1697592f, 0.f, .7765344f);
|
|
|
|
const Quaternion slerp_0_7 = SLerp(a, b, .7f);
|
|
EXPECT_TRUE(IsNormalized(slerp_0_7));
|
|
EXPECT_QUATERNION_EQ(slerp_0_7, .2523113f, .5463429f, 0.f, .798654f);
|
|
|
|
const float dot = Dot(a, b);
|
|
EXPECT_FLOAT_EQ(dot, .5f);
|
|
}
|
|
|
|
TEST(QuaternionTransformVector, ozz_math) {
|
|
// 0 length
|
|
EXPECT_FLOAT3_EQ(
|
|
TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(), 0.f),
|
|
Float3::zero()),
|
|
0, 0, 0);
|
|
|
|
// Unit length
|
|
EXPECT_FLOAT3_EQ(
|
|
TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(), 0.f),
|
|
Float3::z_axis()),
|
|
0, 0, 1);
|
|
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(),
|
|
ozz::math::kPi_2),
|
|
Float3::y_axis()),
|
|
0, 1, 0);
|
|
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(),
|
|
ozz::math::kPi_2),
|
|
Float3::x_axis()),
|
|
0, 0, -1);
|
|
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::y_axis(),
|
|
ozz::math::kPi_2),
|
|
Float3::z_axis()),
|
|
1, 0, 0);
|
|
|
|
// Non unit
|
|
EXPECT_FLOAT3_EQ(TransformVector(Quaternion::FromAxisAngle(Float3::z_axis(),
|
|
ozz::math::kPi_2),
|
|
Float3::x_axis() * 2),
|
|
0, 2, 0);
|
|
}
|