Not Enough Math
Lightweight zero-dependency C++ math library
Loading...
Searching...
No Matches
quat_utils.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "quat.hpp"
4#include "vec.hpp"
5#include "mat.hpp"
6#include "utils.hpp"
7#include "trig.hpp"
8#include "power.hpp"
9
10namespace nem
11{
12 template <typename T = nem::real>
13 constexpr T sqr_length(const nem::quat_t<T>& q)
14 {
15 return nem::sqr(q.s) + nem::sqr(q.x) + nem::sqr(q.y) + nem::sqr(q.z);
16 }
17
18 template <typename T = nem::real>
20 {
21 return nem::sqrt(nem::sqr_length(q));
22 }
23
24 template <typename T = nem::real>
26 {
27 const T l = nem::length(q);
28 q /= l;
29 return q;
30 }
31
32 template<typename T = nem::real>
34 {
35 return nem::quat_t<T> { vec4.x, vec4.y, vec4.z, vec4.w };
36 }
37
38 template<typename T = nem::real>
39 constexpr nem::quat_t<T> make_quat(T scalar, T x, T y, T z)
40 {
41 return nem::quat_t<T> { scalar, x, y, z };
42 }
43
47 template<typename T = nem::real>
49 {
50 return nem::quat_t<T> { q.s, -q.x, -q.y, -q.z };
51 }
52
53 template<typename T = nem::real>
55 {
56 return nem::conjugate(q) / nem::sqr_length(q);
57 }
58
59 template<typename T = nem::real>
61 {
62 const nem::sincos a = nem::get_sincos(radians * T{0.5});
63 return nem::make_quat<T>(
64 axis.x * a.sin,
65 axis.y * a.sin,
66 axis.z * a.sin,
67 a.cos
68 );
69 }
70
71 template <typename T = nem::real>
72 nem::quat_t<T> from_euler(T pitch, T yaw, T roll)
73 {
74 nem::quat_t qx = nem::from_axis_angle({ 1,0,0 }, pitch);
75 nem::quat_t qy = nem::from_axis_angle({ 0,1,0 }, yaw);
76 nem::quat_t qz = nem::from_axis_angle({ 0,0,1 }, roll);
77 return qy * qx * qz;
78 }
79
80 template <typename T = nem::real>
82 {
83 // implies that q is normalized, hence s^2 + x^2 + y^2 + z^2 = 1, hence different notation
84 if (!nem::equal(nem::sqr_length(q), T{1}))
85 {
87 }
88
89 // https://www.johndcook.com/blog/2025/05/07/quaternions-and-rotation-matrices/
90 auto q0 = q.s, q1 = q.x, q2 = q.y, q3 = q.z;
91 return nem::mat<T, 3, 3>({
92 { 2 * (q0 * q0 + q1 * q1) - 1, 2 * (q1 * q2 - q0 * q3), 2 * (q1 * q3 + q0 * q2) },
93 { 2 * (q1 * q2 + q0 * q3), 2 * (q0 * q0 + q2 * q2) - 1, 2 * (q2 * q3 - q0 * q1) },
94 { 2 * (q1 * q3 - q0 * q2), 2 * (q2 * q3 + q0 * q1), 2 * (q0 * q0 + q3 * q3) - 1 }
95 });
96 }
97
98 template <typename T>
100 {
101 return nem::vec<T, 3>(q.x, q.y, q.z);
102 }
103}
#define NEM_INLINE
Definition config.hpp:12
T invalid_result(nem::error::Kind kind=Kind::RuntimeError, const char *const msg=nullptr)
Definition err.hpp:120
Definition config.hpp:16
nem::quat_t< T > normalize(nem::quat_t< T > q)
T sqrt(T value)
Definition power.hpp:180
constexpr nem::quat_t< T > make_quat(const nem::vec< T, 4 > &vec4)
constexpr nem::quat_t< T > inverse(const nem::quat_t< T > &q)
constexpr nem::quat_t< T > conjugate(const nem::quat_t< T > &q)
Conjugates the quaternion, yielding a quaternion with the same angle (scalar) but inverse axis (vecto...
constexpr nem::sincos< T > get_sincos(T radians)
Definition trig.hpp:120
constexpr T sqr_length(const nem::quat_t< T > &q)
constexpr T radians(T radians) noexcept
Converts radians to radians (passes the argument unchanged). Used to make units explicit.
Definition trig.hpp:35
constexpr T sqr(T value) noexcept
Definition utils.hpp:72
constexpr bool equal(T a, T b) noexcept
Are a and b nearly equal? Given an Epsilon > 0, within each all numbers are considered indistinguisab...
Definition utils.hpp:56
T length(const nem::quat_t< T > &q)
constexpr nem::mat< T, 3, 3 > norm_quaterion_to_rotation_matrix(const nem::quat_t< T > &q)
nem::quat_t< T > from_axis_angle(const nem::vec< T, 3 > &axis, T radians)
nem::quat_t< T > from_euler(T pitch, T yaw, T roll)
constexpr nem::vec< T, 3 > extract_vector(const nem::quat_t< T > &q)