opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
quaternion_functions.h
Go to the documentation of this file.
1#pragma once
2
12
13#include <concepts>
14#include <type_traits>
15#include <utility>
16
17namespace osc
18{
19 // returns a vector containing `isnan(qv)` for each `qv` in `q`
20 template<std::floating_point T>
22 {
23 return {isnan(q.w), isnan(q.x), isnan(q.y), isnan(q.z)};
24 }
25
26 template<typename T>
27 requires std::is_arithmetic_v<T>
28 constexpr Qua<T> conjugate(const Qua<T>& q)
29 {
30 return Qua<T>::wxyz(q.w, -q.x, -q.y, -q.z);
31 }
32
33 template<typename T>
34 requires std::is_arithmetic_v<T>
35 constexpr T dot(const Qua<T>& a, const Qua<T>& b)
36 {
37 return (a.w*b.w + a.x*b.x) + (a.y*b.y + a.z*b.z);
38 }
39
40 template<typename T>
41 requires std::is_arithmetic_v<T>
42 constexpr Qua<T> inverse(const Qua<T>& q)
43 {
44 return conjugate(q) / dot(q, q);
45 }
46
47 template<typename T>
48 T length(const Qua<T>& q)
49 {
50 return sqrt(dot(q, q));
51 }
52
53 // returns a normalized version of the provided argument
54 template<std::floating_point T>
56 {
57 const T len = length(q);
58
59 if (len <= static_cast<T>(0)) { // uh oh
60 return Qua<T>::wxyz(
61 static_cast<T>(1),
62 static_cast<T>(0),
63 static_cast<T>(0),
64 static_cast<T>(0)
65 );
66 }
67
68 const T one_over_len = static_cast<T>(1) / len;
70 }
71
72 template<typename T>
74 {
75 const T four_x_squared_minus_1 = m[0][0] - m[1][1] - m[2][2];
76 const T four_y_squared_minus_1 = m[1][1] - m[0][0] - m[2][2];
77 const T four_z_squared_minus_1 = m[2][2] - m[0][0] - m[1][1];
78 const T four_w_squared_minus_1 = m[0][0] + m[1][1] + m[2][2];
79
80 int biggest_index = 0;
84 biggest_index = 1;
85 }
88 biggest_index = 2;
89 }
92 biggest_index = 3;
93 }
94
95 const T biggest_val = sqrt(four_biggest_squared_minus_1 + static_cast<T>(1)) * static_cast<T>(0.5);
96 const T mult = static_cast<T>(0.25) / biggest_val;
97
98 switch(biggest_index) {
99 case 0:
100 return Qua<T>::wxyz(biggest_val, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult);
101 case 1:
102 return Qua<T>::wxyz((m[1][2] - m[2][1]) * mult, biggest_val, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult);
103 case 2:
104 return Qua<T>::wxyz((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggest_val, (m[1][2] + m[2][1]) * mult);
105 case 3:
106 return Qua<T>::wxyz((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggest_val);
107 default:
108 std::unreachable();
109 }
110 }
111
112 template<typename T>
117
118 template<typename T>
120 {
121 const T qxx(q.x * q.x);
122 const T qyy(q.y * q.y);
123 const T qzz(q.z * q.z);
124 const T qxz(q.x * q.z);
125 const T qxy(q.x * q.y);
126 const T qyz(q.y * q.z);
127 const T qwx(q.w * q.x);
128 const T qwy(q.w * q.y);
129 const T qwz(q.w * q.z);
130
131 Matrix<T, 3, 3> rv(T(1));
132
133 rv[0][0] = T(1) - T(2) * (qyy + qzz);
134 rv[0][1] = T(2) * (qxy + qwz);
135 rv[0][2] = T(2) * (qxz - qwy);
136
137 rv[1][0] = T(2) * (qxy - qwz);
138 rv[1][1] = T(1) - T(2) * (qxx + qzz);
139 rv[1][2] = T(2) * (qyz + qwx);
140
141 rv[2][0] = T(2) * (qxz + qwy);
142 rv[2][1] = T(2) * (qyz - qwx);
143 rv[2][2] = T(1) - T(2) * (qxx + qyy);
144
145 return rv;
146 }
147
148 template<typename T>
150 {
152 }
153
154 template<typename T>
156 {
157 return Qua<T>::wxyz(
158 static_cast<T>(1),
159 static_cast<T>(0),
160 static_cast<T>(0),
161 static_cast<T>(0)
162 );
163 }
164
165 template<
166 std::floating_point T,
167 AngularUnitTraits Units,
168 std::convertible_to<const Vector<T, 3>&> VectorLike
169 >
171 {
172 const T s = sin(angle * static_cast<T>(0.5));
173 return Qua<T>(cos(angle * static_cast<T>(0.5)), static_cast<const Vector<T, 3>&>(axis) * s);
174 }
175
176 template<
177 std::floating_point T,
178 AngularUnitTraits Units
179 >
181 {
182 return angle_axis(angle, direction.direction_vector<T>());
183 }
184
185 // computes the rotation from `origin` to `destination`
186 template<typename T>
187 Qua<T> rotation(const Vector<T, 3>& origin, const Vector<T, 3>& destination)
188 {
189 const T cos_theta = dot(origin, destination);
190 if (cos_theta >= static_cast<T>(1) - epsilon_v<T>) {
191 // origin and destination point in the same direction
192 return quaternion_identity<T>();
193 }
194
196 if (cos_theta < static_cast<T>(-1) + epsilon_v<T>) {
197 // special case when vectors in opposite directions :
198 // there is no "ideal" rotation axis
199 // So guess one; any will do as long as it's perpendicular to start
200 // This implementation favors a rotation around the Up axis (Y),
201 // since it's often what you want to do.
202 rotation_axis = cross(Vector<T, 3>(0, 0, 1), origin);
203 if (length2(rotation_axis) < epsilon_v<T>) { // bad luck, they were parallel, try again!
204 rotation_axis = cross(Vector<T, 3>(1, 0, 0), origin);
205 }
206
208 return angle_axis(Degrees{180}, rotation_axis);
209 }
210
211 // Implementation from Stan Melax's Game Programming Gems 1 article
212 rotation_axis = cross(origin, destination);
213
214 const T s = sqrt((T(1) + cos_theta) * static_cast<T>(2));
215 const T invs = static_cast<T>(1) / s;
216
217 return Qua<T>::wxyz(
218 s * static_cast<T>(0.5f),
219 rotation_axis.x() * invs,
220 rotation_axis.y() * invs,
221 rotation_axis.z() * invs
222 );
223 }
224
225 template<typename T>
227 {
228 const T y = static_cast<T>(2) * (q.y * q.z + q.w * q.x);
229 const T x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z;
230
232 //avoid atan2(0,0) - handle singularity - Matiis
233 return static_cast<T>(2) * atan2(q.x, q.w);
234 }
235
236 return atan2(y, x);
237 }
238
239 template<typename T>
241 {
242 return asin(clamp(static_cast<T>(-2) * (q.x * q.z - q.w * q.y), static_cast<T>(-1), static_cast<T>(1)));
243 }
244
245 template<typename T>
247 {
248 const T y = static_cast<T>(2) * (q.x * q.y + q.w * q.z);
249 const T x = q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z;
250
252 //avoid atan2(0,0) - handle singularity - Matiis
253 return RadiansT<T>{0};
254 }
255
256 return atan2(y, x);
257 }
258
259 template<typename T>
261 {
262 return Vector<RadiansT<T>, 3>(pitch(x), yaw(x), roll(x));
263 }
264}
Definition angle.h:25
Definition coordinate_direction.h:16
constexpr Vector< T, 3 > direction_vector() const
Definition coordinate_direction.h:90
Definition vector.h:63
Definition custom_decoration_generator.h:5
bool equal_within_epsilon(T x, T y)
Definition common_functions.h:265
RadiansT< T > pitch(const Qua< T > &q)
Definition quaternion_functions.h:226
constexpr Angle< Rep, Units > clamp(const Angle< Rep, Units > &v, const AngleMin &min, const AngleMax &max)
Definition angle.h:303
GenType cos(GenType v)
Definition trigonometric_functions.h:34
RadiansT< T > roll(const Qua< T > &q)
Definition quaternion_functions.h:246
constexpr Matrix< T, 4, 4 > matrix4x4_cast(const Qua< T > &q)
Definition quaternion_functions.h:149
T length(const Vector< T, N > &v)
Definition geometric_functions.h:60
Qua< T > quaternion_cast(const Matrix< T, 3, 3 > &m)
Definition quaternion_functions.h:73
Vector< RadiansT< T >, 3 > to_euler_angles(const Qua< T > &x)
Definition quaternion_functions.h:260
constexpr T dot(T x, T y)
Definition geometric_functions.h:29
constexpr Matrix< T, 3, 3 > matrix3x3_cast(const Qua< T > &q)
Definition quaternion_functions.h:119
constexpr T length2(const Vector< T, N > &v)
Definition geometric_functions.h:67
Qua< T > rotation(const Vector< T, 3 > &origin, const Vector< T, 3 > &destination)
Definition quaternion_functions.h:187
RadiansT< T > yaw(const Qua< T > &q)
Definition quaternion_functions.h:240
constexpr U to(T &&value)
Definition conversion.h:56
GenType sin(GenType v)
Definition trigonometric_functions.h:13
constexpr Qua< T > quaternion_identity()
Definition quaternion_functions.h:155
T inverse(const Matrix< T, 3, 3 > &m)
Definition matrix_functions.h:158
constexpr Qua< T > conjugate(const Qua< T > &q)
Definition quaternion_functions.h:28
constexpr bool all_of(const Vector< bool, N > &v)
Definition functors.h:49
Vector< T, N > normalize(const Vector< T, N > &v)
Definition geometric_functions.h:74
bool isnan(T num)
Definition common_functions.h:319
Qua< T > angle_axis(Angle< T, Units > angle, VectorLike &&axis)
Definition quaternion_functions.h:170
RadiansT< Rep > atan2(Rep x, Rep y)
Definition trigonometric_functions.h:100
T sqrt(T num)
Definition geometric_functions.h:14
RadiansT< Rep > asin(Rep num)
Definition trigonometric_functions.h:94
constexpr CoordinateDirection cross(CoordinateDirection x, CoordinateDirection y)
Definition coordinate_direction.h:117
Definition matrix.h:15
Definition qua.h:22
T w
Definition qua.h:184
static constexpr Qua< T > wxyz(T w, T x, T y, T z)
Definition qua.h:34
T y
Definition qua.h:186
T x
Definition qua.h:185
T z
Definition qua.h:187