Blame Imath/ImathQuat.h

Packit 8dc392
///////////////////////////////////////////////////////////////////////////
Packit 8dc392
//
Packit 8dc392
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
Packit 8dc392
// Digital Ltd. LLC
Packit 8dc392
// 
Packit 8dc392
// All rights reserved.
Packit 8dc392
// 
Packit 8dc392
// Redistribution and use in source and binary forms, with or without
Packit 8dc392
// modification, are permitted provided that the following conditions are
Packit 8dc392
// met:
Packit 8dc392
// *       Redistributions of source code must retain the above copyright
Packit 8dc392
// notice, this list of conditions and the following disclaimer.
Packit 8dc392
// *       Redistributions in binary form must reproduce the above
Packit 8dc392
// copyright notice, this list of conditions and the following disclaimer
Packit 8dc392
// in the documentation and/or other materials provided with the
Packit 8dc392
// distribution.
Packit 8dc392
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 8dc392
// its contributors may be used to endorse or promote products derived
Packit 8dc392
// from this software without specific prior written permission. 
Packit 8dc392
// 
Packit 8dc392
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 8dc392
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 8dc392
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 8dc392
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 8dc392
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 8dc392
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 8dc392
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 8dc392
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 8dc392
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 8dc392
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 8dc392
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 8dc392
//
Packit 8dc392
///////////////////////////////////////////////////////////////////////////
Packit 8dc392
Packit 8dc392
Packit 8dc392
Packit 8dc392
#ifndef INCLUDED_IMATHQUAT_H
Packit 8dc392
#define INCLUDED_IMATHQUAT_H
Packit 8dc392
Packit 8dc392
//----------------------------------------------------------------------
Packit 8dc392
//
Packit 8dc392
//	template class Quat<T>
Packit 8dc392
//
Packit 8dc392
//	"Quaternions came from Hamilton ... and have been an unmixed
Packit 8dc392
//	evil to those who have touched them in any way. Vector is a
Packit 8dc392
//	useless survival ... and has never been of the slightest use
Packit 8dc392
//	to any creature."
Packit 8dc392
//
Packit 8dc392
//	    - Lord Kelvin
Packit 8dc392
//
Packit 8dc392
//	This class implements the quaternion numerical type -- you
Packit 8dc392
//      will probably want to use this class to represent orientations
Packit 8dc392
//	in R3 and to convert between various euler angle reps. You
Packit 8dc392
//	should probably use Imath::Euler<> for that.
Packit 8dc392
//
Packit 8dc392
//----------------------------------------------------------------------
Packit 8dc392
Packit 8dc392
#include "ImathExc.h"
Packit 8dc392
#include "ImathMatrix.h"
Packit 8dc392
#include "ImathNamespace.h"
Packit 8dc392
Packit 8dc392
#include <iostream>
Packit 8dc392
Packit 8dc392
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
Packit 8dc392
Packit 8dc392
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
Packit 8dc392
// Disable MS VC++ warnings about conversion from double to float
Packit 8dc392
#pragma warning(disable:4244)
Packit 8dc392
#endif
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
class Quat
Packit 8dc392
{
Packit 8dc392
  public:
Packit 8dc392
Packit 8dc392
    T			r;	    // real part
Packit 8dc392
    Vec3<T>		v;	    // imaginary vector
Packit 8dc392
Packit 8dc392
Packit 8dc392
    //-----------------------------------------------------
Packit 8dc392
    //	Constructors - default constructor is identity quat
Packit 8dc392
    //-----------------------------------------------------
Packit 8dc392
Packit 8dc392
    Quat ();
Packit 8dc392
Packit 8dc392
    template <class S>
Packit 8dc392
    Quat (const Quat<S> &q);
Packit 8dc392
Packit 8dc392
    Quat (T s, T i, T j, T k);
Packit 8dc392
Packit 8dc392
    Quat (T s, Vec3<T> d);
Packit 8dc392
Packit 8dc392
    static Quat<T> identity ();
Packit 8dc392
Packit 8dc392
Packit 8dc392
    //-------------------------------------------------
Packit 8dc392
    //	Basic Algebra - Operators and Methods
Packit 8dc392
    //  The operator return values are *NOT* normalized
Packit 8dc392
    //
Packit 8dc392
    //  operator^ and euclideanInnnerProduct() both
Packit 8dc392
    //            implement the 4D dot product
Packit 8dc392
    //
Packit 8dc392
    //  operator/ uses the inverse() quaternion
Packit 8dc392
    //
Packit 8dc392
    //	operator~ is conjugate -- if (S+V) is quat then
Packit 8dc392
    //		  the conjugate (S+V)* == (S-V)
Packit 8dc392
    //
Packit 8dc392
    //  some operators (*,/,*=,/=) treat the quat as
Packit 8dc392
    //	a 4D vector when one of the operands is scalar
Packit 8dc392
    //-------------------------------------------------
Packit 8dc392
Packit 8dc392
    const Quat<T> &	operator =	(const Quat<T> &q);
Packit 8dc392
    const Quat<T> &	operator *=	(const Quat<T> &q);
Packit 8dc392
    const Quat<T> &	operator *=	(T t);
Packit 8dc392
    const Quat<T> &	operator /=	(const Quat<T> &q);
Packit 8dc392
    const Quat<T> &	operator /=	(T t);
Packit 8dc392
    const Quat<T> &	operator +=	(const Quat<T> &q);
Packit 8dc392
    const Quat<T> &	operator -=	(const Quat<T> &q);
Packit 8dc392
    T &			operator []	(int index);	// as 4D vector
Packit 8dc392
    T			operator []	(int index) const;
Packit 8dc392
Packit 8dc392
    template <class S> bool operator == (const Quat<S> &q) const;
Packit 8dc392
    template <class S> bool operator != (const Quat<S> &q) const;
Packit 8dc392
Packit 8dc392
    Quat<T> &		invert ();		// this -> 1 / this
Packit 8dc392
    Quat<T>		inverse () const;
Packit 8dc392
    Quat<T> &		normalize ();		// returns this
Packit 8dc392
    Quat<T>		normalized () const;
Packit 8dc392
    T			length () const;	// in R4
Packit 8dc392
    Vec3<T>             rotateVector(const Vec3<T> &original) const;
Packit 8dc392
    T                   euclideanInnerProduct(const Quat<T> &q) const;
Packit 8dc392
Packit 8dc392
    //-----------------------
Packit 8dc392
    //	Rotation conversion
Packit 8dc392
    //-----------------------
Packit 8dc392
Packit 8dc392
    Quat<T> &		setAxisAngle (const Vec3<T> &axis, T radians);
Packit 8dc392
Packit 8dc392
    Quat<T> &		setRotation (const Vec3<T> &fromDirection,
Packit 8dc392
				     const Vec3<T> &toDirection);
Packit 8dc392
Packit 8dc392
    T			angle () const;
Packit 8dc392
    Vec3<T>		axis () const;
Packit 8dc392
Packit 8dc392
    Matrix33<T>		toMatrix33 () const;
Packit 8dc392
    Matrix44<T>		toMatrix44 () const;
Packit 8dc392
Packit 8dc392
    Quat<T>		log () const;
Packit 8dc392
    Quat<T>		exp () const;
Packit 8dc392
Packit 8dc392
Packit 8dc392
  private:
Packit 8dc392
Packit 8dc392
    void		setRotationInternal (const Vec3<T> &f0,
Packit 8dc392
					     const Vec3<T> &t0,
Packit 8dc392
					     Quat<T> &q);
Packit 8dc392
};
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			slerp (const Quat<T> &q1, const Quat<T> &q2, T t);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			slerpShortestArc
Packit 8dc392
                              (const Quat<T> &q1, const Quat<T> &q2, T t);
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			squad (const Quat<T> &q1, const Quat<T> &q2, 
Packit 8dc392
			       const Quat<T> &qa, const Quat<T> &qb, T t);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
void			intermediate (const Quat<T> &q0, const Quat<T> &q1, 
Packit 8dc392
				      const Quat<T> &q2, const Quat<T> &q3,
Packit 8dc392
				      Quat<T> &qa, Quat<T> &qb;;
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Matrix33<T>		operator * (const Matrix33<T> &M, const Quat<T> &q);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Matrix33<T>		operator * (const Quat<T> &q, const Matrix33<T> &M);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
std::ostream &		operator << (std::ostream &o, const Quat<T> &q);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator * (const Quat<T> &q1, const Quat<T> &q2;;
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator / (const Quat<T> &q1, const Quat<T> &q2;;
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator / (const Quat<T> &q, T t);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator * (const Quat<T> &q, T t);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator * (T t, const Quat<T> &q);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator + (const Quat<T> &q1, const Quat<T> &q2;;
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator - (const Quat<T> &q1, const Quat<T> &q2;;
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator ~ (const Quat<T> &q);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>			operator - (const Quat<T> &q);
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Vec3<T>			operator * (const Vec3<T> &v, const Quat<T> &q);
Packit 8dc392
Packit 8dc392
Packit 8dc392
//--------------------
Packit 8dc392
// Convenient typedefs
Packit 8dc392
//--------------------
Packit 8dc392
Packit 8dc392
typedef Quat<float>	Quatf;
Packit 8dc392
typedef Quat<double>	Quatd;
Packit 8dc392
Packit 8dc392
Packit 8dc392
//---------------
Packit 8dc392
// Implementation
Packit 8dc392
//---------------
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline
Packit 8dc392
Quat<T>::Quat (): r (1), v (0, 0, 0)
Packit 8dc392
{
Packit 8dc392
    // empty
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
template <class S>
Packit 8dc392
inline
Packit 8dc392
Quat<T>::Quat (const Quat<S> &q): r (q.r), v (q.v)
Packit 8dc392
{
Packit 8dc392
    // empty
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline
Packit 8dc392
Quat<T>::Quat (T s, T i, T j, T k): r (s), v (i, j, k)
Packit 8dc392
{
Packit 8dc392
    // empty
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline
Packit 8dc392
Quat<T>::Quat (T s, Vec3<T> d): r (s), v (d)
Packit 8dc392
{
Packit 8dc392
    // empty
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
Quat<T>::identity ()
Packit 8dc392
{
Packit 8dc392
    return Quat<T>();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline const Quat<T> &
Packit 8dc392
Quat<T>::operator = (const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    r = q.r;
Packit 8dc392
    v = q.v;
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline const Quat<T> &
Packit 8dc392
Quat<T>::operator *= (const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    T rtmp = r * q.r - (v ^ q.v);
Packit 8dc392
    v = r * q.v + v * q.r + v % q.v;
Packit 8dc392
    r = rtmp;
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline const Quat<T> &
Packit 8dc392
Quat<T>::operator *= (T t)
Packit 8dc392
{
Packit 8dc392
    r *= t;
Packit 8dc392
    v *= t;
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline const Quat<T> &
Packit 8dc392
Quat<T>::operator /= (const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    *this = *this * q.inverse();
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline const Quat<T> &
Packit 8dc392
Quat<T>::operator /= (T t)
Packit 8dc392
{
Packit 8dc392
    r /= t;
Packit 8dc392
    v /= t;
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline const Quat<T> &
Packit 8dc392
Quat<T>::operator += (const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    r += q.r;
Packit 8dc392
    v += q.v;
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline const Quat<T> &
Packit 8dc392
Quat<T>::operator -= (const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    r -= q.r;
Packit 8dc392
    v -= q.v;
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline T &
Packit 8dc392
Quat<T>::operator [] (int index)
Packit 8dc392
{
Packit 8dc392
    return index ? v[index - 1] : r;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline T
Packit 8dc392
Quat<T>::operator [] (int index) const
Packit 8dc392
{
Packit 8dc392
    return index ? v[index - 1] : r;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
template <class S>
Packit 8dc392
inline bool
Packit 8dc392
Quat<T>::operator == (const Quat<S> &q) const
Packit 8dc392
{
Packit 8dc392
    return r == q.r && v == q.v;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
template <class S>
Packit 8dc392
inline bool
Packit 8dc392
Quat<T>::operator != (const Quat<S> &q) const
Packit 8dc392
{
Packit 8dc392
    return r != q.r || v != q.v;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline T
Packit 8dc392
operator ^ (const Quat<T>& q1 ,const Quat<T>& q2)
Packit 8dc392
{
Packit 8dc392
    return q1.r * q2.r + (q1.v ^ q2.v);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline T
Packit 8dc392
Quat<T>::length () const
Packit 8dc392
{
Packit 8dc392
    return Math<T>::sqrt (r * r + (v ^ v));
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline Quat<T> &
Packit 8dc392
Quat<T>::normalize ()
Packit 8dc392
{
Packit 8dc392
    if (T l = length())
Packit 8dc392
    {
Packit 8dc392
	r /= l;
Packit 8dc392
	v /= l;
Packit 8dc392
    }
Packit 8dc392
    else
Packit 8dc392
    {
Packit 8dc392
	r = 1;
Packit 8dc392
	v = Vec3<T> (0);
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
Quat<T>::normalized () const
Packit 8dc392
{
Packit 8dc392
    if (T l = length())
Packit 8dc392
	return Quat (r / l, v / l);
Packit 8dc392
Packit 8dc392
    return Quat();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
Quat<T>::inverse () const
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // 1    Q*
Packit 8dc392
    // - = ----   where Q* is conjugate (operator~)
Packit 8dc392
    // Q   Q* Q   and (Q* Q) == Q ^ Q (4D dot)
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    T qdot = *this ^ *this;
Packit 8dc392
    return Quat (r / qdot, -v / qdot);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T> &
Packit 8dc392
Quat<T>::invert ()
Packit 8dc392
{
Packit 8dc392
    T qdot = (*this) ^ (*this);
Packit 8dc392
    r /= qdot;
Packit 8dc392
    v = -v / qdot;
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Vec3<T>
Packit 8dc392
Quat<T>::rotateVector(const Vec3<T>& original) const
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Given a vector p and a quaternion q (aka this),
Packit 8dc392
    // calculate p' = qpq*
Packit 8dc392
    //
Packit 8dc392
    // Assumes unit quaternions (because non-unit
Packit 8dc392
    // quaternions cannot be used to rotate vectors
Packit 8dc392
    // anyway).
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    Quat<T> vec (0, original);  // temporarily promote grade of original
Packit 8dc392
    Quat<T> inv (*this);
Packit 8dc392
    inv.v *= -1;                // unit multiplicative inverse
Packit 8dc392
    Quat<T> result = *this * vec * inv;
Packit 8dc392
    return result.v;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline T 
Packit 8dc392
Quat<T>::euclideanInnerProduct (const Quat<T> &q) const
Packit 8dc392
{
Packit 8dc392
    return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
T
Packit 8dc392
angle4D (const Quat<T> &q1, const Quat<T> &q2)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Compute the angle between two quaternions,
Packit 8dc392
    // interpreting the quaternions as 4D vectors.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    Quat<T> d = q1 - q2;
Packit 8dc392
    T lengthD = Math<T>::sqrt (d ^ d);
Packit 8dc392
Packit 8dc392
    Quat<T> s = q1 + q2;
Packit 8dc392
    T lengthS = Math<T>::sqrt (s ^ s);
Packit 8dc392
Packit 8dc392
    return 2 * Math<T>::atan2 (lengthD, lengthS);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>
Packit 8dc392
slerp (const Quat<T> &q1, const Quat<T> &q2, T t)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Spherical linear interpolation.
Packit 8dc392
    // Assumes q1 and q2 are normalized and that q1 != -q2.
Packit 8dc392
    //
Packit 8dc392
    // This method does *not* interpolate along the shortest
Packit 8dc392
    // arc between q1 and q2.  If you desire interpolation
Packit 8dc392
    // along the shortest arc, and q1^q2 is negative, then
Packit 8dc392
    // consider calling slerpShortestArc(), below, or flipping
Packit 8dc392
    // the second quaternion explicitly.
Packit 8dc392
    //
Packit 8dc392
    // The implementation of squad() depends on a slerp()
Packit 8dc392
    // that interpolates as is, without the automatic
Packit 8dc392
    // flipping.
Packit 8dc392
    //
Packit 8dc392
    // Don Hatch explains the method we use here on his
Packit 8dc392
    // web page, The Right Way to Calculate Stuff, at
Packit 8dc392
    // http://www.plunk.org/~hatch/rightway.php
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    T a = angle4D (q1, q2);
Packit 8dc392
    T s = 1 - t;
Packit 8dc392
Packit 8dc392
    Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 +
Packit 8dc392
	        sinx_over_x (t * a) / sinx_over_x (a) * t * q2;
Packit 8dc392
Packit 8dc392
    return q.normalized();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>
Packit 8dc392
slerpShortestArc (const Quat<T> &q1, const Quat<T> &q2, T t)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Spherical linear interpolation along the shortest
Packit 8dc392
    // arc from q1 to either q2 or -q2, whichever is closer.
Packit 8dc392
    // Assumes q1 and q2 are unit quaternions.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    if ((q1 ^ q2) >= 0)
Packit 8dc392
        return slerp (q1, q2, t);
Packit 8dc392
    else
Packit 8dc392
        return slerp (q1, -q2, t);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>
Packit 8dc392
spline (const Quat<T> &q0, const Quat<T> &q1,
Packit 8dc392
        const Quat<T> &q2, const Quat<T> &q3,
Packit 8dc392
	T t)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Spherical Cubic Spline Interpolation -
Packit 8dc392
    // from Advanced Animation and Rendering
Packit 8dc392
    // Techniques by Watt and Watt, Page 366:
Packit 8dc392
    // A spherical curve is constructed using three
Packit 8dc392
    // spherical linear interpolations of a quadrangle
Packit 8dc392
    // of unit quaternions: q1, qa, qb, q2.
Packit 8dc392
    // Given a set of quaternion keys: q0, q1, q2, q3,
Packit 8dc392
    // this routine does the interpolation between
Packit 8dc392
    // q1 and q2 by constructing two intermediate
Packit 8dc392
    // quaternions: qa and qb. The qa and qb are 
Packit 8dc392
    // computed by the intermediate function to 
Packit 8dc392
    // guarantee the continuity of tangents across
Packit 8dc392
    // adjacent cubic segments. The qa represents in-tangent
Packit 8dc392
    // for q1 and the qb represents the out-tangent for q2.
Packit 8dc392
    // 
Packit 8dc392
    // The q1 q2 is the cubic segment being interpolated. 
Packit 8dc392
    // The q0 is from the previous adjacent segment and q3 is 
Packit 8dc392
    // from the next adjacent segment. The q0 and q3 are used
Packit 8dc392
    // in computing qa and qb.
Packit 8dc392
    // 
Packit 8dc392
Packit 8dc392
    Quat<T> qa = intermediate (q0, q1, q2);
Packit 8dc392
    Quat<T> qb = intermediate (q1, q2, q3);
Packit 8dc392
    Quat<T> result = squad (q1, qa, qb, q2, t);
Packit 8dc392
Packit 8dc392
    return result;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>
Packit 8dc392
squad (const Quat<T> &q1, const Quat<T> &qa,
Packit 8dc392
       const Quat<T> &qb, const Quat<T> &q2,
Packit 8dc392
       T t)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Spherical Quadrangle Interpolation -
Packit 8dc392
    // from Advanced Animation and Rendering
Packit 8dc392
    // Techniques by Watt and Watt, Page 366:
Packit 8dc392
    // It constructs a spherical cubic interpolation as 
Packit 8dc392
    // a series of three spherical linear interpolations 
Packit 8dc392
    // of a quadrangle of unit quaternions. 
Packit 8dc392
    //     
Packit 8dc392
  
Packit 8dc392
    Quat<T> r1 = slerp (q1, q2, t);
Packit 8dc392
    Quat<T> r2 = slerp (qa, qb, t);
Packit 8dc392
    Quat<T> result = slerp (r1, r2, 2 * t * (1 - t));
Packit 8dc392
Packit 8dc392
    return result;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Quat<T>
Packit 8dc392
intermediate (const Quat<T> &q0, const Quat<T> &q1, const Quat<T> &q2)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // From advanced Animation and Rendering
Packit 8dc392
    // Techniques by Watt and Watt, Page 366:
Packit 8dc392
    // computing the inner quadrangle 
Packit 8dc392
    // points (qa and qb) to guarantee tangent
Packit 8dc392
    // continuity.
Packit 8dc392
    // 
Packit 8dc392
Packit 8dc392
    Quat<T> q1inv = q1.inverse();
Packit 8dc392
    Quat<T> c1 = q1inv * q2;
Packit 8dc392
    Quat<T> c2 = q1inv * q0;
Packit 8dc392
    Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log());
Packit 8dc392
    Quat<T> qa = q1 * c3.exp();
Packit 8dc392
    qa.normalize();
Packit 8dc392
    return qa;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
Quat<T>::log () const
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // For unit quaternion, from Advanced Animation and 
Packit 8dc392
    // Rendering Techniques by Watt and Watt, Page 366:
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    T theta = Math<T>::acos (std::min (r, (T) 1.0));
Packit 8dc392
Packit 8dc392
    if (theta == 0)
Packit 8dc392
	return Quat<T> (0, v);
Packit 8dc392
    
Packit 8dc392
    T sintheta = Math<T>::sin (theta);
Packit 8dc392
    
Packit 8dc392
    T k;
Packit 8dc392
    if (abs (sintheta) < 1 && abs (theta) >= limits<T>::max() * abs (sintheta))
Packit 8dc392
	k = 1;
Packit 8dc392
    else
Packit 8dc392
	k = theta / sintheta;
Packit 8dc392
Packit 8dc392
    return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
Quat<T>::exp () const
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // For pure quaternion (zero scalar part):
Packit 8dc392
    // from Advanced Animation and Rendering
Packit 8dc392
    // Techniques by Watt and Watt, Page 366:
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    T theta = v.length();
Packit 8dc392
    T sintheta = Math<T>::sin (theta);
Packit 8dc392
    
Packit 8dc392
    T k;
Packit 8dc392
    if (abs (theta) < 1 && abs (sintheta) >= limits<T>::max() * abs (theta))
Packit 8dc392
	k = 1;
Packit 8dc392
    else
Packit 8dc392
	k = sintheta / theta;
Packit 8dc392
Packit 8dc392
    T costheta = Math<T>::cos (theta);
Packit 8dc392
Packit 8dc392
    return Quat<T> (costheta, v.x * k, v.y * k, v.z * k);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline T
Packit 8dc392
Quat<T>::angle () const
Packit 8dc392
{
Packit 8dc392
    return 2 * Math<T>::atan2 (v.length(), r);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline Vec3<T>
Packit 8dc392
Quat<T>::axis () const
Packit 8dc392
{
Packit 8dc392
    return v.normalized();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
inline Quat<T> &
Packit 8dc392
Quat<T>::setAxisAngle (const Vec3<T> &axis, T radians)
Packit 8dc392
{
Packit 8dc392
    r = Math<T>::cos (radians / 2);
Packit 8dc392
    v = axis.normalized() * Math<T>::sin (radians / 2);
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
Quat<T> &
Packit 8dc392
Quat<T>::setRotation (const Vec3<T> &from, const Vec3<T> &to)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Create a quaternion that rotates vector from into vector to,
Packit 8dc392
    // such that the rotation is around an axis that is the cross
Packit 8dc392
    // product of from and to.
Packit 8dc392
    //
Packit 8dc392
    // This function calls function setRotationInternal(), which is
Packit 8dc392
    // numerically accurate only for rotation angles that are not much
Packit 8dc392
    // greater than pi/2.  In order to achieve good accuracy for angles
Packit 8dc392
    // greater than pi/2, we split large angles in half, and rotate in
Packit 8dc392
    // two steps.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    //
Packit 8dc392
    // Normalize from and to, yielding f0 and t0.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    Vec3<T> f0 = from.normalized();
Packit 8dc392
    Vec3<T> t0 = to.normalized();
Packit 8dc392
Packit 8dc392
    if ((f0 ^ t0) >= 0)
Packit 8dc392
    {
Packit 8dc392
	//
Packit 8dc392
	// The rotation angle is less than or equal to pi/2.
Packit 8dc392
	//
Packit 8dc392
Packit 8dc392
	setRotationInternal (f0, t0, *this);
Packit 8dc392
    }
Packit 8dc392
    else
Packit 8dc392
    {
Packit 8dc392
	//
Packit 8dc392
	// The angle is greater than pi/2.  After computing h0,
Packit 8dc392
	// which is halfway between f0 and t0, we rotate first
Packit 8dc392
	// from f0 to h0, then from h0 to t0.
Packit 8dc392
	//
Packit 8dc392
Packit 8dc392
	Vec3<T> h0 = (f0 + t0).normalized();
Packit 8dc392
Packit 8dc392
	if ((h0 ^ h0) != 0)
Packit 8dc392
	{
Packit 8dc392
	    setRotationInternal (f0, h0, *this);
Packit 8dc392
Packit 8dc392
	    Quat<T> q;
Packit 8dc392
	    setRotationInternal (h0, t0, q);
Packit 8dc392
Packit 8dc392
	    *this *= q;
Packit 8dc392
	}
Packit 8dc392
	else
Packit 8dc392
	{
Packit 8dc392
	    //
Packit 8dc392
	    // f0 and t0 point in exactly opposite directions.
Packit 8dc392
	    // Pick an arbitrary axis that is orthogonal to f0,
Packit 8dc392
	    // and rotate by pi.
Packit 8dc392
	    //
Packit 8dc392
Packit 8dc392
	    r = T (0);
Packit 8dc392
Packit 8dc392
	    Vec3<T> f02 = f0 * f0;
Packit 8dc392
Packit 8dc392
	    if (f02.x <= f02.y && f02.x <= f02.z)
Packit 8dc392
		v = (f0 % Vec3<T> (1, 0, 0)).normalized();
Packit 8dc392
	    else if (f02.y <= f02.z)
Packit 8dc392
		v = (f0 % Vec3<T> (0, 1, 0)).normalized();
Packit 8dc392
	    else
Packit 8dc392
		v = (f0 % Vec3<T> (0, 0, 1)).normalized();
Packit 8dc392
	}
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    return *this;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template <class T>
Packit 8dc392
void
Packit 8dc392
Quat<T>::setRotationInternal (const Vec3<T> &f0, const Vec3<T> &t0, Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // The following is equivalent to setAxisAngle(n,2*phi),
Packit 8dc392
    // where the rotation axis, n, is orthogonal to the f0 and
Packit 8dc392
    // t0 vectors, and 2*phi is the angle between f0 and t0.
Packit 8dc392
    //
Packit 8dc392
    // This function is called by setRotation(), above; it assumes
Packit 8dc392
    // that f0 and t0 are normalized and that the angle between
Packit 8dc392
    // them is not much greater than pi/2.  This function becomes
Packit 8dc392
    // numerically inaccurate if f0 and t0 point into nearly
Packit 8dc392
    // opposite directions.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    //
Packit 8dc392
    // Find a normalized vector, h0, that is halfway between f0 and t0.
Packit 8dc392
    // The angle between f0 and h0 is phi.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    Vec3<T> h0 = (f0 + t0).normalized();
Packit 8dc392
Packit 8dc392
    //
Packit 8dc392
    // Store the rotation axis and rotation angle.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    q.r = f0 ^ h0;	//  f0 ^ h0 == cos (phi)
Packit 8dc392
    q.v = f0 % h0;	// (f0 % h0).length() == sin (phi)
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Matrix33<T>
Packit 8dc392
Quat<T>::toMatrix33() const
Packit 8dc392
{
Packit 8dc392
    return Matrix33<T> (1 - 2 * (v.y * v.y + v.z * v.z),
Packit 8dc392
			    2 * (v.x * v.y + v.z * r),
Packit 8dc392
			    2 * (v.z * v.x - v.y * r),
Packit 8dc392
Packit 8dc392
			    2 * (v.x * v.y - v.z * r),
Packit 8dc392
		        1 - 2 * (v.z * v.z + v.x * v.x),
Packit 8dc392
			    2 * (v.y * v.z + v.x * r),
Packit 8dc392
Packit 8dc392
			    2 * (v.z * v.x + v.y * r),
Packit 8dc392
			    2 * (v.y * v.z - v.x * r),
Packit 8dc392
		        1 - 2 * (v.y * v.y + v.x * v.x));
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
Matrix44<T>
Packit 8dc392
Quat<T>::toMatrix44() const
Packit 8dc392
{
Packit 8dc392
    return Matrix44<T> (1 - 2 * (v.y * v.y + v.z * v.z),
Packit 8dc392
			    2 * (v.x * v.y + v.z * r),
Packit 8dc392
			    2 * (v.z * v.x - v.y * r),
Packit 8dc392
			    0,
Packit 8dc392
			    2 * (v.x * v.y - v.z * r),
Packit 8dc392
		        1 - 2 * (v.z * v.z + v.x * v.x),
Packit 8dc392
			    2 * (v.y * v.z + v.x * r),
Packit 8dc392
			    0,
Packit 8dc392
			    2 * (v.z * v.x + v.y * r),
Packit 8dc392
			    2 * (v.y * v.z - v.x * r),
Packit 8dc392
		        1 - 2 * (v.y * v.y + v.x * v.x),
Packit 8dc392
			    0,
Packit 8dc392
			    0,
Packit 8dc392
			    0,
Packit 8dc392
			    0,
Packit 8dc392
			    1);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Matrix33<T>
Packit 8dc392
operator * (const Matrix33<T> &M, const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    return M * q.toMatrix33();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Matrix33<T>
Packit 8dc392
operator * (const Quat<T> &q, const Matrix33<T> &M)
Packit 8dc392
{
Packit 8dc392
    return q.toMatrix33() * M;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
std::ostream &
Packit 8dc392
operator << (std::ostream &o, const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    return o << "(" << q.r
Packit 8dc392
	     << " " << q.v.x
Packit 8dc392
	     << " " << q.v.y
Packit 8dc392
	     << " " << q.v.z
Packit 8dc392
	     << ")";
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator * (const Quat<T> &q1, const Quat<T> &q2)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (q1.r * q2.r - (q1.v ^ q2.v),
Packit 8dc392
		    q1.r * q2.v + q1.v * q2.r + q1.v % q2.v);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator / (const Quat<T> &q1, const Quat<T> &q2)
Packit 8dc392
{
Packit 8dc392
    return q1 * q2.inverse();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator / (const Quat<T> &q, T t)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (q.r / t, q.v / t);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator * (const Quat<T> &q, T t)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (q.r * t, q.v * t);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator * (T t, const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (q.r * t, q.v * t);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator + (const Quat<T> &q1, const Quat<T> &q2)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (q1.r + q2.r, q1.v + q2.v);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator - (const Quat<T> &q1, const Quat<T> &q2)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (q1.r - q2.r, q1.v - q2.v);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator ~ (const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (q.r, -q.v);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Quat<T>
Packit 8dc392
operator - (const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    return Quat<T> (-q.r, -q.v);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
template<class T>
Packit 8dc392
inline Vec3<T>
Packit 8dc392
operator * (const Vec3<T> &v, const Quat<T> &q)
Packit 8dc392
{
Packit 8dc392
    Vec3<T> a = q.v % v;
Packit 8dc392
    Vec3<T> b = q.v % a;
Packit 8dc392
    return v + T (2) * (q.r * a + b);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
Packit 8dc392
#pragma warning(default:4244)
Packit 8dc392
#endif
Packit 8dc392
Packit 8dc392
IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
Packit 8dc392
Packit 8dc392
#endif // INCLUDED_IMATHQUAT_H