HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImathQuat.h
Go to the documentation of this file.
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_IMATHQUAT_H
18 #define INCLUDED_IMATHQUAT_H
19 
20 #include "ImathExport.h"
21 #include "ImathNamespace.h"
22 
23 #include "ImathMatrix.h"
24 
25 #include <iostream>
26 
27 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
28 
29 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
30 // Disable MS VC++ warnings about conversion from double to float
31 # pragma warning(push)
32 # pragma warning(disable : 4244)
33 #endif
34 
35 ///
36 /// The Quat class implements the quaternion numerical type -- you
37 /// will probably want to use this class to represent orientations
38 /// in R3 and to convert between various euler angle reps. You
39 /// should probably use Imath::Euler<> for that.
40 ///
41 
42 template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Quat
43 {
44 public:
45  using value_type = T;
46 
47  /// @{
48  /// @name Direct access to elements
49 
50  /// The real part
51  T r;
52 
53  /// The imaginary vector
55 
56  /// @}
57 
58  /// Element access: q[0] is the real part, (q[1],q[2],q[3]) is the
59  /// imaginary part.
60  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T&
61  operator[] (int index) IMATH_NOEXCEPT; // as 4D vector
62 
63  /// Element access: q[0] is the real part, (q[1],q[2],q[3]) is the
64  /// imaginary part.
65  IMATH_HOSTDEVICE constexpr T operator[] (int index) const IMATH_NOEXCEPT;
66 
67  /// @{
68  /// @name Constructors
69 
70  /// Default constructor is the identity quat
72 
73  /// Copy constructor
74  IMATH_HOSTDEVICE constexpr Quat (const Quat& q) IMATH_NOEXCEPT;
75 
76  /// Construct from a quaternion of a another base type
77  template <class S>
78  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat (const Quat<S>& q) IMATH_NOEXCEPT;
79 
80  /// Initialize with real part `s` and imaginary vector 1(i,j,k)`
81  IMATH_HOSTDEVICE constexpr Quat (T s, T i, T j, T k) IMATH_NOEXCEPT;
82 
83  /// Initialize with real part `s` and imaginary vector `d`
84  IMATH_HOSTDEVICE constexpr Quat (T s, Vec3<T> d) IMATH_NOEXCEPT;
85 
86  /// The identity quaternion
87  IMATH_HOSTDEVICE constexpr static Quat<T> identity () IMATH_NOEXCEPT;
88 
89  /// Assignment
90  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>&
91  operator= (const Quat<T>& q) IMATH_NOEXCEPT;
92 
93  /// Destructor
94  ~Quat () IMATH_NOEXCEPT = default;
95 
96  /// @}
97 
98  /// @{
99  /// @name Basic Algebra
100  ///
101  /// Note that the operator return values are *NOT* normalized
102  //
103 
104  /// Quaternion multiplication
105  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>&
106  operator*= (const Quat<T>& q) IMATH_NOEXCEPT;
107 
108  /// Scalar multiplication: multiply both real and imaginary parts
109  /// by the given scalar.
110  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>&
111  operator*= (T t) IMATH_NOEXCEPT;
112 
113  /// Quaterion division, using the inverse()
114  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>&
115  operator/= (const Quat<T>& q) IMATH_NOEXCEPT;
116 
117  /// Scalar division: multiply both real and imaginary parts
118  /// by the given scalar.
119  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>&
120  operator/= (T t) IMATH_NOEXCEPT;
121 
122  /// Quaternion addition
123  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>&
124  operator+= (const Quat<T>& q) IMATH_NOEXCEPT;
125 
126  /// Quaternion subtraction
127  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>&
128  operator-= (const Quat<T>& q) IMATH_NOEXCEPT;
129 
130  /// Equality
131  template <class S>
132  IMATH_HOSTDEVICE constexpr bool
133  operator== (const Quat<S>& q) const IMATH_NOEXCEPT;
134 
135  /// Inequality
136  template <class S>
137  IMATH_HOSTDEVICE constexpr bool
138  operator!= (const Quat<S>& q) const IMATH_NOEXCEPT;
139 
140  /// @}
141 
142  /// @{
143  /// @name Query
144 
145  /// Return the R4 length
146  IMATH_HOSTDEVICE constexpr T length () const IMATH_NOEXCEPT; // in R4
147 
148  /// Return the angle of the axis/angle representation
149  IMATH_HOSTDEVICE constexpr T angle () const IMATH_NOEXCEPT;
150 
151  /// Return the axis of the axis/angle representation
152  IMATH_HOSTDEVICE constexpr Vec3<T> axis () const IMATH_NOEXCEPT;
153 
154  /// Return a 3x3 rotation matrix
155  IMATH_HOSTDEVICE constexpr Matrix33<T> toMatrix33 () const IMATH_NOEXCEPT;
156 
157  /// Return a 4x4 rotation matrix
158  IMATH_HOSTDEVICE constexpr Matrix44<T> toMatrix44 () const IMATH_NOEXCEPT;
159 
160  /// Return the logarithm of the quaterion
161  IMATH_HOSTDEVICE Quat<T> log () const IMATH_NOEXCEPT;
162 
163  /// Return the exponent of the quaterion
164  IMATH_HOSTDEVICE Quat<T> exp () const IMATH_NOEXCEPT;
165 
166  /// @}
167 
168  /// @{
169  /// @name Utility Methods
170 
171  /// Invert in place: this = 1 / this.
172  /// @return const reference to this.
173  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& invert () IMATH_NOEXCEPT;
174 
175  /// Return 1/this, leaving this unchanged.
176  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> inverse () const IMATH_NOEXCEPT;
177 
178  /// Normalize in place
179  /// @return const reference to this.
180  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& normalize () IMATH_NOEXCEPT;
181 
182  /// Return a normalized quaternion, leaving this unmodified.
183  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>
184  normalized () const IMATH_NOEXCEPT;
185 
186  /// Rotate the given point by the quaterion.
187  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T>
188  rotateVector (const Vec3<T>& original) const IMATH_NOEXCEPT;
189 
190  /// Return the Euclidean inner product.
191  IMATH_HOSTDEVICE constexpr T
192  euclideanInnerProduct (const Quat<T>& q) const IMATH_NOEXCEPT;
193 
194  /// Set the quaterion to be a rotation around the given axis by the
195  /// given angle.
196  /// @return const reference to this.
197  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>&
198  setAxisAngle (const Vec3<T>& axis, T radians) IMATH_NOEXCEPT;
199 
200  /// Set the quaternion to be a rotation that transforms the
201  /// direction vector `fromDirection` to `toDirection`
202  /// @return const reference to this.
203  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>&
204  setRotation (const Vec3<T>& fromDirection, const Vec3<T>& toDirection)
205  IMATH_NOEXCEPT;
206 
207  /// @}
208 
209  /// The base type: In templates that accept a parameter `V`, you
210  /// can refer to `T` as `V::BaseType`
211  typedef T BaseType;
212 
213 private:
214  IMATH_HOSTDEVICE void setRotationInternal (
215  const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q) IMATH_NOEXCEPT;
216 };
217 
218 template <class T>
219 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>
220 slerp (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT;
221 
222 template <class T>
223 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>
224 slerpShortestArc (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT;
225 
226 template <class T>
227 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> squad (
228  const Quat<T>& q1,
229  const Quat<T>& q2,
230  const Quat<T>& qa,
231  const Quat<T>& qb,
232  T t) IMATH_NOEXCEPT;
233 
234 ///
235 /// From advanced Animation and Rendering Techniques by Watt and Watt,
236 /// Page 366:
237 ///
238 /// computing the inner quadrangle points (qa and qb) to guarantee
239 /// tangent continuity.
240 template <class T>
242  const Quat<T>& q0,
243  const Quat<T>& q1,
244  const Quat<T>& q2,
245  const Quat<T>& q3,
246  Quat<T>& qa,
247  Quat<T>& qb) IMATH_NOEXCEPT;
248 
249 template <class T>
250 IMATH_HOSTDEVICE constexpr Matrix33<T>
251 operator* (const Matrix33<T>& M, const Quat<T>& q) IMATH_NOEXCEPT;
252 
253 template <class T>
254 IMATH_HOSTDEVICE constexpr Matrix33<T>
255 operator* (const Quat<T>& q, const Matrix33<T>& M) IMATH_NOEXCEPT;
256 
257 template <class T> std::ostream& operator<< (std::ostream& o, const Quat<T>& q);
258 
259 template <class T>
260 IMATH_HOSTDEVICE constexpr Quat<T>
261 operator* (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
262 
263 template <class T>
264 IMATH_HOSTDEVICE constexpr Quat<T>
265 operator/ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
266 
267 template <class T>
268 IMATH_HOSTDEVICE constexpr Quat<T>
269 operator/ (const Quat<T>& q, T t) IMATH_NOEXCEPT;
270 
271 template <class T>
272 IMATH_HOSTDEVICE constexpr Quat<T>
273 operator* (const Quat<T>& q, T t) IMATH_NOEXCEPT;
274 
275 template <class T>
276 IMATH_HOSTDEVICE constexpr Quat<T>
277 operator* (T t, const Quat<T>& q) IMATH_NOEXCEPT;
278 
279 template <class T>
280 IMATH_HOSTDEVICE constexpr Quat<T>
281 operator+ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
282 
283 template <class T>
284 IMATH_HOSTDEVICE constexpr Quat<T>
285 operator- (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT;
286 
287 template <class T>
288 IMATH_HOSTDEVICE constexpr Quat<T> operator~ (const Quat<T>& q) IMATH_NOEXCEPT;
289 
290 template <class T>
291 IMATH_HOSTDEVICE constexpr Quat<T> operator- (const Quat<T>& q) IMATH_NOEXCEPT;
292 
293 template <class T>
294 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T>
295 operator* (const Vec3<T>& v, const Quat<T>& q) IMATH_NOEXCEPT;
296 
297 /// Quaternion of type float
298 typedef Quat<float> Quatf;
299 
300 /// Quaternion of type double
301 typedef Quat<double> Quatd;
302 
303 //---------------
304 // Implementation
305 //---------------
306 
307 template <class T>
308 IMATH_HOSTDEVICE constexpr inline Quat<T>::Quat () IMATH_NOEXCEPT : r (1),
309  v (0, 0, 0)
310 {
311  // empty
312 }
313 
314 template <class T>
315 template <class S>
317  IMATH_CONSTEXPR14 inline Quat<T>::Quat (const Quat<S>& q) IMATH_NOEXCEPT
318  : r (q.r),
319  v (q.v)
320 {
321  // empty
322 }
323 
324 template <class T>
325 IMATH_HOSTDEVICE constexpr inline Quat<T>::Quat (T s, T i, T j, T k)
326  IMATH_NOEXCEPT : r (s),
327  v (i, j, k)
328 {
329  // empty
330 }
331 
332 template <class T>
334  : r (s),
335  v (d)
336 {
337  // empty
338 }
339 
340 template <class T>
341 IMATH_HOSTDEVICE constexpr inline Quat<T>::Quat (const Quat<T>& q)
342  IMATH_NOEXCEPT : r (q.r),
343  v (q.v)
344 {
345  // empty
346 }
347 
348 template <class T>
349 IMATH_HOSTDEVICE constexpr inline Quat<T>
351 {
352  return Quat<T> ();
353 }
354 
355 template <class T>
356 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
358 {
359  r = q.r;
360  v = q.v;
361  return *this;
362 }
363 
364 template <class T>
365 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
367 {
368  T rtmp = r * q.r - (v ^ q.v);
369  v = r * q.v + v * q.r + v % q.v;
370  r = rtmp;
371  return *this;
372 }
373 
374 template <class T>
375 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
377 {
378  r *= t;
379  v *= t;
380  return *this;
381 }
382 
383 template <class T>
384 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
386 {
387  *this = *this * q.inverse ();
388  return *this;
389 }
390 
391 template <class T>
392 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
394 {
395  r /= t;
396  v /= t;
397  return *this;
398 }
399 
400 template <class T>
401 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
403 {
404  r += q.r;
405  v += q.v;
406  return *this;
407 }
408 
409 template <class T>
410 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Quat<T>&
412 {
413  r -= q.r;
414  v -= q.v;
415  return *this;
416 }
417 
418 template <class T>
419 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T&
421 {
422  return index ? v[index - 1] : r;
423 }
424 
425 template <class T>
426 IMATH_HOSTDEVICE constexpr inline T
428 {
429  return index ? v[index - 1] : r;
430 }
431 
432 template <class T>
433 template <class S>
434 IMATH_HOSTDEVICE constexpr inline bool
436 {
437  return r == q.r && v == q.v;
438 }
439 
440 template <class T>
441 template <class S>
442 IMATH_HOSTDEVICE constexpr inline bool
444 {
445  return r != q.r || v != q.v;
446 }
447 
448 /// 4D dot product
449 template <class T>
450 IMATH_HOSTDEVICE constexpr inline T
452 {
453  return q1.r * q2.r + (q1.v ^ q2.v);
454 }
455 
456 template <class T>
457 IMATH_HOSTDEVICE constexpr inline T
459 {
460  return std::sqrt (r * r + (v ^ v));
461 }
462 
463 template <class T>
464 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
466 {
467  if (T l = length ())
468  {
469  r /= l;
470  v /= l;
471  }
472  else
473  {
474  r = 1;
475  v = Vec3<T> (0);
476  }
477 
478  return *this;
479 }
480 
481 template <class T>
482 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
484 {
485  if (T l = length ()) return Quat (r / l, v / l);
486 
487  return Quat ();
488 }
489 
490 template <class T>
491 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
493 {
494  //
495  // 1 Q*
496  // - = ---- where Q* is conjugate (operator~)
497  // Q Q* Q and (Q* Q) == Q ^ Q (4D dot)
498  //
499 
500  T qdot = *this ^ *this;
501  return Quat (r / qdot, -v / qdot);
502 }
503 
504 template <class T>
505 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
507 {
508  T qdot = (*this) ^ (*this);
509  r /= qdot;
510  v = -v / qdot;
511  return *this;
512 }
513 
514 template <class T>
515 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3<T>
517 {
518  //
519  // Given a vector p and a quaternion q (aka this),
520  // calculate p' = qpq*
521  //
522  // Assumes unit quaternions (because non-unit
523  // quaternions cannot be used to rotate vectors
524  // anyway).
525  //
526 
527  Quat<T> vec (0, original); // temporarily promote grade of original
528  Quat<T> inv (*this);
529  inv.v *= -1; // unit multiplicative inverse
530  Quat<T> result = *this * vec * inv;
531  return result.v;
532 }
533 
534 template <class T>
535 IMATH_HOSTDEVICE constexpr inline T
537 {
538  return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z;
539 }
540 
541 ///
542 /// Compute the angle between two quaternions,
543 /// interpreting the quaternions as 4D vectors.
544 template <class T>
545 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
546 angle4D (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT
547 {
548  Quat<T> d = q1 - q2;
549  T lengthD = std::sqrt (d ^ d);
550 
551  Quat<T> s = q1 + q2;
552  T lengthS = std::sqrt (s ^ s);
553 
554  return 2 * std::atan2 (lengthD, lengthS);
555 }
556 
557 ///
558 /// Spherical linear interpolation.
559 /// Assumes q1 and q2 are normalized and that q1 != -q2.
560 ///
561 /// This method does *not* interpolate along the shortest
562 /// arc between q1 and q2. If you desire interpolation
563 /// along the shortest arc, and q1^q2 is negative, then
564 /// consider calling slerpShortestArc(), below, or flipping
565 /// the second quaternion explicitly.
566 ///
567 /// The implementation of squad() depends on a slerp()
568 /// that interpolates as is, without the automatic
569 /// flipping.
570 ///
571 /// Don Hatch explains the method we use here on his
572 /// web page, The Right Way to Calculate Stuff, at
573 /// http://www.plunk.org/~hatch/rightway.php
574 template <class T>
575 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
576 slerp (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT
577 {
578  T a = angle4D (q1, q2);
579  T s = 1 - t;
580 
581  Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 +
582  sinx_over_x (t * a) / sinx_over_x (a) * t * q2;
583 
584  return q.normalized ();
585 }
586 
587 ///
588 /// Spherical linear interpolation along the shortest
589 /// arc from q1 to either q2 or -q2, whichever is closer.
590 /// Assumes q1 and q2 are unit quaternions.
591 template <class T>
592 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
594 {
595  if ((q1 ^ q2) >= 0)
596  return slerp (q1, q2, t);
597  else
598  return slerp (q1, -q2, t);
599 }
600 
601 ///
602 /// Spherical Cubic Spline Interpolation - from Advanced Animation and
603 /// Rendering Techniques by Watt and Watt, Page 366:
604 ///
605 /// A spherical curve is constructed using three spherical linear
606 /// interpolations of a quadrangle of unit quaternions: q1, qa, qb,
607 /// q2. Given a set of quaternion keys: q0, q1, q2, q3, this routine
608 /// does the interpolation between q1 and q2 by constructing two
609 /// intermediate quaternions: qa and qb. The qa and qb are computed by
610 /// the intermediate function to guarantee the continuity of tangents
611 /// across adjacent cubic segments. The qa represents in-tangent for
612 /// q1 and the qb represents the out-tangent for q2.
613 ///
614 /// The q1 q2 is the cubic segment being interpolated.
615 ///
616 /// The q0 is from the previous adjacent segment and q3 is from the
617 /// next adjacent segment. The q0 and q3 are used in computing qa and
618 /// qb.
619 template <class T>
620 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
622  const Quat<T>& q0,
623  const Quat<T>& q1,
624  const Quat<T>& q2,
625  const Quat<T>& q3,
627 {
628  Quat<T> qa = intermediate (q0, q1, q2);
629  Quat<T> qb = intermediate (q1, q2, q3);
630  Quat<T> result = squad (q1, qa, qb, q2, t);
631 
632  return result;
633 }
634 
635 ///
636 /// Spherical Quadrangle Interpolation - from Advanced Animation and
637 /// Rendering Techniques by Watt and Watt, Page 366:
638 ///
639 /// It constructs a spherical cubic interpolation as a series of three
640 /// spherical linear interpolations of a quadrangle of unit
641 /// quaternions.
642 template <class T>
643 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
645  const Quat<T>& q1,
646  const Quat<T>& qa,
647  const Quat<T>& qb,
648  const Quat<T>& q2,
650 {
651  Quat<T> r1 = slerp (q1, q2, t);
652  Quat<T> r2 = slerp (qa, qb, t);
653  Quat<T> result = slerp (r1, r2, 2 * t * (1 - t));
654 
655  return result;
656 }
657 
658 /// Compute the intermediate point between three quaternions `q0`, `q1`,
659 /// and `q2`.
660 template <class T>
661 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>
662 intermediate (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2)
664 {
665  Quat<T> q1inv = q1.inverse ();
666  Quat<T> c1 = q1inv * q2;
667  Quat<T> c2 = q1inv * q0;
668  Quat<T> c3 = (T) (-0.25) * (c2.log () + c1.log ());
669  Quat<T> qa = q1 * c3.exp ();
670  qa.normalize ();
671  return qa;
672 }
673 
674 template <class T>
677 {
678  //
679  // For unit quaternion, from Advanced Animation and
680  // Rendering Techniques by Watt and Watt, Page 366:
681  //
682 
683  T theta = std::acos (std::min (r, (T) 1.0));
684 
685  if (theta == 0) return Quat<T> (0, v);
686 
687  T sintheta = std::sin (theta);
688 
689  T k;
690  if (std::abs (sintheta) < 1 &&
691  std::abs (theta) >=
692  std::numeric_limits<T>::max () * std::abs (sintheta))
693  k = 1;
694  else
695  k = theta / sintheta;
696 
697  return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k);
698 }
699 
700 template <class T>
703 {
704  //
705  // For pure quaternion (zero scalar part):
706  // from Advanced Animation and Rendering
707  // Techniques by Watt and Watt, Page 366:
708  //
709 
710  T theta = v.length ();
711  T sintheta = std::sin (theta);
712 
713  T k;
714  if (abs (theta) < 1 &&
715  abs (sintheta) >= std::numeric_limits<T>::max () * abs (theta))
716  k = 1;
717  else
718  k = sintheta / theta;
719 
720  T costheta = std::cos (theta);
721 
722  return Quat<T> (costheta, v.x * k, v.y * k, v.z * k);
723 }
724 
725 template <class T>
726 IMATH_HOSTDEVICE constexpr inline T
728 {
729  return 2 * std::atan2 (v.length (), r);
730 }
731 
732 template <class T>
733 IMATH_HOSTDEVICE constexpr inline Vec3<T>
735 {
736  return v.normalized ();
737 }
738 
739 template <class T>
740 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
742 {
743  r = std::cos (radians / 2);
744  v = axis.normalized () * std::sin (radians / 2);
745  return *this;
746 }
747 
748 template <class T>
749 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Quat<T>&
751 {
752  //
753  // Create a quaternion that rotates vector from into vector to,
754  // such that the rotation is around an axis that is the cross
755  // product of from and to.
756  //
757  // This function calls function setRotationInternal(), which is
758  // numerically accurate only for rotation angles that are not much
759  // greater than pi/2. In order to achieve good accuracy for angles
760  // greater than pi/2, we split large angles in half, and rotate in
761  // two steps.
762  //
763 
764  //
765  // Normalize from and to, yielding f0 and t0.
766  //
767 
768  Vec3<T> f0 = from.normalized ();
769  Vec3<T> t0 = to.normalized ();
770 
771  if ((f0 ^ t0) >= 0)
772  {
773  //
774  // The rotation angle is less than or equal to pi/2.
775  //
776 
777  setRotationInternal (f0, t0, *this);
778  }
779  else
780  {
781  //
782  // The angle is greater than pi/2. After computing h0,
783  // which is halfway between f0 and t0, we rotate first
784  // from f0 to h0, then from h0 to t0.
785  //
786 
787  Vec3<T> h0 = (f0 + t0).normalized ();
788 
789  if ((h0 ^ h0) != 0)
790  {
791  setRotationInternal (f0, h0, *this);
792 
793  Quat<T> q;
794  setRotationInternal (h0, t0, q);
795 
796  *this *= q;
797  }
798  else
799  {
800  //
801  // f0 and t0 point in exactly opposite directions.
802  // Pick an arbitrary axis that is orthogonal to f0,
803  // and rotate by pi.
804  //
805 
806  r = T (0);
807 
808  Vec3<T> f02 = f0 * f0;
809 
810  if (f02.x <= f02.y && f02.x <= f02.z)
811  v = (f0 % Vec3<T> (1, 0, 0)).normalized ();
812  else if (f02.y <= f02.z)
813  v = (f0 % Vec3<T> (0, 1, 0)).normalized ();
814  else
815  v = (f0 % Vec3<T> (0, 0, 1)).normalized ();
816  }
817  }
818 
819  return *this;
820 }
821 
822 template <class T>
823 IMATH_HOSTDEVICE inline void
824 Quat<T>::setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q)
826 {
827  //
828  // The following is equivalent to setAxisAngle(n,2*phi),
829  // where the rotation axis, n, is orthogonal to the f0 and
830  // t0 vectors, and 2*phi is the angle between f0 and t0.
831  //
832  // This function is called by setRotation(), above; it assumes
833  // that f0 and t0 are normalized and that the angle between
834  // them is not much greater than pi/2. This function becomes
835  // numerically inaccurate if f0 and t0 point into nearly
836  // opposite directions.
837  //
838 
839  //
840  // Find a normalized vector, h0, that is halfway between f0 and t0.
841  // The angle between f0 and h0 is phi.
842  //
843 
844  Vec3<T> h0 = (f0 + t0).normalized ();
845 
846  //
847  // Store the rotation axis and rotation angle.
848  //
849 
850  q.r = f0 ^ h0; // f0 ^ h0 == cos (phi)
851  q.v = f0 % h0; // (f0 % h0).length() == sin (phi)
852 }
853 
854 template <class T>
855 IMATH_HOSTDEVICE constexpr inline Matrix33<T>
857 {
858  return Matrix33<T> (
859  1 - 2 * (v.y * v.y + v.z * v.z),
860  2 * (v.x * v.y + v.z * r),
861  2 * (v.z * v.x - v.y * r),
862 
863  2 * (v.x * v.y - v.z * r),
864  1 - 2 * (v.z * v.z + v.x * v.x),
865  2 * (v.y * v.z + v.x * r),
866 
867  2 * (v.z * v.x + v.y * r),
868  2 * (v.y * v.z - v.x * r),
869  1 - 2 * (v.y * v.y + v.x * v.x));
870 }
871 
872 template <class T>
873 IMATH_HOSTDEVICE constexpr inline Matrix44<T>
875 {
876  return Matrix44<T> (
877  1 - 2 * (v.y * v.y + v.z * v.z),
878  2 * (v.x * v.y + v.z * r),
879  2 * (v.z * v.x - v.y * r),
880  0,
881  2 * (v.x * v.y - v.z * r),
882  1 - 2 * (v.z * v.z + v.x * v.x),
883  2 * (v.y * v.z + v.x * r),
884  0,
885  2 * (v.z * v.x + v.y * r),
886  2 * (v.y * v.z - v.x * r),
887  1 - 2 * (v.y * v.y + v.x * v.x),
888  0,
889  0,
890  0,
891  0,
892  1);
893 }
894 
895 /// Transform the quaternion by the matrix
896 /// @return M * q
897 template <class T>
898 IMATH_HOSTDEVICE constexpr inline Matrix33<T>
900 {
901  return M * q.toMatrix33 ();
902 }
903 
904 /// Transform the matrix by the quaterion:
905 /// @return q * M
906 template <class T>
907 IMATH_HOSTDEVICE constexpr inline Matrix33<T>
909 {
910  return q.toMatrix33 () * M;
911 }
912 
913 /// Stream output as "(r x y z)"
914 template <class T>
915 std::ostream&
916 operator<< (std::ostream& o, const Quat<T>& q)
917 {
918  return o << "(" << q.r << " " << q.v.x << " " << q.v.y << " " << q.v.z
919  << ")";
920 }
921 
922 /// Quaterion multiplication
923 template <class T>
924 IMATH_HOSTDEVICE constexpr inline Quat<T>
926 {
927  return Quat<T> (
928  q1.r * q2.r - (q1.v ^ q2.v), q1.r * q2.v + q1.v * q2.r + q1.v % q2.v);
929 }
930 
931 /// Quaterion division
932 template <class T>
933 IMATH_HOSTDEVICE constexpr inline Quat<T>
935 {
936  return q1 * q2.inverse ();
937 }
938 
939 /// Quaterion division
940 template <class T>
941 IMATH_HOSTDEVICE constexpr inline Quat<T>
943 {
944  return Quat<T> (q.r / t, q.v / t);
945 }
946 
947 /// Quaterion*scalar multiplication
948 /// @return q * t
949 template <class T>
950 IMATH_HOSTDEVICE constexpr inline Quat<T>
952 {
953  return Quat<T> (q.r * t, q.v * t);
954 }
955 
956 /// Quaterion*scalar multiplication
957 /// @return q * t
958 template <class T>
959 IMATH_HOSTDEVICE constexpr inline Quat<T>
961 {
962  return Quat<T> (q.r * t, q.v * t);
963 }
964 
965 /// Quaterion addition
966 template <class T>
967 IMATH_HOSTDEVICE constexpr inline Quat<T>
969 {
970  return Quat<T> (q1.r + q2.r, q1.v + q2.v);
971 }
972 
973 /// Quaterion subtraction
974 template <class T>
975 IMATH_HOSTDEVICE constexpr inline Quat<T>
977 {
978  return Quat<T> (q1.r - q2.r, q1.v - q2.v);
979 }
980 
981 /// Compute the conjugate
982 template <class T>
983 IMATH_HOSTDEVICE constexpr inline Quat<T>
985 {
986  return Quat<T> (q.r, -q.v);
987 }
988 
989 /// Negate the quaterion
990 template <class T>
991 IMATH_HOSTDEVICE constexpr inline Quat<T>
993 {
994  return Quat<T> (-q.r, -q.v);
995 }
996 
997 /// Quaterion*vector multiplcation
998 /// @return v * q
999 template <class T>
1000 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3<T>
1002 {
1003  Vec3<T> a = q.v % v;
1004  Vec3<T> b = q.v % a;
1005  return v + T (2) * (q.r * a + b);
1006 }
1007 
1008 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
1009 # pragma warning(pop)
1010 #endif
1011 
1012 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
1013 
1014 #endif // INCLUDED_IMATHQUAT_H
IMATH_HOSTDEVICE constexpr T euclideanInnerProduct(const Quat< T > &q) const IMATH_NOEXCEPT
Return the Euclidean inner product.
Definition: ImathQuat.h:536
T BaseType
Definition: ImathQuat.h:211
T z
Definition: ImathVec.h:368
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat< T > & operator=(const Quat< T > &q) IMATH_NOEXCEPT
Assignment.
Definition: ImathQuat.h:357
#define IMATH_NOEXCEPT
Definition: ImathConfig.h:78
Definition: ImathVec.h:40
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
Definition: thread.h:632
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > & normalize() IMATH_NOEXCEPT
Definition: ImathQuat.h:465
Definition: ImathQuat.h:42
SIM_API const UT_StringHolder angle
GLboolean invert
Definition: glcorearb.h:549
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat< T > & operator+=(const Quat< T > &q) IMATH_NOEXCEPT
Quaternion addition.
Definition: ImathQuat.h:402
const GLdouble * v
Definition: glcorearb.h:837
IMATH_HOSTDEVICE constexpr Quat< T > operator-(const Quat< T > &q1, const Quat< T > &q2) IMATH_NOEXCEPT
Quaterion subtraction.
Definition: ImathQuat.h:976
vfloat4 sqrt(const vfloat4 &a)
Definition: simd.h:7694
T value_type
Definition: ImathQuat.h:45
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
IMATH_HOSTDEVICE Vec3< T > normalized() const IMATH_NOEXCEPT
Return a normalized vector. Does not modify *this.
Definition: ImathVec.h:2131
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > squad(const Quat< T > &q1, const Quat< T > &q2, const Quat< T > &qa, const Quat< T > &qb, T t) IMATH_NOEXCEPT
Definition: ImathQuat.h:644
IMATH_HOSTDEVICE static constexpr Quat< T > identity() IMATH_NOEXCEPT
The identity quaternion.
Definition: ImathQuat.h:350
Vec3< T > v
The imaginary vector.
Definition: ImathQuat.h:54
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > spline(const Quat< T > &q0, const Quat< T > &q1, const Quat< T > &q2, const Quat< T > &q3, T t) IMATH_NOEXCEPT
Definition: ImathQuat.h:621
IMATH_HOSTDEVICE Quat< T > exp() const IMATH_NOEXCEPT
Return the exponent of the quaterion.
Definition: ImathQuat.h:702
**But if you need a result
Definition: thread.h:622
IMATH_HOSTDEVICE constexpr T operator^(const Quat< T > &q1, const Quat< T > &q2) IMATH_NOEXCEPT
4D dot product
Definition: ImathQuat.h:451
IMATH_HOSTDEVICE constexpr T angle() const IMATH_NOEXCEPT
Return the angle of the axis/angle representation.
Definition: ImathQuat.h:727
IMATH_HOSTDEVICE constexpr bool operator==(const Quat< S > &q) const IMATH_NOEXCEPT
Equality.
Definition: ImathQuat.h:435
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
#define IMATH_HOSTDEVICE
Definition: ImathConfig.h:108
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T angle4D(const Quat< T > &q1, const Quat< T > &q2) IMATH_NOEXCEPT
Definition: ImathQuat.h:546
IMATH_HOSTDEVICE Quat< T > log() const IMATH_NOEXCEPT
Return the logarithm of the quaterion.
Definition: ImathQuat.h:676
T r
The real part.
Definition: ImathQuat.h:51
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat< T > & operator/=(const Quat< T > &q) IMATH_NOEXCEPT
Quaterion division, using the inverse()
Definition: ImathQuat.h:385
IMATH_HOSTDEVICE constexpr bool operator!=(const Quat< S > &q) const IMATH_NOEXCEPT
Inequality.
Definition: ImathQuat.h:443
T x
Definition: ImathVec.h:368
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat< T > & operator-=(const Quat< T > &q) IMATH_NOEXCEPT
Quaternion subtraction.
Definition: ImathQuat.h:411
IMATH_HOSTDEVICE constexpr T length() const IMATH_NOEXCEPT
Return the R4 length.
Definition: ImathQuat.h:458
IMATH_HOSTDEVICE constexpr Quat() IMATH_NOEXCEPT
Default constructor is the identity quat.
Definition: ImathQuat.h:308
IMATH_HOSTDEVICE constexpr Matrix44< T > toMatrix44() const IMATH_NOEXCEPT
Return a 4x4 rotation matrix.
Definition: ImathQuat.h:874
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > & setRotation(const Vec3< T > &fromDirection, const Vec3< T > &toDirection) IMATH_NOEXCEPT
Definition: ImathQuat.h:750
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > & invert() IMATH_NOEXCEPT
Definition: ImathQuat.h:506
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T & operator[](int index) IMATH_NOEXCEPT
Definition: ImathQuat.h:420
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > & setAxisAngle(const Vec3< T > &axis, T radians) IMATH_NOEXCEPT
Definition: ImathQuat.h:741
GLint GLenum GLboolean normalized
Definition: glcorearb.h:872
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
IMATH_HOSTDEVICE constexpr Quat< T > operator+(const Quat< T > &q1, const Quat< T > &q2) IMATH_NOEXCEPT
Quaterion addition.
Definition: ImathQuat.h:968
GLdouble t
Definition: glad.h:2397
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > slerp(const Quat< T > &q1, const Quat< T > &q2, T t) IMATH_NOEXCEPT
Definition: ImathQuat.h:576
GLint j
Definition: glad.h:2733
IMATH_HOSTDEVICE constexpr Quat< T > operator~(const Quat< T > &q) IMATH_NOEXCEPT
Compute the conjugate.
Definition: ImathQuat.h:984
IMATH_HOSTDEVICE constexpr Matrix33< T > operator*(const Matrix33< T > &M, const Quat< T > &q) IMATH_NOEXCEPT
Definition: ImathQuat.h:899
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > inverse() const IMATH_NOEXCEPT
Return 1/this, leaving this unchanged.
Definition: ImathQuat.h:492
GLuint index
Definition: glcorearb.h:786
#define IMATH_EXPORT_TEMPLATE_TYPE
Definition: ImathExport.h:61
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3< T > rotateVector(const Vec3< T > &original) const IMATH_NOEXCEPT
Rotate the given point by the quaterion.
Definition: ImathQuat.h:516
FMT_CONSTEXPR basic_fp< F > normalize(basic_fp< F > value)
Definition: format.h:1701
T y
Definition: ImathVec.h:368
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE constexpr T abs(T a) IMATH_NOEXCEPT
Definition: ImathFun.h:26
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE T sinx_over_x(T x)
Definition: ImathMath.h:135
IMATH_HOSTDEVICE constexpr Vec3< T > axis() const IMATH_NOEXCEPT
Return the axis of the axis/angle representation.
Definition: ImathQuat.h:734
GLboolean r
Definition: glcorearb.h:1222
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat< T > & operator*=(const Quat< T > &q) IMATH_NOEXCEPT
Quaternion multiplication.
Definition: ImathQuat.h:366
IMATH_HOSTDEVICE void intermediate(const Quat< T > &q0, const Quat< T > &q1, const Quat< T > &q2, const Quat< T > &q3, Quat< T > &qa, Quat< T > &qb) IMATH_NOEXCEPT
IMATH_HOSTDEVICE constexpr Matrix33< T > toMatrix33() const IMATH_NOEXCEPT
Return a 3x3 rotation matrix.
Definition: ImathQuat.h:856
OIIO_FORCEINLINE T log(const T &v)
Definition: simd.h:7905
IMATH_HOSTDEVICE constexpr Quat< T > operator/(const Quat< T > &q1, const Quat< T > &q2) IMATH_NOEXCEPT
Quaterion division.
Definition: ImathQuat.h:934
OIIO_FORCEINLINE OIIO_HOSTDEVICE T radians(T deg)
Convert degrees to radians.
Definition: fmath.h:677
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > normalized() const IMATH_NOEXCEPT
Return a normalized quaternion, leaving this unmodified.
Definition: ImathQuat.h:483
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > slerpShortestArc(const Quat< T > &q1, const Quat< T > &q2, T t) IMATH_NOEXCEPT
Definition: ImathQuat.h:593