UFO 1.0.0
An Efficient Probabilistic 3D Mapping Framework That Embraces the Unknown
Loading...
Searching...
No Matches
quat.hpp
1
41#ifndef UFO_NUMERIC_QUAT_HPP
42#define UFO_NUMERIC_QUAT_HPP
43
44// UFO
45#include <ufo/numeric/mat.hpp>
46#include <ufo/numeric/vec.hpp>
47
48// STL
49#include <algorithm>
50#include <cassert>
51#include <cmath>
52#include <concepts>
53#include <format>
54#include <limits>
55#include <numbers>
56#include <ostream>
57
63namespace ufo
64{
65
75template <std::floating_point T = float>
76struct Quat {
77 using value_type = T;
78 using size_type = std::size_t;
79
84 T w{1}; // Real (scalar) part.
85 T x{}; // First imaginary component.
86 T y{}; // Second imaginary component.
87 T z{}; // Third imaginary component.
88
89 /**************************************************************************************
90 | |
91 | Constructors |
92 | |
93 **************************************************************************************/
94
98 constexpr Quat() noexcept = default;
99
103 constexpr Quat(Quat const&) noexcept = default;
104
111 template <std::floating_point U>
112 constexpr explicit(!std::is_same_v<T, U>) Quat(Quat<U> const& q) noexcept
113 : w(static_cast<T>(q.w))
114 , x(static_cast<T>(q.x))
115 , y(static_cast<T>(q.y))
116 , z(static_cast<T>(q.z))
117 {
118 }
119
127 constexpr Quat(T w, T x, T y, T z) noexcept : w(w), x(x), y(y), z(z) {}
128
136 Quat(Vec<3, T> const& u, Vec<3, T> const& v)
137 {
138 T norm_u_norm_v = std::sqrt(dot(u, u) * dot(v, v));
139 T real_part = norm_u_norm_v + dot(u, v);
140 Vec<3, T> t;
141
142 if (real_part < T(1.e-6) * norm_u_norm_v) {
143 real_part = T(0);
144 t = std::abs(u[0]) > std::abs(u[2]) ? Vec<3, T>(-u[1], u[0], T(0))
145 : Vec<3, T>(T(0), -u[2], u[1]);
146 } else {
147 t = cross(u, v);
148 }
149
150 *this = normalize(Quat<T>(real_part, t[0], t[1], t[2]));
151 }
152
158 explicit Quat(Vec<3, T> const& euler_angles)
159 {
160 Vec<3, T> const c{std::cos(euler_angles[0] * T(0.5)),
161 std::cos(euler_angles[1] * T(0.5)),
162 std::cos(euler_angles[2] * T(0.5))};
163 Vec<3, T> const s{std::sin(euler_angles[0] * T(0.5)),
164 std::sin(euler_angles[1] * T(0.5)),
165 std::sin(euler_angles[2] * T(0.5))};
166
167 w = c[0] * c[1] * c[2] + s[0] * s[1] * s[2];
168 x = s[0] * c[1] * c[2] - c[0] * s[1] * s[2];
169 y = c[0] * s[1] * c[2] + s[0] * c[1] * s[2];
170 z = c[0] * c[1] * s[2] - s[0] * s[1] * c[2];
171 }
172
178 constexpr Quat(Mat<3, 3, T> const& m) noexcept
179 {
180 T const trace = m[0][0] + m[1][1] + m[2][2];
181
182 if (trace > T(0)) {
183 T s = std::sqrt(trace + T(1));
184 w = s * T(0.5);
185 s = T(0.5) / s;
186 // Row-major: m[row][col] — x = (R_{2,1} - R_{1,2}) * s
187 x = (m[2][1] - m[1][2]) * s;
188 y = (m[0][2] - m[2][0]) * s;
189 z = (m[1][0] - m[0][1]) * s;
190 } else {
191 unsigned const i = m[0][0] < m[1][1] ? (m[1][1] < m[2][2] ? 2u : 1u)
192 : (m[0][0] < m[2][2] ? 2u : 0u);
193 unsigned const j = (i + 1u) % 3u;
194 unsigned const k = (i + 2u) % 3u;
195
196 T q[4]{};
197 T s = std::sqrt(m[i][i] - m[j][j] - m[k][k] + T(1));
198 q[i + 1] = s * T(0.5);
199 s = T(0.5) / s;
200 q[0] = (m[k][j] - m[j][k]) * s; // row-major: swap j,k vs column-major
201 q[j + 1] = (m[j][i] + m[i][j]) * s; // symmetric — same as column-major
202 q[k + 1] = (m[k][i] + m[i][k]) * s;
203 w = q[0];
204 x = q[1];
205 y = q[2];
206 z = q[3];
207 }
208 }
209
214 constexpr Quat(Mat<4, 4, T> const& m) noexcept : Quat(Mat<3, 3, T>(m)) {}
215
216 /**************************************************************************************
217 | |
218 | Assignment operator |
219 | |
220 **************************************************************************************/
221
226 constexpr Quat& operator=(Quat const&) noexcept = default;
227
234 template <std::floating_point U>
235 constexpr Quat& operator=(Quat<U> const& rhs) noexcept
236 {
237 w = static_cast<T>(rhs.w);
238 x = static_cast<T>(rhs.x);
239 y = static_cast<T>(rhs.y);
240 z = static_cast<T>(rhs.z);
241 return *this;
242 }
243
244 /**************************************************************************************
245 | |
246 | Conversion operator |
247 | |
248 **************************************************************************************/
249
255 [[nodiscard]] constexpr explicit operator Mat<3, 3, T>() const noexcept
256 {
257 T const xx(x * x), yy(y * y), zz(z * z);
258 T const xz(x * z), xy(x * y), yz(y * z);
259 T const wx(w * x), wy(w * y), wz(w * z);
260
261 return Mat<3, 3, T>(
262 Vec<3, T>(T(1) - T(2) * (yy + zz), T(2) * (xy - wz), T(2) * (xz + wy)),
263 Vec<3, T>(T(2) * (xy + wz), T(1) - T(2) * (xx + zz), T(2) * (yz - wx)),
264 Vec<3, T>(T(2) * (xz - wy), T(2) * (yz + wx), T(1) - T(2) * (xx + yy)));
265 }
266
272 [[nodiscard]] constexpr explicit operator Mat<4, 4, T>() const noexcept
273 {
274 // TODO: Should we add a constructor for this?
275 Mat<4, 4, T> m(Mat<3, 3, T>(*this));
276 m[3][3] = T(1);
277 return m;
278 }
279
280 /**************************************************************************************
281 | |
282 | Element access |
283 | |
284 **************************************************************************************/
285
292 [[nodiscard]] constexpr auto& operator[](this auto& self, size_type pos) noexcept
293 {
294 assert(4 > pos);
295 switch (pos) {
296 case 0: return self.w;
297 case 1: return self.x;
298 case 2: return self.y;
299 default: return self.z;
300 }
301 }
302
303 /**************************************************************************************
304 | |
305 | Compound assignment operator |
306 | |
307 **************************************************************************************/
308
314 constexpr Quat& operator+=(Quat const& q) noexcept
315 {
316 w += q.w;
317 x += q.x;
318 y += q.y;
319 z += q.z;
320 return *this;
321 }
322
328 constexpr Quat& operator-=(Quat const& q) noexcept
329 {
330 w -= q.w;
331 x -= q.x;
332 y -= q.y;
333 z -= q.z;
334 return *this;
335 }
336
342 constexpr Quat& operator*=(Quat const& q) noexcept
343 {
344 Quat const p(*this);
345 w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z;
346 x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y;
347 y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z;
348 z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x;
349 return *this;
350 }
351
357 constexpr Quat& operator*=(T s) noexcept
358 {
359 w *= s;
360 x *= s;
361 y *= s;
362 z *= s;
363 return *this;
364 }
365
371 constexpr Quat& operator/=(T s) noexcept
372 {
373 w /= s;
374 x /= s;
375 y /= s;
376 z /= s;
377 return *this;
378 }
379
380 /**************************************************************************************
381 | |
382 | Capacity |
383 | |
384 **************************************************************************************/
385
390 [[nodiscard]] static constexpr size_type size() noexcept { return 4; }
391
392 /**************************************************************************************
393 | |
394 | Operations |
395 | |
396 **************************************************************************************/
397
402 void swap(Quat& other) noexcept
403 {
404 using std::swap;
405 swap(w, other.w);
406 swap(x, other.x);
407 swap(y, other.y);
408 swap(z, other.z);
409 }
410
418 constexpr bool operator==(Quat const&) const noexcept = default;
419};
420
421/**************************************************************************************
422| |
423| Aliases |
424| |
425**************************************************************************************/
426
427using Quatf = Quat<float>;
428using Quatd = Quat<double>;
429
430/**************************************************************************************
431| |
432| Unary operators |
433| |
434**************************************************************************************/
435
442template <std::floating_point T>
443[[nodiscard]] constexpr Quat<T> operator+(Quat<T> const& q) noexcept
444{
445 return q;
446}
447
454template <std::floating_point T>
455[[nodiscard]] constexpr Quat<T> operator-(Quat<T> const& q) noexcept
456{
457 return {-q.w, -q.x, -q.y, -q.z};
458}
459
460/**************************************************************************************
461| |
462| Binary operators |
463| |
464**************************************************************************************/
465
473template <std::floating_point T>
474[[nodiscard]] constexpr Quat<T> operator+(Quat<T> lhs, Quat<T> const& rhs) noexcept
475{
476 lhs += rhs;
477 return lhs;
478}
479
487template <std::floating_point T>
488[[nodiscard]] constexpr Quat<T> operator-(Quat<T> lhs, Quat<T> const& rhs) noexcept
489{
490 lhs -= rhs;
491 return lhs;
492}
493
501template <std::floating_point T>
502[[nodiscard]] constexpr Quat<T> operator*(Quat<T> lhs, Quat<T> const& rhs) noexcept
503{
504 lhs *= rhs;
505 return lhs;
506}
507
517template <std::floating_point T>
518[[nodiscard]] constexpr Vec<3, T> operator*(Quat<T> const& q, Vec<3, T> const& v) noexcept
519{
520 Vec<3, T> const qvec(q.x, q.y, q.z);
521 Vec<3, T> const uv(cross(qvec, v));
522 Vec<3, T> const uuv(cross(qvec, uv));
523 return v + ((uv * q.w) + uuv) * T(2);
524}
525
534template <std::floating_point T>
535[[nodiscard]] constexpr Vec<3, T> operator*(Vec<3, T> const& v, Quat<T> const& q) noexcept
536{
537 return inverse(q) * v;
538}
539
548template <std::floating_point T>
549[[nodiscard]] constexpr Vec<4, T> operator*(Quat<T> const& q, Vec<4, T> const& v) noexcept
550{
551 Vec<3, T> const r = q * Vec<3, T>(v[0], v[1], v[2]);
552 return Vec<4, T>(r[0], r[1], r[2], v[3]);
553}
554
562template <std::floating_point T>
563[[nodiscard]] constexpr Vec<4, T> operator*(Vec<4, T> const& v, Quat<T> const& q) noexcept
564{
565 Vec<3, T> const r = inverse(q) * Vec<3, T>(v[0], v[1], v[2]);
566 return Vec<4, T>(r[0], r[1], r[2], v[3]);
567}
568
576template <std::floating_point T>
577[[nodiscard]] constexpr Quat<T> operator*(Quat<T> lhs, T s) noexcept
578{
579 lhs *= s;
580 return lhs;
581}
582
590template <std::floating_point T>
591[[nodiscard]] constexpr Quat<T> operator*(T s, Quat<T> rhs) noexcept
592{
593 rhs *= s;
594 return rhs;
595}
596
604template <std::floating_point T>
605[[nodiscard]] constexpr Quat<T> operator/(Quat<T> lhs, T s) noexcept
606{
607 lhs /= s;
608 return lhs;
609}
610
611/**************************************************************************************
612| |
613| Operations |
614| |
615**************************************************************************************/
616
623template <std::floating_point T>
624void swap(Quat<T>& lhs, Quat<T>& rhs) noexcept
625{
626 lhs.swap(rhs);
627}
628
629/**************************************************************************************
630| |
631| Functions |
632| |
633**************************************************************************************/
634
642template <std::floating_point T>
643[[nodiscard]] constexpr T dot(Quat<T> const& a, Quat<T> const& b) noexcept
644{
645 return a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
646}
647
654template <std::floating_point T>
655[[nodiscard]] constexpr T normSquared(Quat<T> const& q) noexcept
656{
657 return dot(q, q);
658}
659
666template <std::floating_point T>
667[[nodiscard]] constexpr T norm(Quat<T> const& q) noexcept
668{
669 return std::sqrt(normSquared(q));
670}
671
678template <std::floating_point T>
679[[nodiscard]] constexpr Quat<T> normalize(Quat<T> const& q) noexcept
680{
681 T const len = norm(q);
682 if (len <= T(0)) {
683 return {T(1), T(0), T(0), T(0)};
684 }
685 return q / len;
686}
687
694template <std::floating_point T>
695[[nodiscard]] constexpr Quat<T> conjugate(Quat<T> const& q) noexcept
696{
697 return {q.w, -q.x, -q.y, -q.z};
698}
699
706template <std::floating_point T>
707[[nodiscard]] constexpr Quat<T> inverse(Quat<T> const& q) noexcept
708{
709 return conjugate(q) / normSquared(q);
710}
711
720template <std::floating_point T>
721[[nodiscard]] constexpr Quat<T> cross(Quat<T> const& q1, Quat<T> const& q2) noexcept
722{
723 return {q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z,
724 q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y,
725 q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z,
726 q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x};
727}
728
729/**************************************************************************************
730| |
731| Interpolation |
732| |
733**************************************************************************************/
734
745template <std::floating_point T>
746[[nodiscard]] Quat<T> mix(Quat<T> const& x, Quat<T> const& y, T a)
747{
748 T const cos_theta = dot(x, y);
749
750 if (cos_theta > T(1) - std::numeric_limits<T>::epsilon()) {
751 return {std::lerp(x.w, y.w, a), std::lerp(x.x, y.x, a), std::lerp(x.y, y.y, a),
752 std::lerp(x.z, y.z, a)};
753 }
754
755 T const angle = std::acos(cos_theta);
756 return (std::sin((T(1) - a) * angle) * x + std::sin(a * angle) * y) / std::sin(angle);
757}
758
769template <std::floating_point T>
770[[nodiscard]] constexpr Quat<T> lerp(Quat<T> const& x, Quat<T> const& y, T a) noexcept
771{
772 assert(a >= T(0) && a <= T(1));
773 return x * (T(1) - a) + y * a;
774}
775
786template <std::floating_point T>
787[[nodiscard]] Quat<T> slerp(Quat<T> const& x, Quat<T> const& y, T a)
788{
789 Quat<T> z = y;
790 T cos_theta = dot(x, y);
791
792 if (cos_theta < T(0)) {
793 z = -y;
794 cos_theta = -cos_theta;
795 }
796
797 if (cos_theta > T(1) - std::numeric_limits<T>::epsilon()) {
798 return {std::lerp(x.w, z.w, a), std::lerp(x.x, z.x, a), std::lerp(x.y, z.y, a),
799 std::lerp(x.z, z.z, a)};
800 }
801
802 T const angle = std::acos(cos_theta);
803 return (std::sin((T(1) - a) * angle) * x + std::sin(a * angle) * z) / std::sin(angle);
804}
805
817// k-th extra spin slerp (Graphics Gems III, page 96)
818template <std::floating_point T, std::floating_point S>
819[[nodiscard]] Quat<T> slerp(Quat<T> const& x, Quat<T> const& y, T a, S k)
820{
821 Quat<T> z = y;
822 T cos_theta = dot(x, y);
823
824 if (cos_theta < T(0)) {
825 z = -y;
826 cos_theta = -cos_theta;
827 }
828
829 if (cos_theta > T(1) - std::numeric_limits<T>::epsilon()) {
830 return {std::lerp(x.w, z.w, a), std::lerp(x.x, z.x, a), std::lerp(x.y, z.y, a),
831 std::lerp(x.z, z.z, a)};
832 }
833
834 T const angle = std::acos(cos_theta);
835 T const phi = angle + T(k) * std::numbers::pi_v<T>;
836 return (std::sin(angle - a * phi) * x + std::sin(a * phi) * z) / std::sin(angle);
837}
838
839/**************************************************************************************
840| |
841| Trigonometric |
842| |
843**************************************************************************************/
844
851template <std::floating_point T>
852[[nodiscard]] T angle(Quat<T> const& q) noexcept
853{
854 constexpr T cos_one_over_two = T(0.877582561890372716130286068203503191);
855 if (std::abs(q.w) > cos_one_over_two) {
856 T const a = std::asin(std::sqrt(q.x * q.x + q.y * q.y + q.z * q.z)) * T(2);
857 return q.w < T(0) ? std::numbers::pi_v<T> * T(2) - a : a;
858 }
859 return std::acos(q.w) * T(2);
860}
861
868template <std::floating_point T>
869[[nodiscard]] Vec<3, T> axis(Quat<T> const& q) noexcept
870{
871 T const tmp = T(1) - q.w * q.w;
872 if (tmp <= T(0)) {
873 return Vec<3, T>(T(0), T(0), T(1));
874 }
875 return Vec<3, T>(q.x, q.y, q.z) / std::sqrt(tmp);
876}
877
885template <std::floating_point T>
886[[nodiscard]] constexpr Quat<T> angleAxis(T angle, Vec<3, T> const& a) noexcept
887{
888 T const s = std::sin(angle * T(0.5));
889 return Quat<T>(std::cos(angle * T(0.5)), a[0] * s, a[1] * s, a[2] * s);
890}
891
892/**************************************************************************************
893| |
894| Euler angles |
895| |
896**************************************************************************************/
897
904template <std::floating_point T>
905[[nodiscard]] T roll(Quat<T> const& q) noexcept
906{
907 return T(std::atan2(T(2) * (q.x * q.y + q.w * q.z),
908 q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z));
909}
910
917template <std::floating_point T>
918[[nodiscard]] T pitch(Quat<T> const& q) noexcept
919{
920 return T(std::atan2(T(2) * (q.y * q.z + q.w * q.x),
921 q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z));
922}
923
930template <std::floating_point T>
931[[nodiscard]] T yaw(Quat<T> const& q) noexcept
932{
933 return std::asin(std::clamp(T(-2) * (q.x * q.z - q.w * q.y), T(-1), T(1)));
934}
935
942template <std::floating_point T>
943[[nodiscard]] Vec<3, T> eulerAngles(Quat<T> const& q) noexcept
944{
945 return Vec<3, T>{pitch(q), yaw(q), roll(q)};
946}
947
948/**************************************************************************************
949| |
950| Transform |
951| |
952**************************************************************************************/
953
964template <std::floating_point T>
965[[nodiscard]] Quat<T> rotate(Quat<T> const& q, T angle, Vec<3, T> axis)
966{
967 T const len = length(axis);
968 if (std::abs(len - T(1)) > T(0.001)) {
969 axis /= len;
970 }
971 T const s = std::sin(angle * T(0.5));
972 return q * Quat<T>(std::cos(angle * T(0.5)), axis[0] * s, axis[1] * s, axis[2] * s);
973}
974
982template <std::floating_point T>
983[[nodiscard]] Quat<T> quatLookAt(Vec<3, T> const& direction, Vec<3, T> const& up)
984{
985 Vec<3, T> const fwd = -direction;
986 Vec<3, T> right = cross(up, fwd);
987 right /= std::max(std::sqrt(T(0.00001)), norm(right));
988 Vec<3, T> const up_c = cross(fwd, right);
989
990 // Build rotation matrix in row-major where columns are right, up_c, fwd
991 Mat<3, 3, T> const m(Vec<3, T>(right[0], up_c[0], fwd[0]),
992 Vec<3, T>(right[1], up_c[1], fwd[1]),
993 Vec<3, T>(right[2], up_c[2], fwd[2]));
994 return Quat<T>(m);
995}
996
997/**************************************************************************************
998| |
999| isnan / isinf |
1000| |
1001**************************************************************************************/
1002
1009template <std::floating_point T>
1010[[nodiscard]] Vec<4, bool> isnan(Quat<T> const& q) noexcept
1011{
1012 return Vec<4, bool>(std::isnan(q.w), std::isnan(q.x), std::isnan(q.y), std::isnan(q.z));
1013}
1014
1021template <std::floating_point T>
1022[[nodiscard]] Vec<4, bool> isinf(Quat<T> const& q) noexcept
1023{
1024 return Vec<4, bool>(std::isinf(q.w), std::isinf(q.x), std::isinf(q.y), std::isinf(q.z));
1025}
1026
1027/**************************************************************************************
1028| |
1029| Print |
1030| |
1031**************************************************************************************/
1032
1040template <std::floating_point T>
1041std::ostream& operator<<(std::ostream& out, Quat<T> const& q)
1042{
1043 return out << "qw: " << q.w << " qx: " << q.x << " qy: " << q.y << " qz: " << q.z;
1044}
1045
1046} // namespace ufo
1047
1048template <std::floating_point T>
1049 requires std::formattable<T, char>
1050struct std::formatter<ufo::Quat<T>> {
1051 constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); }
1052
1053 auto format(ufo::Quat<T> const& q, std::format_context& ctx) const
1054 {
1055 return std::format_to(ctx.out(), "qw: {} qx: {} qy: {} qz: {}", q.w, q.x, q.y, q.z);
1056 }
1057};
1058
1063#endif // UFO_NUMERIC_QUAT_HPP
void swap(Quat &other) noexcept
Swaps all components with other.
Definition quat.hpp:402
Vec< 4, bool > isnan(Quat< T > const &q) noexcept
Returns a bool vector indicating which components are NaN.
Definition quat.hpp:1010
Quat< T > mix(Quat< T > const &x, Quat< T > const &y, T a)
Spherical or linear interpolation between two quaternions.
Definition quat.hpp:746
T angle(Quat< T > const &q) noexcept
Extracts the rotation angle (in radians) from a unit quaternion.
Definition quat.hpp:852
constexpr Quat() noexcept=default
Default constructor; initializes to the identity rotation (1, 0, 0, 0).
constexpr auto & operator[](this auto &self, size_type pos) noexcept
Component access by index: 0->w, 1->x, 2->y, 3->z.
Definition quat.hpp:292
T roll(Quat< T > const &q) noexcept
Extracts the roll angle (rotation about the X-axis) in radians.
Definition quat.hpp:905
constexpr Quat & operator+=(Quat const &q) noexcept
Component-wise addition.
Definition quat.hpp:314
constexpr Quat & operator=(Quat const &) noexcept=default
Copy assignment operator.
constexpr T dot(Quat< T > const &a, Quat< T > const &b) noexcept
Computes the four-component dot product a.w*b.w + a.x*b.x + a.y*b.y + a.z*b.z.
Definition quat.hpp:643
static constexpr size_type size() noexcept
Returns the number of components (always 4: w, x, y, z).
Definition quat.hpp:390
STL namespace.
All vision-related classes and functions.
Definition cloud.hpp:49
constexpr T normSquared(Quat< T > const &q) noexcept
Returns the squared norm (dot product with itself).
Definition quat.hpp:655
constexpr T b(Lab< T, Flags > color) noexcept
Returns the un-weighted blue–yellow axis value.
Definition lab.hpp:326
constexpr Mat< Rows, Cols, T > operator*(Mat< Rows, Cols, T > lhs, T rhs) noexcept
Multiplies every element of lhs by scalar rhs.
Definition mat.hpp:863
constexpr Mat< Rows, Cols, T > operator/(Mat< Rows, Cols, T > lhs, T rhs) noexcept
Divides every element of lhs by scalar rhs.
Definition mat.hpp:880
Quat< T > slerp(Quat< T > const &x, Quat< T > const &y, T a)
Spherical linear interpolation (SLERP) between two unit quaternions.
Definition quat.hpp:787
constexpr T a(Lab< T, Flags > color) noexcept
Returns the un-weighted green–red axis value.
Definition lab.hpp:310
Quat< T > quatLookAt(Vec< 3, T > const &direction, Vec< 3, T > const &up)
Builds a quaternion that orients an object to look in direction.
Definition quat.hpp:983
T pitch(Quat< T > const &q) noexcept
Extracts the pitch angle (rotation about the Y-axis) in radians.
Definition quat.hpp:918
constexpr Quat< T > angleAxis(T angle, Vec< 3, T > const &a) noexcept
Constructs a unit quaternion from an angle-axis representation.
Definition quat.hpp:886
constexpr T length(Vec< Dim, T > const &v) noexcept
Computes the Euclidean length (magnitude) of a vector.
Definition vec.hpp:1101
Vec< 3, T > eulerAngles(Quat< T > const &q) noexcept
Returns the Euler angles (pitch, yaw, roll) in radians.
Definition quat.hpp:943
Vec< 4, bool > isinf(Quat< T > const &q) noexcept
Returns a bool vector indicating which components are infinite.
Definition quat.hpp:1022
constexpr Quat< T > normalize(Quat< T > const &q) noexcept
Returns a unit quaternion in the same direction as q.
Definition quat.hpp:679
constexpr T norm(Quat< T > const &q) noexcept
Returns the Euclidean norm sqrt(w² + x² + y² + z²).
Definition quat.hpp:667
T yaw(Quat< T > const &q) noexcept
Extracts the yaw angle (rotation about the Z-axis) in radians.
Definition quat.hpp:931
constexpr Quat< T > cross(Quat< T > const &q1, Quat< T > const &q2) noexcept
Computes the Hamilton cross product of two quaternions.
Definition quat.hpp:721
constexpr Quat< T > lerp(Quat< T > const &x, Quat< T > const &y, T a) noexcept
Normalised linear interpolation (NLERP) between two quaternions.
Definition quat.hpp:770
constexpr M inverse(M const &m) noexcept
Computes the inverse of a square floating-point matrix.
Definition mat.hpp:1097
Mat< 4, 4, T > rotate(Mat< 4, 4, T > const &m, T angle, Vec< 3, T > const &v)
Applies an axis-angle rotation to a 4×4 matrix.
Definition mat.hpp:1535
Vec< 3, T > axis(Quat< T > const &q) noexcept
Extracts the unit rotation axis from a unit quaternion.
Definition quat.hpp:869
constexpr Quat< T > conjugate(Quat< T > const &q) noexcept
Returns the quaternion conjugate (w, -x, -y, -z).
Definition quat.hpp:695
A fixed-size matrix with Rows rows and Cols columns.
Definition mat.hpp:113
Unit quaternion representing an orientation or rotation in 3-D space.
Definition quat.hpp:76
constexpr Quat(T w, T x, T y, T z) noexcept
Constructs a quaternion from explicit (w, x, y, z) components.
Definition quat.hpp:127
constexpr Quat & operator=(Quat< U > const &rhs) noexcept
Converting assignment from a quaternion with a different scalar type.
Definition quat.hpp:235
constexpr bool operator==(Quat const &) const noexcept=default
Component-wise equality comparison.
constexpr Quat & operator*=(Quat const &q) noexcept
Hamilton (quaternion) product in place.
Definition quat.hpp:342
constexpr Quat & operator/=(T s) noexcept
Divides all components by scalar s.
Definition quat.hpp:371
constexpr Quat & operator*=(T s) noexcept
Scales all components by scalar s.
Definition quat.hpp:357
constexpr Quat(Mat< 3, 3, T > const &m) noexcept
Constructs a quaternion from a row-major 3×3 rotation matrix.
Definition quat.hpp:178
constexpr explicit(!std::is_same_v< T, U >) Quat(Quat< U > const &q) noexcept
Converting constructor from a quaternion with a different scalar type.
Definition quat.hpp:112
T w
Quaternion components. Must satisfy w^2 + x^2 + y^2 + z^2 == 1 for a valid rotation.
Definition quat.hpp:84
constexpr Quat(Mat< 4, 4, T > const &m) noexcept
Constructs a quaternion from the upper-left 3×3 block of a 4×4 matrix.
Definition quat.hpp:214
constexpr Quat & operator-=(Quat const &q) noexcept
Component-wise subtraction.
Definition quat.hpp:328
Quat(Vec< 3, T > const &u, Vec< 3, T > const &v)
Constructs the shortest-arc rotation quaternion from u to v.
Definition quat.hpp:136
Quat(Vec< 3, T > const &euler_angles)
Constructs a quaternion from Euler angles (pitch, yaw, roll) in radians.
Definition quat.hpp:158
A fixed-size arithmetic vector of up to 4 dimensions.
Definition vec.hpp:76
constexpr auto & w(this auto &self) noexcept
Accesses the fourth component (w).
Definition vec.hpp:166