180 lines
5.6 KiB
C
180 lines
5.6 KiB
C
#include "../HandmadeTest.h"
|
|
|
|
TEST(QuaternionOps, Inverse)
|
|
{
|
|
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
|
hmm_quaternion inverse = HMM_InverseQuaternion(q1);
|
|
|
|
hmm_quaternion result = HMM_MultiplyQuaternion(q1, inverse);
|
|
|
|
EXPECT_FLOAT_EQ(result.X, 0.0f);
|
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
|
EXPECT_FLOAT_EQ(result.W, 1.0f);
|
|
}
|
|
|
|
TEST(QuaternionOps, Dot)
|
|
{
|
|
hmm_quaternion q1 = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
|
hmm_quaternion q2 = HMM_Quaternion(5.0f, 6.0f, 7.0f, 8.0f);
|
|
|
|
{
|
|
float result = HMM_DotQuaternion(q1, q2);
|
|
EXPECT_FLOAT_EQ(result, 70.0f);
|
|
}
|
|
#ifdef __cplusplus
|
|
{
|
|
float result = HMM_Dot(q1, q2);
|
|
EXPECT_FLOAT_EQ(result, 70.0f);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
TEST(QuaternionOps, Normalize)
|
|
{
|
|
hmm_quaternion q = HMM_Quaternion(1.0f, 2.0f, 3.0f, 4.0f);
|
|
|
|
{
|
|
hmm_quaternion result = HMM_NormalizeQuaternion(q);
|
|
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
|
|
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
|
|
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
|
|
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
|
|
}
|
|
#ifdef __cplusplus
|
|
{
|
|
hmm_quaternion result = HMM_Normalize(q);
|
|
EXPECT_FLOAT_EQ(result.X, 0.1825741858f);
|
|
EXPECT_FLOAT_EQ(result.Y, 0.3651483717f);
|
|
EXPECT_FLOAT_EQ(result.Z, 0.5477225575f);
|
|
EXPECT_FLOAT_EQ(result.W, 0.7302967433f);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
TEST(QuaternionOps, NLerp)
|
|
{
|
|
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
|
|
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
|
|
|
|
hmm_quaternion result = HMM_NLerp(from, 0.5f, to);
|
|
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
|
|
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
|
|
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
|
|
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
|
|
}
|
|
|
|
TEST(QuaternionOps, Slerp)
|
|
{
|
|
hmm_quaternion from = HMM_Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
|
|
hmm_quaternion to = HMM_Quaternion(0.5f, 0.5f, -0.5f, 0.5f);
|
|
|
|
hmm_quaternion result = HMM_Slerp(from, 0.5f, to);
|
|
EXPECT_FLOAT_EQ(result.X, 0.28867513f);
|
|
EXPECT_FLOAT_EQ(result.Y, 0.28867513f);
|
|
EXPECT_FLOAT_EQ(result.Z, -0.28867513f);
|
|
EXPECT_FLOAT_EQ(result.W, 0.86602540f);
|
|
}
|
|
|
|
TEST(QuaternionOps, QuatToMat4)
|
|
{
|
|
const float abs_error = 0.0001f;
|
|
|
|
hmm_quaternion rot = HMM_Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f);
|
|
|
|
hmm_mat4 result = HMM_QuaternionToMat4(rot);
|
|
|
|
EXPECT_NEAR(result.Elements[0][0], 1.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[0][1], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[0][2], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[0][3], 0.0f, abs_error);
|
|
|
|
EXPECT_NEAR(result.Elements[1][0], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[1][1], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[1][2], 1.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[1][3], 0.0f, abs_error);
|
|
|
|
EXPECT_NEAR(result.Elements[2][0], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[2][1], -1.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[2][2], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[2][3], 0.0f, abs_error);
|
|
|
|
EXPECT_NEAR(result.Elements[3][0], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[3][1], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[3][2], 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Elements[3][3], 1.0f, abs_error);
|
|
}
|
|
|
|
TEST(QuaternionOps, Mat4ToQuat)
|
|
{
|
|
const float abs_error = 0.0001f;
|
|
|
|
// Rotate 90 degrees on the X axis
|
|
{
|
|
hmm_mat4 m = HMM_Rotate(90, HMM_Vec3(1, 0, 0));
|
|
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
|
|
|
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
|
|
|
EXPECT_NEAR(result.X, sinf, abs_error);
|
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
|
}
|
|
|
|
// Rotate 90 degrees on the Y axis (axis not normalized, just for fun)
|
|
{
|
|
hmm_mat4 m = HMM_Rotate(90, HMM_Vec3(0, 2, 0));
|
|
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
|
|
|
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
|
|
|
EXPECT_NEAR(result.X, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Y, sinf, abs_error);
|
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
|
}
|
|
|
|
// Rotate 90 degrees on the Z axis
|
|
{
|
|
hmm_mat4 m = HMM_Rotate(90, HMM_Vec3(0, 0, 1));
|
|
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
|
|
|
|
float cosf = 0.707107f; // cos(90/2 degrees)
|
|
float sinf = 0.707107f; // sin(90/2 degrees)
|
|
|
|
EXPECT_NEAR(result.X, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Z, sinf, abs_error);
|
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
|
}
|
|
|
|
// Rotate 45 degrees on the X axis (this hits case 4)
|
|
{
|
|
hmm_mat4 m = HMM_Rotate(45, HMM_Vec3(1, 0, 0));
|
|
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
|
|
|
|
float cosf = 0.9238795325f; // cos(90/2 degrees)
|
|
float sinf = 0.3826834324f; // sin(90/2 degrees)
|
|
|
|
EXPECT_NEAR(result.X, sinf, abs_error);
|
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
|
}
|
|
}
|
|
|
|
TEST(QuaternionOps, FromAxisAngle)
|
|
{
|
|
hmm_vec3 axis = HMM_Vec3(1.0f, 0.0f, 0.0f);
|
|
float angle = HMM_PI32 / 2.0f;
|
|
|
|
hmm_quaternion result = HMM_QuaternionFromAxisAngle(axis, angle);
|
|
EXPECT_NEAR(result.X, 0.707107f, FLT_EPSILON * 2);
|
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
|
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
|
|
}
|