forked from hkrn/nanoem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheuler.cc
154 lines (141 loc) · 4.04 KB
/
euler.cc
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
Copyright (c) 2015-2021 hkrn All rights reserved
This file is licensed under MIT license. for more details, see LICENSE.txt.
*/
#include <iostream>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/io.hpp>
#define LEFT_ORDER
namespace {
static void
createUnitAxes(const glm::vec3 &radians, glm::quat &x, glm::quat &y, glm::quat &z)
{
x = glm::angleAxis(radians.x, glm::vec3(1, 0, 0));
y = glm::angleAxis(radians.y, glm::vec3(0, 1, 0));
z = glm::angleAxis(radians.z, glm::vec3(0, 0, 1));
}
static glm::quat
rotateZXY(const glm::vec3 &radians)
{
glm::quat x, y, z;
createUnitAxes(radians, x, y, z);
#ifdef LEFT_ORDER
return z * x * y;
#else
return y * x * z;
#endif
}
static glm::quat
rotateXYZ(const glm::vec3 &radians)
{
glm::quat x, y, z;
createUnitAxes(radians, x, y, z);
#ifdef LEFT_ORDER
return x * y * z;
#else
return z * y * x;
#endif
}
static glm::quat
rotateYZX(const glm::vec3 &radians)
{
glm::quat x, y, z;
createUnitAxes(radians, x, y, z);
#ifdef LEFT_ORDER
return y * z * x;
#else
return x * z * y;
#endif
}
static glm::vec3
extractEulerZXY(const glm::mat3 &matrix)
{
glm::vec3 radians;
#ifdef LEFT_ORDER
radians.x = glm::asin(matrix[1][2]);
radians.y = glm::atan(-matrix[0][2], matrix[2][2]);
radians.z = glm::atan(-matrix[1][0], matrix[1][1]);
#elif 0
const float *v = glm::value_ptr(matrix);
radians.x = glm::asin(-v[7]);
radians.y = glm::atan(v[6], v[8]);
radians.z = glm::atan(v[1], v[4]);
#else
radians.x = glm::asin(-matrix[2][1]);
radians.y = glm::atan(matrix[2][0], matrix[2][2]);
radians.z = glm::atan(matrix[0][1], matrix[1][1]);
#endif
return radians;
}
static glm::vec3
extractEulerXYZ(const glm::mat3 &matrix)
{
glm::vec3 radians;
#ifdef LEFT_ORDER
radians.x = glm::atan(-matrix[2][1], matrix[2][2]);
radians.y = glm::asin(matrix[2][0]);
radians.z = glm::atan(-matrix[1][0], matrix[0][0]);
#elif 0
const float *v = glm::value_ptr(matrix);
radians.x = glm::atan(v[5], v[8]);
radians.y = glm::asin(-v[2]);
radians.z = glm::atan(v[1], v[0]);
#else
radians.x = glm::atan(matrix[1][2], matrix[2][2]);
radians.y = glm::asin(-matrix[0][2]);
radians.z = glm::atan(matrix[0][1], matrix[0][0]);
#endif
return radians;
}
static glm::vec3
extractEulerYZX(const glm::mat3 &matrix)
{
glm::vec3 radians;
#ifdef LEFT_ORDER
radians.x = glm::atan(-matrix[2][1], matrix[1][1]);
radians.y = glm::atan(-matrix[0][2], matrix[0][0]);
radians.z = glm::asin(matrix[0][1]);
#elif 0
const float *v = glm::value_ptr(matrix);
radians.x = glm::atan(v[5], v[4]);
radians.y = glm::atan(v[6], v[0]);
radians.z = glm::asin(-v[3]);
#else
radians.x = glm::atan(matrix[1][2], matrix[1][1]);
radians.y = glm::atan(matrix[2][0], matrix[0][0]);
radians.z = glm::asin(-matrix[1][0]);
#endif
return radians;
}
}
int
main(void)
{
static const glm::vec3 input(glm::radians(glm::vec3(150, 150, 30)));
{
glm::quat q = rotateXYZ(input);
glm::vec3 output = extractEulerXYZ(glm::mat3_cast(q));
std::cerr << "XYZ: " << glm::degrees(output) << " "
<< glm::all(glm::lessThan(glm::abs(output - input), glm::vec3(glm::epsilon<glm::vec3::value_type>())))
<< std::endl;
}
{
glm::quat q = rotateYZX(input);
glm::vec3 output = extractEulerYZX(glm::mat3_cast(q));
std::cerr << "YZX: " << glm::degrees(output) << " "
<< glm::all(glm::lessThan(glm::abs(output - input), glm::vec3(glm::epsilon<glm::vec3::value_type>())))
<< std::endl;
}
{
glm::quat q = rotateZXY(input);
glm::vec3 output = extractEulerZXY(glm::mat3_cast(q));
std::cerr << "ZXY: " << glm::degrees(output) << " "
<< glm::all(glm::lessThan(glm::abs(output - input), glm::vec3(glm::epsilon<glm::vec3::value_type>())))
<< std::endl;
std::flush(std::cerr);
}
return 0;
}