Coverage Report

Created: 2023-03-26 07:07

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