Atoms Crowd  7.0.0
ImathQuat.h
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 //
7 // A quaternion
8 //
9 // "Quaternions came from Hamilton ... and have been an unmixed
10 // evil to those who have touched them in any way. Vector is a
11 // useless survival ... and has never been of the slightest use
12 // to any creature."
13 //
14 // - Lord Kelvin
15 //
16 
17 #ifndef INCLUDED_ATOMSMATHQUAT_H
18 #define INCLUDED_ATOMSMATHQUAT_H
19 
20 #include <AtomsMath/ImathMatrix.h>
21 #include <AtomsMath/ImathNamespace.h>
22 
23 #include <algorithm>
24 #include <iostream>
25 
26 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_ENTER
27 
28 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
29 // Disable MS VC++ warnings about conversion from double to float
30 # pragma warning(disable : 4244)
31 #endif
32 
39 
40 template <class T> class Quat
41 {
42  public:
43 
46 
48  T r;
49 
52 
54 
57  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T& operator[] (int index) noexcept; // as 4D vector
58 
61  ATOMSMATH_HOSTDEVICE constexpr T operator[] (int index) const noexcept;
62 
65 
67  ATOMSMATH_HOSTDEVICE constexpr Quat() noexcept;
68 
70  ATOMSMATH_HOSTDEVICE constexpr Quat (const Quat& q) noexcept;
71 
73  template <class S> ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat (const Quat<S>& q) noexcept;
74 
76  ATOMSMATH_HOSTDEVICE constexpr Quat (T s, T i, T j, T k) noexcept;
77 
79  ATOMSMATH_HOSTDEVICE constexpr Quat (T s, Vec3<T> d) noexcept;
80 
82  ATOMSMATH_HOSTDEVICE constexpr static Quat<T> identity() noexcept;
83 
85  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat<T>& operator= (const Quat<T>& q) noexcept;
86 
88  ~Quat() noexcept = default;
89 
91 
96  //
97 
99  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat<T>& operator*= (const Quat<T>& q) noexcept;
100 
103  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat<T>& operator*= (T t) noexcept;
104 
106  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat<T>& operator/= (const Quat<T>& q) noexcept;
107 
110  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat<T>& operator/= (T t) noexcept;
111 
113  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat<T>& operator+= (const Quat<T>& q) noexcept;
114 
116  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat<T>& operator-= (const Quat<T>& q) noexcept;
117 
119  template <class S> ATOMSMATH_HOSTDEVICE constexpr bool operator== (const Quat<S>& q) const noexcept;
120 
122  template <class S> ATOMSMATH_HOSTDEVICE constexpr bool operator!= (const Quat<S>& q) const noexcept;
123 
125 
126 
129 
131  ATOMSMATH_HOSTDEVICE constexpr T length() const noexcept; // in R4
132 
134  ATOMSMATH_HOSTDEVICE constexpr T angle() const noexcept;
135 
137  ATOMSMATH_HOSTDEVICE constexpr Vec3<T> axis() const noexcept;
138 
140  ATOMSMATH_HOSTDEVICE constexpr Matrix33<T> toMatrix33() const noexcept;
141 
143  ATOMSMATH_HOSTDEVICE constexpr Matrix44<T> toMatrix44() const noexcept;
144 
146  ATOMSMATH_HOSTDEVICE Quat<T> log() const noexcept;
147 
149  ATOMSMATH_HOSTDEVICE Quat<T> exp() const noexcept;
150 
152 
155 
158  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat<T>& invert() noexcept;
159 
161  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat<T> inverse() const noexcept;
162 
165  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat<T>& normalize() noexcept;
166 
168  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat<T> normalized() const noexcept;
169 
171  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Vec3<T> rotateVector (const Vec3<T>& original) const noexcept;
172 
174  ATOMSMATH_HOSTDEVICE constexpr T euclideanInnerProduct (const Quat<T>& q) const noexcept;
175 
179  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat<T>& setAxisAngle (const Vec3<T>& axis, T radians) noexcept;
180 
184  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat<T>&
185  setRotation (const Vec3<T>& fromDirection, const Vec3<T>& toDirection) noexcept;
186 
188 
191  typedef T BaseType;
192 
193  private:
194  ATOMSMATH_HOSTDEVICE void setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q) noexcept;
195 };
196 
197 template <class T> ATOMSMATH_CONSTEXPR14 Quat<T> slerp (const Quat<T>& q1, const Quat<T>& q2, T t) noexcept;
198 
199 template <class T>
200 ATOMSMATH_CONSTEXPR14 Quat<T> slerpShortestArc (const Quat<T>& q1, const Quat<T>& q2, T t) noexcept;
201 
202 template <class T>
203 ATOMSMATH_CONSTEXPR14 Quat<T>
204 squad (const Quat<T>& q1, const Quat<T>& q2, const Quat<T>& qa, const Quat<T>& qb, T t) noexcept;
205 
212 template <class T>
213 void intermediate (const Quat<T>& q0,
214  const Quat<T>& q1,
215  const Quat<T>& q2,
216  const Quat<T>& q3,
217  Quat<T>& qa,
218  Quat<T>& qb) noexcept;
219 
220 template <class T> constexpr Matrix33<T> operator* (const Matrix33<T>& M, const Quat<T>& q) noexcept;
221 
222 template <class T> constexpr Matrix33<T> operator* (const Quat<T>& q, const Matrix33<T>& M) noexcept;
223 
224 template <class T> std::ostream& operator<< (std::ostream& o, const Quat<T>& q);
225 
226 template <class T> constexpr Quat<T> operator* (const Quat<T>& q1, const Quat<T>& q2) noexcept;
227 
228 template <class T> constexpr Quat<T> operator/ (const Quat<T>& q1, const Quat<T>& q2) noexcept;
229 
230 template <class T> constexpr Quat<T> operator/ (const Quat<T>& q, T t) noexcept;
231 
232 template <class T> constexpr Quat<T> operator* (const Quat<T>& q, T t) noexcept;
233 
234 template <class T> constexpr Quat<T> operator* (T t, const Quat<T>& q) noexcept;
235 
236 template <class T> constexpr Quat<T> operator+ (const Quat<T>& q1, const Quat<T>& q2) noexcept;
237 
238 template <class T> constexpr Quat<T> operator- (const Quat<T>& q1, const Quat<T>& q2) noexcept;
239 
240 template <class T> constexpr Quat<T> operator~ (const Quat<T>& q) noexcept;
241 
242 template <class T> constexpr Quat<T> operator- (const Quat<T>& q) noexcept;
243 
244 template <class T> ATOMSMATH_CONSTEXPR14 Vec3<T> operator* (const Vec3<T>& v, const Quat<T>& q) noexcept;
245 
247 typedef Quat<float> Quatf;
248 
250 typedef Quat<double> Quatd;
251 
252 //---------------
253 // Implementation
254 //---------------
255 
256 template <class T> constexpr inline Quat<T>::Quat() noexcept : r (1), v (0, 0, 0)
257 {
258  // empty
259 }
260 
261 template <class T>
262 template <class S>
263 ATOMSMATH_CONSTEXPR14 inline Quat<T>::Quat (const Quat<S>& q) noexcept : r (q.r), v (q.v)
264 {
265  // empty
266 }
267 
268 template <class T> constexpr inline Quat<T>::Quat (T s, T i, T j, T k) noexcept : r (s), v (i, j, k)
269 {
270  // empty
271 }
272 
273 template <class T> constexpr inline Quat<T>::Quat (T s, Vec3<T> d) noexcept : r (s), v (d)
274 {
275  // empty
276 }
277 
278 template <class T> constexpr inline Quat<T>::Quat (const Quat<T>& q) noexcept : r (q.r), v (q.v)
279 {
280  // empty
281 }
282 
283 template <class T>
284 constexpr inline Quat<T>
286 {
287  return Quat<T>();
288 }
289 
290 template <class T>
291 ATOMSMATH_CONSTEXPR14 inline const Quat<T>&
292 Quat<T>::operator= (const Quat<T>& q) noexcept
293 {
294  r = q.r;
295  v = q.v;
296  return *this;
297 }
298 
299 template <class T>
300 ATOMSMATH_CONSTEXPR14 inline const Quat<T>&
301 Quat<T>::operator*= (const Quat<T>& q) noexcept
302 {
303  T rtmp = r * q.r - (v ^ q.v);
304  v = r * q.v + v * q.r + v % q.v;
305  r = rtmp;
306  return *this;
307 }
308 
309 template <class T>
310 ATOMSMATH_CONSTEXPR14 inline const Quat<T>&
311 Quat<T>::operator*= (T t) noexcept
312 {
313  r *= t;
314  v *= t;
315  return *this;
316 }
317 
318 template <class T>
319 ATOMSMATH_CONSTEXPR14 inline const Quat<T>&
320 Quat<T>::operator/= (const Quat<T>& q) noexcept
321 {
322  *this = *this * q.inverse();
323  return *this;
324 }
325 
326 template <class T>
327 ATOMSMATH_CONSTEXPR14 inline const Quat<T>&
328 Quat<T>::operator/= (T t) noexcept
329 {
330  r /= t;
331  v /= t;
332  return *this;
333 }
334 
335 template <class T>
336 ATOMSMATH_CONSTEXPR14 inline const Quat<T>&
337 Quat<T>::operator+= (const Quat<T>& q) noexcept
338 {
339  r += q.r;
340  v += q.v;
341  return *this;
342 }
343 
344 template <class T>
345 ATOMSMATH_CONSTEXPR14 inline const Quat<T>&
346 Quat<T>::operator-= (const Quat<T>& q) noexcept
347 {
348  r -= q.r;
349  v -= q.v;
350  return *this;
351 }
352 
353 template <class T>
354 ATOMSMATH_CONSTEXPR14 inline T&
355 Quat<T>::operator[] (int index) noexcept
356 {
357  return index ? v[index - 1] : r;
358 }
359 
360 template <class T>
361 constexpr inline T
362 Quat<T>::operator[] (int index) const noexcept
363 {
364  return index ? v[index - 1] : r;
365 }
366 
367 template <class T>
368 template <class S>
369 constexpr inline bool
370 Quat<T>::operator== (const Quat<S>& q) const noexcept
371 {
372  return r == q.r && v == q.v;
373 }
374 
375 template <class T>
376 template <class S>
377 constexpr inline bool
378 Quat<T>::operator!= (const Quat<S>& q) const noexcept
379 {
380  return r != q.r || v != q.v;
381 }
382 
384 template <class T>
385 ATOMSMATH_HOSTDEVICE constexpr inline T
386 operator^ (const Quat<T>& q1, const Quat<T>& q2) noexcept
387 {
388  return q1.r * q2.r + (q1.v ^ q2.v);
389 }
390 
391 template <class T>
392 constexpr inline T
393 Quat<T>::length() const noexcept
394 {
395  return std::sqrt (r * r + (v ^ v));
396 }
397 
398 template <class T>
399 ATOMSMATH_CONSTEXPR14 inline Quat<T>&
401 {
402  if (T l = length())
403  {
404  r /= l;
405  v /= l;
406  }
407  else
408  {
409  r = 1;
410  v = Vec3<T> (0);
411  }
412 
413  return *this;
414 }
415 
416 template <class T>
417 ATOMSMATH_CONSTEXPR14 inline Quat<T>
418 Quat<T>::normalized() const noexcept
419 {
420  if (T l = length())
421  return Quat (r / l, v / l);
422 
423  return Quat();
424 }
425 
426 template <class T>
427 ATOMSMATH_CONSTEXPR14 inline Quat<T>
428 Quat<T>::inverse() const noexcept
429 {
430  //
431  // 1 Q*
432  // - = ---- where Q* is conjugate (operator~)
433  // Q Q* Q and (Q* Q) == Q ^ Q (4D dot)
434  //
435 
436  T qdot = *this ^ *this;
437  return Quat (r / qdot, -v / qdot);
438 }
439 
440 template <class T>
441 ATOMSMATH_CONSTEXPR14 inline Quat<T>&
442 Quat<T>::invert() noexcept
443 {
444  T qdot = (*this) ^ (*this);
445  r /= qdot;
446  v = -v / qdot;
447  return *this;
448 }
449 
450 template <class T>
451 ATOMSMATH_CONSTEXPR14 inline Vec3<T>
452 Quat<T>::rotateVector (const Vec3<T>& original) const noexcept
453 {
454  //
455  // Given a vector p and a quaternion q (aka this),
456  // calculate p' = qpq*
457  //
458  // Assumes unit quaternions (because non-unit
459  // quaternions cannot be used to rotate vectors
460  // anyway).
461  //
462 
463  Quat<T> vec (0, original); // temporarily promote grade of original
464  Quat<T> inv (*this);
465  inv.v *= -1; // unit multiplicative inverse
466  Quat<T> result = *this * vec * inv;
467  return result.v;
468 }
469 
470 template <class T>
471 constexpr inline T
472 Quat<T>::euclideanInnerProduct (const Quat<T>& q) const noexcept
473 {
474  return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z;
475 }
476 
480 template <class T>
481 ATOMSMATH_CONSTEXPR14 inline T
482 angle4D (const Quat<T>& q1, const Quat<T>& q2) noexcept
483 {
484  Quat<T> d = q1 - q2;
485  T lengthD = std::sqrt (d ^ d);
486 
487  Quat<T> s = q1 + q2;
488  T lengthS = std::sqrt (s ^ s);
489 
490  return 2 * std::atan2 (lengthD, lengthS);
491 }
492 
510 template <class T>
511 ATOMSMATH_CONSTEXPR14 inline Quat<T>
512 slerp (const Quat<T>& q1, const Quat<T>& q2, T t) noexcept
513 {
514  T a = angle4D (q1, q2);
515  T s = 1 - t;
516 
517  Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 +
518  sinx_over_x (t * a) / sinx_over_x (a) * t * q2;
519 
520  return q.normalized();
521 }
522 
527 template <class T>
528 ATOMSMATH_CONSTEXPR14 inline Quat<T>
529 slerpShortestArc (const Quat<T>& q1, const Quat<T>& q2, T t) noexcept
530 {
531  if ((q1 ^ q2) >= 0)
532  return slerp (q1, q2, t);
533  else
534  return slerp (q1, -q2, t);
535 }
536 
555 template <class T>
556 ATOMSMATH_CONSTEXPR14 inline Quat<T>
557 spline (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2, const Quat<T>& q3, T t) noexcept
558 {
559  Quat<T> qa = intermediate (q0, q1, q2);
560  Quat<T> qb = intermediate (q1, q2, q3);
561  Quat<T> result = squad (q1, qa, qb, q2, t);
562 
563  return result;
564 }
565 
573 template <class T>
574 ATOMSMATH_CONSTEXPR14 inline Quat<T>
575 squad (const Quat<T>& q1, const Quat<T>& qa, const Quat<T>& qb, const Quat<T>& q2, T t) noexcept
576 {
577  Quat<T> r1 = slerp (q1, q2, t);
578  Quat<T> r2 = slerp (qa, qb, t);
579  Quat<T> result = slerp (r1, r2, 2 * t * (1 - t));
580 
581  return result;
582 }
583 
586 template <class T>
587 ATOMSMATH_CONSTEXPR14 inline Quat<T>
588 intermediate (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2) noexcept
589 {
590  Quat<T> q1inv = q1.inverse();
591  Quat<T> c1 = q1inv * q2;
592  Quat<T> c2 = q1inv * q0;
593  Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log());
594  Quat<T> qa = q1 * c3.exp();
595  qa.normalize();
596  return qa;
597 }
598 
599 template <class T>
600 inline Quat<T>
601 Quat<T>::log() const noexcept
602 {
603  //
604  // For unit quaternion, from Advanced Animation and
605  // Rendering Techniques by Watt and Watt, Page 366:
606  //
607 
608  T theta = std::acos (std::min (r, (T) 1.0));
609 
610  if (theta == 0)
611  return Quat<T> (0, v);
612 
613  T sintheta = std::sin (theta);
614 
615  T k;
616  if (std::abs(sintheta) < 1 && std::abs(theta) >= std::numeric_limits<T>::max() * std::abs(sintheta))
617  k = 1;
618  else
619  k = theta / sintheta;
620 
621  return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k);
622 }
623 
624 template <class T>
625 inline Quat<T>
626 Quat<T>::exp() const noexcept
627 {
628  //
629  // For pure quaternion (zero scalar part):
630  // from Advanced Animation and Rendering
631  // Techniques by Watt and Watt, Page 366:
632  //
633 
634  T theta = v.length();
635  T sintheta = std::sin (theta);
636 
637  T k;
638  if (abs (theta) < 1 && abs (sintheta) >= std::numeric_limits<T>::max() * abs (theta))
639  k = 1;
640  else
641  k = sintheta / theta;
642 
643  T costheta = std::cos (theta);
644 
645  return Quat<T> (costheta, v.x * k, v.y * k, v.z * k);
646 }
647 
648 template <class T>
649 constexpr inline T
650 Quat<T>::angle() const noexcept
651 {
652  return 2 * std::atan2 (v.length(), r);
653 }
654 
655 template <class T>
656 constexpr inline Vec3<T>
657 Quat<T>::axis() const noexcept
658 {
659  return v.normalized();
660 }
661 
662 template <class T>
663 ATOMSMATH_CONSTEXPR14 inline Quat<T>&
664 Quat<T>::setAxisAngle (const Vec3<T>& axis, T radians) noexcept
665 {
666  r = std::cos (radians / 2);
667  v = axis.normalized() * std::sin (radians / 2);
668  return *this;
669 }
670 
671 template <class T>
672 ATOMSMATH_CONSTEXPR14 inline Quat<T>&
673 Quat<T>::setRotation (const Vec3<T>& from, const Vec3<T>& to) noexcept
674 {
675  //
676  // Create a quaternion that rotates vector from into vector to,
677  // such that the rotation is around an axis that is the cross
678  // product of from and to.
679  //
680  // This function calls function setRotationInternal(), which is
681  // numerically accurate only for rotation angles that are not much
682  // greater than pi/2. In order to achieve good accuracy for angles
683  // greater than pi/2, we split large angles in half, and rotate in
684  // two steps.
685  //
686 
687  //
688  // Normalize from and to, yielding f0 and t0.
689  //
690 
691  Vec3<T> f0 = from.normalized();
692  Vec3<T> t0 = to.normalized();
693 
694  if ((f0 ^ t0) >= 0)
695  {
696  //
697  // The rotation angle is less than or equal to pi/2.
698  //
699 
700  setRotationInternal (f0, t0, *this);
701  }
702  else
703  {
704  //
705  // The angle is greater than pi/2. After computing h0,
706  // which is halfway between f0 and t0, we rotate first
707  // from f0 to h0, then from h0 to t0.
708  //
709 
710  Vec3<T> h0 = (f0 + t0).normalized();
711 
712  if ((h0 ^ h0) != 0)
713  {
714  setRotationInternal (f0, h0, *this);
715 
716  Quat<T> q;
717  setRotationInternal (h0, t0, q);
718 
719  *this *= q;
720  }
721  else
722  {
723  //
724  // f0 and t0 point in exactly opposite directions.
725  // Pick an arbitrary axis that is orthogonal to f0,
726  // and rotate by pi.
727  //
728 
729  r = T (0);
730 
731  Vec3<T> f02 = f0 * f0;
732 
733  if (f02.x <= f02.y && f02.x <= f02.z)
734  v = (f0 % Vec3<T> (1, 0, 0)).normalized();
735  else if (f02.y <= f02.z)
736  v = (f0 % Vec3<T> (0, 1, 0)).normalized();
737  else
738  v = (f0 % Vec3<T> (0, 0, 1)).normalized();
739  }
740  }
741 
742  return *this;
743 }
744 
745 template <class T>
746 inline void
747 Quat<T>::setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q) noexcept
748 {
749  //
750  // The following is equivalent to setAxisAngle(n,2*phi),
751  // where the rotation axis, n, is orthogonal to the f0 and
752  // t0 vectors, and 2*phi is the angle between f0 and t0.
753  //
754  // This function is called by setRotation(), above; it assumes
755  // that f0 and t0 are normalized and that the angle between
756  // them is not much greater than pi/2. This function becomes
757  // numerically inaccurate if f0 and t0 point into nearly
758  // opposite directions.
759  //
760 
761  //
762  // Find a normalized vector, h0, that is halfway between f0 and t0.
763  // The angle between f0 and h0 is phi.
764  //
765 
766  Vec3<T> h0 = (f0 + t0).normalized();
767 
768  //
769  // Store the rotation axis and rotation angle.
770  //
771 
772  q.r = f0 ^ h0; // f0 ^ h0 == cos (phi)
773  q.v = f0 % h0; // (f0 % h0).length() == sin (phi)
774 }
775 
776 template <class T>
777 constexpr inline Matrix33<T>
778 Quat<T>::toMatrix33() const noexcept
779 {
780  return Matrix33<T> (1 - 2 * (v.y * v.y + v.z * v.z),
781  2 * (v.x * v.y + v.z * r),
782  2 * (v.z * v.x - v.y * r),
783 
784  2 * (v.x * v.y - v.z * r),
785  1 - 2 * (v.z * v.z + v.x * v.x),
786  2 * (v.y * v.z + v.x * r),
787 
788  2 * (v.z * v.x + v.y * r),
789  2 * (v.y * v.z - v.x * r),
790  1 - 2 * (v.y * v.y + v.x * v.x));
791 }
792 
793 template <class T>
794 constexpr inline Matrix44<T>
795 Quat<T>::toMatrix44() const noexcept
796 {
797  return Matrix44<T> (1 - 2 * (v.y * v.y + v.z * v.z),
798  2 * (v.x * v.y + v.z * r),
799  2 * (v.z * v.x - v.y * r),
800  0,
801  2 * (v.x * v.y - v.z * r),
802  1 - 2 * (v.z * v.z + v.x * v.x),
803  2 * (v.y * v.z + v.x * r),
804  0,
805  2 * (v.z * v.x + v.y * r),
806  2 * (v.y * v.z - v.x * r),
807  1 - 2 * (v.y * v.y + v.x * v.x),
808  0,
809  0,
810  0,
811  0,
812  1);
813 }
814 
817 template <class T>
818 constexpr inline Matrix33<T>
819 operator* (const Matrix33<T>& M, const Quat<T>& q) noexcept
820 {
821  return M * q.toMatrix33();
822 }
823 
826 template <class T>
827 constexpr inline Matrix33<T>
828 operator* (const Quat<T>& q, const Matrix33<T>& M) noexcept
829 {
830  return q.toMatrix33() * M;
831 }
832 
834 template <class T>
835 std::ostream&
836 operator<< (std::ostream& o, const Quat<T>& q)
837 {
838  return o << "(" << q.r << ", " << q.v.x << ", " << q.v.y << ", " << q.v.z << ")";
839 }
840 
842 template <class T>
843 constexpr inline Quat<T>
844 operator* (const Quat<T>& q1, const Quat<T>& q2) noexcept
845 {
846  return Quat<T> (q1.r * q2.r - (q1.v ^ q2.v), q1.r * q2.v + q1.v * q2.r + q1.v % q2.v);
847 }
848 
850 template <class T>
851 constexpr inline Quat<T>
852 operator/ (const Quat<T>& q1, const Quat<T>& q2) noexcept
853 {
854  return q1 * q2.inverse();
855 }
856 
858 template <class T>
859 constexpr inline Quat<T>
860 operator/ (const Quat<T>& q, T t) noexcept
861 {
862  return Quat<T> (q.r / t, q.v / t);
863 }
864 
867 template <class T>
868 constexpr inline Quat<T>
869 operator* (const Quat<T>& q, T t) noexcept
870 {
871  return Quat<T> (q.r * t, q.v * t);
872 }
873 
876 template <class T>
877 constexpr inline Quat<T>
878 operator* (T t, const Quat<T>& q) noexcept
879 {
880  return Quat<T> (q.r * t, q.v * t);
881 }
882 
884 template <class T>
885 constexpr inline Quat<T>
886 operator+ (const Quat<T>& q1, const Quat<T>& q2) noexcept
887 {
888  return Quat<T> (q1.r + q2.r, q1.v + q2.v);
889 }
890 
892 template <class T>
893 constexpr inline Quat<T>
894 operator- (const Quat<T>& q1, const Quat<T>& q2) noexcept
895 {
896  return Quat<T> (q1.r - q2.r, q1.v - q2.v);
897 }
898 
900 template <class T>
901 constexpr inline Quat<T>
902 operator~ (const Quat<T>& q) noexcept
903 {
904  return Quat<T> (q.r, -q.v);
905 }
906 
908 template <class T>
909 constexpr inline Quat<T>
910 operator- (const Quat<T>& q) noexcept
911 {
912  return Quat<T> (-q.r, -q.v);
913 }
914 
917 template <class T>
918 ATOMSMATH_CONSTEXPR14 inline Vec3<T>
919 operator* (const Vec3<T>& v, const Quat<T>& q) noexcept
920 {
921  Vec3<T> a = q.v % v;
922  Vec3<T> b = q.v % a;
923  return v + T (2) * (q.r * a + b);
924 }
925 
926 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
927 # pragma warning(default : 4244)
928 #endif
929 
930 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_EXIT
931 
932 #endif // INCLUDED_ATOMSMATHQUAT_H
Definition: ImathMatrix.h:305
Definition: ImathMatrix.h:631
Definition: ImathQuat.h:41
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat< T > & setRotation(const Vec3< T > &fromDirection, const Vec3< T > &toDirection) noexcept
Definition: ImathQuat.h:673
constexpr ATOMSMATH_HOSTDEVICE T euclideanInnerProduct(const Quat< T > &q) const noexcept
Return the Euclidean inner product.
Definition: ImathQuat.h:472
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat< T > & operator/=(const Quat< T > &q) noexcept
Quaterion division, using the inverse()
Definition: ImathQuat.h:320
constexpr ATOMSMATH_HOSTDEVICE bool operator==(const Quat< S > &q) const noexcept
Equality.
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat< T > & operator-=(const Quat< T > &q) noexcept
Quaternion subtraction.
Definition: ImathQuat.h:346
Vec3< T > v
The imaginary vector.
Definition: ImathQuat.h:51
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat< T > & invert() noexcept
Definition: ImathQuat.h:442
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat< T > & operator+=(const Quat< T > &q) noexcept
Quaternion addition.
Definition: ImathQuat.h:337
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat< T > & operator=(const Quat< T > &q) noexcept
Assignment.
Definition: ImathQuat.h:292
constexpr ATOMSMATH_HOSTDEVICE T length() const noexcept
Return the R4 length.
Definition: ImathQuat.h:393
ATOMSMATH_HOSTDEVICE Quat< T > log() const noexcept
Return the logarithm of the quaterion.
Definition: ImathQuat.h:601
constexpr ATOMSMATH_HOSTDEVICE Quat() noexcept
Default constructor is the identity quat.
Definition: ImathQuat.h:256
ATOMSMATH_HOSTDEVICE Quat< T > exp() const noexcept
Return the exponent of the quaterion.
Definition: ImathQuat.h:626
constexpr ATOMSMATH_HOSTDEVICE T angle() const noexcept
Return the angle of the axis/angle representation.
Definition: ImathQuat.h:650
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat< T > inverse() const noexcept
Return 1/this, leaving this unchanged.
Definition: ImathQuat.h:428
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat< T > normalized() const noexcept
Return a normalized quaternion, leaving this unmodified.
Definition: ImathQuat.h:418
T r
The real part.
Definition: ImathQuat.h:48
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Quat< T > & operator*=(const Quat< T > &q) noexcept
Quaternion multiplication.
Definition: ImathQuat.h:301
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat< T > & setAxisAngle(const Vec3< T > &axis, T radians) noexcept
Definition: ImathQuat.h:664
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T & operator[](int index) noexcept
Definition: ImathQuat.h:355
constexpr ATOMSMATH_HOSTDEVICE bool operator!=(const Quat< S > &q) const noexcept
Inequality.
constexpr ATOMSMATH_HOSTDEVICE Matrix33< T > toMatrix33() const noexcept
Return a 3x3 rotation matrix.
Definition: ImathQuat.h:778
constexpr static ATOMSMATH_HOSTDEVICE Quat< T > identity() noexcept
The identity quaternion.
Definition: ImathQuat.h:285
constexpr ATOMSMATH_HOSTDEVICE Vec3< T > axis() const noexcept
Return the axis of the axis/angle representation.
Definition: ImathQuat.h:657
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Vec3< T > rotateVector(const Vec3< T > &original) const noexcept
Rotate the given point by the quaterion.
Definition: ImathQuat.h:452
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Quat< T > & normalize() noexcept
Definition: ImathQuat.h:400
T BaseType
Definition: ImathQuat.h:191
constexpr ATOMSMATH_HOSTDEVICE Matrix44< T > toMatrix44() const noexcept
Return a 4x4 rotation matrix.
Definition: ImathQuat.h:795
Definition: ImathVec.h:260
ATOMSMATH_HOSTDEVICE Vec3< T > normalized() const noexcept
Return a normalized vector. Does not modify *this.
Definition: ImathVec.h:1629