master
ブランチ master
ShaderPlayground / deps / glm / glm / detail / type_quat.inl
10.1 KB、379行 生 Blame 履歴
1#include "../trigonometric.hpp"
2#include "../exponential.hpp"
3#include "../ext/quaternion_geometric.hpp"
4#include <limits>
5
6namespace glm{
7namespace detail
8{
9 template <typename T>
10 struct genTypeTrait<qua<T> >
11 {
12 static const genTypeEnum GENTYPE = GENTYPE_QUAT;
13 };
14
15 template<typename T, qualifier Q, bool Aligned>
16 struct compute_dot<qua<T, Q>, T, Aligned>
17 {
18 static GLM_FUNC_QUALIFIER T call(qua<T, Q> const& a, qua<T, Q> const& b)
19 {
20 vec<4, T, Q> tmp(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
21 return (tmp.x + tmp.y) + (tmp.z + tmp.w);
22 }
23 };
24
25 template<typename T, qualifier Q, bool Aligned>
26 struct compute_quat_add
27 {
28 static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
29 {
30 return qua<T, Q>(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z);
31 }
32 };
33
34 template<typename T, qualifier Q, bool Aligned>
35 struct compute_quat_sub
36 {
37 static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
38 {
39 return qua<T, Q>(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z);
40 }
41 };
42
43 template<typename T, qualifier Q, bool Aligned>
44 struct compute_quat_mul_scalar
45 {
46 static qua<T, Q> call(qua<T, Q> const& q, T s)
47 {
48 return qua<T, Q>(q.w * s, q.x * s, q.y * s, q.z * s);
49 }
50 };
51
52 template<typename T, qualifier Q, bool Aligned>
53 struct compute_quat_div_scalar
54 {
55 static qua<T, Q> call(qua<T, Q> const& q, T s)
56 {
57 return qua<T, Q>(q.w / s, q.x / s, q.y / s, q.z / s);
58 }
59 };
60
61 template<typename T, qualifier Q, bool Aligned>
62 struct compute_quat_mul_vec4
63 {
64 static vec<4, T, Q> call(qua<T, Q> const& q, vec<4, T, Q> const& v)
65 {
66 return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w);
67 }
68 };
69}//namespace detail
70
71 // -- Component accesses --
72
73 template<typename T, qualifier Q>
74 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & qua<T, Q>::operator[](typename qua<T, Q>::length_type i)
75 {
76 assert(i >= 0 && i < this->length());
77 return (&x)[i];
78 }
79
80 template<typename T, qualifier Q>
81 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& qua<T, Q>::operator[](typename qua<T, Q>::length_type i) const
82 {
83 assert(i >= 0 && i < this->length());
84 return (&x)[i];
85 }
86
87 // -- Implicit basic constructors --
88
89# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE
90 template<typename T, qualifier Q>
91 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua()
92# if GLM_CONFIG_DEFAULTED_FUNCTIONS != GLM_DISABLE
93 : x(0), y(0), z(0), w(1)
94# endif
95 {}
96
97 template<typename T, qualifier Q>
98 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, Q> const& q)
99 : x(q.x), y(q.y), z(q.z), w(q.w)
100 {}
101# endif
102
103 template<typename T, qualifier Q>
104 template<qualifier P>
105 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, P> const& q)
106 : x(q.x), y(q.y), z(q.z), w(q.w)
107 {}
108
109 // -- Explicit basic constructors --
110
111 template<typename T, qualifier Q>
112 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T s, vec<3, T, Q> const& v)
113 : x(v.x), y(v.y), z(v.z), w(s)
114 {}
115
116 template <typename T, qualifier Q>
117 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T _w, T _x, T _y, T _z)
118 : x(_x), y(_y), z(_z), w(_w)
119 {}
120
121 // -- Conversion constructors --
122
123 template<typename T, qualifier Q>
124 template<typename U, qualifier P>
125 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<U, P> const& q)
126 : x(static_cast<T>(q.x))
127 , y(static_cast<T>(q.y))
128 , z(static_cast<T>(q.z))
129 , w(static_cast<T>(q.w))
130 {}
131
132 //template<typename valType>
133 //GLM_FUNC_QUALIFIER qua<valType>::qua
134 //(
135 // valType const& pitch,
136 // valType const& yaw,
137 // valType const& roll
138 //)
139 //{
140 // vec<3, valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5));
141 // vec<3, valType> c = glm::cos(eulerAngle * valType(0.5));
142 // vec<3, valType> s = glm::sin(eulerAngle * valType(0.5));
143 //
144 // this->w = c.x * c.y * c.z + s.x * s.y * s.z;
145 // this->x = s.x * c.y * c.z - c.x * s.y * s.z;
146 // this->y = c.x * s.y * c.z + s.x * c.y * s.z;
147 // this->z = c.x * c.y * s.z - s.x * s.y * c.z;
148 //}
149
150 template<typename T, qualifier Q>
151 GLM_FUNC_QUALIFIER qua<T, Q>::qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v)
152 {
153 T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v));
154 T real_part = norm_u_norm_v + dot(u, v);
155 vec<3, T, Q> t;
156
157 if(real_part < static_cast<T>(1.e-6f) * norm_u_norm_v)
158 {
159 // If u and v are exactly opposite, rotate 180 degrees
160 // around an arbitrary orthogonal axis. Axis normalisation
161 // can happen later, when we normalise the quaternion.
162 real_part = static_cast<T>(0);
163 t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast<T>(0)) : vec<3, T, Q>(static_cast<T>(0), -u.z, u.y);
164 }
165 else
166 {
167 // Otherwise, build quaternion the standard way.
168 t = cross(u, v);
169 }
170
171 *this = normalize(qua<T, Q>(real_part, t.x, t.y, t.z));
172 }
173
174 template<typename T, qualifier Q>
175 GLM_FUNC_QUALIFIER qua<T, Q>::qua(vec<3, T, Q> const& eulerAngle)
176 {
177 vec<3, T, Q> c = glm::cos(eulerAngle * T(0.5));
178 vec<3, T, Q> s = glm::sin(eulerAngle * T(0.5));
179
180 this->w = c.x * c.y * c.z + s.x * s.y * s.z;
181 this->x = s.x * c.y * c.z - c.x * s.y * s.z;
182 this->y = c.x * s.y * c.z + s.x * c.y * s.z;
183 this->z = c.x * c.y * s.z - s.x * s.y * c.z;
184 }
185
186 template<typename T, qualifier Q>
187 GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<3, 3, T, Q> const& m)
188 {
189 *this = quat_cast(m);
190 }
191
192 template<typename T, qualifier Q>
193 GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<4, 4, T, Q> const& m)
194 {
195 *this = quat_cast(m);
196 }
197
198# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
199 template<typename T, qualifier Q>
200 GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<3, 3, T, Q>()
201 {
202 return mat3_cast(*this);
203 }
204
205 template<typename T, qualifier Q>
206 GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<4, 4, T, Q>()
207 {
208 return mat4_cast(*this);
209 }
210# endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
211
212 // -- Unary arithmetic operators --
213
214# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE
215 template<typename T, qualifier Q>
216 GLM_FUNC_QUALIFIER qua<T, Q> & qua<T, Q>::operator=(qua<T, Q> const& q)
217 {
218 this->w = q.w;
219 this->x = q.x;
220 this->y = q.y;
221 this->z = q.z;
222 return *this;
223 }
224# endif
225
226 template<typename T, qualifier Q>
227 template<typename U>
228 GLM_FUNC_QUALIFIER qua<T, Q> & qua<T, Q>::operator=(qua<U, Q> const& q)
229 {
230 this->w = static_cast<T>(q.w);
231 this->x = static_cast<T>(q.x);
232 this->y = static_cast<T>(q.y);
233 this->z = static_cast<T>(q.z);
234 return *this;
235 }
236
237 template<typename T, qualifier Q>
238 template<typename U>
239 GLM_FUNC_QUALIFIER qua<T, Q> & qua<T, Q>::operator+=(qua<U, Q> const& q)
240 {
241 return (*this = detail::compute_quat_add<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q)));
242 }
243
244 template<typename T, qualifier Q>
245 template<typename U>
246 GLM_FUNC_QUALIFIER qua<T, Q> & qua<T, Q>::operator-=(qua<U, Q> const& q)
247 {
248 return (*this = detail::compute_quat_sub<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q)));
249 }
250
251 template<typename T, qualifier Q>
252 template<typename U>
253 GLM_FUNC_QUALIFIER qua<T, Q> & qua<T, Q>::operator*=(qua<U, Q> const& r)
254 {
255 qua<T, Q> const p(*this);
256 qua<T, Q> const q(r);
257
258 this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z;
259 this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y;
260 this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z;
261 this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x;
262 return *this;
263 }
264
265 template<typename T, qualifier Q>
266 template<typename U>
267 GLM_FUNC_QUALIFIER qua<T, Q> & qua<T, Q>::operator*=(U s)
268 {
269 return (*this = detail::compute_quat_mul_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
270 }
271
272 template<typename T, qualifier Q>
273 template<typename U>
274 GLM_FUNC_QUALIFIER qua<T, Q> & qua<T, Q>::operator/=(U s)
275 {
276 return (*this = detail::compute_quat_div_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
277 }
278
279 // -- Unary bit operators --
280
281 template<typename T, qualifier Q>
282 GLM_FUNC_QUALIFIER qua<T, Q> operator+(qua<T, Q> const& q)
283 {
284 return q;
285 }
286
287 template<typename T, qualifier Q>
288 GLM_FUNC_QUALIFIER qua<T, Q> operator-(qua<T, Q> const& q)
289 {
290 return qua<T, Q>(-q.w, -q.x, -q.y, -q.z);
291 }
292
293 // -- Binary operators --
294
295 template<typename T, qualifier Q>
296 GLM_FUNC_QUALIFIER qua<T, Q> operator+(qua<T, Q> const& q, qua<T, Q> const& p)
297 {
298 return qua<T, Q>(q) += p;
299 }
300
301 template<typename T, qualifier Q>
302 GLM_FUNC_QUALIFIER qua<T, Q> operator-(qua<T, Q> const& q, qua<T, Q> const& p)
303 {
304 return qua<T, Q>(q) -= p;
305 }
306
307 template<typename T, qualifier Q>
308 GLM_FUNC_QUALIFIER qua<T, Q> operator*(qua<T, Q> const& q, qua<T, Q> const& p)
309 {
310 return qua<T, Q>(q) *= p;
311 }
312
313 template<typename T, qualifier Q>
314 GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v)
315 {
316 vec<3, T, Q> const QuatVector(q.x, q.y, q.z);
317 vec<3, T, Q> const uv(glm::cross(QuatVector, v));
318 vec<3, T, Q> const uuv(glm::cross(QuatVector, uv));
319
320 return v + ((uv * q.w) + uuv) * static_cast<T>(2);
321 }
322
323 template<typename T, qualifier Q>
324 GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua<T, Q> const& q)
325 {
326 return glm::inverse(q) * v;
327 }
328
329 template<typename T, qualifier Q>
330 GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(qua<T, Q> const& q, vec<4, T, Q> const& v)
331 {
332 return detail::compute_quat_mul_vec4<T, Q, detail::is_aligned<Q>::value>::call(q, v);
333 }
334
335 template<typename T, qualifier Q>
336 GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua<T, Q> const& q)
337 {
338 return glm::inverse(q) * v;
339 }
340
341 template<typename T, qualifier Q>
342 GLM_FUNC_QUALIFIER qua<T, Q> operator*(qua<T, Q> const& q, T const& s)
343 {
344 return qua<T, Q>(
345 q.w * s, q.x * s, q.y * s, q.z * s);
346 }
347
348 template<typename T, qualifier Q>
349 GLM_FUNC_QUALIFIER qua<T, Q> operator*(T const& s, qua<T, Q> const& q)
350 {
351 return q * s;
352 }
353
354 template<typename T, qualifier Q>
355 GLM_FUNC_QUALIFIER qua<T, Q> operator/(qua<T, Q> const& q, T const& s)
356 {
357 return qua<T, Q>(
358 q.w / s, q.x / s, q.y / s, q.z / s);
359 }
360
361 // -- Boolean operators --
362
363 template<typename T, qualifier Q>
364 GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(qua<T, Q> const& q1, qua<T, Q> const& q2)
365 {
366 return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w;
367 }
368
369 template<typename T, qualifier Q>
370 GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(qua<T, Q> const& q1, qua<T, Q> const& q2)
371 {
372 return q1.x != q2.x || q1.y != q2.y || q1.z != q2.z || q1.w != q2.w;
373 }
374}//namespace glm
375
376#if GLM_CONFIG_SIMD == GLM_ENABLE
377# include "type_quat_simd.inl"
378#endif
379