-
Notifications
You must be signed in to change notification settings - Fork 47
/
Quaternion.cpp
111 lines (89 loc) · 4.48 KB
/
Quaternion.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "gtest/gtest.h"
#include "math/Quaternion.h"
#include "math/Matrix4.h"
namespace test
{
// Fuzzy equality assertion for Quaternions
void expectNear(const Quaternion& q1, const Quaternion& q2)
{
EXPECT_DOUBLE_EQ(q1.x(), q2.x());
EXPECT_DOUBLE_EQ(q1.y(), q2.y());
EXPECT_DOUBLE_EQ(q1.z(), q2.z());
EXPECT_DOUBLE_EQ(q1.w(), q2.w());
}
TEST(MathTest, QuaternionForXRotation)
{
math::Degrees angle(45);
Quaternion xRot = Quaternion::createForX(angle.asRadians());
expectNear(xRot, Quaternion(sin(angle.asRadians() / 2), 0, 0,
cos(angle.asRadians() / 2)));
expectNear(xRot,
Quaternion::createForMatrix(Matrix4::getRotationAboutX(angle)));
}
TEST(MathTest, QuaternionForYRotation)
{
math::Degrees angle(60);
Quaternion yRot = Quaternion::createForY(angle.asRadians());
expectNear(yRot, Quaternion(0, sin(angle.asRadians() / 2), 0,
cos(angle.asRadians() / 2)));
expectNear(yRot,
Quaternion::createForMatrix(Matrix4::getRotationAboutY(angle)));
}
TEST(MathTest, QuaternionForZRotation)
{
math::Degrees angle(75);
Quaternion zRot = Quaternion::createForZ(angle.asRadians());
expectNear(zRot, Quaternion(0, 0, sin(angle.asRadians() / 2),
cos(angle.asRadians() / 2)));
expectNear(zRot,
Quaternion::createForMatrix(Matrix4::getRotationAboutZ(angle)));
}
TEST(MathTest, QuaternionMultiplication)
{
Quaternion q1(3, 5, 7, 11);
Quaternion q2(13, 17, 19, 23);
Quaternion product = q1.getMultipliedBy(q2);
EXPECT_EQ(product.x(), 188) << "Quaternion multiplication failed on x";
EXPECT_EQ(product.y(), 336) << "Quaternion multiplication failed on y";
EXPECT_EQ(product.z(), 356) << "Quaternion multiplication failed on z";
EXPECT_EQ(product.w(), -4) << "Quaternion multiplication failed on w";
}
TEST(MathTest, QuaternionInPlaceMultiplication)
{
Quaternion q1(3, 5, 7, 11);
Quaternion q2(13, 17, 19, 23);
Quaternion q1multiplied = q1;
q1multiplied.multiplyBy(q2);
EXPECT_EQ(q1multiplied.x(), 188) << "Quaternion in-place multiplication failed on x";
EXPECT_EQ(q1multiplied.y(), 336) << "Quaternion in-place multiplication failed on y";
EXPECT_EQ(q1multiplied.z(), 356) << "Quaternion in-place multiplication failed on z";
EXPECT_EQ(q1multiplied.w(), -4) << "Quaternion in-place multiplication failed on w";
}
TEST(MathTest, QuaternionInverse)
{
Quaternion q1(3, 5, 7, 11);
Quaternion q1inverted = q1.getInverse();
EXPECT_EQ(q1inverted.x(), -3) << "Quaternion inversion failed on x";
EXPECT_EQ(q1inverted.y(), -5) << "Quaternion inversion failed on y";
EXPECT_EQ(q1inverted.z(), -7) << "Quaternion inversion failed on z";
EXPECT_EQ(q1inverted.w(), 11) << "Quaternion inversion failed on w";
}
TEST(MathTest, QuaternionNormalised)
{
Quaternion q1(3, 5, 7, 11);
Quaternion normalised = q1.getNormalised();
EXPECT_DOUBLE_EQ(normalised.x(), 0.2100420126042014) << "Quaternion normalisation failed on x";
EXPECT_DOUBLE_EQ(normalised.y(), 0.3500700210070024) << "Quaternion normalisation failed on y";
EXPECT_DOUBLE_EQ(normalised.z(), 0.4900980294098034) << "Quaternion normalisation failed on z";
EXPECT_DOUBLE_EQ(normalised.w(), 0.7701540462154052) << "Quaternion normalisation failed on w";
}
TEST(MathTest, QuaternionTransformPoint)
{
Quaternion q1(3, 5, 7, 11);
Vector3 point(13, 17, 19);
Vector3 transformed = q1.transformPoint(point);
EXPECT_EQ(transformed.x(), q1.w() * q1.w() * point.x() + 2 * q1.y() * q1.w() * point.z() - 2 * q1.z() * q1.w() * point.y() + q1.x() * q1.x() * point.x() + 2 * q1.y() * q1.x() * point.y() + 2 * q1.z() * q1.x() * point.z() - q1.z() * q1.z() * point.x() - q1.y() * q1.y() * point.x()) << "Quaternion point transformation failed on x";
EXPECT_EQ(transformed.y(), 2 * q1.x() * q1.y() * point.x() + q1.y() * q1.y() * point.y() + 2 * q1.z() * q1.y() * point.z() + 2 * q1.w() * q1.z() * point.x() - q1.z() * q1.z() * point.y() + q1.w() * q1.w() * point.y() - 2 * q1.x() * q1.w() * point.z() - q1.x() * q1.x() * point.y()) << "Quaternion point transformation failed on y";
EXPECT_EQ(transformed.z(), 2 * q1.x() * q1.z() * point.x() + 2 * q1.y() * q1.z() * point.y() + q1.z() * q1.z() * point.z() - 2 * q1.w() * q1.y() * point.x() - q1.y() * q1.y() * point.z() + 2 * q1.w() * q1.x() * point.y() - q1.x() * q1.x() * point.z() + q1.w() * q1.w() * point.z()) << "Quaternion point transformation failed on z";
}
}