master
ブランチ master
VulkanExample / dep / include / glm / gtc / quaternion.inl
6.5 KB、208行 生 Blame 履歴
1#include "../trigonometric.hpp"
2#include "../geometric.hpp"
3#include "../exponential.hpp"
4#include "epsilon.hpp"
5#include <limits>
6
7namespace glm
8{
9 template<typename T, qualifier Q>
10 GLM_FUNC_QUALIFIER vec<3, T, Q> eulerAngles(qua<T, Q> const& x)
11 {
12 return vec<3, T, Q>(pitch(x), yaw(x), roll(x));
13 }
14
15 template<typename T, qualifier Q>
16 GLM_FUNC_QUALIFIER T roll(qua<T, Q> const& q)
17 {
18 T const y = static_cast<T>(2) * (q.x * q.y + q.w * q.z);
19 T const x = q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z;
20
21 if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon<T>()))) //avoid atan2(0,0) - handle singularity - Matiis
22 return static_cast<T>(0);
23
24 return static_cast<T>(atan(y, x));
25 }
26
27 template<typename T, qualifier Q>
28 GLM_FUNC_QUALIFIER T pitch(qua<T, Q> const& q)
29 {
30 //return T(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z));
31 T const y = static_cast<T>(2) * (q.y * q.z + q.w * q.x);
32 T const x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z;
33
34 if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon<T>()))) //avoid atan2(0,0) - handle singularity - Matiis
35 return static_cast<T>(static_cast<T>(2) * atan(q.x, q.w));
36
37 return static_cast<T>(atan(y, x));
38 }
39
40 template<typename T, qualifier Q>
41 GLM_FUNC_QUALIFIER T yaw(qua<T, Q> const& q)
42 {
43 return asin(clamp(static_cast<T>(-2) * (q.x * q.z - q.w * q.y), static_cast<T>(-1), static_cast<T>(1)));
44 }
45
46 template<typename T, qualifier Q>
47 GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat3_cast(qua<T, Q> const& q)
48 {
49 mat<3, 3, T, Q> Result(T(1));
50 T qxx(q.x * q.x);
51 T qyy(q.y * q.y);
52 T qzz(q.z * q.z);
53 T qxz(q.x * q.z);
54 T qxy(q.x * q.y);
55 T qyz(q.y * q.z);
56 T qwx(q.w * q.x);
57 T qwy(q.w * q.y);
58 T qwz(q.w * q.z);
59
60 Result[0][0] = T(1) - T(2) * (qyy + qzz);
61 Result[0][1] = T(2) * (qxy + qwz);
62 Result[0][2] = T(2) * (qxz - qwy);
63
64 Result[1][0] = T(2) * (qxy - qwz);
65 Result[1][1] = T(1) - T(2) * (qxx + qzz);
66 Result[1][2] = T(2) * (qyz + qwx);
67
68 Result[2][0] = T(2) * (qxz + qwy);
69 Result[2][1] = T(2) * (qyz - qwx);
70 Result[2][2] = T(1) - T(2) * (qxx + qyy);
71 return Result;
72 }
73
74 template<typename T, qualifier Q>
75 GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat4_cast(qua<T, Q> const& q)
76 {
77 return mat<4, 4, T, Q>(mat3_cast(q));
78 }
79
80 template<typename T, qualifier Q>
81 GLM_FUNC_QUALIFIER qua<T, Q> quat_cast(mat<3, 3, T, Q> const& m)
82 {
83 T fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2];
84 T fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2];
85 T fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1];
86 T fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2];
87
88 int biggestIndex = 0;
89 T fourBiggestSquaredMinus1 = fourWSquaredMinus1;
90 if(fourXSquaredMinus1 > fourBiggestSquaredMinus1)
91 {
92 fourBiggestSquaredMinus1 = fourXSquaredMinus1;
93 biggestIndex = 1;
94 }
95 if(fourYSquaredMinus1 > fourBiggestSquaredMinus1)
96 {
97 fourBiggestSquaredMinus1 = fourYSquaredMinus1;
98 biggestIndex = 2;
99 }
100 if(fourZSquaredMinus1 > fourBiggestSquaredMinus1)
101 {
102 fourBiggestSquaredMinus1 = fourZSquaredMinus1;
103 biggestIndex = 3;
104 }
105
106 T biggestVal = sqrt(fourBiggestSquaredMinus1 + static_cast<T>(1)) * static_cast<T>(0.5);
107 T mult = static_cast<T>(0.25) / biggestVal;
108
109 switch(biggestIndex)
110 {
111 case 0:
112 return qua<T, Q>::wxyz(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult);
113 case 1:
114 return qua<T, Q>::wxyz((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult);
115 case 2:
116 return qua<T, Q>::wxyz((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult);
117 case 3:
118 return qua<T, Q>::wxyz((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal);
119 default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity.
120 assert(false);
121 return qua<T, Q>::wxyz(1, 0, 0, 0);
122 }
123 }
124
125 template<typename T, qualifier Q>
126 GLM_FUNC_QUALIFIER qua<T, Q> quat_cast(mat<4, 4, T, Q> const& m4)
127 {
128 return quat_cast(mat<3, 3, T, Q>(m4));
129 }
130
131 template<typename T, qualifier Q>
132 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> lessThan(qua<T, Q> const& x, qua<T, Q> const& y)
133 {
134 vec<4, bool, Q> Result(false, false, false, false);
135 for(length_t i = 0; i < x.length(); ++i)
136 Result[i] = x[i] < y[i];
137 return Result;
138 }
139
140 template<typename T, qualifier Q>
141 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> lessThanEqual(qua<T, Q> const& x, qua<T, Q> const& y)
142 {
143 vec<4, bool, Q> Result(false, false, false, false);
144 for(length_t i = 0; i < x.length(); ++i)
145 Result[i] = x[i] <= y[i];
146 return Result;
147 }
148
149 template<typename T, qualifier Q>
150 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> greaterThan(qua<T, Q> const& x, qua<T, Q> const& y)
151 {
152 vec<4, bool, Q> Result(false, false, false, false);
153 for(length_t i = 0; i < x.length(); ++i)
154 Result[i] = x[i] > y[i];
155 return Result;
156 }
157
158 template<typename T, qualifier Q>
159 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> greaterThanEqual(qua<T, Q> const& x, qua<T, Q> const& y)
160 {
161 vec<4, bool, Q> Result(false, false, false, false);
162 for(length_t i = 0; i < x.length(); ++i)
163 Result[i] = x[i] >= y[i];
164 return Result;
165 }
166
167
168 template<typename T, qualifier Q>
169 GLM_FUNC_QUALIFIER qua<T, Q> quatLookAt(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
170 {
171# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT
172 return quatLookAtLH(direction, up);
173# else
174 return quatLookAtRH(direction, up);
175# endif
176 }
177
178 template<typename T, qualifier Q>
179 GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtRH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
180 {
181 mat<3, 3, T, Q> Result;
182
183 Result[2] = -direction;
184 vec<3, T, Q> const& Right = cross(up, Result[2]);
185 Result[0] = Right * inversesqrt(max(static_cast<T>(0.00001), dot(Right, Right)));
186 Result[1] = cross(Result[2], Result[0]);
187
188 return quat_cast(Result);
189 }
190
191 template<typename T, qualifier Q>
192 GLM_FUNC_QUALIFIER qua<T, Q> quatLookAtLH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up)
193 {
194 mat<3, 3, T, Q> Result;
195
196 Result[2] = direction;
197 vec<3, T, Q> const& Right = cross(up, Result[2]);
198 Result[0] = Right * inversesqrt(max(static_cast<T>(0.00001), dot(Right, Right)));
199 Result[1] = cross(Result[2], Result[0]);
200
201 return quat_cast(Result);
202 }
203}//namespace glm
204
205#if GLM_CONFIG_SIMD == GLM_ENABLE
206# include "quaternion_simd.inl"
207#endif
208