Antkeeper  0.0.1
quaternion.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_MATH_QUATERNION_HPP
21 #define ANTKEEPER_MATH_QUATERNION_HPP
22 
23 #include <engine/math/numbers.hpp>
24 #include <engine/math/matrix.hpp>
25 #include <engine/math/vector.hpp>
26 #include <array>
27 #include <cmath>
28 #include <utility>
29 
30 namespace math {
31 
37 template <class T>
38 struct quaternion
39 {
41  using scalar_type = T;
42 
45 
48 
51 
54 
57  [[nodiscard]] inline constexpr scalar_type& w() noexcept
58  {
59  return r;
60  }
61  [[nodiscard]] inline constexpr const scalar_type& w() const noexcept
62  {
63  return r;
64  }
66 
69  [[nodiscard]] inline constexpr scalar_type& x() noexcept
70  {
71  return i.x();
72  }
73  [[nodiscard]] inline constexpr const scalar_type& x() const noexcept
74  {
75  return i.x();
76  }
78 
81  [[nodiscard]] inline constexpr scalar_type& y() noexcept
82  {
83  return i.y();
84  }
85  [[nodiscard]] inline constexpr const scalar_type& y() const noexcept
86  {
87  return i.y();
88  }
90 
93  [[nodiscard]] inline constexpr scalar_type& z() noexcept
94  {
95  return i.z();
96  }
97  [[nodiscard]] inline constexpr const scalar_type& z() const noexcept
98  {
99  return i.z();
100  }
102 
110  [[nodiscard]] static quaternion rotate_x(scalar_type angle)
111  {
112  return {std::cos(angle * T{0.5}), std::sin(angle * T{0.5}), T{0}, T{0}};
113  }
114 
122  [[nodiscard]] static quaternion rotate_y(scalar_type angle)
123  {
124  return {std::cos(angle * T{0.5}), T{0}, std::sin(angle * T{0.5}), T{0}};
125  }
126 
133  [[nodiscard]] static quaternion rotate_z(scalar_type angle)
134  {
135  return {std::cos(angle * T{0.5}), T{0}, T{0}, std::sin(angle * T{0.5})};
136  }
137 
145  template <class U>
146  [[nodiscard]] inline constexpr explicit operator quaternion<U>() const noexcept
147  {
148  return {static_cast<U>(r), vec3<U>(i)};
149  }
150 
157  [[nodiscard]] constexpr explicit operator matrix_type() const noexcept
158  {
159  const T xx = x() * x();
160  const T xy = x() * y();
161  const T xz = x() * z();
162  const T xw = x() * w();
163  const T yy = y() * y();
164  const T yz = y() * z();
165  const T yw = y() * w();
166  const T zz = z() * z();
167  const T zw = z() * w();
168 
169  return
170  {
171  T{1} - (yy + zz) * T{2}, (xy + zw) * T{2}, (xz - yw) * T{2},
172  (xy - zw) * T{2}, T{1} - (xx + zz) * T{2}, (yz + xw) * T{2},
173  (xz + yw) * T{2}, (yz - xw) * T{2}, T{1} - (xx + yy) * T{2}
174  };
175  }
176 
177  [[nodiscard]] inline constexpr matrix_type matrix() const noexcept
178  {
179  return matrix_type(*this);
180  }
182 
188  [[nodiscard]] inline constexpr explicit operator vec4<T>() const noexcept
189  {
190  return {r, i.x(), i.y(), i.z()};
191  }
192 
194  [[nodiscard]] static constexpr quaternion zero() noexcept
195  {
196  return {};
197  }
198 
200  [[nodiscard]] static constexpr quaternion identity() noexcept
201  {
202  return {T{1}, vector_type::zero()};
203  }
204 };
205 
207 namespace quaternion_types {
208 
210 template <class T>
212 
219 
226 
227 } // namespace quaternion_types
228 
229 // Bring quaternion types into math namespace
230 using namespace quaternion_types;
231 
232 // Bring quaternion types into math::types namespace
233 namespace types { using namespace math::quaternion_types; }
234 
243 template <class T>
244 [[nodiscard]] constexpr quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept;
245 
254 template <class T>
255 [[nodiscard]] constexpr quaternion<T> add(const quaternion<T>& a, T b) noexcept;
256 
264 template <class T>
265 [[nodiscard]] constexpr quaternion<T> conjugate(const quaternion<T>& q) noexcept;
266 
275 template <class T>
276 [[nodiscard]] constexpr T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept;
277 
286 template <class T>
287 [[nodiscard]] constexpr quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept;
288 
297 template <class T>
298 [[nodiscard]] constexpr quaternion<T> div(const quaternion<T>& a, T b) noexcept;
299 
308 template <class T>
309 [[nodiscard]] constexpr quaternion<T> div(T a, const quaternion<T>& b) noexcept;
310 
318 template <class T>
319 [[nodiscard]] T inv_length(const quaternion<T>& q);
320 
328 template <class T>
329 [[nodiscard]] T length(const quaternion<T>& q);
330 
340 template <class T>
341 [[nodiscard]] constexpr quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept;
342 
351 template <class T>
352 [[nodiscard]] quaternion<T> look_rotation(const vec3<T>& forward, vec3<T> up);
353 
362 template <class T>
363 [[nodiscard]] constexpr quaternion<T> mul(const quaternion<T>& a, const quaternion<T>& b) noexcept;
364 
373 template <class T>
374 [[nodiscard]] constexpr quaternion<T> mul(const quaternion<T>& a, T b) noexcept;
375 
388 template <class T>
389 [[nodiscard]] constexpr vec3<T> mul(const quaternion<T>& q, const vec3<T>& v) noexcept;
390 
401 template <class T>
402 [[nodiscard]] constexpr vec3<T> mul(const vec3<T>& v, const quaternion<T>& q) noexcept;
403 
411 template <class T>
412 [[nodiscard]] constexpr quaternion<T> negate(const quaternion<T>& q) noexcept;
413 
423 template <class T>
424 [[nodiscard]] quaternion<T> nlerp(const quaternion<T>& a, const quaternion<T>& b, T t);
425 
433 template <class T>
434 [[nodiscard]] quaternion<T> normalize(const quaternion<T>& q);
435 
444 template <class T>
445 [[nodiscard]] quaternion<T> angle_axis(T angle, const vec3<T>& axis);
446 
458 template <class T>
459 [[nodiscard]] quaternion<T> rotation(const vec3<T>& from, const vec3<T>& to, T tolerance = T{1e-6});
460 
472 template <class T>
473 [[nodiscard]] quaternion<T> rotate_towards(const vec3<T>& from, const vec3<T>& to, T max_angle);
474 
485 template <class T>
486 [[nodiscard]] quaternion<T> slerp(const quaternion<T>& a, const quaternion<T>& b, T t, T tolerance = T{1e-6});
487 
495 template <class T>
496 [[nodiscard]] constexpr T sqr_length(const quaternion<T>& q) noexcept;
497 
506 template <class T>
507 [[nodiscard]] constexpr quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept;
508 
518 template <class T>
519 [[nodiscard]] constexpr quaternion<T> sub(const quaternion<T>& a, T b) noexcept;
520 template <class T>
521 [[nodiscard]] constexpr quaternion<T> sub(T a, const quaternion<T>& b) noexcept;
523 
540 template <class T>
541 [[nodiscard]] std::array<quaternion<T>, 2> swing_twist(const quaternion<T>& q, const vec3<T>& twist_axis, T tolerance = T{1e-6});
542 
550 template <class T>
551 [[nodiscard]] quaternion<T> quaternion_cast(const mat3<T>& m);
552 
553 template <class T>
554 inline constexpr quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept
555 {
556  return {a.r + b.r, a.i + b.i};
557 }
558 
559 template <class T>
560 inline constexpr quaternion<T> add(const quaternion<T>& a, T b) noexcept
561 {
562  return {a.r + b, a.i + b};
563 }
564 
565 template <class T>
566 inline constexpr quaternion<T> conjugate(const quaternion<T>& q) noexcept
567 {
568  return {q.r, -q.i};
569 }
570 
571 template <class T>
572 inline constexpr T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept
573 {
574  return a.r * b.r + dot(a.i, b.i);
575 }
576 
577 template <class T>
578 inline constexpr quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept
579 {
580  return {a.r / b.r, a.i / b.i};
581 }
582 
583 template <class T>
584 inline constexpr quaternion<T> div(const quaternion<T>& a, T b) noexcept
585 {
586  return {a.r / b, a.i / b};
587 }
588 
589 template <class T>
590 inline constexpr quaternion<T> div(T a, const quaternion<T>& b) noexcept
591 {
592  return {a / b.r, a / b.i};
593 }
594 
595 template <class T>
596 inline T inv_length(const quaternion<T>& q)
597 {
598  return T{1} / length(q);
599 }
600 
601 template <class T>
602 inline T length(const quaternion<T>& q)
603 {
604  return std::sqrt(sqr_length(q));
605 }
606 
607 template <class T>
608 inline constexpr quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept
609 {
610  return
611  {
612  (b.r - a.r) * t + a.r,
613  (b.i - a.i) * t + a.i
614  };
615 }
616 
617 template <class T>
619 {
620  const vec3<T> right = normalize(cross(forward, up));
621  up = cross(right, forward);
622 
623  const mat3<T> m =
624  {
625  right,
626  up,
627  -forward
628  };
629 
630  // Convert to quaternion
631  return normalize(quaternion_cast(m));
632 }
633 
634 template <class T>
635 constexpr quaternion<T> mul(const quaternion<T>& a, const quaternion<T>& b) noexcept
636 {
637  return
638  {
639  a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
640  a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
641  a.w() * b.y() - a.x() * b.z() + a.y() * b.w() + a.z() * b.x(),
642  a.w() * b.z() + a.x() * b.y() - a.y() * b.x() + a.z() * b.w()
643  };
644 }
645 
646 template <class T>
647 inline constexpr quaternion<T> mul(const quaternion<T>& a, T b) noexcept
648 {
649  return {a.r * b, a.i * b};
650 }
651 
652 template <class T>
653 constexpr vec3<T> mul(const quaternion<T>& q, const vec3<T>& v) noexcept
654 {
655  const auto t = cross(q.i, v) * T{2};
656  return v + q.r * t + cross(q.i, t);
657 }
658 
659 template <class T>
660 inline constexpr vec3<T> mul(const vec3<T>& v, const quaternion<T>& q) noexcept
661 {
662  const auto t = cross(v, q.i) * T{2};
663  return v + q.r * t + cross(t, q.i);
664 }
665 
666 template <class T>
667 inline constexpr quaternion<T> negate(const quaternion<T>& q) noexcept
668 {
669  return {-q.r, -q.i};
670 }
671 
672 template <class T>
674 {
675  return normalize(add(mul(a, T{1} - t), mul(b, std::copysign(t, dot(a, b)))));
676 }
677 
678 template <class T>
680 {
681  return mul(q, inv_length(q));
682 }
683 
684 template <class T>
686 {
687  return {std::cos(angle * T{0.5}), axis * std::sin(angle * T{0.5})};
688 }
689 
690 template <class T>
691 quaternion<T> rotation(const vec3<T>& from, const vec3<T>& to, T tolerance)
692 {
693  const auto cos_theta = dot(from, to);
694 
695  if (cos_theta <= T{-1} + tolerance)
696  {
697  // Direction vectors are opposing, return 180 degree rotation about arbitrary axis
698  return quaternion<T>{T{0}, {T{1}, T{0}, T{0}}};
699  }
700  else if (cos_theta >= T{1} - tolerance)
701  {
702  // Direction vectors are parallel, return identity quaternion
703  return quaternion<T>::identity();
704  }
705  else
706  {
707  const auto r = cos_theta + T{1};
708  const auto i = cross(from, to);
709  const auto inv_length = T{1.0} / std::sqrt(r + r);
710 
711  return quaternion<T>{r * inv_length, i * inv_length};
712  }
713 }
714 
715 template <class T>
716 quaternion<T> rotate_towards(const vec3<T>& from, const vec3<T>& to, T max_angle)
717 {
718  const auto angle = std::acos(dot(from, to));
719  const auto axis = cross(from, to);
720  return angle_axis(std::min(max_angle, angle), axis);
721 }
722 
723 template <class T>
724 quaternion<T> slerp(const quaternion<T>& a, const quaternion<T>& b, T t, T tolerance)
725 {
726  T cos_theta = dot(a, b);
727  if (cos_theta >= T{1} - tolerance)
728  {
729  // Use linear interpolation if quaternions are nearly aligned
730  return normalize(lerp(a, b, t));
731  }
732 
733  // Clamp to acos domain
734  cos_theta = std::min<T>(std::max<T>(cos_theta, T{-1}), T{1});
735 
736  const T theta = std::acos(cos_theta) * t;
737 
738  const quaternion<T> c = normalize(sub(b, mul(a, cos_theta)));
739 
740  return add(mul(a, std::cos(theta)), mul(c, std::sin(theta)));
741 }
742 
743 template <class T>
744 inline constexpr T sqr_length(const quaternion<T>& q) noexcept
745 {
746  return q.r * q.r + sqr_length(q.i);
747 }
748 
749 template <class T>
750 inline constexpr quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept
751 {
752  return {a.r - b.r, a.i - b.i};
753 }
754 
755 template <class T>
756 inline constexpr quaternion<T> sub(const quaternion<T>& a, T b) noexcept
757 {
758  return {a.r - b, a.i - b};
759 }
760 
761 template <class T>
762 inline constexpr quaternion<T> sub(T a, const quaternion<T>& b) noexcept
763 {
764  return {a - b.r, a - b.i};
765 }
766 
767 template <class T>
768 std::array<quaternion<T>, 2> swing_twist(const quaternion<T>& q, const vec3<T>& twist_axis, T tolerance)
769 {
770  quaternion<T> swing;
771  quaternion<T> twist;
772 
773  if (sqr_length(q.i) <= tolerance)
774  {
775  // Singularity, rotate 180 degrees about twist axis
776  twist = angle_axis(pi<T>, twist_axis);
777 
778  const auto rotated_twist_axis = mul(q, twist_axis);
779  const auto swing_axis = cross(twist_axis, rotated_twist_axis);
780  const auto swing_axis_sqr_length = sqr_length(swing_axis);
781 
782  if (swing_axis_sqr_length <= tolerance)
783  {
784  // Swing axis and twist axis are parallel, no swing
785  swing = quaternion<T>::identity();
786  }
787  else
788  {
789  const auto cos_swing_angle = std::min<T>(std::max<T>(dot(twist_axis, rotated_twist_axis), T{-1}), T{1});
790  swing = angle_axis(std::acos(cos_swing_angle), swing_axis * (T{1} / std::sqrt(swing_axis_sqr_length)));
791  }
792  }
793  else
794  {
795  twist = normalize(quaternion<T>{q.r, twist_axis * dot(twist_axis, q.i)});
796  swing = mul(q, conjugate(twist));
797  }
798 
799  return {std::move(swing), std::move(twist)};
800 }
801 
802 template <class T>
804 {
805  const T t = trace(m);
806 
807  if (t > T{0})
808  {
809  const T s = T{0.5} / std::sqrt(t + T{1});
810  return
811  {
812  T{0.25} / s,
813  (m[1][2] - m[2][1]) * s,
814  (m[2][0] - m[0][2]) * s,
815  (m[0][1] - m[1][0]) * s
816  };
817  }
818  else
819  {
820  if (m[0][0] > m[1][1] && m[0][0] > m[2][2])
821  {
822  const T s = T{2} * std::sqrt(T{1} + m[0][0] - m[1][1] - m[2][2]);
823 
824  return
825  {
826  (m[1][2] - m[2][1]) / s,
827  T{0.25} * s,
828  (m[1][0] + m[0][1]) / s,
829  (m[2][0] + m[0][2]) / s
830  };
831  }
832  else if (m[1][1] > m[2][2])
833  {
834  const T s = T{2} * std::sqrt(T{1} + m[1][1] - m[0][0] - m[2][2]);
835  return
836  {
837  (m[2][0] - m[0][2]) / s,
838  (m[1][0] + m[0][1]) / s,
839  T{0.25} * s,
840  (m[2][1] + m[1][2]) / s
841  };
842  }
843  else
844  {
845  const T s = T{2} * std::sqrt(T{1} + m[2][2] - m[0][0] - m[1][1]);
846  return
847  {
848  (m[0][1] - m[1][0]) / s,
849  (m[2][0] + m[0][2]) / s,
850  (m[2][1] + m[1][2]) / s,
851  T{0.25} * s
852  };
853  }
854  }
855 }
856 
857 namespace operators {
858 
860 template <class T>
861 inline constexpr quaternion<T> operator+(const quaternion<T>& a, const quaternion<T>& b) noexcept
862 {
863  return add(a, b);
864 }
865 
868 template <class T>
869 inline constexpr quaternion<T> operator+(const quaternion<T>& a, T b) noexcept
870 {
871  return add(a, b);
872 }
873 template <class T>
874 inline constexpr quaternion<T> operator+(T a, const quaternion<T>& b) noexcept
875 {
876  return add(b, a);
877 }
879 
881 template <class T>
882 inline constexpr quaternion<T> operator/(const quaternion<T>& a, const quaternion<T>& b) noexcept
883 {
884  return div(a, b);
885 }
886 
888 template <class T>
889 inline constexpr quaternion<T> operator/(const quaternion<T>& a, T b) noexcept
890 {
891  return div(a, b);
892 }
893 
895 template <class T>
896 inline constexpr quaternion<T> operator/(T a, const quaternion<T>& b) noexcept
897 {
898  return div(a, b);
899 }
900 
902 template <class T>
903 inline constexpr quaternion<T> operator*(const quaternion<T>& a, const quaternion<T>& b) noexcept
904 {
905  return mul(a, b);
906 }
907 
910 template <class T>
911 inline constexpr quaternion<T> operator*(const quaternion<T>& a, T b) noexcept
912 {
913  return mul(a, b);
914 }
915 template <class T>
916 inline constexpr quaternion<T> operator*(T a, const quaternion<T>& b) noexcept
917 {
918  return mul(b, a);
919 }
921 
923 template <class T>
924 inline constexpr vec3<T> operator*(const quaternion<T>& q, const vec3<T>& v) noexcept
925 {
926  return mul(q, v);
927 }
928 
930 template <class T>
931 inline constexpr vec3<T> operator*(const vec3<T>& v, const quaternion<T>& q) noexcept
932 {
933  return mul(v, q);
934 }
935 
937 template <class T>
938 inline constexpr quaternion<T> operator-(const quaternion<T>& a, const quaternion<T>& b) noexcept
939 {
940  return sub(a, b);
941 }
942 
945 template <class T>
946 inline constexpr quaternion<T> operator-(const quaternion<T>& a, T b) noexcept
947 {
948  return sub(a, b);
949 }
950 template <class T>
951 inline constexpr quaternion<T> operator-(T a, const quaternion<T>& b) noexcept
952 {
953  return sub(a, b);
954 }
956 
958 template <class T>
959 inline constexpr quaternion<T> operator-(const quaternion<T>& q) noexcept
960 {
961  return negate(q);
962 }
963 
973 template <class T>
974 inline constexpr quaternion<T>& operator+=(quaternion<T>& a, const quaternion<T>& b) noexcept
975 {
976  return (a = a + b);
977 }
978 template <class T>
979 inline constexpr quaternion<T>& operator+=(quaternion<T>& a, T b) noexcept
980 {
981  return (a = a + b);
982 }
984 
994 template <class T>
995 inline constexpr quaternion<T>& operator-=(quaternion<T>& a, const quaternion<T>& b) noexcept
996 {
997  return (a = a - b);
998 }
999 template <class T>
1000 inline constexpr quaternion<T>& operator-=(quaternion<T>& a, T b) noexcept
1001 {
1002  return (a = a - b);
1003 }
1005 
1015 template <class T>
1016 inline constexpr quaternion<T>& operator*=(quaternion<T>& a, const quaternion<T>& b) noexcept
1017 {
1018  return (a = a * b);
1019 }
1020 template <class T>
1021 inline constexpr quaternion<T>& operator*=(quaternion<T>& a, T b) noexcept
1022 {
1023  return (a = a * b);
1024 }
1026 
1036 template <class T>
1037 inline constexpr quaternion<T>& operator/=(quaternion<T>& a, const quaternion<T>& b) noexcept
1038 {
1039  return (a = a / b);
1040 }
1041 template <class T>
1042 inline constexpr quaternion<T>& operator/=(quaternion<T>& a, T b) noexcept
1043 {
1044  return (a = a / b);
1045 }
1047 
1048 } // namespace operators
1049 
1050 } // namespace math
1051 
1052 // Bring quaternion operators into global namespace
1053 using namespace math::operators;
1054 
1055 #endif // ANTKEEPER_MATH_QUATERNION_HPP
constexpr T e
e.
Definition: numbers.hpp:37
Mathematical operators.
constexpr quaternion< T > operator-(const quaternion< T > &q) noexcept
Negates a quaternion.
Definition: quaternion.hpp:959
constexpr vec3< T > operator*(const vec3< T > &v, const quaternion< T > &q) noexcept
Rotates a vector by the inverse of a unit quaternion.
Definition: quaternion.hpp:931
constexpr quaternion< T > & operator/=(quaternion< T > &a, T b) noexcept
Divides the first value by the second value and stores the result in the first value.
constexpr quaternion< T > operator+(T a, const quaternion< T > &b) noexcept
Definition: quaternion.hpp:874
constexpr quaternion< T > operator/(T a, const quaternion< T > &b) noexcept
Divides a scalar by a quaternion.
Definition: quaternion.hpp:896
constexpr quaternion< T > & operator-=(quaternion< T > &a, T b) noexcept
Subtracts the first value by the second value and stores the result in the first value.
constexpr quaternion< T > & operator*=(quaternion< T > &a, T b) noexcept
Multiplies two values and stores the result in the first value.
constexpr quaternion< T > & operator+=(quaternion< T > &a, T b) noexcept
Adds two values and stores the result in the first value.
Definition: quaternion.hpp:979
Quaternion types.
Definition: quaternion.hpp:207
Mathematical functions and data types.
Definition: angles.hpp:26
quaternion< T > nlerp(const quaternion< T > &a, const quaternion< T > &b, T t)
Performs normalized linear interpolation between two quaternions.
Definition: quaternion.hpp:673
quaternion< T > rotate_towards(const vec3< T > &from, const vec3< T > &to, T max_angle)
Constructs a quaternion representing an angle-limited rotation from one direction towards another dir...
Definition: quaternion.hpp:716
quaternion< T > quaternion_cast(const mat3< T > &m)
Converts a 3x3 rotation matrix to a quaternion.
Definition: quaternion.hpp:803
constexpr matrix< T, P, M > mul(const matrix< T, N, M > &a, const matrix< T, P, N > &b) noexcept
Multiplies two matrices.
T angle(const vector< T, N > &from, const vector< T, N > &to)
Calculates the angle between two direction vectors.
Definition: vector.hpp:1030
constexpr T trace(const matrix< T, N, N > &m) noexcept
Calculates the trace of a square matrix.
quaternion< T > slerp(const quaternion< T > &a, const quaternion< T > &b, T t, T tolerance=T{1e-6})
Performs spherical linear interpolation between two quaternions.
Definition: quaternion.hpp:724
quaternion< T > normalize(const quaternion< T > &q)
Normalizes a quaternion.
Definition: quaternion.hpp:679
constexpr matrix< T, N, M > div(const matrix< T, N, M > &a, const matrix< T, N, M > &b) noexcept
Divides a matrix by a matrix.
quaternion< T > angle_axis(T angle, const vec3< T > &axis)
Creates a rotation from an angle and axis.
Definition: quaternion.hpp:685
T length(const quaternion< T > &q)
Calculates the length of a quaternion.
Definition: quaternion.hpp:602
quaternion< T > look_rotation(const vec3< T > &forward, vec3< T > up)
Creates a unit quaternion rotation using forward and up vectors.
Definition: quaternion.hpp:618
constexpr matrix< T, N, M > add(const matrix< T, N, M > &a, const matrix< T, N, M > &b) noexcept
Adds two matrices.
quaternion< T > rotation(const vec3< T > &from, const vec3< T > &to, T tolerance=T{1e-6})
Constructs a quaternion representing the minimum rotation from one direction to another direction.
Definition: quaternion.hpp:691
constexpr T sqr_length(const quaternion< T > &q) noexcept
Calculates the square length of a quaternion.
Definition: quaternion.hpp:744
constexpr matrix< T, N, M > sub(const matrix< T, N, M > &a, const matrix< T, N, M > &b) noexcept
Subtracts a matrix from another matrix.
std::array< quaternion< T >, 2 > swing_twist(const quaternion< T > &q, const vec3< T > &twist_axis, T tolerance=T{1e-6})
Decomposes a quaternion into swing and twist rotation components.
Definition: quaternion.hpp:768
constexpr quaternion< T > conjugate(const quaternion< T > &q) noexcept
Calculates the conjugate of a quaternion.
Definition: quaternion.hpp:566
constexpr vector< T, 3 > cross(const vector< T, 3 > &x, const vector< T, 3 > &y) noexcept
Calculates the cross product of two vectors.
Definition: vector.hpp:1095
vector< T, N > sqrt(const vector< T, N > &x)
Takes the square root of each element.
constexpr T lerp(const T &x, const T &y, S a) noexcept
Linearly interpolates between x and y.
constexpr T dot(const quaternion< T > &a, const quaternion< T > &b) noexcept
Calculates the dot product of two quaternions.
Definition: quaternion.hpp:572
T inv_length(const quaternion< T > &q)
Calculates the inverse length of a quaternion.
Definition: quaternion.hpp:596
constexpr vector< T, N > min(const vector< T, N > &x, const vector< T, N > &y)
Returns a vector containing the minimum elements of two vectors.
Definition: vector.hpp:1347
constexpr quaternion< T > negate(const quaternion< T > &q) noexcept
Negates a quaternion.
Definition: quaternion.hpp:667
n by m column-major matrix.
Definition: math/matrix.hpp:44
Quaternion composed of a real scalar part and imaginary vector part.
Definition: quaternion.hpp:39
constexpr const scalar_type & w() const noexcept
Returns a reference to the quaternion real part.
Definition: quaternion.hpp:61
mat3< T > matrix_type
Rotation matrix type.
Definition: quaternion.hpp:47
scalar_type r
Quaternion real part.
Definition: quaternion.hpp:50
constexpr matrix_type matrix() const noexcept
Constructs a matrix representing the rotation described by the quaternion.
Definition: quaternion.hpp:177
constexpr scalar_type & w() noexcept
Returns a reference to the quaternion real part.
Definition: quaternion.hpp:57
constexpr const scalar_type & x() const noexcept
Returns a reference to the first element of the quaternion imaginary part.
Definition: quaternion.hpp:73
static quaternion rotate_z(scalar_type angle)
Returns a quaternion representing a rotation about the z-axis.
Definition: quaternion.hpp:133
static constexpr quaternion zero() noexcept
Returns a zero quaternion, where every scalar is equal to zero.
Definition: quaternion.hpp:194
T scalar_type
Scalar type.
Definition: quaternion.hpp:41
static quaternion rotate_x(scalar_type angle)
Returns a quaternion representing a rotation about the x-axis.
Definition: quaternion.hpp:110
vector_type i
Quaternion imaginary part.
Definition: quaternion.hpp:53
static quaternion rotate_y(scalar_type angle)
Returns a quaternion representing a rotation about the y-axis.
Definition: quaternion.hpp:122
constexpr const scalar_type & z() const noexcept
Returns a reference to the third element of the quaternion imaginary part.
Definition: quaternion.hpp:97
constexpr scalar_type & y() noexcept
Returns a reference to the second element of the quaternion imaginary part.
Definition: quaternion.hpp:81
constexpr scalar_type & z() noexcept
Returns a reference to the third element of the quaternion imaginary part.
Definition: quaternion.hpp:93
static constexpr quaternion identity() noexcept
Returns a rotation identity quaternion.
Definition: quaternion.hpp:200
constexpr scalar_type & x() noexcept
Returns a reference to the first element of the quaternion imaginary part.
Definition: quaternion.hpp:69
constexpr const scalar_type & y() const noexcept
Returns a reference to the second element of the quaternion imaginary part.
Definition: quaternion.hpp:85
n-dimensional vector.
Definition: vector.hpp:44
constexpr element_type & x() noexcept
Returns a reference to the first element.
Definition: vector.hpp:164
constexpr element_type & y() noexcept
Returns a reference to the second element.
Definition: vector.hpp:180
static constexpr vector zero() noexcept
Returns a zero vector, where every element is equal to zero.
Definition: vector.hpp:306
constexpr element_type & z() noexcept
Returns a reference to the third element.
Definition: vector.hpp:196