1 ///////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
6 // All rights reserved.
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
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
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.
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.
33 ///////////////////////////////////////////////////////////////////////////
37 #ifndef INCLUDED_IMATHQUAT_H
38 #define INCLUDED_IMATHQUAT_H
40 //----------------------------------------------------------------------
42 // template class Quat<T>
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
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.
56 //----------------------------------------------------------------------
59 #include "ImathMatrix.h"
65 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
66 // Disable MS VC++ warnings about conversion from double to float
67 #pragma warning(disable:4244)
74 Quat<T> slerp (const Quat<T> &q1,const Quat<T> &q2, T t);
77 Quat<T> squad (const Quat<T> &q1,const Quat<T> &q2,
78 const Quat<T> &qa,const Quat<T> &qb, T t);
81 void intermediate (const Quat<T> &q0, const Quat<T> &q1,
82 const Quat<T> &q2, const Quat<T> &q3,
83 Quat<T> &qa, Quat<T> &qb);
91 Vec3<T> v; // imaginary vector
93 //-----------------------------------------------------
94 // Constructors - default constructor is identity quat
95 //-----------------------------------------------------
97 Quat() : r(1), v(0,0,0) {}
100 Quat( const Quat<S>& q) : r(q.r), v(q.v) {}
102 Quat( T s, T i, T j, T k ) : r(s), v(i,j,k) {}
104 Quat( T s, Vec3<T> d ) : r(s), v(d) {}
106 static Quat<T> identity() { return Quat<T>(); }
108 //------------------------------------------------
109 // Basic Algebra - Operators and Methods
110 // The operator return values are *NOT* normalized
112 // operator^ is 4D dot product
113 // operator/ uses the inverse() quaternion
114 // operator~ is conjugate -- if (S+V) is quat then
115 // the conjugate (S+V)* == (S-V)
117 // some operators (*,/,*=,/=) treat the quat as
118 // a 4D vector when one of the operands is scalar
119 //------------------------------------------------
121 const Quat<T>& operator= (const Quat<T>&);
122 const Quat<T>& operator*= (const Quat<T>&);
123 const Quat<T>& operator*= (T);
124 const Quat<T>& operator/= (const Quat<T>&);
125 const Quat<T>& operator/= (T);
126 const Quat<T>& operator+= (const Quat<T>&);
127 const Quat<T>& operator-= (const Quat<T>&);
128 T& operator[] (int index); // as 4D vector
129 T operator[] (int index) const;
131 template <class S> bool operator == (const Quat<S> &q) const;
132 template <class S> bool operator != (const Quat<S> &q) const;
134 Quat<T>& invert(); // this -> 1 / this
135 Quat<T> inverse() const;
136 Quat<T>& normalize(); // returns this
137 Quat<T> normalized() const;
138 T length() const; // in R4
140 //-----------------------
141 // Rotation conversion
142 //-----------------------
144 Quat<T>& setAxisAngle(const Vec3<T>& axis, T radians);
145 Quat<T>& setRotation(const Vec3<T>& fromDirection,
146 const Vec3<T>& toDirection);
149 Vec3<T> axis() const;
151 Matrix33<T> toMatrix33() const;
152 Matrix44<T> toMatrix44() const;
159 //--------------------
160 // Convenient typedefs
161 //--------------------
163 typedef Quat<float> Quatf;
164 typedef Quat<double> Quatd;
172 inline const Quat<T>& Quat<T>::operator= (const Quat<T>& q)
180 inline const Quat<T>& Quat<T>::operator*= (const Quat<T>& q)
182 T rtmp = r * q.r - (v ^ q.v);
183 v = r * q.v + v * q.r + v % q.v;
189 inline const Quat<T>& Quat<T>::operator*= (T t)
197 inline const Quat<T>& Quat<T>::operator/= (const Quat<T>& q)
199 *this = *this * q.inverse();
204 inline const Quat<T>& Quat<T>::operator/= (T t)
212 inline const Quat<T>& Quat<T>::operator+= (const Quat<T>& q)
220 inline const Quat<T>& Quat<T>::operator-= (const Quat<T>& q)
227 inline T& Quat<T>::operator[] (int index)
229 return index ? v[index-1] : r;
233 inline T Quat<T>::operator[] (int index) const
235 return index ? v[index-1] : r;
241 Quat<T>::operator == (const Quat<S> &q) const
243 return r == q.r && v == q.v;
249 Quat<T>::operator != (const Quat<S> &q) const
251 return r != q.r || v != q.v;
255 inline T operator^ (const Quat<T>& q1,const Quat<T>& q2)
257 return q1.r * q2.r + (q1.v ^ q2.v);
261 inline T Quat<T>::length() const
263 return Math<T>::sqrt( r * r + (v ^ v) );
267 inline Quat<T>& Quat<T>::normalize()
269 if ( T l = length() ) { r /= l; v /= l; }
270 else { r = 1; v = Vec3<T>(0); }
275 inline Quat<T> Quat<T>::normalized() const
277 if ( T l = length() ) return Quat( r / l, v / l );
282 inline Quat<T> Quat<T>::inverse() const
285 // - = ---- where Q* is conjugate (operator~)
286 // Q Q* Q and (Q* Q) == Q ^ Q (4D dot)
288 T qdot = *this ^ *this;
289 return Quat( r / qdot, -v / qdot );
293 inline Quat<T>& Quat<T>::invert()
295 T qdot = (*this) ^ (*this);
303 slerp(const Quat<T> &q1,const Quat<T> &q2, T t)
306 // Spherical linear interpolation.
308 // NOTE: Assumes q1 and q2 are normalized and that 0 <= t <= 1.
310 // This method does *not* interpolate along the shortest arc
311 // between q1 and q2. If you desire interpolation along the
312 // shortest arc, then consider flipping the second quaternion
313 // explicitly before calling slerp. The implementation of squad()
314 // depends on a slerp() that interpolates as is, without the
315 // automatic flipping.
318 T cosomega = q1 ^ q2;
319 if (cosomega >= (T) 1.0)
322 // Special case: q1 and q2 are the same, so just return one of them.
323 // This also catches the case where cosomega is very slightly > 1.0
329 T sinomega = Math<T>::sqrt (1 - cosomega * cosomega);
333 if (sinomega * limits<T>::max() > 1)
335 T omega = Math<T>::acos (cosomega);
336 T s1 = Math<T>::sin ((1.0 - t) * omega) / sinomega;
337 T s2 = Math<T>::sin (t * omega) / sinomega;
339 result = s1 * q1 + s2 * q2;
341 else if (cosomega > 0)
350 result = s1 * q1 + s2 * q2;
358 result.v.x = - q1.v.y;
363 T s1 = Math<T>::sin ((0.5 - t) * M_PI);
364 T s2 = Math<T>::sin (t * M_PI);
366 result = s1 * q1 + s2 * result;
373 Quat<T> spline(const Quat<T> &q0, const Quat<T> &q1,
374 const Quat<T> &q2, const Quat<T> &q3,
377 // Spherical Cubic Spline Interpolation -
378 // from Advanced Animation and Rendering
379 // Techniques by Watt and Watt, Page 366:
380 // A spherical curve is constructed using three
381 // spherical linear interpolations of a quadrangle
382 // of unit quaternions: q1, qa, qb, q2.
383 // Given a set of quaternion keys: q0, q1, q2, q3,
384 // this routine does the interpolation between
385 // q1 and q2 by constructing two intermediate
386 // quaternions: qa and qb. The qa and qb are
387 // computed by the intermediate function to
388 // guarantee the continuity of tangents across
389 // adjacent cubic segments. The qa represents in-tangent
390 // for q1 and the qb represents the out-tangent for q2.
392 // The q1 q2 is the cubic segment being interpolated.
393 // The q0 is from the previous adjacent segment and q3 is
394 // from the next adjacent segment. The q0 and q3 are used
395 // in computing qa and qb.
398 Quat<T> qa = intermediate (q0, q1, q2);
399 Quat<T> qb = intermediate (q1, q2, q3);
400 Quat<T> result = squad(q1, qa, qb, q2, t);
406 Quat<T> squad(const Quat<T> &q1, const Quat<T> &qa,
407 const Quat<T> &qb, const Quat<T> &q2,
410 // Spherical Quadrangle Interpolation -
411 // from Advanced Animation and Rendering
412 // Techniques by Watt and Watt, Page 366:
413 // It constructs a spherical cubic interpolation as
414 // a series of three spherical linear interpolations
415 // of a quadrangle of unit quaternions.
418 Quat<T> r1 = slerp(q1, q2, t);
419 Quat<T> r2 = slerp(qa, qb, t);
420 Quat<T> result = slerp(r1, r2, 2*t*(1-t));
426 Quat<T> intermediate(const Quat<T> &q0, const Quat<T> &q1, const Quat<T> &q2)
428 // From advanced Animation and Rendering
429 // Techniques by Watt and Watt, Page 366:
430 // computing the inner quadrangle
431 // points (qa and qb) to guarantee tangent
434 Quat<T> q1inv = q1.inverse();
435 Quat<T> c1 = q1inv*q2;
436 Quat<T> c2 = q1inv*q0;
437 Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log());
438 Quat<T> qa = q1 * c3.exp();
444 inline Quat<T> Quat<T>::log() const
447 // For unit quaternion, from Advanced Animation and
448 // Rendering Techniques by Watt and Watt, Page 366:
451 T theta = Math<T>::acos (std::min (r, (T) 1.0));
453 return Quat<T> (0, v);
455 T sintheta = Math<T>::sin (theta);
458 if (abs (sintheta) < 1 && abs (theta) >= limits<T>::max() * abs (sintheta))
461 k = theta / sintheta;
463 return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k);
467 inline Quat<T> Quat<T>::exp() const
470 // For pure quaternion (zero scalar part):
471 // from Advanced Animation and Rendering
472 // Techniques by Watt and Watt, Page 366:
475 T theta = v.length();
476 T sintheta = Math<T>::sin (theta);
479 if (abs (theta) < 1 && abs (sintheta) >= limits<T>::max() * abs (theta))
482 k = sintheta / theta;
484 T costheta = Math<T>::cos (theta);
486 return Quat<T> (costheta, v.x * k, v.y * k, v.z * k);
490 inline T Quat<T>::angle() const
492 return 2.0*Math<T>::acos(r);
496 inline Vec3<T> Quat<T>::axis() const
498 return v.normalized();
502 inline Quat<T>& Quat<T>::setAxisAngle(const Vec3<T>& axis, T radians)
504 r = Math<T>::cos(radians/2);
505 v = axis.normalized() * Math<T>::sin(radians/2);
512 Quat<T>::setRotation(const Vec3<T>& from, const Vec3<T>& to)
515 // Ported from SbRotation
518 T cost = from.dot(to) / Math<T>::sqrt(from.dot(from) * to.dot(to));
520 // check for degeneracies
524 // Vectors are parallel.
530 else if (cost < -0.99999)
533 // Vectors are opposite. Find an axis to rotate around,
534 // which should be perpendicular to the original axis.
537 Vec3<T> frm = from.normalized();
538 v = frm.cross(Vec3<T>(1, 0, 0));
539 if (v.length() < 0.00001)
540 v = frm.cross(Vec3<T>(0, 1, 0));
547 // Use half-angle formulae:
548 // cos^2 t = ( 1 + cos (2t) ) / 2
549 // w part is cosine of half the rotation angle
552 r = Math<T>::sqrt(0.5 * (1.0 + cost));
555 // sin^2 t = ( 1 - cos (2t) ) / 2
556 // Do the normalization of the axis vector at the same time so
557 // we only call sqrt once.
561 v *= Math<T>::sqrt((0.5 * (1.0 - cost))/(v.dot(v)));
568 Matrix33<T> Quat<T>::toMatrix33() const
570 return Matrix33<T>(1. - 2.0 * (v.y * v.y + v.z * v.z),
571 2.0 * (v.x * v.y + v.z * r),
572 2.0 * (v.z * v.x - v.y * r),
574 2.0 * (v.x * v.y - v.z * r),
575 1. - 2.0 * (v.z * v.z + v.x * v.x),
576 2.0 * (v.y * v.z + v.x * r),
578 2.0 * (v.z * v.x + v.y * r),
579 2.0 * (v.y * v.z - v.x * r),
580 1. - 2.0 * (v.y * v.y + v.x * v.x));
584 Matrix44<T> Quat<T>::toMatrix44() const
586 return Matrix44<T>(1. - 2.0 * (v.y * v.y + v.z * v.z),
587 2.0 * (v.x * v.y + v.z * r),
588 2.0 * (v.z * v.x - v.y * r),
590 2.0 * (v.x * v.y - v.z * r),
591 1. - 2.0 * (v.z * v.z + v.x * v.x),
592 2.0 * (v.y * v.z + v.x * r),
594 2.0 * (v.z * v.x + v.y * r),
595 2.0 * (v.y * v.z - v.x * r),
596 1. - 2.0 * (v.y * v.y + v.x * v.x),
606 inline Matrix33<T> operator* (const Matrix33<T> &M, const Quat<T> &q)
608 return M * q.toMatrix33();
612 inline Matrix33<T> operator* (const Quat<T> &q, const Matrix33<T> &M)
614 return q.toMatrix33() * M;
618 std::ostream& operator<< (std::ostream &o, const Quat<T> &q)
620 return o << "(" << q.r
629 inline Quat<T> operator* (const Quat<T>& q1, const Quat<T>& q2)
631 // (S1+V1) (S2+V2) = S1 S2 - V1.V2 + S1 V2 + V1 S2 + V1 x V2
632 return Quat<T>( q1.r * q2.r - (q1.v ^ q2.v),
633 q1.r * q2.v + q1.v * q2.r + q1.v % q2.v );
637 inline Quat<T> operator/ (const Quat<T>& q1, const Quat<T>& q2)
639 return q1 * q2.inverse();
643 inline Quat<T> operator/ (const Quat<T>& q,T t)
645 return Quat<T>(q.r/t,q.v/t);
649 inline Quat<T> operator* (const Quat<T>& q,T t)
651 return Quat<T>(q.r*t,q.v*t);
655 inline Quat<T> operator* (T t, const Quat<T>& q)
657 return Quat<T>(q.r*t,q.v*t);
661 inline Quat<T> operator+ (const Quat<T>& q1, const Quat<T>& q2)
663 return Quat<T>( q1.r + q2.r, q1.v + q2.v );
667 inline Quat<T> operator- (const Quat<T>& q1, const Quat<T>& q2)
669 return Quat<T>( q1.r - q2.r, q1.v - q2.v );
673 inline Quat<T> operator~ (const Quat<T>& q)
675 return Quat<T>( q.r, -q.v ); // conjugate: (S+V)* = S-V
679 inline Quat<T> operator- (const Quat<T>& q)
681 return Quat<T>( -q.r, -q.v );
684 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
685 #pragma warning(default:4244)