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 //
3 // Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // * Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 ///////////////////////////////////////////////////////////////////////////
34 
35 
36 
37 #ifndef INCLUDED_IMATHEULER_H
38 #define INCLUDED_IMATHEULER_H
39 
40 //----------------------------------------------------------------------
41 //
42 // template class Euler<T>
43 //
44 // This class represents euler angle orientations. The class
45 // inherits from Vec3 to it can be freely cast. The additional
46 // information is the euler priorities rep. This class is
47 // essentially a rip off of Ken Shoemake's GemsIV code. It has
48 // been modified minimally to make it more understandable, but
49 // hardly enough to make it easy to grok completely.
50 //
51 // There are 24 possible combonations of Euler angle
52 // representations of which 12 are common in CG and you will
53 // probably only use 6 of these which in this scheme are the
54 // non-relative-non-repeating types.
55 //
56 // The representations can be partitioned according to two
57 // criteria:
58 //
59 // 1) Are the angles measured relative to a set of fixed axis
60 // or relative to each other (the latter being what happens
61 // when rotation matrices are multiplied together and is
62 // almost ubiquitous in the cg community)
63 //
64 // 2) Is one of the rotations repeated (ala XYX rotation)
65 //
66 // When you construct a given representation from scratch you
67 // must order the angles according to their priorities. So, the
68 // easiest is a softimage or aerospace (yaw/pitch/roll) ordering
69 // of ZYX.
70 //
71 // float x_rot = 1;
72 // float y_rot = 2;
73 // float z_rot = 3;
74 //
75 // Eulerf angles(z_rot, y_rot, x_rot, Eulerf::ZYX);
76 // -or-
77 // Eulerf angles( V3f(z_rot,y_rot,z_rot), Eulerf::ZYX );
78 //
79 // If instead, the order was YXZ for instance you would have to
80 // do this:
81 //
82 // float x_rot = 1;
83 // float y_rot = 2;
84 // float z_rot = 3;
85 //
86 // Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ);
87 // -or-
88 // Eulerf angles( V3f(y_rot,x_rot,z_rot), Eulerf::YXZ );
89 //
90 // Notice how the order you put the angles into the three slots
91 // should correspond to the enum (YXZ) ordering. The input angle
92 // vector is called the "ijk" vector -- not an "xyz" vector. The
93 // ijk vector order is the same as the enum. If you treat the
94 // Euler<> as a Vec<> (which it inherts from) you will find the
95 // angles are ordered in the same way, i.e.:
96 //
97 // V3f v = angles;
98 // // v.x == y_rot, v.y == x_rot, v.z == z_rot
99 //
100 // If you just want the x, y, and z angles stored in a vector in
101 // that order, you can do this:
102 //
103 // V3f v = angles.toXYZVector()
104 // // v.x == x_rot, v.y == y_rot, v.z == z_rot
105 //
106 // If you want to set the Euler with an XYZVector use the
107 // optional layout argument:
108 //
109 // Eulerf angles(x_rot, y_rot, z_rot,
110 // Eulerf::YXZ,
111 // Eulerf::XYZLayout);
112 //
113 // This is the same as:
114 //
115 // Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ);
116 //
117 // Note that this won't do anything intelligent if you have a
118 // repeated axis in the euler angles (e.g. XYX)
119 //
120 // If you need to use the "relative" versions of these, you will
121 // need to use the "r" enums.
122 //
123 // The units of the rotation angles are assumed to be radians.
124 //
125 //----------------------------------------------------------------------
126 
127 
128 #include "ImathMath.h"
129 #include "ImathVec.h"
130 #include "ImathQuat.h"
131 #include "ImathMatrix.h"
132 #include "ImathLimits.h"
133 #include "ImathNamespace.h"
134 
135 #include <iostream>
136 
138 
139 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
140 // Disable MS VC++ warnings about conversion from double to float
141 #pragma warning(disable:4244)
142 #endif
143 
144 template <class T>
145 class Euler : public Vec3<T>
146 {
147  public:
148 
149  using Vec3<T>::x;
150  using Vec3<T>::y;
151  using Vec3<T>::z;
152 
153  enum Order
154  {
155  //
156  // All 24 possible orderings
157  //
158 
159  XYZ = 0x0101, // "usual" orderings
160  XZY = 0x0001,
161  YZX = 0x1101,
162  YXZ = 0x1001,
163  ZXY = 0x2101,
164  ZYX = 0x2001,
165 
166  XZX = 0x0011, // first axis repeated
167  XYX = 0x0111,
168  YXY = 0x1011,
169  YZY = 0x1111,
170  ZYZ = 0x2011,
171  ZXZ = 0x2111,
172 
173  XYZr = 0x2000, // relative orderings -- not common
174  XZYr = 0x2100,
175  YZXr = 0x1000,
176  YXZr = 0x1100,
177  ZXYr = 0x0000,
178  ZYXr = 0x0100,
179 
180  XZXr = 0x2110, // relative first axis repeated
181  XYXr = 0x2010,
182  YXYr = 0x1110,
183  YZYr = 0x1010,
184  ZYZr = 0x0110,
185  ZXZr = 0x0010,
186  // ||||
187  // VVVV
188  // Legend: ABCD
189  // A -> Initial Axis (0==x, 1==y, 2==z)
190  // B -> Parity Even (1==true)
191  // C -> Initial Repeated (1==true)
192  // D -> Frame Static (1==true)
193  //
194 
195  Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX |
196  XZX | XYX | YXY | YZY | ZYZ | ZXZ |
197  XYZr| XZYr| YZXr| YXZr| ZXYr| ZYXr|
198  XZXr| XYXr| YXYr| YZYr| ZYZr| ZXZr,
199 
200  Min = 0x0000,
201  Max = 0x2111,
203  };
204 
205  enum Axis { X = 0, Y = 1, Z = 2 };
206 
208 
209  //--------------------------------------------------------------------
210  // Constructors -- all default to ZYX non-relative ala softimage
211  // (where there is no argument to specify it)
212  //
213  // The Euler-from-matrix constructors assume that the matrix does
214  // not include shear or non-uniform scaling, but the constructors
215  // do not examine the matrix to verify this assumption. If necessary,
216  // you can adjust the matrix by calling the removeScalingAndShear()
217  // function, defined in ImathMatrixAlgo.h.
218  //--------------------------------------------------------------------
219 
220  Euler();
221  Euler(const Euler&);
222  Euler(Order p);
223  Euler(const Vec3<T> &v, Order o = Default, InputLayout l = IJKLayout);
224  Euler(T i, T j, T k, Order o = Default, InputLayout l = IJKLayout);
225  Euler(const Euler<T> &euler, Order newp);
226  Euler(const Matrix33<T> &, Order o = Default);
227  Euler(const Matrix44<T> &, Order o = Default);
228 
229  //---------------------------------
230  // Algebraic functions/ Operators
231  //---------------------------------
232 
233  const Euler<T>& operator= (const Euler<T>&);
234  const Euler<T>& operator= (const Vec3<T>&);
235 
236  //--------------------------------------------------------
237  // Set the euler value
238  // This does NOT convert the angles, but setXYZVector()
239  // does reorder the input vector.
240  //--------------------------------------------------------
241 
242  static bool legal(Order);
243 
244  void setXYZVector(const Vec3<T> &);
245 
246  Order order() const;
247  void setOrder(Order);
248 
249  void set(Axis initial,
250  bool relative,
251  bool parityEven,
252  bool firstRepeats);
253 
254  //------------------------------------------------------------
255  // Conversions, toXYZVector() reorders the angles so that
256  // the X rotation comes first, followed by the Y and Z
257  // in cases like XYX ordering, the repeated angle will be
258  // in the "z" component
259  //
260  // The Euler-from-matrix extract() functions assume that the
261  // matrix does not include shear or non-uniform scaling, but
262  // the extract() functions do not examine the matrix to verify
263  // this assumption. If necessary, you can adjust the matrix
264  // by calling the removeScalingAndShear() function, defined
265  // in ImathMatrixAlgo.h.
266  //------------------------------------------------------------
267 
268  void extract(const Matrix33<T>&);
269  void extract(const Matrix44<T>&);
270  void extract(const Quat<T>&);
271 
272  Matrix33<T> toMatrix33() const;
273  Matrix44<T> toMatrix44() const;
274  Quat<T> toQuat() const;
275  Vec3<T> toXYZVector() const;
276 
277  //---------------------------------------------------
278  // Use this function to unpack angles from ijk form
279  //---------------------------------------------------
280 
281  void angleOrder(int &i, int &j, int &k) const;
282 
283  //---------------------------------------------------
284  // Use this function to determine mapping from xyz to ijk
285  // - reshuffles the xyz to match the order
286  //---------------------------------------------------
287 
288  void angleMapping(int &i, int &j, int &k) const;
289 
290  //----------------------------------------------------------------------
291  //
292  // Utility methods for getting continuous rotations. None of these
293  // methods change the orientation given by its inputs (or at least
294  // that is the intent).
295  //
296  // angleMod() converts an angle to its equivalent in [-PI, PI]
297  //
298  // simpleXYZRotation() adjusts xyzRot so that its components differ
299  // from targetXyzRot by no more than +-PI
300  //
301  // nearestRotation() adjusts xyzRot so that its components differ
302  // from targetXyzRot by as little as possible.
303  // Note that xyz here really means ijk, because
304  // the order must be provided.
305  //
306  // makeNear() adjusts "this" Euler so that its components differ
307  // from target by as little as possible. This method
308  // might not make sense for Eulers with different order
309  // and it probably doesn't work for repeated axis and
310  // relative orderings (TODO).
311  //
312  //-----------------------------------------------------------------------
313 
314  static float angleMod (T angle);
315  static void simpleXYZRotation (Vec3<T> &xyzRot,
316  const Vec3<T> &targetXyzRot);
317  static void nearestRotation (Vec3<T> &xyzRot,
318  const Vec3<T> &targetXyzRot,
319  Order order = XYZ);
320 
321  void makeNear (const Euler<T> &target);
322 
323  bool frameStatic() const { return _frameStatic; }
324  bool initialRepeated() const { return _initialRepeated; }
325  bool parityEven() const { return _parityEven; }
326  Axis initialAxis() const { return _initialAxis; }
327 
328  protected:
329 
330  bool _frameStatic : 1; // relative or static rotations
331  bool _initialRepeated : 1; // init axis repeated as last
332  bool _parityEven : 1; // "parity of axis permutation"
333 #if defined _WIN32 || defined _WIN64
334  Axis _initialAxis ; // First axis of rotation
335 #else
336  Axis _initialAxis : 2; // First axis of rotation
337 #endif
338 };
339 
340 
341 //--------------------
342 // Convenient typedefs
343 //--------------------
344 
347 
348 
349 //---------------
350 // Implementation
351 //---------------
352 
353 template<class T>
354 inline void
355  Euler<T>::angleOrder(int &i, int &j, int &k) const
356 {
357  i = _initialAxis;
358  j = _parityEven ? (i+1)%3 : (i > 0 ? i-1 : 2);
359  k = _parityEven ? (i > 0 ? i-1 : 2) : (i+1)%3;
360 }
361 
362 template<class T>
363 inline void
364  Euler<T>::angleMapping(int &i, int &j, int &k) const
365 {
366  int m[3];
367 
368  m[_initialAxis] = 0;
369  m[(_initialAxis+1) % 3] = _parityEven ? 1 : 2;
370  m[(_initialAxis+2) % 3] = _parityEven ? 2 : 1;
371  i = m[0];
372  j = m[1];
373  k = m[2];
374 }
375 
376 template<class T>
377 inline void
379 {
380  int i,j,k;
381  angleMapping(i,j,k);
382  (*this)[i] = v.x;
383  (*this)[j] = v.y;
384  (*this)[k] = v.z;
385 }
386 
387 template<class T>
388 inline Vec3<T>
390 {
391  int i,j,k;
392  angleMapping(i,j,k);
393  return Vec3<T>((*this)[i],(*this)[j],(*this)[k]);
394 }
395 
396 
397 template<class T>
399  Vec3<T>(0,0,0),
400  _frameStatic(true),
401  _initialRepeated(false),
402  _parityEven(true),
403  _initialAxis(X)
404 {}
405 
406 template<class T>
407 Euler<T>::Euler(typename Euler<T>::Order p) :
408  Vec3<T>(0,0,0),
409  _frameStatic(true),
410  _initialRepeated(false),
411  _parityEven(true),
412  _initialAxis(X)
413 {
414  setOrder(p);
415 }
416 
417 template<class T>
418 inline Euler<T>::Euler( const Vec3<T> &v,
419  typename Euler<T>::Order p,
420  typename Euler<T>::InputLayout l )
421 {
422  setOrder(p);
423  if ( l == XYZLayout ) setXYZVector(v);
424  else { x = v.x; y = v.y; z = v.z; }
425 }
426 
427 template<class T>
428 inline Euler<T>::Euler(const Euler<T> &euler)
429 {
430  operator=(euler);
431 }
432 
433 template<class T>
434 inline Euler<T>::Euler(const Euler<T> &euler,Order p)
435 {
436  setOrder(p);
437  Matrix33<T> M = euler.toMatrix33();
438  extract(M);
439 }
440 
441 template<class T>
442 inline Euler<T>::Euler( T xi, T yi, T zi,
443  typename Euler<T>::Order p,
444  typename Euler<T>::InputLayout l)
445 {
446  setOrder(p);
447  if ( l == XYZLayout ) setXYZVector(Vec3<T>(xi,yi,zi));
448  else { x = xi; y = yi; z = zi; }
449 }
450 
451 template<class T>
452 inline Euler<T>::Euler( const Matrix33<T> &M, typename Euler::Order p )
453 {
454  setOrder(p);
455  extract(M);
456 }
457 
458 template<class T>
459 inline Euler<T>::Euler( const Matrix44<T> &M, typename Euler::Order p )
460 {
461  setOrder(p);
462  extract(M);
463 }
464 
465 template<class T>
466 inline void Euler<T>::extract(const Quat<T> &q)
467 {
468  extract(q.toMatrix33());
469 }
470 
471 template<class T>
473 {
474  int i,j,k;
475  angleOrder(i,j,k);
476 
477  if (_initialRepeated)
478  {
479  //
480  // Extract the first angle, x.
481  //
482 
483  x = Math<T>::atan2 (M[j][i], M[k][i]);
484 
485  //
486  // Remove the x rotation from M, so that the remaining
487  // rotation, N, is only around two axes, and gimbal lock
488  // cannot occur.
489  //
490 
491  Vec3<T> r (0, 0, 0);
492  r[i] = (_parityEven? -x: x);
493 
494  Matrix44<T> N;
495  N.rotate (r);
496 
497  N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0,
498  M[1][0], M[1][1], M[1][2], 0,
499  M[2][0], M[2][1], M[2][2], 0,
500  0, 0, 0, 1);
501  //
502  // Extract the other two angles, y and z, from N.
503  //
504 
505  T sy = Math<T>::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]);
506  y = Math<T>::atan2 (sy, N[i][i]);
507  z = Math<T>::atan2 (N[j][k], N[j][j]);
508  }
509  else
510  {
511  //
512  // Extract the first angle, x.
513  //
514 
515  x = Math<T>::atan2 (M[j][k], M[k][k]);
516 
517  //
518  // Remove the x rotation from M, so that the remaining
519  // rotation, N, is only around two axes, and gimbal lock
520  // cannot occur.
521  //
522 
523  Vec3<T> r (0, 0, 0);
524  r[i] = (_parityEven? -x: x);
525 
526  Matrix44<T> N;
527  N.rotate (r);
528 
529  N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0,
530  M[1][0], M[1][1], M[1][2], 0,
531  M[2][0], M[2][1], M[2][2], 0,
532  0, 0, 0, 1);
533  //
534  // Extract the other two angles, y and z, from N.
535  //
536 
537  T cy = Math<T>::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]);
538  y = Math<T>::atan2 (-N[i][k], cy);
539  z = Math<T>::atan2 (-N[j][i], N[j][j]);
540  }
541 
542  if (!_parityEven)
543  *this *= -1;
544 
545  if (!_frameStatic)
546  {
547  T t = x;
548  x = z;
549  z = t;
550  }
551 }
552 
553 template<class T>
555 {
556  int i,j,k;
557  angleOrder(i,j,k);
558 
559  if (_initialRepeated)
560  {
561  //
562  // Extract the first angle, x.
563  //
564 
565  x = Math<T>::atan2 (M[j][i], M[k][i]);
566 
567  //
568  // Remove the x rotation from M, so that the remaining
569  // rotation, N, is only around two axes, and gimbal lock
570  // cannot occur.
571  //
572 
573  Vec3<T> r (0, 0, 0);
574  r[i] = (_parityEven? -x: x);
575 
576  Matrix44<T> N;
577  N.rotate (r);
578  N = N * M;
579 
580  //
581  // Extract the other two angles, y and z, from N.
582  //
583 
584  T sy = Math<T>::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]);
585  y = Math<T>::atan2 (sy, N[i][i]);
586  z = Math<T>::atan2 (N[j][k], N[j][j]);
587  }
588  else
589  {
590  //
591  // Extract the first angle, x.
592  //
593 
594  x = Math<T>::atan2 (M[j][k], M[k][k]);
595 
596  //
597  // Remove the x rotation from M, so that the remaining
598  // rotation, N, is only around two axes, and gimbal lock
599  // cannot occur.
600  //
601 
602  Vec3<T> r (0, 0, 0);
603  r[i] = (_parityEven? -x: x);
604 
605  Matrix44<T> N;
606  N.rotate (r);
607  N = N * M;
608 
609  //
610  // Extract the other two angles, y and z, from N.
611  //
612 
613  T cy = Math<T>::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]);
614  y = Math<T>::atan2 (-N[i][k], cy);
615  z = Math<T>::atan2 (-N[j][i], N[j][j]);
616  }
617 
618  if (!_parityEven)
619  *this *= -1;
620 
621  if (!_frameStatic)
622  {
623  T t = x;
624  x = z;
625  z = t;
626  }
627 }
628 
629 template<class T>
631 {
632  int i,j,k;
633  angleOrder(i,j,k);
634 
635  Vec3<T> angles;
636 
637  if ( _frameStatic ) angles = (*this);
638  else angles = Vec3<T>(z,y,x);
639 
640  if ( !_parityEven ) angles *= -1.0;
641 
642  T ci = Math<T>::cos(angles.x);
643  T cj = Math<T>::cos(angles.y);
644  T ch = Math<T>::cos(angles.z);
645  T si = Math<T>::sin(angles.x);
646  T sj = Math<T>::sin(angles.y);
647  T sh = Math<T>::sin(angles.z);
648 
649  T cc = ci*ch;
650  T cs = ci*sh;
651  T sc = si*ch;
652  T ss = si*sh;
653 
654  Matrix33<T> M;
655 
656  if ( _initialRepeated )
657  {
658  M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci;
659  M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc;
660  M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss;
661  }
662  else
663  {
664  M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss;
665  M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc;
666  M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci;
667  }
668 
669  return M;
670 }
671 
672 template<class T>
674 {
675  int i,j,k;
676  angleOrder(i,j,k);
677 
678  Vec3<T> angles;
679 
680  if ( _frameStatic ) angles = (*this);
681  else angles = Vec3<T>(z,y,x);
682 
683  if ( !_parityEven ) angles *= -1.0;
684 
685  T ci = Math<T>::cos(angles.x);
686  T cj = Math<T>::cos(angles.y);
687  T ch = Math<T>::cos(angles.z);
688  T si = Math<T>::sin(angles.x);
689  T sj = Math<T>::sin(angles.y);
690  T sh = Math<T>::sin(angles.z);
691 
692  T cc = ci*ch;
693  T cs = ci*sh;
694  T sc = si*ch;
695  T ss = si*sh;
696 
697  Matrix44<T> M;
698 
699  if ( _initialRepeated )
700  {
701  M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci;
702  M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc;
703  M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss;
704  }
705  else
706  {
707  M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss;
708  M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc;
709  M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci;
710  }
711 
712  return M;
713 }
714 
715 template<class T>
717 {
718  Vec3<T> angles;
719  int i,j,k;
720  angleOrder(i,j,k);
721 
722  if ( _frameStatic ) angles = (*this);
723  else angles = Vec3<T>(z,y,x);
724 
725  if ( !_parityEven ) angles.y = -angles.y;
726 
727  T ti = angles.x*0.5;
728  T tj = angles.y*0.5;
729  T th = angles.z*0.5;
730  T ci = Math<T>::cos(ti);
731  T cj = Math<T>::cos(tj);
732  T ch = Math<T>::cos(th);
733  T si = Math<T>::sin(ti);
734  T sj = Math<T>::sin(tj);
735  T sh = Math<T>::sin(th);
736  T cc = ci*ch;
737  T cs = ci*sh;
738  T sc = si*ch;
739  T ss = si*sh;
740 
741  T parity = _parityEven ? 1.0 : -1.0;
742 
743  Quat<T> q;
744  Vec3<T> a;
745 
746  if ( _initialRepeated )
747  {
748  a[i] = cj*(cs + sc);
749  a[j] = sj*(cc + ss) * parity,
750  a[k] = sj*(cs - sc);
751  q.r = cj*(cc - ss);
752  }
753  else
754  {
755  a[i] = cj*sc - sj*cs,
756  a[j] = (cj*ss + sj*cc) * parity,
757  a[k] = cj*cs - sj*sc;
758  q.r = cj*cc + sj*ss;
759  }
760 
761  q.v = a;
762 
763  return q;
764 }
765 
766 template<class T>
767 inline bool
769 {
770  return (order & ~Legal) ? false : true;
771 }
772 
773 template<class T>
774 typename Euler<T>::Order
776 {
777  int foo = (_initialAxis == Z ? 0x2000 : (_initialAxis == Y ? 0x1000 : 0));
778 
779  if (_parityEven) foo |= 0x0100;
780  if (_initialRepeated) foo |= 0x0010;
781  if (_frameStatic) foo++;
782 
783  return (Order)foo;
784 }
785 
786 template<class T>
787 inline void Euler<T>::setOrder(typename Euler<T>::Order p)
788 {
789  set( p & 0x2000 ? Z : (p & 0x1000 ? Y : X), // initial axis
790  !(p & 0x1), // static?
791  !!(p & 0x100), // permutation even?
792  !!(p & 0x10)); // initial repeats?
793 }
794 
795 template<class T>
796 void Euler<T>::set(typename Euler<T>::Axis axis,
797  bool relative,
798  bool parityEven,
799  bool firstRepeats)
800 {
801  _initialAxis = axis;
802  _frameStatic = !relative;
803  _parityEven = parityEven;
804  _initialRepeated = firstRepeats;
805 }
806 
807 template<class T>
809 {
810  x = euler.x;
811  y = euler.y;
812  z = euler.z;
813  _initialAxis = euler._initialAxis;
814  _frameStatic = euler._frameStatic;
815  _parityEven = euler._parityEven;
816  _initialRepeated = euler._initialRepeated;
817  return *this;
818 }
819 
820 template<class T>
822 {
823  x = v.x;
824  y = v.y;
825  z = v.z;
826  return *this;
827 }
828 
829 template<class T>
830 std::ostream& operator << (std::ostream &o, const Euler<T> &euler)
831 {
832  char a[3] = { 'X', 'Y', 'Z' };
833 
834  const char* r = euler.frameStatic() ? "" : "r";
835  int i,j,k;
836  euler.angleOrder(i,j,k);
837 
838  if ( euler.initialRepeated() ) k = i;
839 
840  return o << "("
841  << euler.x << " "
842  << euler.y << " "
843  << euler.z << " "
844  << a[i] << a[j] << a[k] << r << ")";
845 }
846 
847 template <class T>
848 float
850 {
851  angle = fmod(T (angle), T (2 * M_PI));
852 
853  if (angle < -M_PI) angle += 2 * M_PI;
854  if (angle > +M_PI) angle -= 2 * M_PI;
855 
856  return angle;
857 }
858 
859 template <class T>
860 void
861 Euler<T>::simpleXYZRotation (Vec3<T> &xyzRot, const Vec3<T> &targetXyzRot)
862 {
863  Vec3<T> d = xyzRot - targetXyzRot;
864  xyzRot[0] = targetXyzRot[0] + angleMod(d[0]);
865  xyzRot[1] = targetXyzRot[1] + angleMod(d[1]);
866  xyzRot[2] = targetXyzRot[2] + angleMod(d[2]);
867 }
868 
869 template <class T>
870 void
871 Euler<T>::nearestRotation (Vec3<T> &xyzRot, const Vec3<T> &targetXyzRot,
872  Order order)
873 {
874  int i,j,k;
875  Euler<T> e (0,0,0, order);
876  e.angleOrder(i,j,k);
877 
878  simpleXYZRotation(xyzRot, targetXyzRot);
879 
880  Vec3<T> otherXyzRot;
881  otherXyzRot[i] = M_PI+xyzRot[i];
882  otherXyzRot[j] = M_PI-xyzRot[j];
883  otherXyzRot[k] = M_PI+xyzRot[k];
884 
885  simpleXYZRotation(otherXyzRot, targetXyzRot);
886 
887  Vec3<T> d = xyzRot - targetXyzRot;
888  Vec3<T> od = otherXyzRot - targetXyzRot;
889  T dMag = d.dot(d);
890  T odMag = od.dot(od);
891 
892  if (odMag < dMag)
893  {
894  xyzRot = otherXyzRot;
895  }
896 }
897 
898 template <class T>
899 void
901 {
902  Vec3<T> xyzRot = toXYZVector();
903  Vec3<T> targetXyz;
904  if (order() != target.order())
905  {
906  Euler<T> targetSameOrder = Euler<T>(target, order());
907  targetXyz = targetSameOrder.toXYZVector();
908  }
909  else
910  {
911  targetXyz = target.toXYZVector();
912  }
913 
914  nearestRotation(xyzRot, targetXyz, order());
915 
916  setXYZVector(xyzRot);
917 }
918 
919 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
920 #pragma warning(default:4244)
921 #endif
922 
924 
925 
926 #endif // INCLUDED_IMATHEULER_H
#define IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
const Euler< T > & operator=(const Euler< T > &)
Definition: ImathEuler.h:808
SYS_API double fmod(double x, double y)
Definition: SYS_FPUMath.h:85
T z
Definition: ImathVec.h:275
static T sin(T x)
Definition: ImathMath.h:99
bool initialRepeated() const
Definition: ImathEuler.h:324
#define IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
static float angleMod(T angle)
Definition: ImathEuler.h:849
void setXYZVector(const Vec3< T > &)
Definition: ImathEuler.h:378
const GLdouble * v
Definition: glcorearb.h:836
Euler()
Definition: ImathEuler.h:398
Matrix44< T > toMatrix44() const
Definition: ImathEuler.h:673
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
Quat< T > toQuat() const
Definition: ImathEuler.h:716
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
static void simpleXYZRotation(Vec3< T > &xyzRot, const Vec3< T > &targetXyzRot)
Definition: ImathEuler.h:861
Vec3< T > v
Definition: ImathQuat.h:77
bool _frameStatic
Definition: ImathEuler.h:330
GLint y
Definition: glcorearb.h:102
static T cos(T x)
Definition: ImathMath.h:98
png_uint_32 i
Definition: png.h:2877
#define M_PI
Definition: ImathPlatform.h:51
T r
Definition: ImathQuat.h:76
Matrix33< T > toMatrix33() const
Definition: ImathEuler.h:630
T x
Definition: ImathVec.h:275
Order order() const
Definition: ImathEuler.h:775
void extract(const Matrix33< T > &)
Definition: ImathEuler.h:472
T dot(const Vec3 &v) const
Definition: ImathVec.h:1467
Vec3< T > toXYZVector() const
Definition: ImathEuler.h:389
void makeNear(const Euler< T > &target)
Definition: ImathEuler.h:900
void set(Axis initial, bool relative, bool parityEven, bool firstRepeats)
Definition: ImathEuler.h:796
T angle(const Vec2< T > &v1, const Vec2< T > &v2)
Definition: Vec2.h:472
GLenum target
Definition: glcorearb.h:1666
Axis initialAxis() const
Definition: ImathEuler.h:326
bool parityEven() const
Definition: ImathEuler.h:325
Euler< float > Eulerf
Definition: ImathEuler.h:345
static T atan2(T x, T y)
Definition: ImathMath.h:97
static bool legal(Order)
Definition: ImathEuler.h:768
bool _parityEven
Definition: ImathEuler.h:332
void setOrder(Order)
Definition: ImathEuler.h:787
Euler< double > Eulerd
Definition: ImathEuler.h:346
Axis _initialAxis
Definition: ImathEuler.h:336
void angleMapping(int &i, int &j, int &k) const
Definition: ImathEuler.h:364
InputLayout
Definition: ImathEuler.h:207
GLint GLenum GLint x
Definition: glcorearb.h:408
bool frameStatic() const
Definition: ImathEuler.h:323
GA_API const UT_StringHolder N
const Matrix44 & rotate(const Vec3< S > &r)
void angleOrder(int &i, int &j, int &k) const
Definition: ImathEuler.h:355
T y
Definition: ImathVec.h:275
bool _initialRepeated
Definition: ImathEuler.h:331
static void nearestRotation(Vec3< T > &xyzRot, const Vec3< T > &targetXyzRot, Order order=XYZ)
Definition: ImathEuler.h:871
GLboolean r
Definition: glcorearb.h:1221
static T sqrt(T x)
Definition: ImathMath.h:115
Matrix33< T > toMatrix33() const
Definition: ImathQuat.h:810