HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImathEuler.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 // Euler angle representation of rotation/orientation
8 //
9 
10 #ifndef INCLUDED_IMATHEULER_H
11 #define INCLUDED_IMATHEULER_H
12 
13 #include "ImathExport.h"
14 #include "ImathNamespace.h"
15 
16 #include "ImathMath.h"
17 #include "ImathMatrix.h"
18 #include "ImathQuat.h"
19 #include "ImathVec.h"
20 
21 #include <iostream>
22 
23 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
24 
25 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
26 // Disable MS VC++ warnings about conversion from double to float
27 # pragma warning(push)
28 # pragma warning(disable : 4244)
29 #endif
30 
31 ///
32 /// Template class `Euler<T>`
33 ///
34 /// The Euler class represents euler angle orientations. The class
35 /// inherits from Vec3 to it can be freely cast. The additional
36 /// information is the euler priorities rep. This class is
37 /// essentially a rip off of Ken Shoemake's GemsIV code. It has
38 /// been modified minimally to make it more understandable, but
39 /// hardly enough to make it easy to grok completely.
40 ///
41 /// There are 24 possible combonations of Euler angle
42 /// representations of which 12 are common in CG and you will
43 /// probably only use 6 of these which in this scheme are the
44 /// non-relative-non-repeating types.
45 ///
46 /// The representations can be partitioned according to two
47 /// criteria:
48 ///
49 /// 1) Are the angles measured relative to a set of fixed axis
50 /// or relative to each other (the latter being what happens
51 /// when rotation matrices are multiplied together and is
52 /// almost ubiquitous in the cg community)
53 ///
54 /// 2) Is one of the rotations repeated (ala XYX rotation)
55 ///
56 /// When you construct a given representation from scratch you
57 /// must order the angles according to their priorities. So, the
58 /// easiest is a softimage or aerospace (yaw/pitch/roll) ordering
59 /// of ZYX.
60 ///
61 /// float x_rot = 1;
62 /// float y_rot = 2;
63 /// float z_rot = 3;
64 ///
65 /// Eulerf angles(z_rot, y_rot, x_rot, Eulerf::ZYX);
66 ///
67 /// or:
68 ///
69 /// Eulerf angles( V3f(z_rot,y_rot,z_rot), Eulerf::ZYX );
70 ///
71 ///
72 /// If instead, the order was YXZ for instance you would have to
73 /// do this:
74 ///
75 /// float x_rot = 1;
76 /// float y_rot = 2;
77 /// float z_rot = 3;
78 ///
79 /// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ);
80 ///
81 /// or:
82 ///
83 ///
84 /// Eulerf angles( V3f(y_rot,x_rot,z_rot), Eulerf::YXZ );
85 ///
86 /// Notice how the order you put the angles into the three slots
87 /// should correspond to the enum (YXZ) ordering. The input angle
88 /// vector is called the "ijk" vector -- not an "xyz" vector. The
89 /// ijk vector order is the same as the enum. If you treat the
90 /// Euler as a Vec3 (which it inherts from) you will find the
91 /// angles are ordered in the same way, i.e.:
92 ///
93 /// V3f v = angles;
94 /// v.x == y_rot, v.y == x_rot, v.z == z_rot
95 ///
96 /// If you just want the x, y, and z angles stored in a vector in
97 /// that order, you can do this:
98 ///
99 /// V3f v = angles.toXYZVector()
100 /// v.x == x_rot, v.y == y_rot, v.z == z_rot
101 ///
102 /// If you want to set the Euler with an XYZVector use the
103 /// optional layout argument:
104 ///
105 /// Eulerf angles(x_rot, y_rot, z_rot, Eulerf::YXZ, Eulerf::XYZLayout);
106 ///
107 /// This is the same as:
108 ///
109 /// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ);
110 ///
111 /// Note that this won't do anything intelligent if you have a
112 /// repeated axis in the euler angles (e.g. XYX)
113 ///
114 /// If you need to use the "relative" versions of these, you will
115 /// need to use the "r" enums.
116 ///
117 /// The units of the rotation angles are assumed to be radians.
118 ///
119 
120 template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Euler : public Vec3<T>
121 {
122 public:
123  using Vec3<T>::x;
124  using Vec3<T>::y;
125  using Vec3<T>::z;
126 
127  ///
128  /// All 24 possible orderings
129  ///
131  {
132  XYZ = 0x0101, // "usual" orderings
133  XZY = 0x0001,
134  YZX = 0x1101,
135  YXZ = 0x1001,
136  ZXY = 0x2101,
137  ZYX = 0x2001,
138 
139  XZX = 0x0011, // first axis repeated
140  XYX = 0x0111,
141  YXY = 0x1011,
142  YZY = 0x1111,
143  ZYZ = 0x2011,
144  ZXZ = 0x2111,
145 
146  XYZr = 0x2000, // relative orderings -- not common
147  XZYr = 0x2100,
148  YZXr = 0x1000,
149  YXZr = 0x1100,
150  ZXYr = 0x0000,
151  ZYXr = 0x0100,
152 
153  XZXr = 0x2110, // relative first axis repeated
154  XYXr = 0x2010,
155  YXYr = 0x1110,
156  YZYr = 0x1010,
157  ZYZr = 0x0110,
158  ZXZr = 0x0010,
159  // ||||
160  // VVVV
161  // ABCD
162  // Legend:
163  // A -> Initial Axis (0==x, 1==y, 2==z)
164  // B -> Parity Even (1==true)
165  // C -> Initial Repeated (1==true)
166  // D -> Frame Static (1==true)
167  //
168 
169  Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX | XZX | XYX | YXY | YZY |
170  ZYZ | ZXZ | XYZr | XZYr | YZXr | YXZr | ZXYr | ZYXr | XZXr |
171  XYXr | YXYr | YZYr | ZYZr | ZXZr,
172 
173  Min = 0x0000,
174  Max = 0x2111,
175  Default = XYZ
176  };
177 
178  ///
179  /// Axes
180  ///
182  {
183  X = 0,
184  Y = 1,
185  Z = 2
186  };
187 
188  ///
189  /// Layout
190  ///
191 
192  enum IMATH_EXPORT_ENUM InputLayout
193  {
195  IJKLayout
196  };
197 
198  /// @{
199  /// @name Constructors
200  ///
201  /// All default to `ZYX` non-relative (ala Softimage 3D/Maya),
202  /// where there is no argument to specify it.
203  ///
204  /// The Euler-from-matrix constructors assume that the matrix does
205  /// not include shear or non-uniform scaling, but the constructors
206  /// do not examine the matrix to verify this assumption. If necessary,
207  /// you can adjust the matrix by calling the removeScalingAndShear()
208  /// function, defined in ImathMatrixAlgo.h.
209 
210  /// No initialization by default
212 
213  /// Copy constructor
214  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (const Euler&) IMATH_NOEXCEPT;
215 
216  /// Construct from given Order
217  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (Order p) IMATH_NOEXCEPT;
218 
219  /// Construct from vector, order, layout
220  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (
221  const Vec3<T>& v,
222  Order o = Default,
223  InputLayout l = IJKLayout) IMATH_NOEXCEPT;
224  /// Construct from explicit axes, order, layout
225  IMATH_HOSTDEVICE IMATH_CONSTEXPR14
226  Euler (T i, T j, T k, Order o = Default, InputLayout l = IJKLayout)
227  IMATH_NOEXCEPT;
228 
229  /// Copy constructor with new Order
230  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (const Euler<T>& euler, Order newp)
231  IMATH_NOEXCEPT;
232 
233  /// Construct from Matrix33
234  IMATH_HOSTDEVICE IMATH_CONSTEXPR14
235  Euler (const Matrix33<T>&, Order o = Default) IMATH_NOEXCEPT;
236 
237  /// Construct from Matrix44
238  IMATH_HOSTDEVICE IMATH_CONSTEXPR14
239  Euler (const Matrix44<T>&, Order o = Default) IMATH_NOEXCEPT;
240 
241  /// Destructor
242  ~Euler () = default;
243 
244  /// @}
245 
246  /// @{
247  /// @name Query
248 
249  /// Return whether the given value is a legal Order
250  IMATH_HOSTDEVICE constexpr static bool legal (Order) IMATH_NOEXCEPT;
251 
252  /// Return the order
253  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Order order () const IMATH_NOEXCEPT;
254 
255  /// Return frameStatic
256  IMATH_HOSTDEVICE constexpr bool frameStatic () const
257  {
258  return _frameStatic;
259  }
260 
261  /// Return intialRepeated
262  IMATH_HOSTDEVICE constexpr bool initialRepeated () const
263  {
264  return _initialRepeated;
265  }
266 
267  /// Return partityEven
268  IMATH_HOSTDEVICE constexpr bool parityEven () const { return _parityEven; }
269 
270  /// Return initialAxis
271  IMATH_HOSTDEVICE constexpr Axis initialAxis () const
272  {
273  return _initialAxis;
274  }
275 
276  /// Unpack angles from ijk form
277  IMATH_HOSTDEVICE void
278  angleOrder (int& i, int& j, int& k) const IMATH_NOEXCEPT;
279 
280  /// Determine mapping from xyz to ijk (reshuffle the xyz to match the order)
281  IMATH_HOSTDEVICE void
282  angleMapping (int& i, int& j, int& k) const IMATH_NOEXCEPT;
283 
284  /// @}
285 
286  /// @{
287  /// @name Set Value
288 
289  /// Set the order. This does NOT convert the angles, but it
290  /// does reorder the input vector.
291  IMATH_HOSTDEVICE void setOrder (Order) IMATH_NOEXCEPT;
292 
293  /// Set the euler value: set the first angle to `v[0]`, the second to
294  /// `v[1]`, the third to `v[2]`.
295  IMATH_HOSTDEVICE void setXYZVector (const Vec3<T>&) IMATH_NOEXCEPT;
296 
297  /// Set the value.
298  IMATH_HOSTDEVICE void
299  set (Axis initial, bool relative, bool parityEven, bool firstRepeats)
300  IMATH_NOEXCEPT;
301 
302  /// @}
303 
304  /// @{
305  /// @name Assignments and Conversions
306  ///
307 
308  /// Assignment
309  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Euler<T>&
310  operator= (const Euler<T>&) IMATH_NOEXCEPT;
311 
312  /// Assignment
313  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Euler<T>&
314  operator= (const Vec3<T>&) IMATH_NOEXCEPT;
315 
316  /// Assign from Matrix33, assumed to be affine
317  IMATH_HOSTDEVICE void extract (const Matrix33<T>&) IMATH_NOEXCEPT;
318 
319  /// Assign from Matrix44, assumed to be affine
320  IMATH_HOSTDEVICE void extract (const Matrix44<T>&) IMATH_NOEXCEPT;
321 
322  /// Assign from Quaternion
323  IMATH_HOSTDEVICE void extract (const Quat<T>&) IMATH_NOEXCEPT;
324 
325  /// Convert to Matrix33
326  IMATH_HOSTDEVICE Matrix33<T> toMatrix33 () const IMATH_NOEXCEPT;
327 
328  /// Convert to Matrix44
329  IMATH_HOSTDEVICE Matrix44<T> toMatrix44 () const IMATH_NOEXCEPT;
330 
331  /// Convert to Quat
332  IMATH_HOSTDEVICE Quat<T> toQuat () const IMATH_NOEXCEPT;
333 
334  /// Reorder the angles so that the X rotation comes first,
335  /// followed by the Y and Z in cases like XYX ordering, the
336  /// repeated angle will be in the "z" component
337  IMATH_HOSTDEVICE Vec3<T> toXYZVector () const IMATH_NOEXCEPT;
338 
339  /// @}
340 
341  /// @{
342  /// @name Comparison
343 
344  /// Equality
345  template <class S>
346  IMATH_HOSTDEVICE constexpr bool
347  operator== (const Euler<S>& other) const IMATH_NOEXCEPT;
348 
349  /// Inequality
350  template <class S>
351  IMATH_HOSTDEVICE constexpr bool
352  operator!= (const Euler<S>& other) const IMATH_NOEXCEPT;
353 
354  /// @}
355 
356  /// @{
357  /// @name Utility Methods
358  ///
359  /// Utility methods for getting continuous rotations. None of these
360  /// methods change the orientation given by its inputs (or at least
361  /// that is the intent).
362 
363  /// Convert an angle to its equivalent in [-PI, PI]
364  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 static float
365  angleMod (T angle) IMATH_NOEXCEPT;
366 
367  /// Adjust xyzRot so that its components differ from targetXyzRot by no more than +/-PI
368  IMATH_HOSTDEVICE static void simpleXYZRotation (
369  Vec3<T>& xyzRot, const Vec3<T>& targetXyzRot) IMATH_NOEXCEPT;
370 
371  /// Adjust xyzRot so that its components differ from targetXyzRot by as little as possible.
372  /// Note that xyz here really means ijk, because the order must be provided.
373  IMATH_HOSTDEVICE static void nearestRotation (
374  Vec3<T>& xyzRot,
375  const Vec3<T>& targetXyzRot,
376  Order order = XYZ) IMATH_NOEXCEPT;
377 
378  /// Adjusts "this" Euler so that its components differ from target
379  /// by as little as possible. This method might not make sense for
380  /// Eulers with different order and it probably doesn't work for
381  /// repeated axis and relative orderings (TODO).
382  IMATH_HOSTDEVICE void makeNear (const Euler<T>& target) IMATH_NOEXCEPT;
383 
384  /// @}
385 
386 protected:
387  /// relative or static rotations
388  bool _frameStatic : 1;
389 
390  /// init axis repeated as last
391  bool _initialRepeated : 1;
392 
393  /// "parity of axis permutation"
394  bool _parityEven : 1;
395 
396 #if defined _WIN32 || defined _WIN64
397  /// First axis of rotation
398  Axis _initialAxis;
399 #else
400  /// First axis of rotation
401  Axis _initialAxis : 2;
402 #endif
403 };
404 
405 //
406 // Convenient typedefs
407 //
408 
409 /// Euler of type float
411 /// Euler of type double
413 
414 //
415 // Implementation
416 //
417 
418 /// @cond Doxygen_Suppress
419 
420 template <class T>
421 IMATH_HOSTDEVICE inline void
422 Euler<T>::angleOrder (int& i, int& j, int& k) const IMATH_NOEXCEPT
423 {
424  i = _initialAxis;
425  j = _parityEven ? (i + 1) % 3 : (i > 0 ? i - 1 : 2);
426  k = _parityEven ? (i > 0 ? i - 1 : 2) : (i + 1) % 3;
427 }
428 
429 template <class T>
430 IMATH_HOSTDEVICE inline void
431 Euler<T>::angleMapping (int& i, int& j, int& k) const IMATH_NOEXCEPT
432 {
433  int m[3];
434 
435  m[_initialAxis] = 0;
436  m[(_initialAxis + 1) % 3] = _parityEven ? 1 : 2;
437  m[(_initialAxis + 2) % 3] = _parityEven ? 2 : 1;
438  i = m[0];
439  j = m[1];
440  k = m[2];
441 }
442 
443 template <class T>
444 IMATH_HOSTDEVICE inline void
446 {
447  int i, j, k;
448  angleMapping (i, j, k);
449  (*this)[i] = v.x;
450  (*this)[j] = v.y;
451  (*this)[k] = v.z;
452 }
453 
454 template <class T>
457 {
458  int i, j, k;
459  angleMapping (i, j, k);
460  return Vec3<T> ((*this)[i], (*this)[j], (*this)[k]);
461 }
462 
463 template <class T>
465  : Vec3<T> (0, 0, 0),
466  _frameStatic (true),
467  _initialRepeated (false),
468  _parityEven (true),
469  _initialAxis (X)
470 {}
471 
472 template <class T>
473 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Euler<T>::Euler (
474  typename Euler<T>::Order p) IMATH_NOEXCEPT : Vec3<T> (0, 0, 0),
475  _frameStatic (true),
476  _initialRepeated (false),
477  _parityEven (true),
478  _initialAxis (X)
479 {
480  setOrder (p);
481 }
482 
483 template <class T>
484 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Euler<T>::Euler (
485  const Vec3<T>& v,
486  typename Euler<T>::Order p,
488 {
489  setOrder (p);
490  if (l == XYZLayout)
491  setXYZVector (v);
492  else
493  {
494  x = v.x;
495  y = v.y;
496  z = v.z;
497  }
498 }
499 
500 template <class T>
501 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Euler<T>::Euler (
502  const Euler<T>& euler) IMATH_NOEXCEPT
503 {
504  operator= (euler);
505 }
506 
507 template <class T>
508 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Euler<T>::Euler (
509  const Euler<T>& euler, Order p) IMATH_NOEXCEPT
510 {
511  setOrder (p);
512  Matrix33<T> M = euler.toMatrix33 ();
513  extract (M);
514 }
515 
516 template <class T>
517 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Euler<T>::Euler (
518  T xi,
519  T yi,
520  T zi,
521  typename Euler<T>::Order p,
523 {
524  setOrder (p);
525  if (l == XYZLayout)
526  setXYZVector (Vec3<T> (xi, yi, zi));
527  else
528  {
529  x = xi;
530  y = yi;
531  z = zi;
532  }
533 }
534 
535 template <class T>
536 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Euler<T>::Euler (
537  const Matrix33<T>& M, typename Euler::Order p) IMATH_NOEXCEPT
538 {
539  setOrder (p);
540  extract (M);
541 }
542 
543 template <class T>
544 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Euler<T>::Euler (
545  const Matrix44<T>& M, typename Euler::Order p) IMATH_NOEXCEPT
546 {
547  setOrder (p);
548  extract (M);
549 }
550 
551 template <class T>
552 IMATH_HOSTDEVICE inline void
554 {
555  extract (q.toMatrix33 ());
556 }
557 
558 template <class T>
559 IMATH_HOSTDEVICE void
561 {
562  int i, j, k;
563  angleOrder (i, j, k);
564 
565  if (_initialRepeated)
566  {
567  //
568  // Extract the first angle, x.
569  //
570 
571  x = std::atan2 (M[j][i], M[k][i]);
572 
573  //
574  // Remove the x rotation from M, so that the remaining
575  // rotation, N, is only around two axes, and gimbal lock
576  // cannot occur.
577  //
578 
579  Vec3<T> r (0, 0, 0);
580  r[i] = (_parityEven ? -x : x);
581 
582  Matrix44<T> N;
583  N.rotate (r);
584 
585  N = N * Matrix44<T> (
586  M[0][0],
587  M[0][1],
588  M[0][2],
589  0,
590  M[1][0],
591  M[1][1],
592  M[1][2],
593  0,
594  M[2][0],
595  M[2][1],
596  M[2][2],
597  0,
598  0,
599  0,
600  0,
601  1);
602  //
603  // Extract the other two angles, y and z, from N.
604  //
605 
606  T sy = std::sqrt (N[j][i] * N[j][i] + N[k][i] * N[k][i]);
607  y = std::atan2 (sy, N[i][i]);
608  z = std::atan2 (N[j][k], N[j][j]);
609  }
610  else
611  {
612  //
613  // Extract the first angle, x.
614  //
615 
616  x = std::atan2 (M[j][k], M[k][k]);
617 
618  //
619  // Remove the x rotation from M, so that the remaining
620  // rotation, N, is only around two axes, and gimbal lock
621  // cannot occur.
622  //
623 
624  Vec3<T> r (0, 0, 0);
625  r[i] = (_parityEven ? -x : x);
626 
627  Matrix44<T> N;
628  N.rotate (r);
629 
630  N = N * Matrix44<T> (
631  M[0][0],
632  M[0][1],
633  M[0][2],
634  0,
635  M[1][0],
636  M[1][1],
637  M[1][2],
638  0,
639  M[2][0],
640  M[2][1],
641  M[2][2],
642  0,
643  0,
644  0,
645  0,
646  1);
647  //
648  // Extract the other two angles, y and z, from N.
649  //
650 
651  T cy = std::sqrt (N[i][i] * N[i][i] + N[i][j] * N[i][j]);
652  y = std::atan2 (-N[i][k], cy);
653  z = std::atan2 (-N[j][i], N[j][j]);
654  }
655 
656  if (!_parityEven) *this *= -1;
657 
658  if (!_frameStatic)
659  {
660  T t = x;
661  x = z;
662  z = t;
663  }
664 }
665 
666 template <class T>
667 IMATH_HOSTDEVICE void
669 {
670  int i, j, k;
671  angleOrder (i, j, k);
672 
673  if (_initialRepeated)
674  {
675  //
676  // Extract the first angle, x.
677  //
678 
679  x = std::atan2 (M[j][i], M[k][i]);
680 
681  //
682  // Remove the x rotation from M, so that the remaining
683  // rotation, N, is only around two axes, and gimbal lock
684  // cannot occur.
685  //
686 
687  Vec3<T> r (0, 0, 0);
688  r[i] = (_parityEven ? -x : x);
689 
690  Matrix44<T> N;
691  N.rotate (r);
692  N = N * M;
693 
694  //
695  // Extract the other two angles, y and z, from N.
696  //
697 
698  T sy = std::sqrt (N[j][i] * N[j][i] + N[k][i] * N[k][i]);
699  y = std::atan2 (sy, N[i][i]);
700  z = std::atan2 (N[j][k], N[j][j]);
701  }
702  else
703  {
704  //
705  // Extract the first angle, x.
706  //
707 
708  x = std::atan2 (M[j][k], M[k][k]);
709 
710  //
711  // Remove the x rotation from M, so that the remaining
712  // rotation, N, is only around two axes, and gimbal lock
713  // cannot occur.
714  //
715 
716  Vec3<T> r (0, 0, 0);
717  r[i] = (_parityEven ? -x : x);
718 
719  Matrix44<T> N;
720  N.rotate (r);
721  N = N * M;
722 
723  //
724  // Extract the other two angles, y and z, from N.
725  //
726 
727  T cy = std::sqrt (N[i][i] * N[i][i] + N[i][j] * N[i][j]);
728  y = std::atan2 (-N[i][k], cy);
729  z = std::atan2 (-N[j][i], N[j][j]);
730  }
731 
732  if (!_parityEven) *this *= -1;
733 
734  if (!_frameStatic)
735  {
736  T t = x;
737  x = z;
738  z = t;
739  }
740 }
741 
742 template <class T>
745 {
746  int i, j, k;
747  angleOrder (i, j, k);
748 
749  Vec3<T> angles;
750 
751  if (_frameStatic)
752  angles = (*this);
753  else
754  angles = Vec3<T> (z, y, x);
755 
756  if (!_parityEven) angles *= -1.0;
757 
758  T ci = std::cos (angles.x);
759  T cj = std::cos (angles.y);
760  T ch = std::cos (angles.z);
761  T si = std::sin (angles.x);
762  T sj = std::sin (angles.y);
763  T sh = std::sin (angles.z);
764 
765  T cc = ci * ch;
766  T cs = ci * sh;
767  T sc = si * ch;
768  T ss = si * sh;
769 
770  Matrix33<T> M;
771 
772  if (_initialRepeated)
773  {
774  M[i][i] = cj;
775  M[j][i] = sj * si;
776  M[k][i] = sj * ci;
777  M[i][j] = sj * sh;
778  M[j][j] = -cj * ss + cc;
779  M[k][j] = -cj * cs - sc;
780  M[i][k] = -sj * ch;
781  M[j][k] = cj * sc + cs;
782  M[k][k] = cj * cc - ss;
783  }
784  else
785  {
786  M[i][i] = cj * ch;
787  M[j][i] = sj * sc - cs;
788  M[k][i] = sj * cc + ss;
789  M[i][j] = cj * sh;
790  M[j][j] = sj * ss + cc;
791  M[k][j] = sj * cs - sc;
792  M[i][k] = -sj;
793  M[j][k] = cj * si;
794  M[k][k] = cj * ci;
795  }
796 
797  return M;
798 }
799 
800 template <class T>
803 {
804  int i, j, k;
805  angleOrder (i, j, k);
806 
807  Vec3<T> angles;
808 
809  if (_frameStatic)
810  angles = (*this);
811  else
812  angles = Vec3<T> (z, y, x);
813 
814  if (!_parityEven) angles *= -1.0;
815 
816  T ci = std::cos (angles.x);
817  T cj = std::cos (angles.y);
818  T ch = std::cos (angles.z);
819  T si = std::sin (angles.x);
820  T sj = std::sin (angles.y);
821  T sh = std::sin (angles.z);
822 
823  T cc = ci * ch;
824  T cs = ci * sh;
825  T sc = si * ch;
826  T ss = si * sh;
827 
828  Matrix44<T> M;
829 
830  if (_initialRepeated)
831  {
832  M[i][i] = cj;
833  M[j][i] = sj * si;
834  M[k][i] = sj * ci;
835  M[i][j] = sj * sh;
836  M[j][j] = -cj * ss + cc;
837  M[k][j] = -cj * cs - sc;
838  M[i][k] = -sj * ch;
839  M[j][k] = cj * sc + cs;
840  M[k][k] = cj * cc - ss;
841  }
842  else
843  {
844  M[i][i] = cj * ch;
845  M[j][i] = sj * sc - cs;
846  M[k][i] = sj * cc + ss;
847  M[i][j] = cj * sh;
848  M[j][j] = sj * ss + cc;
849  M[k][j] = sj * cs - sc;
850  M[i][k] = -sj;
851  M[j][k] = cj * si;
852  M[k][k] = cj * ci;
853  }
854 
855  return M;
856 }
857 
858 template <class T>
861 {
862  Vec3<T> angles;
863  int i, j, k;
864  angleOrder (i, j, k);
865 
866  if (_frameStatic)
867  angles = (*this);
868  else
869  angles = Vec3<T> (z, y, x);
870 
871  if (!_parityEven) angles.y = -angles.y;
872 
873  T ti = angles.x * 0.5;
874  T tj = angles.y * 0.5;
875  T th = angles.z * 0.5;
876  T ci = std::cos (ti);
877  T cj = std::cos (tj);
878  T ch = std::cos (th);
879  T si = std::sin (ti);
880  T sj = std::sin (tj);
881  T sh = std::sin (th);
882  T cc = ci * ch;
883  T cs = ci * sh;
884  T sc = si * ch;
885  T ss = si * sh;
886 
887  T parity = _parityEven ? 1.0 : -1.0;
888 
889  Quat<T> q;
890  Vec3<T> a;
891 
892  if (_initialRepeated)
893  {
894  a[i] = cj * (cs + sc);
895  a[j] = sj * (cc + ss) * parity;
896  a[k] = sj * (cs - sc);
897  q.r = cj * (cc - ss);
898  }
899  else
900  {
901  a[i] = cj * sc - sj * cs;
902  a[j] = (cj * ss + sj * cc) * parity;
903  a[k] = cj * cs - sj * sc;
904  q.r = cj * cc + sj * ss;
905  }
906 
907  q.v = a;
908 
909  return q;
910 }
911 
912 template <class T>
913 IMATH_HOSTDEVICE constexpr inline bool
915 {
916  return (order & ~Legal) ? false : true;
917 }
918 
919 template <class T>
920 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 typename Euler<T>::Order
922 {
923  int foo = (_initialAxis == Z ? 0x2000 : (_initialAxis == Y ? 0x1000 : 0));
924 
925  if (_parityEven) foo |= 0x0100;
926  if (_initialRepeated) foo |= 0x0010;
927  if (_frameStatic) foo++;
928 
929  return (Order) foo;
930 }
931 
932 template <class T>
933 IMATH_HOSTDEVICE inline void
935 {
936  set (
937  p & 0x2000 ? Z : (p & 0x1000 ? Y : X), // initial axis
938  !(p & 0x1), // static?
939  !!(p & 0x100), // permutation even?
940  !!(p & 0x10)); // initial repeats?
941 }
942 
943 template <class T>
944 IMATH_HOSTDEVICE inline void
946  typename Euler<T>::Axis axis,
947  bool relative,
948  bool parityEven,
949  bool firstRepeats) IMATH_NOEXCEPT
950 {
951  _initialAxis = axis;
952  _frameStatic = !relative;
953  _parityEven = parityEven;
954  _initialRepeated = firstRepeats;
955 }
956 
957 template <class T>
958 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Euler<T>&
960 {
961  x = euler.x;
962  y = euler.y;
963  z = euler.z;
964  _initialAxis = euler._initialAxis;
965  _frameStatic = euler._frameStatic;
966  _parityEven = euler._parityEven;
967  _initialRepeated = euler._initialRepeated;
968  return *this;
969 }
970 
971 template <class T>
972 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Euler<T>&
974 {
975  x = v.x;
976  y = v.y;
977  z = v.z;
978  return *this;
979 }
980 
981 template <class T>
982 template <class S>
983 IMATH_HOSTDEVICE constexpr inline bool
985 {
986  return Vec3<T>::operator==(other) && order() == other.order();
987 }
988 
989 template <class T>
990 template <class S>
991 IMATH_HOSTDEVICE constexpr inline bool
993 {
994  return Vec3<T>::operator!=(other) || order() != other.order();
995 }
996 
997 template <class T>
998 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline float
1000 {
1001  const T pi = static_cast<T> (M_PI);
1002  angle = fmod (T (angle), T (2 * pi));
1003 
1004  if (angle < -pi) angle += 2 * pi;
1005  if (angle > +pi) angle -= 2 * pi;
1006 
1007  return angle;
1008 }
1009 
1010 template <class T>
1011 IMATH_HOSTDEVICE inline void
1012 Euler<T>::simpleXYZRotation (Vec3<T>& xyzRot, const Vec3<T>& targetXyzRot)
1014 {
1015  Vec3<T> d = xyzRot - targetXyzRot;
1016  xyzRot.x = targetXyzRot.x + angleMod (d.x);
1017  xyzRot.y = targetXyzRot.y + angleMod (d.y);
1018  xyzRot.z = targetXyzRot.z + angleMod (d.z);
1019 }
1020 
1021 template <class T>
1022 IMATH_HOSTDEVICE void
1024  Vec3<T>& xyzRot, const Vec3<T>& targetXyzRot, Order order) IMATH_NOEXCEPT
1025 {
1026  int i, j, k;
1027  Euler<T> e (0, 0, 0, order);
1028  e.angleOrder (i, j, k);
1029 
1030  simpleXYZRotation (xyzRot, targetXyzRot);
1031 
1032  Vec3<T> otherXyzRot;
1033  otherXyzRot[i] = M_PI + xyzRot[i];
1034  otherXyzRot[j] = M_PI - xyzRot[j];
1035  otherXyzRot[k] = M_PI + xyzRot[k];
1036 
1037  simpleXYZRotation (otherXyzRot, targetXyzRot);
1038 
1039  Vec3<T> d = xyzRot - targetXyzRot;
1040  Vec3<T> od = otherXyzRot - targetXyzRot;
1041  T dMag = d.dot (d);
1042  T odMag = od.dot (od);
1043 
1044  if (odMag < dMag) { xyzRot = otherXyzRot; }
1045 }
1046 
1047 template <class T>
1048 IMATH_HOSTDEVICE void
1050 {
1051  Vec3<T> xyzRot = toXYZVector ();
1052  Vec3<T> targetXyz;
1053  if (order () != target.order ())
1054  {
1055  Euler<T> targetSameOrder = Euler<T> (target, order ());
1056  targetXyz = targetSameOrder.toXYZVector ();
1057  }
1058  else
1059  {
1060  targetXyz = target.toXYZVector ();
1061  }
1062 
1063  nearestRotation (xyzRot, targetXyz, order ());
1064 
1065  setXYZVector (xyzRot);
1066 }
1067 
1068 /// @endcond
1069 
1070 /// Stream ouput, as "(x y z i j k)"
1071 template <class T>
1072 std::ostream&
1073 operator<< (std::ostream& o, const Euler<T>& euler)
1074 {
1075  char a[3] = {'X', 'Y', 'Z'};
1076 
1077  const char* r = euler.frameStatic () ? "" : "r";
1078  int i, j, k;
1079  euler.angleOrder (i, j, k);
1080 
1081  if (euler.initialRepeated ()) k = i;
1082 
1083  return o << "(" << euler.x << " " << euler.y << " " << euler.z << " "
1084  << a[i] << a[j] << a[k] << r << ")";
1085 }
1086 
1087 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
1088 # pragma warning(pop)
1089 #endif
1090 
1091 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
1092 
1093 #endif // INCLUDED_IMATHEULER_H
IMATH_HOSTDEVICE constexpr bool parityEven() const
Return partityEven.
Definition: ImathEuler.h:268
ZYZr
Definition: ImathEuler.h:157
YXY
Definition: ImathEuler.h:141
static IMATH_HOSTDEVICE void simpleXYZRotation(Vec3< T > &xyzRot, const Vec3< T > &targetXyzRot) IMATH_NOEXCEPT
Adjust xyzRot so that its components differ from targetXyzRot by no more than +/-PI.
T z
Definition: ImathVec.h:368
YZY
Definition: ImathEuler.h:142
#define IMATH_NOEXCEPT
Definition: ImathConfig.h:78
Definition: ImathVec.h:40
Y
Definition: ImathEuler.h:184
*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
Legal
Definition: ImathEuler.h:169
Definition: ImathQuat.h:42
SIM_API const UT_StringHolder angle
Max
Definition: ImathEuler.h:174
const GLdouble * v
Definition: glcorearb.h:837
ZXZr
Definition: ImathEuler.h:158
#define M_PI
Definition: fmath.h:98
IMATH_HOSTDEVICE Matrix44< T > toMatrix44() const IMATH_NOEXCEPT
Convert to Matrix44.
vfloat4 sqrt(const vfloat4 &a)
Definition: simd.h:7694
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
IMATH_HOSTDEVICE void set(Axis initial, bool relative, bool parityEven, bool firstRepeats) IMATH_NOEXCEPT
Set the value.
IMATH_HOSTDEVICE void setXYZVector(const Vec3< T > &) IMATH_NOEXCEPT
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
IMATH_HOSTDEVICE constexpr T dot(const Vec3 &v) const IMATH_NOEXCEPT
Dot product.
Definition: ImathVec.h:1875
ZYZ
Definition: ImathEuler.h:143
X
Definition: ImathEuler.h:183
Vec3< T > v
The imaginary vector.
Definition: ImathQuat.h:54
GLint y
Definition: glcorearb.h:103
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
#define IMATH_HOSTDEVICE
Definition: ImathConfig.h:108
ZXYr
Definition: ImathEuler.h:150
XZXr
Definition: ImathEuler.h:153
OIIO_FORCEINLINE bool extract(const vbool4 &a)
Definition: simd.h:3542
Min
Definition: ImathEuler.h:173
T r
The real part.
Definition: ImathQuat.h:51
YXYr
Definition: ImathEuler.h:155
T x
Definition: ImathVec.h:368
YXZr
Definition: ImathEuler.h:149
XYX
Definition: ImathEuler.h:140
constexpr auto set(type rhs) -> int
Definition: core.h:610
IMATH_HOSTDEVICE static constexpr bool legal(Order) IMATH_NOEXCEPT
Return whether the given value is a legal Order.
XYXr
Definition: ImathEuler.h:154
IMATH_HOSTDEVICE Vec3< T > toXYZVector() const IMATH_NOEXCEPT
IMATH_HOSTDEVICE void extract(const Matrix33< T > &) IMATH_NOEXCEPT
Assign from Matrix33, assumed to be affine.
IMATH_HOSTDEVICE constexpr bool operator==(const Vec3< S > &v) const IMATH_NOEXCEPT
Equality.
Definition: ImathVec.h:1838
IMATH_HOSTDEVICE constexpr Axis initialAxis() const
Return initialAxis.
Definition: ImathEuler.h:271
IMATH_HOSTDEVICE static IMATH_CONSTEXPR14 float angleMod(T angle) IMATH_NOEXCEPT
Convert an angle to its equivalent in [-PI, PI].
#define IMATH_EXPORT_ENUM
Definition: ImathExport.h:60
GLdouble GLdouble GLint GLint order
Definition: glad.h:2676
IMATH_HOSTDEVICE void angleMapping(int &i, int &j, int &k) const IMATH_NOEXCEPT
Determine mapping from xyz to ijk (reshuffle the xyz to match the order)
IMATH_HOSTDEVICE constexpr Euler() IMATH_NOEXCEPT
No initialization by default.
GLenum target
Definition: glcorearb.h:1667
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Order order() const IMATH_NOEXCEPT
Return the order.
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Euler< T > & operator=(const Euler< T > &) IMATH_NOEXCEPT
Assignment.
GLint GLenum GLint x
Definition: glcorearb.h:409
IMATH_HOSTDEVICE constexpr bool operator==(const Euler< S > &other) const IMATH_NOEXCEPT
Equality.
XZYr
Definition: ImathEuler.h:147
IMATH_HOSTDEVICE constexpr bool initialRepeated() const
Return intialRepeated.
Definition: ImathEuler.h:262
XYZLayout
Definition: ImathEuler.h:194
Euler< float > Eulerf
Euler of type float.
Definition: ImathEuler.h:410
YZYr
Definition: ImathEuler.h:156
GLdouble t
Definition: glad.h:2397
IMATH_HOSTDEVICE void angleOrder(int &i, int &j, int &k) const IMATH_NOEXCEPT
Unpack angles from ijk form.
YZXr
Definition: ImathEuler.h:148
GLint j
Definition: glad.h:2733
XYZr
Definition: ImathEuler.h:146
Euler< double > Eulerd
Euler of type double.
Definition: ImathEuler.h:412
__hostdev__ constexpr T pi()
Pi constant taken from Boost to match old behaviour.
Definition: NanoVDB.h:976
IMATH_HOSTDEVICE constexpr bool operator!=(const Vec3< S > &v) const IMATH_NOEXCEPT
Inequality.
Definition: ImathVec.h:1846
LeafData & operator=(const LeafData &)=delete
ZYXr
Definition: ImathEuler.h:151
#define IMATH_EXPORT_TEMPLATE_TYPE
Definition: ImathExport.h:61
IMATH_HOSTDEVICE const Matrix44 & rotate(const Vec3< S > &r) IMATH_NOEXCEPT
IMATH_HOSTDEVICE Matrix33< T > toMatrix33() const IMATH_NOEXCEPT
Convert to Matrix33.
IMATH_HOSTDEVICE void setOrder(Order) IMATH_NOEXCEPT
GA_API const UT_StringHolder N
XZX
Definition: ImathEuler.h:139
T y
Definition: ImathVec.h:368
static IMATH_HOSTDEVICE void nearestRotation(Vec3< T > &xyzRot, const Vec3< T > &targetXyzRot, Order order=XYZ) IMATH_NOEXCEPT
IMATH_HOSTDEVICE constexpr bool operator!=(const Euler< S > &other) const IMATH_NOEXCEPT
Inequality.
GLboolean r
Definition: glcorearb.h:1222
IMATH_HOSTDEVICE void makeNear(const Euler< T > &target) IMATH_NOEXCEPT
IMATH_HOSTDEVICE Quat< T > toQuat() const IMATH_NOEXCEPT
Convert to Quat.
ZXZ
Definition: ImathEuler.h:144