Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/3rdparty/openexr/Imath/ImathEuler.h
16337 views
1
///////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright (c) 2002, 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 <iostream>
134
135
namespace Imath {
136
137
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
138
// Disable MS VC++ warnings about conversion from double to float
139
#pragma warning(disable:4244)
140
#endif
141
142
template <class T>
143
class Euler : public Vec3<T>
144
{
145
public:
146
147
using Vec3<T>::x;
148
using Vec3<T>::y;
149
using Vec3<T>::z;
150
151
enum Order
152
{
153
//
154
// All 24 possible orderings
155
//
156
157
XYZ = 0x0101, // "usual" orderings
158
XZY = 0x0001,
159
YZX = 0x1101,
160
YXZ = 0x1001,
161
ZXY = 0x2101,
162
ZYX = 0x2001,
163
164
XZX = 0x0011, // first axis repeated
165
XYX = 0x0111,
166
YXY = 0x1011,
167
YZY = 0x1111,
168
ZYZ = 0x2011,
169
ZXZ = 0x2111,
170
171
XYZr = 0x2000, // relative orderings -- not common
172
XZYr = 0x2100,
173
YZXr = 0x1000,
174
YXZr = 0x1100,
175
ZXYr = 0x0000,
176
ZYXr = 0x0100,
177
178
XZXr = 0x2110, // relative first axis repeated
179
XYXr = 0x2010,
180
YXYr = 0x1110,
181
YZYr = 0x1010,
182
ZYZr = 0x0110,
183
ZXZr = 0x0010,
184
// ||||
185
// VVVV
186
// Legend: ABCD
187
// A -> Initial Axis (0==x, 1==y, 2==z)
188
// B -> Parity Even (1==true)
189
// C -> Initial Repeated (1==true)
190
// D -> Frame Static (1==true)
191
//
192
193
Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX |
194
XZX | XYX | YXY | YZY | ZYZ | ZXZ |
195
XYZr| XZYr| YZXr| YXZr| ZXYr| ZYXr|
196
XZXr| XYXr| YXYr| YZYr| ZYZr| ZXZr,
197
198
Min = 0x0000,
199
Max = 0x2111,
200
Default = XYZ
201
};
202
203
enum Axis { X = 0, Y = 1, Z = 2 };
204
205
enum InputLayout { XYZLayout, IJKLayout };
206
207
//--------------------------------------------------------------------
208
// Constructors -- all default to ZYX non-relative ala softimage
209
// (where there is no argument to specify it)
210
//
211
// The Euler-from-matrix constructors assume that the matrix does
212
// not include shear or non-uniform scaling, but the constructors
213
// do not examine the matrix to verify this assumption. If necessary,
214
// you can adjust the matrix by calling the removeScalingAndShear()
215
// function, defined in ImathMatrixAlgo.h.
216
//--------------------------------------------------------------------
217
218
Euler();
219
Euler(const Euler&);
220
Euler(Order p);
221
Euler(const Vec3<T> &v, Order o = Default, InputLayout l = IJKLayout);
222
Euler(T i, T j, T k, Order o = Default, InputLayout l = IJKLayout);
223
Euler(const Euler<T> &euler, Order newp);
224
Euler(const Matrix33<T> &, Order o = Default);
225
Euler(const Matrix44<T> &, Order o = Default);
226
227
//---------------------------------
228
// Algebraic functions/ Operators
229
//---------------------------------
230
231
const Euler<T>& operator= (const Euler<T>&);
232
const Euler<T>& operator= (const Vec3<T>&);
233
234
//--------------------------------------------------------
235
// Set the euler value
236
// This does NOT convert the angles, but setXYZVector()
237
// does reorder the input vector.
238
//--------------------------------------------------------
239
240
static bool legal(Order);
241
242
void setXYZVector(const Vec3<T> &);
243
244
Order order() const;
245
void setOrder(Order);
246
247
void set(Axis initial,
248
bool relative,
249
bool parityEven,
250
bool firstRepeats);
251
252
//------------------------------------------------------------
253
// Conversions, toXYZVector() reorders the angles so that
254
// the X rotation comes first, followed by the Y and Z
255
// in cases like XYX ordering, the repeated angle will be
256
// in the "z" component
257
//
258
// The Euler-from-matrix extract() functions assume that the
259
// matrix does not include shear or non-uniform scaling, but
260
// the extract() functions do not examine the matrix to verify
261
// this assumption. If necessary, you can adjust the matrix
262
// by calling the removeScalingAndShear() function, defined
263
// in ImathMatrixAlgo.h.
264
//------------------------------------------------------------
265
266
void extract(const Matrix33<T>&);
267
void extract(const Matrix44<T>&);
268
void extract(const Quat<T>&);
269
270
Matrix33<T> toMatrix33() const;
271
Matrix44<T> toMatrix44() const;
272
Quat<T> toQuat() const;
273
Vec3<T> toXYZVector() const;
274
275
//---------------------------------------------------
276
// Use this function to unpack angles from ijk form
277
//---------------------------------------------------
278
279
void angleOrder(int &i, int &j, int &k) const;
280
281
//---------------------------------------------------
282
// Use this function to determine mapping from xyz to ijk
283
// - reshuffles the xyz to match the order
284
//---------------------------------------------------
285
286
void angleMapping(int &i, int &j, int &k) const;
287
288
//----------------------------------------------------------------------
289
//
290
// Utility methods for getting continuous rotations. None of these
291
// methods change the orientation given by its inputs (or at least
292
// that is the intent).
293
//
294
// angleMod() converts an angle to its equivalent in [-PI, PI]
295
//
296
// simpleXYZRotation() adjusts xyzRot so that its components differ
297
// from targetXyzRot by no more than +-PI
298
//
299
// nearestRotation() adjusts xyzRot so that its components differ
300
// from targetXyzRot by as little as possible.
301
// Note that xyz here really means ijk, because
302
// the order must be provided.
303
//
304
// makeNear() adjusts "this" Euler so that its components differ
305
// from target by as little as possible. This method
306
// might not make sense for Eulers with different order
307
// and it probably doesn't work for repeated axis and
308
// relative orderings (TODO).
309
//
310
//-----------------------------------------------------------------------
311
312
static float angleMod (T angle);
313
static void simpleXYZRotation (Vec3<T> &xyzRot,
314
const Vec3<T> &targetXyzRot);
315
static void nearestRotation (Vec3<T> &xyzRot,
316
const Vec3<T> &targetXyzRot,
317
Order order = XYZ);
318
319
void makeNear (const Euler<T> &target);
320
321
bool frameStatic() const { return _frameStatic; }
322
bool initialRepeated() const { return _initialRepeated; }
323
bool parityEven() const { return _parityEven; }
324
Axis initialAxis() const { return _initialAxis; }
325
326
protected:
327
328
bool _frameStatic : 1; // relative or static rotations
329
bool _initialRepeated : 1; // init axis repeated as last
330
bool _parityEven : 1; // "parity of axis permutation"
331
#if defined _WIN32 || defined _WIN64
332
Axis _initialAxis ; // First axis of rotation
333
#else
334
Axis _initialAxis : 2; // First axis of rotation
335
#endif
336
};
337
338
339
//--------------------
340
// Convenient typedefs
341
//--------------------
342
343
typedef Euler<float> Eulerf;
344
typedef Euler<double> Eulerd;
345
346
347
//---------------
348
// Implementation
349
//---------------
350
351
template<class T>
352
inline void
353
Euler<T>::angleOrder(int &i, int &j, int &k) const
354
{
355
i = _initialAxis;
356
j = _parityEven ? (i+1)%3 : (i > 0 ? i-1 : 2);
357
k = _parityEven ? (i > 0 ? i-1 : 2) : (i+1)%3;
358
}
359
360
template<class T>
361
inline void
362
Euler<T>::angleMapping(int &i, int &j, int &k) const
363
{
364
int m[3];
365
366
m[_initialAxis] = 0;
367
m[(_initialAxis+1) % 3] = _parityEven ? 1 : 2;
368
m[(_initialAxis+2) % 3] = _parityEven ? 2 : 1;
369
i = m[0];
370
j = m[1];
371
k = m[2];
372
}
373
374
template<class T>
375
inline void
376
Euler<T>::setXYZVector(const Vec3<T> &v)
377
{
378
int i,j,k;
379
angleMapping(i,j,k);
380
(*this)[i] = v.x;
381
(*this)[j] = v.y;
382
(*this)[k] = v.z;
383
}
384
385
template<class T>
386
inline Vec3<T>
387
Euler<T>::toXYZVector() const
388
{
389
int i,j,k;
390
angleMapping(i,j,k);
391
return Vec3<T>((*this)[i],(*this)[j],(*this)[k]);
392
}
393
394
395
template<class T>
396
Euler<T>::Euler() :
397
Vec3<T>(0,0,0),
398
_frameStatic(true),
399
_initialRepeated(false),
400
_parityEven(true),
401
_initialAxis(X)
402
{}
403
404
template<class T>
405
Euler<T>::Euler(typename Euler<T>::Order p) :
406
Vec3<T>(0,0,0),
407
_frameStatic(true),
408
_initialRepeated(false),
409
_parityEven(true),
410
_initialAxis(X)
411
{
412
setOrder(p);
413
}
414
415
template<class T>
416
inline Euler<T>::Euler( const Vec3<T> &v,
417
typename Euler<T>::Order p,
418
typename Euler<T>::InputLayout l )
419
{
420
setOrder(p);
421
if ( l == XYZLayout ) setXYZVector(v);
422
else { x = v.x; y = v.y; z = v.z; }
423
}
424
425
template<class T>
426
inline Euler<T>::Euler(const Euler<T> &euler)
427
{
428
operator=(euler);
429
}
430
431
template<class T>
432
inline Euler<T>::Euler(const Euler<T> &euler,Order p)
433
{
434
setOrder(p);
435
Matrix33<T> M = euler.toMatrix33();
436
extract(M);
437
}
438
439
template<class T>
440
inline Euler<T>::Euler( T xi, T yi, T zi,
441
typename Euler<T>::Order p,
442
typename Euler<T>::InputLayout l)
443
{
444
setOrder(p);
445
if ( l == XYZLayout ) setXYZVector(Vec3<T>(xi,yi,zi));
446
else { x = xi; y = yi; z = zi; }
447
}
448
449
template<class T>
450
inline Euler<T>::Euler( const Matrix33<T> &M, typename Euler::Order p )
451
{
452
setOrder(p);
453
extract(M);
454
}
455
456
template<class T>
457
inline Euler<T>::Euler( const Matrix44<T> &M, typename Euler::Order p )
458
{
459
setOrder(p);
460
extract(M);
461
}
462
463
template<class T>
464
inline void Euler<T>::extract(const Quat<T> &q)
465
{
466
extract(q.toMatrix33());
467
}
468
469
template<class T>
470
void Euler<T>::extract(const Matrix33<T> &M)
471
{
472
int i,j,k;
473
angleOrder(i,j,k);
474
475
if (_initialRepeated)
476
{
477
//
478
// Extract the first angle, x.
479
//
480
481
x = Math<T>::atan2 (M[j][i], M[k][i]);
482
483
//
484
// Remove the x rotation from M, so that the remaining
485
// rotation, N, is only around two axes, and gimbal lock
486
// cannot occur.
487
//
488
489
Vec3<T> r (0, 0, 0);
490
r[i] = (_parityEven? -x: x);
491
492
Matrix44<T> N;
493
N.rotate (r);
494
495
N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0,
496
M[1][0], M[1][1], M[1][2], 0,
497
M[2][0], M[2][1], M[2][2], 0,
498
0, 0, 0, 1);
499
//
500
// Extract the other two angles, y and z, from N.
501
//
502
503
T sy = Math<T>::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]);
504
y = Math<T>::atan2 (sy, N[i][i]);
505
z = Math<T>::atan2 (N[j][k], N[j][j]);
506
}
507
else
508
{
509
//
510
// Extract the first angle, x.
511
//
512
513
x = Math<T>::atan2 (M[j][k], M[k][k]);
514
515
//
516
// Remove the x rotation from M, so that the remaining
517
// rotation, N, is only around two axes, and gimbal lock
518
// cannot occur.
519
//
520
521
Vec3<T> r (0, 0, 0);
522
r[i] = (_parityEven? -x: x);
523
524
Matrix44<T> N;
525
N.rotate (r);
526
527
N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0,
528
M[1][0], M[1][1], M[1][2], 0,
529
M[2][0], M[2][1], M[2][2], 0,
530
0, 0, 0, 1);
531
//
532
// Extract the other two angles, y and z, from N.
533
//
534
535
T cy = Math<T>::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]);
536
y = Math<T>::atan2 (-N[i][k], cy);
537
z = Math<T>::atan2 (-N[j][i], N[j][j]);
538
}
539
540
if (!_parityEven)
541
*this *= -1;
542
543
if (!_frameStatic)
544
{
545
T t = x;
546
x = z;
547
z = t;
548
}
549
}
550
551
template<class T>
552
void Euler<T>::extract(const Matrix44<T> &M)
553
{
554
int i,j,k;
555
angleOrder(i,j,k);
556
557
if (_initialRepeated)
558
{
559
//
560
// Extract the first angle, x.
561
//
562
563
x = Math<T>::atan2 (M[j][i], M[k][i]);
564
565
//
566
// Remove the x rotation from M, so that the remaining
567
// rotation, N, is only around two axes, and gimbal lock
568
// cannot occur.
569
//
570
571
Vec3<T> r (0, 0, 0);
572
r[i] = (_parityEven? -x: x);
573
574
Matrix44<T> N;
575
N.rotate (r);
576
N = N * M;
577
578
//
579
// Extract the other two angles, y and z, from N.
580
//
581
582
T sy = Math<T>::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]);
583
y = Math<T>::atan2 (sy, N[i][i]);
584
z = Math<T>::atan2 (N[j][k], N[j][j]);
585
}
586
else
587
{
588
//
589
// Extract the first angle, x.
590
//
591
592
x = Math<T>::atan2 (M[j][k], M[k][k]);
593
594
//
595
// Remove the x rotation from M, so that the remaining
596
// rotation, N, is only around two axes, and gimbal lock
597
// cannot occur.
598
//
599
600
Vec3<T> r (0, 0, 0);
601
r[i] = (_parityEven? -x: x);
602
603
Matrix44<T> N;
604
N.rotate (r);
605
N = N * M;
606
607
//
608
// Extract the other two angles, y and z, from N.
609
//
610
611
T cy = Math<T>::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]);
612
y = Math<T>::atan2 (-N[i][k], cy);
613
z = Math<T>::atan2 (-N[j][i], N[j][j]);
614
}
615
616
if (!_parityEven)
617
*this *= -1;
618
619
if (!_frameStatic)
620
{
621
T t = x;
622
x = z;
623
z = t;
624
}
625
}
626
627
template<class T>
628
Matrix33<T> Euler<T>::toMatrix33() const
629
{
630
int i,j,k;
631
angleOrder(i,j,k);
632
633
Vec3<T> angles;
634
635
if ( _frameStatic ) angles = (*this);
636
else angles = Vec3<T>(z,y,x);
637
638
if ( !_parityEven ) angles *= -1.0;
639
640
T ci = Math<T>::cos(angles.x);
641
T cj = Math<T>::cos(angles.y);
642
T ch = Math<T>::cos(angles.z);
643
T si = Math<T>::sin(angles.x);
644
T sj = Math<T>::sin(angles.y);
645
T sh = Math<T>::sin(angles.z);
646
647
T cc = ci*ch;
648
T cs = ci*sh;
649
T sc = si*ch;
650
T ss = si*sh;
651
652
Matrix33<T> M;
653
654
if ( _initialRepeated )
655
{
656
M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci;
657
M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc;
658
M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss;
659
}
660
else
661
{
662
M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss;
663
M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc;
664
M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci;
665
}
666
667
return M;
668
}
669
670
template<class T>
671
Matrix44<T> Euler<T>::toMatrix44() const
672
{
673
int i,j,k;
674
angleOrder(i,j,k);
675
676
Vec3<T> angles;
677
678
if ( _frameStatic ) angles = (*this);
679
else angles = Vec3<T>(z,y,x);
680
681
if ( !_parityEven ) angles *= -1.0;
682
683
T ci = Math<T>::cos(angles.x);
684
T cj = Math<T>::cos(angles.y);
685
T ch = Math<T>::cos(angles.z);
686
T si = Math<T>::sin(angles.x);
687
T sj = Math<T>::sin(angles.y);
688
T sh = Math<T>::sin(angles.z);
689
690
T cc = ci*ch;
691
T cs = ci*sh;
692
T sc = si*ch;
693
T ss = si*sh;
694
695
Matrix44<T> M;
696
697
if ( _initialRepeated )
698
{
699
M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci;
700
M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc;
701
M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss;
702
}
703
else
704
{
705
M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss;
706
M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc;
707
M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci;
708
}
709
710
return M;
711
}
712
713
template<class T>
714
Quat<T> Euler<T>::toQuat() const
715
{
716
Vec3<T> angles;
717
int i,j,k;
718
angleOrder(i,j,k);
719
720
if ( _frameStatic ) angles = (*this);
721
else angles = Vec3<T>(z,y,x);
722
723
if ( !_parityEven ) angles.y = -angles.y;
724
725
T ti = angles.x*0.5;
726
T tj = angles.y*0.5;
727
T th = angles.z*0.5;
728
T ci = Math<T>::cos(ti);
729
T cj = Math<T>::cos(tj);
730
T ch = Math<T>::cos(th);
731
T si = Math<T>::sin(ti);
732
T sj = Math<T>::sin(tj);
733
T sh = Math<T>::sin(th);
734
T cc = ci*ch;
735
T cs = ci*sh;
736
T sc = si*ch;
737
T ss = si*sh;
738
739
T parity = _parityEven ? 1.0 : -1.0;
740
741
Quat<T> q;
742
Vec3<T> a;
743
744
if ( _initialRepeated )
745
{
746
a[i] = cj*(cs + sc);
747
a[j] = sj*(cc + ss) * parity,
748
a[k] = sj*(cs - sc);
749
q.r = cj*(cc - ss);
750
}
751
else
752
{
753
a[i] = cj*sc - sj*cs,
754
a[j] = (cj*ss + sj*cc) * parity,
755
a[k] = cj*cs - sj*sc;
756
q.r = cj*cc + sj*ss;
757
}
758
759
q.v = a;
760
761
return q;
762
}
763
764
template<class T>
765
inline bool
766
Euler<T>::legal(typename Euler<T>::Order order)
767
{
768
return (order & ~Legal) ? false : true;
769
}
770
771
template<class T>
772
typename Euler<T>::Order
773
Euler<T>::order() const
774
{
775
int foo = (_initialAxis == Z ? 0x2000 : (_initialAxis == Y ? 0x1000 : 0));
776
777
if (_parityEven) foo |= 0x0100;
778
if (_initialRepeated) foo |= 0x0010;
779
if (_frameStatic) foo++;
780
781
return (Order)foo;
782
}
783
784
template<class T>
785
inline void Euler<T>::setOrder(typename Euler<T>::Order p)
786
{
787
set( p & 0x2000 ? Z : (p & 0x1000 ? Y : X), // initial axis
788
!(p & 0x1), // static?
789
!!(p & 0x100), // permutation even?
790
!!(p & 0x10)); // initial repeats?
791
}
792
793
template<class T>
794
void Euler<T>::set(typename Euler<T>::Axis axis,
795
bool relative,
796
bool parityEven,
797
bool firstRepeats)
798
{
799
_initialAxis = axis;
800
_frameStatic = !relative;
801
_parityEven = parityEven;
802
_initialRepeated = firstRepeats;
803
}
804
805
template<class T>
806
const Euler<T>& Euler<T>::operator= (const Euler<T> &euler)
807
{
808
x = euler.x;
809
y = euler.y;
810
z = euler.z;
811
_initialAxis = euler._initialAxis;
812
_frameStatic = euler._frameStatic;
813
_parityEven = euler._parityEven;
814
_initialRepeated = euler._initialRepeated;
815
return *this;
816
}
817
818
template<class T>
819
const Euler<T>& Euler<T>::operator= (const Vec3<T> &v)
820
{
821
x = v.x;
822
y = v.y;
823
z = v.z;
824
return *this;
825
}
826
827
template<class T>
828
std::ostream& operator << (std::ostream &o, const Euler<T> &euler)
829
{
830
char a[3] = { 'X', 'Y', 'Z' };
831
832
const char* r = euler.frameStatic() ? "" : "r";
833
int i,j,k;
834
euler.angleOrder(i,j,k);
835
836
if ( euler.initialRepeated() ) k = i;
837
838
return o << "("
839
<< euler.x << " "
840
<< euler.y << " "
841
<< euler.z << " "
842
<< a[i] << a[j] << a[k] << r << ")";
843
}
844
845
template <class T>
846
float
847
Euler<T>::angleMod (T angle)
848
{
849
angle = fmod(T (angle), T (2 * M_PI));
850
851
if (angle < -M_PI) angle += 2 * M_PI;
852
if (angle > +M_PI) angle -= 2 * M_PI;
853
854
return angle;
855
}
856
857
template <class T>
858
void
859
Euler<T>::simpleXYZRotation (Vec3<T> &xyzRot, const Vec3<T> &targetXyzRot)
860
{
861
Vec3<T> d = xyzRot - targetXyzRot;
862
xyzRot[0] = targetXyzRot[0] + angleMod(d[0]);
863
xyzRot[1] = targetXyzRot[1] + angleMod(d[1]);
864
xyzRot[2] = targetXyzRot[2] + angleMod(d[2]);
865
}
866
867
template <class T>
868
void
869
Euler<T>::nearestRotation (Vec3<T> &xyzRot, const Vec3<T> &targetXyzRot,
870
Order order)
871
{
872
int i,j,k;
873
Euler<T> e (0,0,0, order);
874
e.angleOrder(i,j,k);
875
876
simpleXYZRotation(xyzRot, targetXyzRot);
877
878
Vec3<T> otherXyzRot;
879
otherXyzRot[i] = M_PI+xyzRot[i];
880
otherXyzRot[j] = M_PI-xyzRot[j];
881
otherXyzRot[k] = M_PI+xyzRot[k];
882
883
simpleXYZRotation(otherXyzRot, targetXyzRot);
884
885
Vec3<T> d = xyzRot - targetXyzRot;
886
Vec3<T> od = otherXyzRot - targetXyzRot;
887
T dMag = d.dot(d);
888
T odMag = od.dot(od);
889
890
if (odMag < dMag)
891
{
892
xyzRot = otherXyzRot;
893
}
894
}
895
896
template <class T>
897
void
898
Euler<T>::makeNear (const Euler<T> &target)
899
{
900
Vec3<T> xyzRot = toXYZVector();
901
Vec3<T> targetXyz;
902
if (order() != target.order())
903
{
904
Euler<T> targetSameOrder = Euler<T>(target, order());
905
targetXyz = targetSameOrder.toXYZVector();
906
}
907
else
908
{
909
targetXyz = target.toXYZVector();
910
}
911
912
nearestRotation(xyzRot, targetXyz, order());
913
914
setXYZVector(xyzRot);
915
}
916
917
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
918
#pragma warning(default:4244)
919
#endif
920
921
} // namespace Imath
922
923
924
#endif
925
926