Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
Quaternion.inl
Go to the documentation of this file.
1/*
2 Copyright (c) 2018 DIVIDE-Studio
3 Copyright (c) 2009 Ionut Cava
4
5 This file is part of DIVIDE Framework.
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software
9 and associated documentation files (the "Software"), to deal in the Software
10 without restriction,
11 including without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so,
15 subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED,
22 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
23 PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
25 DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
27 IN CONNECTION WITH THE SOFTWARE
28 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 */
31
32#ifndef DVD_QUATERNION_INL_
33#define DVD_QUATERNION_INL_
34
35namespace Divide {
36
37namespace AVX {
38 //ref: http://stackoverflow.com/questions/18542894/how-to-multiply-two-quaternions-with-minimal-instructions?lq=1
39 static __m128 multiplynew(const __m128 xyzw, const __m128 abcd) noexcept {
40 /* The product of two quaternions is: */
41 /* (X,Y,Z,W) = (xd+yc-zb+wa, -xc+yd+za+wb, xb-ya+zd+wc, -xa-yb-zc+wd) */
42 const __m128 wzyx = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(0, 1, 2, 3));
43 const __m128 baba = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(0, 1, 0, 1));
44 const __m128 dcdc = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(2, 3, 2, 3));
45
46 /* variable names below are for parts of componens of result (X,Y,Z,W) */
47
48 /* nX stands for -X and similarly for the other components */
49 /* znxwy = (xb - ya, zb - wa, wd - zc, yd - xc) */
50 const __m128 ZnXWY = _mm_hsub_ps(_mm_mul_ps(xyzw, baba), _mm_mul_ps(wzyx, dcdc));
52 /* xzynw = (xd + yc, zd + wc, wb + za, yb + xa) */
53 const __m128 XZYnW = _mm_hadd_ps(_mm_mul_ps(xyzw, dcdc), _mm_mul_ps(wzyx, baba));
54
55 /* _mm_shuffle_ps(XZYnW, ZnXWY, _MM_SHUFFLE(3,2,1,0)) */
56 /* = (xd + yc, zd + wc, wd - zc, yd - xc) */
57 /* _mm_shuffle_ps(ZnXWY, XZYnW, _MM_SHUFFLE(2,3,0,1)) */
58 /* = (zb - wa, xb - ya, yb + xa, wb + za) */
60 /* _mm_addsub_ps adds elements 1 and 3 and subtracts elements 0 and 2, so we get: */
61 /* _mm_addsub_ps(*, *) = (xd+yc-zb+wa, xb-ya+zd+wc, wd-zc+yb+xa, yd-xc+wb+za) */
63 const __m128 XZWY = _mm_addsub_ps(_mm_shuffle_ps(XZYnW, ZnXWY, _MM_SHUFFLE(3, 2, 1, 0)),
64 _mm_shuffle_ps(ZnXWY, XZYnW, _MM_SHUFFLE(2, 3, 0, 1)));
66 /* now we only need to shuffle the components in place and return the result */
67 return _mm_shuffle_ps(XZWY, XZWY, _MM_SHUFFLE(2, 1, 3, 0));
68 }
69}
71template <typename T>
73 : Quaternion(0, 0, 0, 1)
74{
75}
76
77template <typename T>
78Quaternion<T>::Quaternion(T x, T y, T z, T w) noexcept
79 : _elements(x, y, z, w)
80{
81}
82
83template <typename T>
84Quaternion<T>::Quaternion(const vec4<T>& values) noexcept
85 : _elements(values)
86{
87}
89template <typename T>
90Quaternion<T>::Quaternion(const mat3<T>& rotationMatrix) noexcept
92 fromMatrix(rotationMatrix);
93}
95template <typename T>
97{
98 fromAxisAngle(axis, angle);
99}
101template <typename T>
102Quaternion<T>::Quaternion(const vec3<T>& forward, const vec3<T>& up) noexcept
104 lookRotation(forward, up);
106
107template <typename T>
110 fromEuler(pitch, yaw, roll);
112
113template <typename T>
115 : _elements(q._elements)
116{
118
119template <typename T>
121 set(q);
122 return *this;
123}
125template <typename T>
126T Quaternion<T>::dot(const Quaternion<T>& rq) const noexcept {
127 return _elements.dot(rq._elements);
128}
130template <typename T>
132 return _elements.length();
133}
135template <typename T>
137 return _elements.lengthSquared();
138}
140template <typename T>
142 T angleRad = Angle::to_RADIANS(static_cast<T>(std::acosf(to_F32(dot(rq)))));
143 const F32 toleranceRad = Angle::to_RADIANS(tolerance);
145 return IS_TOLERANCE(angleRad, toleranceRad) || COMPARE_TOLERANCE(angleRad, M_PI_f, toleranceRad);
146}
147
148template <typename T>
149void Quaternion<T>::set(const vec4<T>& values) noexcept {
150 _elements.set(values);
153template <typename T>
154void Quaternion<T>::set(T x, T y, T z, T w) noexcept {
155 _elements.set(x, y, z, w);
158template <typename T>
159void Quaternion<T>::set(const Quaternion<T>& q) noexcept {
160 set(q._elements);
162
163template <typename T>
165 _elements.normalize();
167
168template <typename T>
170 return getConjugate() * (1.0f / magnitude());
171}
173template <typename T>
175 return Quaternion<T>(-X(), -Y(), -Z(), W());
176}
177
178template <typename T>
180 return Quaternion<T>(W() * rq.X() + X() * rq.W() + Y() * rq.Z() - Z() * rq.Y(),
181 W() * rq.Y() + Y() * rq.W() + Z() * rq.X() - X() * rq.Z(),
182 W() * rq.Z() + Z() * rq.W() + X() * rq.Y() - Y() * rq.X(),
183 W() * rq.W() - X() * rq.X() - Y() * rq.Y() - Z() * rq.Z());
184}
185
186template <>
188 return Quaternion<F32>(AVX::multiplynew(_elements._reg._reg, rq._elements._reg._reg));
189}
190
191template <typename T>
193 *this = *this * rq;
194 return *this;
195}
196
197template <typename T>
199 return *this * rq.inverse();
200}
201
202template <typename T>
204 *this = rq / *this;
205 return *this;
206}
207
208template <typename T>
209vec3<T> Quaternion<T>::operator*(const vec3<T>& vec) const noexcept {
210 // nVidia SDK implementation
211 vec3<T> uv = Cross(_elements.xyz, vec);
212 const vec3<T> uuv = Cross(_elements.xyz, uv);
213 uv *= W() * 2;
214
215 return vec + uv + uuv * 2;
216}
217
218template <typename T>
220 return compare(rq);
221}
222
223template <typename T>
225 return !compare(rq);
226}
227
228template <typename T>
230 _elements += rq._elements;
231 return *this;
232}
233
234template <typename T>
236 _elements -= rq._elements;
237 return *this;
238}
239
240template <typename T>
242 _elements *= scalar;
243 return *this;
244}
245
246template <typename T>
248 _elements /= scalar;
249 return *this;
250}
251
252template <typename T>
254 Quaternion<T> tmp(*this);
255 tmp += rq;
256 return tmp;
257}
258
259template <typename T>
261 Quaternion<T> tmp(*this);
262 tmp -= rq;
263 return tmp;
264}
265
266template <typename T>
268 Quaternion<T> tmp(*this);
269 tmp *= scalar;
270 return tmp;
271}
272
273template <typename T>
275 Quaternion<T> tmp(*this);
276 tmp /= scalar;
277 return tmp;
278}
279
280template <typename T>
281void Quaternion<T>::slerp(const Quaternion<T>& q, const F32 t) noexcept {
282 slerp(*this, q, t);
283}
284
285template <typename T>
286void Quaternion<T>::slerp(const Quaternion<T>& q0, const Quaternion<T>& q1, const F32 t) noexcept {
287 F32 k0 = 0.f, k1 = 0.f;
288 T cosomega = q0.dot(q1);
290 if (cosomega < 0.f) {
291 cosomega = -cosomega;
292 q._elements.set(-q1._elements);
293 } else {
294 q._elements.set(q1._elements);
295 }
296
297 if (1. - cosomega > 1e-6) {
298 const F32 omega = to_F32(std::acos(cosomega));
299 const F32 sinomega = to_F32(std::sin(omega));
300 k0 = to_F32(std::sin((1.f - t) * omega) / sinomega);
301 k1 = to_F32(std::sin(t * omega) / sinomega);
302 } else {
303 k0 = 1.f - t;
304 k1 = t;
305 }
306 _elements.set(q0._elements * k0 + q._elements * k1);
307}
308
309template <typename T>
311 const Angle::RADIANS<T> angleHalfRad = Angle::to_RADIANS(angle) * 0.5f;
312 _elements.set(Normalized(v) * std::sin(angleHalfRad), std::cos(angleHalfRad));
313}
314
315template <typename T>
317 fromEuler(v.pitch, v.yaw, v.roll);
318}
319
320template <typename T>
322 const vec3<F32> eulerAngles(Angle::to_RADIANS(pitch) * 0.5f,
323 Angle::to_RADIANS(yaw) * 0.5f,
324 Angle::to_RADIANS(roll) * 0.5f);
325 const vec3<F32> c(std::cos(eulerAngles.x),
326 std::cos(eulerAngles.y),
327 std::cos(eulerAngles.z));
328 const vec3<F32> s(std::sin(eulerAngles.x),
329 std::sin(eulerAngles.y),
330 std::sin(eulerAngles.z));
331
332 W(c.x * c.y * c.z + s.x * s.y * s.z);
333 X(s.x * c.y * c.z - c.x * s.y * s.z);
334 Y(c.x * s.y * c.z + s.x * c.y * s.z);
335 Z(c.x * c.y * s.z - s.x * s.y * c.z);
336 // normalize(); this method does produce a normalized quaternion
337}
338
339//ref: http://answers.unity3d.com/questions/467614/what-is-the-source-code-of-quaternionlookrotation.html
340template <typename T>
342 Normalize(forward);
343 const vec3<T> right = Normalized(Cross(up, forward));
344 up = Cross(forward, right);
345 const T m00 = right.x;
346 const T m01 = right.y;
347 const T m02 = right.z;
348 const T m10 = up.x;
349 const T m11 = up.y;
350 const T m12 = up.z;
351 const T m20 = forward.x;
352 const T m21 = forward.y;
353 const T m22 = forward.z;
354
355 const T num8 = (m00 + m11) + m22;
356
357 if (num8 > 0) {
358 T num = Divide::Sqrt(num8 + 1);
359 W(num * 0.5); num = T{ 0.5f / num };
360 X((m12 - m21) * num);
361 Y((m20 - m02) * num);
362 Z((m01 - m10) * num);
363 return;
364 }
365
366 if ((m00 >= m11) && (m00 >= m22)) {
367 const T num7 = Divide::Sqrt(((1 + m00) - m11) - m22);
368 const T num4 = T{ 0.5f / num7 };
369 X(0.5 * num7);
370 Y((m01 + m10) * num4);
371 Z((m02 + m20) * num4);
372 W((m12 - m21) * num4);
373 return;
374 }
375
376 if (m11 > m22) {
377 const T num6 = Divide::Sqrt(((1 + m11) - m00) - m22);
378 const T num3 = T{ 0.5f / num6 };
379 X((m10 + m01) * num3);
380 Y(0.5 * num6);
381 Z((m21 + m12) * num3);
382 W((m20 - m02) * num3);
383 return;
384 }
385
386 const T num5 = Divide::Sqrt(((1 + m22) - m00) - m11);
387 const T num2 = T{ 0.5f / num5 };
388 X((m20 + m02) * num2);
389 Y((m21 + m12) * num2);
390 Z(0.5 * num5);
391 W((m01 - m10) * num2);
392}
393
394template <typename T>
395void Quaternion<T>::fromMatrix(const mat4<T>& viewMatrix) noexcept {
396 mat3<T> rotMatrix;
397 viewMatrix.extractMat3(rotMatrix);
398 fromMatrix(rotMatrix);
399}
400
401template <typename T>
402void Quaternion<T>::fromMatrix(const mat3<T>& rotationMatrix) noexcept {
403 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
404 // article "Quaternion Calculus and Fast Animation".
405
406 T fTrace = rotationMatrix.m[0][0] + rotationMatrix.m[1][1] +
407 rotationMatrix.m[2][2];
408 T fRoot = 0;
409
410 if (fTrace > 0) {
411 // |w| > 1/2, may as well choose w > 1/2
412 fRoot = Divide::Sqrt<T, F32>(fTrace + 1.0f); // 2w
413 W(T(0.5f * fRoot));
414 fRoot = T(0.5f / fRoot); // 1/(4w)
415 X((rotationMatrix.m[2][1] - rotationMatrix.m[1][2]) * fRoot);
416 Y((rotationMatrix.m[0][2] - rotationMatrix.m[2][0]) * fRoot);
417 Z((rotationMatrix.m[1][0] - rotationMatrix.m[0][1]) * fRoot);
418 } else {
419 // |w| <= 1/2
420 static size_t s_iNext[3] = {1, 2, 0};
421 size_t i = 0;
422 if (rotationMatrix.m[1][1] > rotationMatrix.m[0][0]) {
423 i = 1;
424 }
425 if (rotationMatrix.m[2][2] > rotationMatrix.m[i][i]) {
426 i = 2;
427 }
428 size_t j = s_iNext[i];
429 size_t k = s_iNext[j];
430
431 fRoot = Divide::Sqrt<T, F32>(rotationMatrix.m[i][i] - rotationMatrix.m[j][j] - rotationMatrix.m[k][k] + 1.0f);
432 T* apkQuat[3] = {&_elements.x, &_elements.y, &_elements.z};
433 *apkQuat[i] = T(0.5f * fRoot);
434 fRoot = T(0.5f / fRoot);
435 W((rotationMatrix.m[k][j] - rotationMatrix.m[j][k]) * fRoot);
436 *apkQuat[j] = (rotationMatrix.m[j][i] + rotationMatrix.m[i][j]) * fRoot;
437 *apkQuat[k] = (rotationMatrix.m[k][i] + rotationMatrix.m[i][k]) * fRoot;
438 }
439}
440
441template <typename T>
442void Quaternion<T>::getMatrix(mat3<T>& outMatrix) const noexcept {
443 const T& x = X();
444 const T& y = Y();
445 const T& z = Z();
446 const T& w = W();
447 T fTx = x + x;
448 T fTy = y + y;
449 T fTz = z + z;
450 T fTwx = fTx*w;
451 T fTwy = fTy*w;
452 T fTwz = fTz*w;
453 T fTxx = fTx*x;
454 T fTxy = fTy*x;
455 T fTxz = fTz*x;
456 T fTyy = fTy*y;
457 T fTyz = fTz*y;
458 T fTzz = fTz*z;
459
460 outMatrix.m[0][0] = static_cast<T>(1.0f - (fTyy + fTzz));
461 outMatrix.m[0][1] = fTxy - fTwz;
462 outMatrix.m[0][2] = fTxz + fTwy;
463 outMatrix.m[1][0] = fTxy + fTwz;
464 outMatrix.m[1][1] = static_cast<T>(1.0f - (fTxx + fTzz));
465 outMatrix.m[1][2] = fTyz - fTwx;
466 outMatrix.m[2][0] = fTxz - fTwy;
467 outMatrix.m[2][1] = fTyz + fTwx;
468 outMatrix.m[2][2] = static_cast<T>(1.0f - (fTxx + fTyy));
469}
470
471template <typename T>
473 axis.set(_elements / _elements.xyz().length());
474 angle = Angle::to_DEGREES(std::acos(W()) * 2.0f);
475}
476
477template <typename T>
480
481 const T& x = X();
482 const T& y = Y();
483 const T& z = Z();
484 const T& w = W();
485 const T sqx = x * x;
486 const T sqy = y * y;
487 const T sqz = z * z;
488 const T sqw = w * w;
489 const T test = x * y + z * w;
490 // if normalized is one, otherwise is correction factor
491 const T unit = sqx + sqy + sqz + sqw;
492
493 if (test > (0.5f - EPSILON_F32) * unit) { // singularity at north pole
494 euler.roll = 0;
495 euler.pitch = 2 * std::atan2(x, w);
496 euler.yaw = -static_cast<T>(M_PI2);
497 } else if (test < -(0.5f - EPSILON_F32) * unit) { // singularity at south pole
498 euler.roll = 0;
499 euler.pitch = -2 * std::atan2(x, w);
500 euler.yaw = static_cast<T>(M_PI2);
501 } else {
502 euler.roll = std::atan2(2 * x * y + 2 * w * z, sqw + sqx - sqy - sqz);
503 euler.pitch = std::atan2(2 * y * z + 2 * w * x, sqw - sqx - sqy + sqz);
504 euler.yaw = std::asin(-2 * (x * z - w * y));
505 }
506
507 return euler;
508}
509
510template <typename T>
512
513 mat3<T> rot;
514 for (U8 col = 0u; col < 3u; col++) {
515 rot.setCol(col, axis[col]);
516 }
517
518 fromMatrix(rot);
519}
520
521template <typename T>
522void Quaternion<T>::fromAxes(const vec3<T>& xAxis, const vec3<T>& yAxis, const vec3<T>& zAxis) {
523
524 mat3<T> rot;
525
526 rot.setCol(0, xAxis);
527 rot.setCol(1, yAxis);
528 rot.setCol(2, zAxis);
529
530 fromMatrix(rot);
531}
532
533template <typename T>
535 toAxes(axis[0], axis[1], axis[2]);
536}
537
538template <typename T>
539void Quaternion<T>::toAxes(vec3<T>& xAxis, vec3<T>& yAxis, vec3<T>& zAxis) const {
540 mat3<T> rot;
541 getMatrix(rot);
542 xAxis.set(rot.getCol(0));
543 yAxis.set(rot.getCol(1));
544 zAxis.set(rot.getCol(2));
545}
546
547template <typename T>
549 const T& x = X();
550 const T& y = Y();
551 const T& z = Z();
552 const T& w = W();
553
554 //T fTx = 2.0f*x;
555 const T fTy = 2.0f*y;
556 const T fTz = 2.0f*z;
557 const T fTwy = fTy*w;
558 const T fTwz = fTz*w;
559 const T fTxy = fTy*x;
560 const T fTxz = fTz*x;
561 const T fTyy = fTy*y;
562 const T fTzz = fTz*z;
563
564 return vec3<T>(1.0f - (fTyy + fTzz), fTxy + fTwz, fTxz - fTwy);
565}
566
567template <typename T>
569 const T& x = X();
570 const T& y = Y();
571 const T& z = Z();
572 const T& w = W();
573
574 const T fTx = 2.0f*x;
575 const T fTy = 2.0f*y;
576 const T fTz = 2.0f*z;
577 const T fTwx = fTx*w;
578 const T fTwz = fTz*w;
579 const T fTxx = fTx*x;
580 const T fTxy = fTy*x;
581 const T fTyz = fTz*y;
582 const T fTzz = fTz*z;
583
584 return vec3<T>(fTxy - fTwz, 1.0f - (fTxx + fTzz), fTyz + fTwx);
585}
586
587template <typename T>
589 const T& x = X();
590 const T& y = Y();
591 const T& z = Z();
592 const T& w = W();
593
594 const T fTx = 2.0f*x;
595 const T fTy = 2.0f*y;
596 const T fTz = 2.0f*z;
597 const T fTwx = fTx*w;
598 const T fTwy = fTy*w;
599 const T fTxx = fTx*x;
600 const T fTxz = fTz*x;
601 const T fTyy = fTy*y;
602 const T fTyz = fTz*y;
603
604 return vec3<T>(fTxz + fTwy, fTyz - fTwx, 1.0f - (fTxx + fTyy));
605}
606
607template <typename T>
608T Quaternion<T>::X() const noexcept {
609 return _elements.x;
610}
611
612template <typename T>
613T Quaternion<T>::Y() const noexcept {
614 return _elements.y;
615}
616
617template <typename T>
618T Quaternion<T>::Z() const noexcept {
619 return _elements.z;
620}
621
622template <typename T>
623T Quaternion<T>::W() const noexcept {
624 return _elements.w;
625}
626
627template <typename T>
628vec3<T> Quaternion<T>::XYZ() const noexcept {
629 return _elements.xyz;
630}
631
632template <typename T>
633template <typename U>
634void Quaternion<T>::X(U x) noexcept {
635 _elements.x = static_cast<T>(x);
636}
637
638template <typename T>
639template <typename U>
640void Quaternion<T>::Y(U y) noexcept {
641 _elements.y = static_cast<T>(y);
642}
643
644template <typename T>
645template <typename U>
646void Quaternion<T>::Z(U z) noexcept {
647 _elements.z = static_cast<T>(z);
648}
649
650template <typename T>
651template <typename U>
652void Quaternion<T>::W(U w) noexcept {
653 _elements.w = static_cast<T>(w);
654}
655
656template <typename T>
657void Quaternion<T>::identity() noexcept {
658 _elements.set(0, 0, 0, 1);
659}
660
661template <typename T>
662const vec4<T>& Quaternion<T>::asVec4() const noexcept {
663 return _elements;
664}
665
666
668template <typename T>
669Quaternion<T> RotationFromVToU(const vec3<T>& v, const vec3<T>& u, const vec3<T>& fallbackAxis) noexcept {
670 // Based on Stan Melax's article in Game Programming Gems
672 // Copy, since cannot modify local
673 vec3<T> v0 = v;
674 vec3<T> v1 = u;
675 v0.normalize();
676 v1.normalize();
677
678 T d = v0.dot(v1);
679 // If dot == 1, vectors are the same
680 if (d >= 1.0f) {
681 return q;
682 }
683
684 if (d < 1e-6f - 1.0f) {
685 if (!fallbackAxis.compare(VECTOR3_ZERO)) {
686 // rotate 180 degrees about the fallback axis
687 q.fromAxisAngle(fallbackAxis, M_PI_f);
688 } else {
689 // Generate an axis
690 vec3<T> axis;
691 axis.cross(WORLD_X_AXIS, v);
692
693 if (axis.isZeroLength()) // pick another if collinear
694 axis.cross(WORLD_Y_AXIS, v);
695
696 axis.normalize();
697 q.fromAxisAngle(axis, M_PI_f);
698 }
699 } else {
700 const F32 s = Divide::Sqrt((1 + d) * 2.0f);
701 const F32 invs = 1.f / s;
702
703 const vec3<T> c(Cross(v0, v1) * invs);
704 q.set(c.x, c.y, c.z, s * 0.5f);
705 q.normalize();
706 }
707
708 return q;
709}
710
711template <typename T>
712Quaternion<T> Slerp(const Quaternion<T>& q0, const Quaternion<T>& q1, F32 t) noexcept {
713 Quaternion<T> temp;
714 temp.slerp(q0, q1, t);
715 return temp;
716}
717
718template <typename T>
719mat3<T> GetMatrix(const Quaternion<T>& q) noexcept {
720 mat3<T> temp;
721 q.getMatrix(temp);
722 return temp;
723}
724
725template <typename T>
727 return q.getEuler();
728}
729
730template <typename T>
731vec3<T> operator*(vec3<T> const & v, Quaternion<T> const & q) {
732 return q.inverse() * v;
733}
734
735template <typename T>
736vec3<T> Rotate(vec3<T> const & v, Quaternion<T> const & q) noexcept {
737 const vec3<T> xyz = q.XYZ();
738 const vec3<T> t = Cross(xyz, v) * 2;
739 return v + q.W() * t + Cross(xyz, t);
740}
741
742template <typename T>
743vec3<T> DirectionFromAxis(const Quaternion<T>& q, const vec3<T>& AXIS) noexcept {
744 return Normalized(Rotate(AXIS, q));
745}
746
747template <typename T>
748vec3<T> DirectionFromEuler(vec3<Angle::DEGREES<T>> const & euler, const vec3<T>& FORWARD_DIRECTION) {
749 Quaternion<F32> q = {};
750 q.fromEuler(euler);
751 return DirectionFromAxis(q, FORWARD_DIRECTION);
752}
753} // namespace Divide
754
755#endif //DVD_QUATERNION_INL_
T magnituteSQ() const
Definition: Quaternion.inl:136
bool compare(const Quaternion &rq, Angle::DEGREES< T > tolerance=1e-3f) const
Definition: Quaternion.inl:141
Quaternion operator/(const Quaternion &rq) const
Dividing q1 by q2.
Definition: Quaternion.inl:198
bool operator==(const Quaternion &rq) const
Definition: Quaternion.inl:219
void fromMatrix(const mat3< T > &rotationMatrix) noexcept
Definition: Quaternion.inl:402
Quaternion & operator-=(const Quaternion &rq)
Definition: Quaternion.inl:235
T dot(const Quaternion &rq) const noexcept
Definition: Quaternion.inl:126
T X() const noexcept
Definition: Quaternion.inl:608
Quaternion getConjugate() const
We need to get the inverse of a quaternion to properly apply a.
Definition: Quaternion.inl:174
T Y() const noexcept
Definition: Quaternion.inl:613
vec3< T > xAxis() const noexcept
Definition: Quaternion.inl:548
void fromAxisAngle(const vec3< T > &v, Angle::DEGREES< T > angle) noexcept
Convert from Axis Angle.
Definition: Quaternion.inl:310
Quaternion & operator*=(const Quaternion &rq) noexcept
Multiply so that rotations are applied in a left to right order.
Definition: Quaternion.inl:192
void set(const vec4< T > &values) noexcept
Definition: Quaternion.inl:149
void fromAxes(const vec3< T > *axis)
X/Y/Z Axis get/set a la Ogre: OgreQuaternion.cpp.
Definition: Quaternion.inl:511
void getAxisAngle(vec3< T > &axis, Angle::DEGREES< T > &angle) const
Convert to Axis/Angles.
Definition: Quaternion.inl:472
Quaternion & operator/=(const Quaternion &rq)
Definition: Quaternion.inl:203
void getMatrix(mat3< T > &outMatrix) const noexcept
Convert to Matrix.
Definition: Quaternion.inl:442
Quaternion operator-(const Quaternion &rq) const
Definition: Quaternion.inl:260
Quaternion & operator+=(const Quaternion &rq)
Definition: Quaternion.inl:229
void toAxes(vec3< T > *axis) const
Definition: Quaternion.inl:534
const vec4< T > & asVec4() const noexcept
Definition: Quaternion.inl:662
void lookRotation(vec3< T > forward, vec3< T > up)
Definition: Quaternion.inl:341
Quaternion operator+(const Quaternion &rq) const
Definition: Quaternion.inl:253
T Z() const noexcept
Definition: Quaternion.inl:618
void identity() noexcept
Definition: Quaternion.inl:657
void normalize() noexcept
normalizing a quaternion works similar to a vector. This method will not
Definition: Quaternion.inl:164
Quaternion operator*(const Quaternion &rq) const noexcept
Definition: Quaternion.inl:179
void slerp(const Quaternion &q, F32 t) noexcept
Definition: Quaternion.inl:281
vec3< T > XYZ() const noexcept
Definition: Quaternion.inl:628
vec4< T > _elements
Definition: Quaternion.h:177
vec3< T > yAxis() const noexcept
Definition: Quaternion.inl:568
vec3< T > zAxis() const noexcept
Definition: Quaternion.inl:588
Quaternion() noexcept
Definition: Quaternion.inl:72
Quaternion inverse() const
Definition: Quaternion.inl:169
vec3< Angle::RADIANS< T > > getEuler() const noexcept
Definition: Quaternion.inl:478
bool operator!=(const Quaternion &rq) const
Definition: Quaternion.inl:224
void fromEuler(const vec3< Angle::DEGREES< T > > &v) noexcept
Definition: Quaternion.inl:316
Quaternion & operator=(const Quaternion &q) noexcept
Definition: Quaternion.inl:120
T W() const noexcept
Definition: Quaternion.inl:623
void setCol(I32 index, const vec3< U > &value) noexcept
vec3< T > getCol(I32 index) const noexcept
T dot(const vec3 &v) const noexcept
calculate the dot product between this vector and the specified one
vec3 & normalize() noexcept
transform the vector to unit length
bool isZeroLength() const noexcept
return true if length is zero
Definition: MathVectors.h:752
void cross(const vec3 &v1, const vec3 &v2) noexcept
set this vector to be equal to the cross of the 2 specified vectors
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:707
static __m128 multiplynew(const __m128 xyzw, const __m128 abcd) noexcept
Definition: Quaternion.inl:39
constexpr DEGREES< T > to_DEGREES(RADIANS< T > angle) noexcept
Definition: MathHelper.inl:380
constexpr RADIANS< T > to_RADIANS(DEGREES< T > angle) noexcept
Definition: MathHelper.inl:368
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr F32 M_PI_f
Definition: MathHelper.h:86
constexpr D64 M_PI2
Definition: MathHelper.h:84
vec2< T > Normalized(vec2< T > vector) noexcept
Definition: MathVectors.inl:98
Quaternion< T > Slerp(const Quaternion< T > &q0, const Quaternion< T > &q1, F32 t) noexcept
Definition: Quaternion.inl:712
vec2< T > operator*(T fl, vec2< T > v) noexcept
multiply a vector by a value
T Sqrt(T input) noexcept
Definition: MathHelper.inl:252
static const vec3< F32 > WORLD_X_AXIS
Definition: MathVectors.h:1439
Quaternion< T > RotationFromVToU(const vec3< T > &v, const vec3< T > &u, const vec3< T > &fallbackAxis=VECTOR3_ZERO) noexcept
get the shortest arc quaternion to rotate vector 'v' to the target vector 'u'(from Ogre3D!...
Definition: Quaternion.inl:669
uint8_t U8
constexpr F32 to_F32(const T value)
bool IS_TOLERANCE(const T X, const T TOLERANCE) noexcept
constexpr F32 EPSILON_F32
vec3< Angle::RADIANS< T > > GetEuler(const Quaternion< T > &q)
Definition: Quaternion.inl:726
vec3< T > DirectionFromAxis(const Quaternion< T > &q, const vec3< T > &AXIS) noexcept
Definition: Quaternion.inl:743
vec2< T > Normalize(vec2< T > &vector) noexcept
vec3< T > DirectionFromEuler(vec3< Angle::DEGREES< T > > const &euler, const vec3< T > &FORWARD_DIRECTION)
Definition: Quaternion.inl:748
bool COMPARE_TOLERANCE(const T X, const U Y, const T TOLERANCE) noexcept
vec2< T > Cross(vec2< T > v1, vec2< T > v2) noexcept
general vec2 cross function
Definition: MathVectors.inl:80
mat3< T > GetMatrix(const Quaternion< T > &q) noexcept
Definition: Quaternion.inl:719
static const vec3< F32 > VECTOR3_ZERO
Definition: MathVectors.h:1434
static const vec3< F32 > WORLD_Y_AXIS
Definition: MathVectors.h:1440
vec3< T > Rotate(vec3< T > const &v, Quaternion< T > const &q) noexcept
Definition: Quaternion.inl:736
float acosf(const float in)