fennec
Loading...
Searching...
No Matches
quaternion.h
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
19#ifndef FENNEC_MATH_EXT_QUATERNION_H
20#define FENNEC_MATH_EXT_QUATERNION_H
21
23#include <fennec/math/vector_base.h>
24
25namespace fennec
26{
27
28template<typename ScalarT> struct quaternion;
29
30template<typename genType> using qua = quaternion<genType>;
31
32using quat = qua<float>;
33using dquat = qua<double>;
34
35
36#ifndef FENNEC_DOXYGEN
37template<typename genType>
38constexpr genType dot(const qua<genType>& x, const qua<genType>& y) {
39 return x.w*y.w + x.x*y.x + x.y*y.y + x.z*y.z;
40}
41#endif
42
47template<typename genType>
48constexpr genType sqnorm(const qua<genType>& q) {
49 return fennec::dot(q, q);
50}
51
56template<typename genType>
57constexpr genType norm(const qua<genType>& q) {
58 return fennec::sqrt(sqnorm(q));
59}
60
65template<typename genType>
66constexpr qua<genType> unit(const qua<genType>& q) {
67 genType n = fennec::norm(q);
68 return q * (genType(1) / n);
69}
70
75template<typename genType>
76constexpr qua<genType> reciprocal(const qua<genType>& q) {
77 return ~q / fennec::sqnorm(q);
78}
79
80
81template<typename ScalarT>
82struct quaternion : detail::vector_base_type<ScalarT, 4>
83{
84public:
85// Typedefs ============================================================================================================
86
87 using base_type = detail::vector_base_type<ScalarT, 4>;
88 using scalar_t = ScalarT;
89 using quat_t = quaternion;
90 using vec3_t = vec<scalar_t, 3>;
91 using vec4_t = vec<scalar_t, 4>;
92
93 using base_type::data;
94 using base_type::x, base_type::y, base_type::z, base_type::w;
95
96
97// Constructors ========================================================================================================
98
101 constexpr quaternion() {
102 data = { 0, 0, 0, 1 };
103 }
104
111 constexpr quaternion(scalar_t w, scalar_t x, scalar_t y, scalar_t z) {
112 data = { x, y, z, w };
113 }
114
119 constexpr quaternion(scalar_t s, vec3_t v) {
120 data = { v.x, v.y, v.z, s };
121 }
122
126 constexpr quaternion(const vec4_t& v) {
127 data = v.data;
128 }
129
133 template<typename DataT, size_t...IndicesV> requires(sizeof...(IndicesV) == 4)
134 constexpr quaternion(const detail::swizzle_storage<DataT, scalar_t, IndicesV...>& s) {
135 data[0] = s[0];
136 data[1] = s[1];
137 data[2] = s[2];
138 data[3] = s[3];
139 }
140
144 constexpr quaternion(const quaternion& q) {
145 data = q.data;
146 }
147
151 constexpr quaternion(quaternion&& q) noexcept {
152 data = q.data;
153 }
154
155
156// Assignment Operators ================================================================================================
157
161 constexpr quat_t& operator=(const quat_t& q) {
162 data = q.data;
163 return *this;
164 }
165
169 constexpr quat_t& operator=(quat_t&& q) noexcept {
170 data = q.data;
171 return *this;
172 }
173
174
175// Comparison Operators ================================================================================================
176
182 constexpr friend bool operator==(const quat_t& lhs, const quat_t& rhs) {
183 return lhs.data == rhs.data;
184 }
185
191 constexpr friend bool operator!=(const quat_t& lhs, const quat_t& rhs) {
192 return lhs.data != rhs.data;
193 }
194
195
196// Unary Operators =====================================================================================================
197
202 constexpr friend quat_t operator-(const quat_t& rhs) {
203 return quat_t(-rhs.w, -rhs.x, -rhs.y, -rhs.z);
204 }
205
210 constexpr friend quat_t operator~(const quat_t& rhs) {
211 return quat_t(rhs.w, -rhs.x, -rhs.y, -rhs.z);
212 }
213
214
215// Quaternion Scalar Arithmetic Operators ==============================================================================
216
222 constexpr friend quat_t operator*(const quat_t& lhs, scalar_t rhs) {
223 return quat_t(lhs.w * rhs, lhs.x * rhs, lhs.y * rhs, lhs.z * rhs);
224 }
225
231 constexpr friend quat_t operator*(scalar_t lhs, const quat_t& rhs) {
232 return quat_t(lhs * rhs.w, lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
233 }
234
240 constexpr friend quat_t operator/(const quat_t& lhs, scalar_t rhs) {
241 return quat_t(lhs.w / rhs, lhs.x / rhs, lhs.y / rhs, lhs.z / rhs);
242 }
243
249 constexpr friend quat_t operator/(scalar_t lhs, const quat_t& rhs) {
250 return quat_t(lhs / rhs.w, lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
251 }
252
253
254// Quaternion Scalar Arithmetic Assignment Operators ===================================================================
255
261 constexpr friend quat_t& operator*=(quat_t& lhs, scalar_t rhs) {
262 lhs.x *= rhs;
263 lhs.y *= rhs;
264 lhs.z *= rhs;
265 lhs.w *= rhs;
266 return lhs;
267 }
268
274 constexpr friend quat_t& operator/=(const quat_t& lhs, scalar_t rhs) {
275 lhs.x /= rhs;
276 lhs.y /= rhs;
277 lhs.z /= rhs;
278 lhs.w /= rhs;
279 return lhs;
280 }
281
282
283// Quaternion Vector Arithmetic Operators ==============================================================================
284
285 constexpr friend vec3_t operator*(const quat_t& q, const vec3_t& v) {
286 const vec3_t u = q.xyz;
287 const vec3_t uv = fennec::cross(u, v);
288 const vec3_t uuv = fennec::cross(u, uv);
289 return v + (uv*q.w + uuv) * scalar_t(2);
290 }
291
292 constexpr friend vec3_t operator*(const vec3_t& v, const quat_t& q) {
293 return fennec::reciprocal(q) * v;
294 }
295
296 constexpr friend vec4_t operator*(const quat_t& q, const vec4_t& v) {
297 return vec4_t(q * v.xyz, v.w);
298 }
299
300 constexpr friend vec4_t operator*(const vec4_t& v, const quat_t& q) {
301 return fennec::reciprocal(q) * v;
302 }
303
304
305// Quaternion Quaternion Arithmetic Operators ==========================================================================
306
307 constexpr friend quat_t operator+(const quat_t& lhs, const quat_t& rhs) {
308 return quat_t(
309 lhs.w + rhs.w,
310 lhs.x + rhs.x,
311 lhs.y + rhs.y,
312 lhs.z + rhs.z
313 );
314 }
315
316 constexpr friend quat_t operator-(const quat_t& lhs, const quat_t& rhs) {
317 return quat_t(
318 lhs.w - rhs.w,
319 lhs.x - rhs.x,
320 lhs.y - rhs.y,
321 lhs.z - rhs.z
322 );
323 }
324
325 constexpr friend quat_t operator*(const quat_t& lhs, const quat_t& rhs) {
326 return quat_t(
327 lhs.w*rhs.w - lhs.x*rhs.x - lhs.y*rhs.y - lhs.z * rhs.z,
328 lhs.w*rhs.x + lhs.x*rhs.w + lhs.y*rhs.z - lhs.z * rhs.y,
329 lhs.w*rhs.y - lhs.x*rhs.z + lhs.y*rhs.w + lhs.z * rhs.x,
330 lhs.w*rhs.z - lhs.x*rhs.y - lhs.y*rhs.x + lhs.z * rhs.w
331 );
332 }
333
334
335// Quaternion Quaternion Arithmetic Assignment Operators ===============================================================
336
337 constexpr friend quat_t& operator+=(quat_t& lhs, const quat_t& rhs) {
338 lhs.w += rhs.w;
339 lhs.x += rhs.x;
340 lhs.y += rhs.y;
341 lhs.z += rhs.z;
342 return lhs;
343 }
344
345 constexpr friend quat_t& operator-=(quat_t& lhs, const quat_t& rhs) {
346 lhs.w -= rhs.w;
347 lhs.x -= rhs.x;
348 lhs.y -= rhs.y;
349 lhs.z -= rhs.z;
350 return lhs;
351 }
352
353 constexpr friend quat_t& operator*=(quat_t& lhs, const quat_t& rhs) {
354 return lhs = lhs * rhs;
355 }
356
357private:
358
359};
360
361}
362
363#endif // FENNEC_MATH_EXT_QUATERNION_H
constexpr genType sqrt(genType x)
Returns .
Definition exponential.h:178
Geometric
constexpr genType dot(const vector< genType, i... > &x, const vector< genType, i... > &y)
Returns the dot product of and , i.e., .
Definition geometric.h:133
constexpr vector< genType, i... > cross(const vector< genType, i... > &x, const vector< genType, i... > &y)
Returns the cross product of and , i.e., .
Definition geometric.h:211
constexpr genType y()
Definition constants.h:672