Not Enough Math
Lightweight zero-dependency C++ math library
Loading...
Searching...
No Matches
quat.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "config.hpp"
4#include "err.hpp"
5#include "utils.hpp"
6#include "vec.hpp"
7#include "vec_utils.hpp"
8
9namespace nem
10{
11 template <typename T> struct quat_t
12 {
13 T s = 0, // scalar
14 x = 0, y = 0, z = 0; // vector
15
16 // static constexpr quat NaN() { quat{ std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN(),
17 // std::numeric_limits<T>::quiet_NaN(), std::numeric_limits<T>::quiet_NaN() }; }
18
19 constexpr quat_t &operator*=(const quat_t &other)
20 {
21 quat_t &q = *this;
22 const quat_t &p = other;
23 /* from wikipedia
24 a = a1a2 - b1b2 - c1c2 - d1d2
25 b = a1b2 + b1a2 + c1d2 - d1c2
26 c = a1c2 - b1d2 + c1a2 + d1b2
27 d = a1d2 + b1c2 - c1b2 + d1a2
28
29 s = s1s2 - x1x2 - y1y2 - z1z2
30 x = s1x2 + x1s2 + y1z2 - z1y2
31 y = s1y2 - x1z2 + y1s2 + z1x2
32 z = s1z2 + x1y2 - y1x2 + z1s2
33
34 s = q.s * p.s - q.x * p.x - q.y * p.y - q.z * p.z
35 x = q.s * p.x + q.x * p.s + q.y * p.z - q.z * p.y
36 y = q.s * p.y - q.x * p.z + q.y * p.s + q.z * p.x
37 z = q.s * p.z + q.x * p.y - q.y * p.x + q.z * p.s
38 */
39
40 decltype(q.s) rs = q.s * p.s - q.x * p.x - q.y * p.y - q.z * p.z;
41 decltype(q.x) rx = q.s * p.x + q.x * p.s + q.y * p.z - q.z * p.y;
42 decltype(q.y) ry = q.s * p.y - q.x * p.z + q.y * p.s + q.z * p.x;
43 decltype(q.z) rz = q.s * p.z + q.x * p.y - q.y * p.x + q.z * p.s;
44 this->s = rs;
45 this->x = rx;
46 this->y = ry;
47 this->z = rz;
48 return *this;
49 }
50
51 constexpr friend quat_t operator*(quat_t lhs, const quat_t &rhs)
52 {
53 lhs *= rhs;
54 return lhs;
55 }
56
57 constexpr quat_t &operator*=(T scalar)
58 {
59 this->s = s * scalar;
60 this->x = x * scalar;
61 this->y = y * scalar;
62 this->z = z * scalar;
63 return *this;
64 }
65
66 constexpr friend quat_t operator*(quat_t q, T scalar)
67 {
68 q *= scalar;
69 return q;
70 }
71
72 constexpr quat_t &operator/=(T scalar)
73 {
74 // TODO: add 0 division protection with nem::err
75 return (*this *= (T{1.0} / scalar));
76 }
77
78 constexpr friend quat_t operator/(quat_t q, T scalar)
79 {
80 q /= scalar;
81 return q;
82 }
83
84 constexpr quat_t &operator+=(const quat_t &other)
85 {
86 this->s += other.s;
87 this->x += other.x;
88 this->y += other.y;
89 this->z += other.z;
90 return *this;
91 }
92
93 constexpr friend quat_t operator+(quat_t lhs, const quat_t &rhs)
94 {
95 lhs += rhs;
96 return lhs;
97 }
98
99 constexpr friend quat_t operator-(quat_t q)
100 {
101 return quat_t{-q.s, -q.x, -q.y, -q.z};
102 }
103
104 constexpr friend nem::vec<T, 3> operator*(const quat_t& q, const nem::vec<T, 3>& v)
105 {
106 const nem::vec<T, 3> w(q.x, q.y, q.z);
107 const T a = q.s;
108 return (v + (T)2.0 * a * nem::cross(w, v) + (T)2.0 * (nem::cross(w, nem::cross(w, v))));
109 }
110};
111
113
114} // namespace nem
Definition config.hpp:16
nem::vec< T, 3 > cross(const nem::vec< T, 3 > &a, const nem::vec< T, 3 > &b)
constexpr quat_t & operator*=(T scalar)
Definition quat.hpp:57
constexpr friend quat_t operator*(quat_t q, T scalar)
Definition quat.hpp:66
constexpr friend quat_t operator+(quat_t lhs, const quat_t &rhs)
Definition quat.hpp:93
constexpr friend quat_t operator*(quat_t lhs, const quat_t &rhs)
Definition quat.hpp:51
constexpr quat_t & operator+=(const quat_t &other)
Definition quat.hpp:84
constexpr friend quat_t operator-(quat_t q)
Definition quat.hpp:99
constexpr friend quat_t operator/(quat_t q, T scalar)
Definition quat.hpp:78
constexpr quat_t & operator*=(const quat_t &other)
Definition quat.hpp:19
constexpr quat_t & operator/=(T scalar)
Definition quat.hpp:72
constexpr friend nem::vec< T, 3 > operator*(const quat_t &q, const nem::vec< T, 3 > &v)
Definition quat.hpp:104