PeriDyno 1.0.0
Loading...
Searching...
No Matches
Quat.inl
Go to the documentation of this file.
1
2#include <cmath>
3#include <cstdlib>
4#include <iostream>
5#include "Vector.h"
6#include "Matrix.h"
7
8namespace dyno
9{
10 template <typename Real>
11 DYN_FUNC Quat<Real>::Quat() :
12 w(1),
13 x(0),
14 y(0),
15 z(0)
16 {
17 }
18
19 template <typename Real>
20 DYN_FUNC Quat<Real>::Quat(Real _x, Real _y, Real _z, Real _w) :
21 w(_w),
22 x(_x),
23 y(_y),
24 z(_z)
25 {
26 }
27
28 template <typename Real>
29 DYN_FUNC Quat<Real>::Quat(Real rot, const Vector<Real, 3>& axis)
30 {
31 const Real a = rot * Real(0.5);
32 const Real s = glm::sin(a);
33 w = glm::cos(a);
34 x = axis[0] * s;
35 y = axis[1] * s;
36 z = axis[2] * s;
37 }
38
39 template <typename Real>
41 {
42 Vector<Real, 3> c = u0.cross(u1);
43 x = c[0];
44 y = c[1];
45 z = c[2];
46 w = u0.dot(u1) + u0.norm() * u1.norm();
47 normalize();
48 }
49
50 template <typename Real>
51 DYN_FUNC Quat<Real>::Quat(const Quat<Real> & quat) :
52 w(quat.w),
56 {
57
58 }
60 template <typename Real>
61 DYN_FUNC Quat<Real>::Quat(const Real yaw, const Real pitch, const Real roll)
62 {
63 Real cy = glm::cos(Real(yaw * 0.5));
64 Real sy = glm::sin(Real(yaw * 0.5));
65 Real cp = glm::cos(Real(pitch * 0.5));
66 Real sp = glm::sin(Real(pitch * 0.5));
67 Real cr = glm::cos(Real(roll * 0.5));
68 Real sr = glm::sin(Real(roll * 0.5));
70 w = cr * cp * cy + sr * sp * sy;
71 x = sr * cp * cy - cr * sp * sy;
72 y = cr * sp * cy + sr * cp * sy;
73 z = cr * cp * sy - sr * sp * cy;
74 }
76
77 template <typename Real>
79 {
80 w = quat.w;
81 x = quat.x;
82 y = quat.y;
83 z = quat.z;
84 return *this;
85 }
86
87 template <typename Real>
89 {
90 w += quat.w;
91 x += quat.x;
92 y += quat.y;
93 z += quat.z;
94 return *this;
95 }
97 template <typename Real>
99 {
100 w -= quat.w;
101 x -= quat.x;
102 y -= quat.y;
103 z -= quat.z;
104 return *this;
105 }
106
107 template <typename Real>
109 {
110 return Quat(x - quat.x, y - quat.y, z - quat.z, w - quat.w);
111 }
112
113 template <typename Real>
115 {
116 return Quat(-x, -y, -z, -w);
117 }
118
119 template <typename Real>
121 {
122 return Quat(x + quat.x, y + quat.y, z + quat.z, w + quat.w);
123 }
124
125 template <typename Real>
126 DYN_FUNC Quat<Real> Quat<Real>::operator * (const Real& scale) const
127 {
128 return Quat(x * scale, y * scale, z * scale, w * scale);
129 }
130
131 template <typename Real>
133 {
134 Quat result;
135
136 result.w = -x * q.x - y * q.y - z * q.z + w * q.w;
137
138 result.x = x * q.w + y * q.z - z * q.y + w * q.x;
139 result.y = -x * q.z + y * q.w + z * q.x + w * q.y;
140 result.z = x * q.y - y * q.x + z * q.w + w * q.z;
141
142 return result;
143 }
144
145 template <typename Real>
146 DYN_FUNC Quat<Real> Quat<Real>::operator / (const Real& scale) const
147 {
148 return Quat(x / scale, y / scale, z / scale, w / scale);
149 }
150
151 template <typename Real>
152 DYN_FUNC bool Quat<Real>::operator == (const Quat<Real> &quat) const
153 {
154 if (w == quat.w && x == quat.x && y == quat.y && z == quat.z)
155 return true;
156 return false;
157 }
158
159 template <typename Real>
160 DYN_FUNC bool Quat<Real>::operator != (const Quat<Real> &quat) const
161 {
162 if (*this == quat)
163 return false;
164 return true;
165 }
166
167 template <typename Real>
168 DYN_FUNC Real Quat<Real>::norm() const
169 {
170 Real result = w * w + x * x + y * y + z * z;
171 result = glm::sqrt(result);
172
173 return result;
174 }
175
176 template <typename Real>
178 {
179 return w * w + x * x + y * y + z * z;
180 }
181
182 template <typename Real>
184 {
185 Real d = norm();
186 // Set the rotation along the x-axis
187 if (d < 0.00001) {
188 z = Real(1.0);
189 x = y = w = Real(0.0);
190 return *this;
191 }
192 d = Real(1) / d;
193 x *= d;
194 y *= d;
195 z *= d;
196 w *= d;
197 return *this;
198 }
199
200 template <typename Real>
202 {
203 return conjugate() / normSquared();
204 }
205
206 template <typename Real>
207 DYN_FUNC void Quat<Real>::toEulerAngle(Real& yaw, Real& pitch, Real& roll) const
208 {
209 // roll (x-axis rotation)
210 Real sinr_cosp = 2 * (w * x + y * z);
211 Real cosr_cosp = 1 - 2 * (x * x + y * y);
212 roll = atan2(sinr_cosp, cosr_cosp);
213
214 // pitch (y-axis rotation)
215 Real sinp = 2 * (w * y - z * x);
216 if (glm::abs(sinp) >= 1)
217 {
218 pitch = sinp > 0 ? Real(M_PI / 2) : -Real(M_PI / 2); // use 90 degrees if out of range
219 }
220 else
221 pitch = glm::asin(sinp);
222
223 // yaw (z-axis rotation)
224 Real siny_cosp = 2 * (w * z + x * y);
225 Real cosy_cosp = 1 - 2 * (y * y + z * z);
226 yaw = atan2(siny_cosp, cosy_cosp);
227 }
228
229
230 template <typename Real>
231 DYN_FUNC Real Quat<Real>::angle() const
232 {
233 return glm::acos(w) * (Real)(2);
234 }
235
236 template <typename Real>
237 DYN_FUNC Real Quat<Real>::angle(const Quat<Real>& quat) const
238 {
239 Real dot_product = dot(quat);
240
241 dot_product = glm::clamp(dot_product, (Real)-1, (Real)1);
242 return glm::acos(dot_product) * (Real)(2);
243 }
244
245 template <typename Real>
246 DYN_FUNC Real Quat<Real>::dot(const Quat<Real> & quat) const
247 {
248 return w * quat.w + x * quat.x + y * quat.y + z * quat.z;
249 }
250
251 template <typename Real>
253 {
254 return Quat<Real>(-x, -y, -z, w);
255 }
256
257 // Refer to "https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles" for more details
258 template <typename Real>
260 {
261 // Extract the vector part of the quaternion
262 Vector<Real, 3> u(x, y, z);
263
264 // Extract the scalar part of the quaternion
265 Real s = w;
266
267 // Do the math
268 return 2.0f * u.dot(v) * u
269 + (s*s - u.dot(u)) * v
270 + 2.0f * s * u.cross(v);
271 }
272
273
274 template <typename Real>
276 {
277 Real x2 = x + x, y2 = y + y, z2 = z + z;
278 Real xx = x2 * x, yy = y2 * y, zz = z2 * z;
279 Real xy = x2 * y, xz = x2 * z, xw = x2 * w;
280 Real yz = y2 * z, yw = y2 * w, zw = z2 * w;
281 return SquareMatrix<Real, 3>(Real(1) - yy - zz, xy - zw, xz + yw,
282 xy + zw, Real(1) - xx - zz, yz - xw,
283 xz - yw, yz + xw, Real(1) - xx - yy);
284 }
285
286 template <typename Real>
288 {
289 Real x2 = x + x, y2 = y + y, z2 = z + z;
290 Real xx = x2 * x, yy = y2 * y, zz = z2 * z;
291 Real xy = x2 * y, xz = x2 * z, xw = x2 * w;
292 Real yz = y2 * z, yw = y2 * w, zw = z2 * w;
293 Real entries[16];
294 entries[0] = Real(1) - yy - zz;
295 entries[1] = xy - zw;
296 entries[2] = xz + yw,
297 entries[3] = 0;
298 entries[4] = xy + zw;
299 entries[5] = Real(1) - xx - zz;
300 entries[6] = yz - xw;
301 entries[7] = 0;
302 entries[8] = xz - yw;
303 entries[9] = yz + xw;
304 entries[10] = Real(1) - xx - yy;
305 entries[11] = 0;
306 entries[12] = 0;
307 entries[13] = 0;
308 entries[14] = 0;
309 entries[15] = 1;
310 return SquareMatrix<Real, 4>(entries[0], entries[1], entries[2], entries[3],
311 entries[4], entries[5], entries[6], entries[7],
312 entries[8], entries[9], entries[10], entries[11],
313 entries[12], entries[13], entries[14], entries[15]);
314
315 }
316
317 template <typename Real>
319 {
320 Real tr = matrix(0, 0) + matrix(1, 1) + matrix(2, 2);
321 if (tr > 0.0)
322 {
323 Real s = glm::sqrt(tr + Real(1.0));
324 w = s * Real(0.5);
325 if (s != 0.0)
326 s = Real(0.5) / s;
327 x = s * (matrix(2, 1) - matrix(1, 2));
328 y = s * (matrix(0, 2) - matrix(2, 0));
329 z = s * (matrix(1, 0) - matrix(0, 1));
330 }
331 else
332 {
333 int i = 0, j, k;
334 int next[3] = { 1, 2, 0 };
335 Real q[4];
336 if (matrix(1, 1) > matrix(0, 0)) i = 1;
337 if (matrix(2, 2) > matrix(i, i)) i = 2;
338 j = next[i];
339 k = next[j];
340 Real s = glm::sqrt(matrix(i, i) - matrix(j, j) - matrix(k, k) + Real(1.0));
341 q[i] = s * Real(0.5);
342 if (s != 0.0)
343 s = Real(0.5) / s;
344 q[3] = s * (matrix(k, j) - matrix(j, k));
345 q[j] = s * (matrix(j, i) + matrix(i, j));
346 q[k] = s * (matrix(k, i) + matrix(i, k));
347 x = q[0];
348 y = q[1];
349 z = q[2];
350 w = q[3];
351 }
352 }
353
354 template <typename Real>
356 {
357 Real tr = matrix(0, 0) + matrix(1, 1) + matrix(2, 2);
358 if (tr > 0.0)
359 {
360 Real s = glm::sqrt(tr + Real(1.0));
361 w = s * Real(0.5);
362 if (s != 0.0)
363 s = Real(0.5) / s;
364 x = s * (matrix(2, 1) - matrix(1, 2));
365 y = s * (matrix(0, 2) - matrix(2, 0));
366 z = s * (matrix(1, 0) - matrix(0, 1));
367 }
368 else
369 {
370 int i = 0, j, k;
371 int next[3] = { 1, 2, 0 };
372 Real q[4];
373 if (matrix(1, 1) > matrix(0, 0)) i = 1;
374 if (matrix(2, 2) > matrix(i, i)) i = 2;
375 j = next[i];
376 k = next[j];
377 Real s = glm::sqrt(matrix(i, i) - matrix(j, j) - matrix(k, k) + Real(1.0));
378 q[i] = s * Real(0.5);
379 if (s != 0.0)
380 s = Real(0.5) / s;
381 q[3] = s * (matrix(k, j) - matrix(j, k));
382 q[j] = s * (matrix(j, i) + matrix(i, j));
383 q[k] = s * (matrix(k, i) + matrix(i, k));
384 x = q[0];
385 y = q[1];
386 z = q[2];
387 w = q[3];
388 }
389 }
390
391 template <typename Real>
392 DYN_FUNC void Quat<Real>::toRotationAxis(Real& rot, Vector<Real, 3>& axis) const
393 {
394 rot = Real(2) * glm::acos(w);
395 if (glm::abs(rot) < EPSILON) {
396 axis[0] = Real(0); axis[1] = Real(0); axis[2] = Real(1);
397 return;
398 }
399 axis[0] = x;
400 axis[1] = y;
401 axis[2] = z;
402 axis.normalize();
403 }
404
405 //template class Quat<float>;
406 //template class Quat<double>;
408 //typedef Quat<float> Quat1f;
409 //typedef Quat<double> Quat1d;
410}
double Real
Definition Typedef.inl:23
#define M_PI
Definition Typedef.inl:36
DYN_FUNC Quat< Real > & operator-=(const Quat< Real > &)
Definition Quat.inl:98
DYN_FUNC Quat< float > & normalize()
DYN_FUNC Quat< Real > operator-(void) const
Definition Quat.inl:114
DYN_FUNC void toRotationAxis(Real &rot, Vector< Real, 3 > &axis) const
Definition Quat.inl:392
DYN_FUNC Real normSquared() const
Definition Quat.inl:177
Real z
Definition Quat.h:123
DYN_FUNC Quat< Real > conjugate() const
Definition Quat.inl:252
DYN_FUNC Quat< Real > inverse() const
Definition Quat.inl:201
DYN_FUNC Quat< Real > operator/(const Real &) const
Definition Quat.inl:146
DYN_FUNC Quat< Real > operator+(const Quat< Real > &) const
Definition Quat.inl:120
DYN_FUNC bool operator==(const Quat< Real > &) const
Definition Quat.inl:152
Real y
Definition Quat.h:123
Real x
Definition Quat.h:123
DYN_FUNC Real dot(const Quat< Real > &) const
Definition Quat.inl:246
DYN_FUNC Quat< Real > & operator=(const Quat< Real > &)
Definition Quat.inl:78
DYN_FUNC void toEulerAngle(Real &yaw, Real &pitch, Real &roll) const
Definition Quat.inl:207
Real w
Definition Quat.h:123
DYN_FUNC Real norm() const
Definition Quat.inl:168
DYN_FUNC Quat< Real > operator*(const Quat< Real > &) const
Definition Quat.inl:132
DYN_FUNC Real angle() const
Definition Quat.inl:231
DYN_FUNC SquareMatrix< Real, 3 > toMatrix3x3() const
Definition Quat.inl:275
DYN_FUNC Quat< Real > & operator+=(const Quat< Real > &)
Definition Quat.inl:88
DYN_FUNC bool operator!=(const Quat< Real > &) const
Definition Quat.inl:160
DYN_FUNC Vector< Real, 3 > rotate(const Vector< Real, 3 > &v) const
Rotate a vector by the quaternion, guarantee the quaternion is normalized before rotating the vector.
Definition Quat.inl:259
DYN_FUNC Quat()
Definition Quat.inl:11
DYN_FUNC SquareMatrix< Real, 4 > toMatrix4x4() const
Definition Quat.inl:287
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
DYN_FUNC T dot(Vector< T, 2 > const &U, Vector< T, 2 > const &V)
Definition SimpleMath.h:199
constexpr Real EPSILON
Definition Typedef.inl:42
vgm::Quat quat
Definition vgMath.h:633