#ifndef INCLUDED_IMATHQUAT_H
#define INCLUDED_IMATHQUAT_H
#include "ImathExc.h"
#include "ImathMatrix.h"
#include <iostream>
namespace Imath {
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
#pragma warning(disable:4244)
#endif
template <class T>
class Quat
{
public:
T r;
Vec3<T> v;
Quat ();
template <class S>
Quat (const Quat<S> &q);
Quat (T s, T i, T j, T k);
Quat (T s, Vec3<T> d);
static Quat<T> identity ();
const Quat<T> & operator = (const Quat<T> &q);
const Quat<T> & operator *= (const Quat<T> &q);
const Quat<T> & operator *= (T t);
const Quat<T> & operator /= (const Quat<T> &q);
const Quat<T> & operator /= (T t);
const Quat<T> & operator += (const Quat<T> &q);
const Quat<T> & operator -= (const Quat<T> &q);
T & operator [] (int index);
T operator [] (int index) const;
template <class S> bool operator == (const Quat<S> &q) const;
template <class S> bool operator != (const Quat<S> &q) const;
Quat<T> & invert ();
Quat<T> inverse () const;
Quat<T> & normalize ();
Quat<T> normalized () const;
T length () const;
Vec3<T> rotateVector(const Vec3<T> &original) const;
T euclideanInnerProduct(const Quat<T> &q) const;
Quat<T> & setAxisAngle (const Vec3<T> &axis, T radians);
Quat<T> & setRotation (const Vec3<T> &fromDirection,
const Vec3<T> &toDirection);
T angle () const;
Vec3<T> axis () const;
Matrix33<T> toMatrix33 () const;
Matrix44<T> toMatrix44 () const;
Quat<T> log () const;
Quat<T> exp () const;
private:
void setRotationInternal (const Vec3<T> &f0,
const Vec3<T> &t0,
Quat<T> &q);
};
template<class T>
Quat<T> slerp (const Quat<T> &q1, const Quat<T> &q2, T t);
template<class T>
Quat<T> slerpShortestArc
(const Quat<T> &q1, const Quat<T> &q2, T t);
template<class T>
Quat<T> squad (const Quat<T> &q1, const Quat<T> &q2,
const Quat<T> &qa, const Quat<T> &qb, T t);
template<class T>
void intermediate (const Quat<T> &q0, const Quat<T> &q1,
const Quat<T> &q2, const Quat<T> &q3,
Quat<T> &qa, Quat<T> &qb);
template<class T>
Matrix33<T> operator * (const Matrix33<T> &M, const Quat<T> &q);
template<class T>
Matrix33<T> operator * (const Quat<T> &q, const Matrix33<T> &M);
template<class T>
std::ostream & operator << (std::ostream &o, const Quat<T> &q);
template<class T>
Quat<T> operator * (const Quat<T> &q1, const Quat<T> &q2);
template<class T>
Quat<T> operator / (const Quat<T> &q1, const Quat<T> &q2);
template<class T>
Quat<T> operator / (const Quat<T> &q, T t);
template<class T>
Quat<T> operator * (const Quat<T> &q, T t);
template<class T>
Quat<T> operator * (T t, const Quat<T> &q);
template<class T>
Quat<T> operator + (const Quat<T> &q1, const Quat<T> &q2);
template<class T>
Quat<T> operator - (const Quat<T> &q1, const Quat<T> &q2);
template<class T>
Quat<T> operator ~ (const Quat<T> &q);
template<class T>
Quat<T> operator - (const Quat<T> &q);
template<class T>
Vec3<T> operator * (const Vec3<T> &v, const Quat<T> &q);
typedef Quat<float> Quatf;
typedef Quat<double> Quatd;
template<class T>
inline
Quat<T>::Quat (): r (1), v (0, 0, 0)
{
}
template<class T>
template <class S>
inline
Quat<T>::Quat (const Quat<S> &q): r (q.r), v (q.v)
{
}
template<class T>
inline
Quat<T>::Quat (T s, T i, T j, T k): r (s), v (i, j, k)
{
}
template<class T>
inline
Quat<T>::Quat (T s, Vec3<T> d): r (s), v (d)
{
}
template<class T>
inline Quat<T>
Quat<T>::identity ()
{
return Quat<T>();
}
template<class T>
inline const Quat<T> &
Quat<T>::operator = (const Quat<T> &q)
{
r = q.r;
v = q.v;
return *this;
}
template<class T>
inline const Quat<T> &
Quat<T>::operator *= (const Quat<T> &q)
{
T rtmp = r * q.r - (v ^ q.v);
v = r * q.v + v * q.r + v % q.v;
r = rtmp;
return *this;
}
template<class T>
inline const Quat<T> &
Quat<T>::operator *= (T t)
{
r *= t;
v *= t;
return *this;
}
template<class T>
inline const Quat<T> &
Quat<T>::operator /= (const Quat<T> &q)
{
*this = *this * q.inverse();
return *this;
}
template<class T>
inline const Quat<T> &
Quat<T>::operator /= (T t)
{
r /= t;
v /= t;
return *this;
}
template<class T>
inline const Quat<T> &
Quat<T>::operator += (const Quat<T> &q)
{
r += q.r;
v += q.v;
return *this;
}
template<class T>
inline const Quat<T> &
Quat<T>::operator -= (const Quat<T> &q)
{
r -= q.r;
v -= q.v;
return *this;
}
template<class T>
inline T &
Quat<T>::operator [] (int index)
{
return index ? v[index - 1] : r;
}
template<class T>
inline T
Quat<T>::operator [] (int index) const
{
return index ? v[index - 1] : r;
}
template <class T>
template <class S>
inline bool
Quat<T>::operator == (const Quat<S> &q) const
{
return r == q.r && v == q.v;
}
template <class T>
template <class S>
inline bool
Quat<T>::operator != (const Quat<S> &q) const
{
return r != q.r || v != q.v;
}
template<class T>
inline T
operator ^ (const Quat<T>& q1 ,const Quat<T>& q2)
{
return q1.r * q2.r + (q1.v ^ q2.v);
}
template <class T>
inline T
Quat<T>::length () const
{
return Math<T>::sqrt (r * r + (v ^ v));
}
template <class T>
inline Quat<T> &
Quat<T>::normalize ()
{
if (T l = length())
{
r /= l;
v /= l;
}
else
{
r = 1;
v = Vec3<T> (0);
}
return *this;
}
template <class T>
inline Quat<T>
Quat<T>::normalized () const
{
if (T l = length())
return Quat (r / l, v / l);
return Quat();
}
template<class T>
inline Quat<T>
Quat<T>::inverse () const
{
T qdot = *this ^ *this;
return Quat (r / qdot, -v / qdot);
}
template<class T>
inline Quat<T> &
Quat<T>::invert ()
{
T qdot = (*this) ^ (*this);
r /= qdot;
v = -v / qdot;
return *this;
}
template<class T>
inline Vec3<T>
Quat<T>::rotateVector(const Vec3<T>& original) const
{
Quat<T> vec (0, original);
Quat<T> inv (*this);
inv.v *= -1;
Quat<T> result = *this * vec * inv;
return result.v;
}
template<class T>
inline T
Quat<T>::euclideanInnerProduct (const Quat<T> &q) const
{
return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z;
}
template<class T>
T
angle4D (const Quat<T> &q1, const Quat<T> &q2)
{
Quat<T> d = q1 - q2;
T lengthD = Math<T>::sqrt (d ^ d);
Quat<T> s = q1 + q2;
T lengthS = Math<T>::sqrt (s ^ s);
return 2 * Math<T>::atan2 (lengthD, lengthS);
}
template<class T>
Quat<T>
slerp (const Quat<T> &q1, const Quat<T> &q2, T t)
{
T a = angle4D (q1, q2);
T s = 1 - t;
Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 +
sinx_over_x (t * a) / sinx_over_x (a) * t * q2;
return q.normalized();
}
template<class T>
Quat<T>
slerpShortestArc (const Quat<T> &q1, const Quat<T> &q2, T t)
{
if ((q1 ^ q2) >= 0)
return slerp (q1, q2, t);
else
return slerp (q1, -q2, t);
}
template<class T>
Quat<T>
spline (const Quat<T> &q0, const Quat<T> &q1,
const Quat<T> &q2, const Quat<T> &q3,
T t)
{
Quat<T> qa = intermediate (q0, q1, q2);
Quat<T> qb = intermediate (q1, q2, q3);
Quat<T> result = squad (q1, qa, qb, q2, t);
return result;
}
template<class T>
Quat<T>
squad (const Quat<T> &q1, const Quat<T> &qa,
const Quat<T> &qb, const Quat<T> &q2,
T t)
{
Quat<T> r1 = slerp (q1, q2, t);
Quat<T> r2 = slerp (qa, qb, t);
Quat<T> result = slerp (r1, r2, 2 * t * (1 - t));
return result;
}
template<class T>
Quat<T>
intermediate (const Quat<T> &q0, const Quat<T> &q1, const Quat<T> &q2)
{
Quat<T> q1inv = q1.inverse();
Quat<T> c1 = q1inv * q2;
Quat<T> c2 = q1inv * q0;
Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log());
Quat<T> qa = q1 * c3.exp();
qa.normalize();
return qa;
}
template <class T>
inline Quat<T>
Quat<T>::log () const
{
T theta = Math<T>::acos (std::min (r, (T) 1.0));
if (theta == 0)
return Quat<T> (0, v);
T sintheta = Math<T>::sin (theta);
T k;
if (abs (sintheta) < 1 && abs (theta) >= limits<T>::max() * abs (sintheta))
k = 1;
else
k = theta / sintheta;
return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k);
}
template <class T>
inline Quat<T>
Quat<T>::exp () const
{
T theta = v.length();
T sintheta = Math<T>::sin (theta);
T k;
if (abs (theta) < 1 && abs (sintheta) >= limits<T>::max() * abs (theta))
k = 1;
else
k = sintheta / theta;
T costheta = Math<T>::cos (theta);
return Quat<T> (costheta, v.x * k, v.y * k, v.z * k);
}
template <class T>
inline T
Quat<T>::angle () const
{
return 2 * Math<T>::atan2 (v.length(), r);
}
template <class T>
inline Vec3<T>
Quat<T>::axis () const
{
return v.normalized();
}
template <class T>
inline Quat<T> &
Quat<T>::setAxisAngle (const Vec3<T> &axis, T radians)
{
r = Math<T>::cos (radians / 2);
v = axis.normalized() * Math<T>::sin (radians / 2);
return *this;
}
template <class T>
Quat<T> &
Quat<T>::setRotation (const Vec3<T> &from, const Vec3<T> &to)
{
Vec3<T> f0 = from.normalized();
Vec3<T> t0 = to.normalized();
if ((f0 ^ t0) >= 0)
{
setRotationInternal (f0, t0, *this);
}
else
{
Vec3<T> h0 = (f0 + t0).normalized();
if ((h0 ^ h0) != 0)
{
setRotationInternal (f0, h0, *this);
Quat<T> q;
setRotationInternal (h0, t0, q);
*this *= q;
}
else
{
r = T (0);
Vec3<T> f02 = f0 * f0;
if (f02.x <= f02.y && f02.x <= f02.z)
v = (f0 % Vec3<T> (1, 0, 0)).normalized();
else if (f02.y <= f02.z)
v = (f0 % Vec3<T> (0, 1, 0)).normalized();
else
v = (f0 % Vec3<T> (0, 0, 1)).normalized();
}
}
return *this;
}
template <class T>
void
Quat<T>::setRotationInternal (const Vec3<T> &f0, const Vec3<T> &t0, Quat<T> &q)
{
Vec3<T> h0 = (f0 + t0).normalized();
q.r = f0 ^ h0;
q.v = f0 % h0;
}
template<class T>
Matrix33<T>
Quat<T>::toMatrix33() const
{
return Matrix33<T> (1 - 2 * (v.y * v.y + v.z * v.z),
2 * (v.x * v.y + v.z * r),
2 * (v.z * v.x - v.y * r),
2 * (v.x * v.y - v.z * r),
1 - 2 * (v.z * v.z + v.x * v.x),
2 * (v.y * v.z + v.x * r),
2 * (v.z * v.x + v.y * r),
2 * (v.y * v.z - v.x * r),
1 - 2 * (v.y * v.y + v.x * v.x));
}
template<class T>
Matrix44<T>
Quat<T>::toMatrix44() const
{
return Matrix44<T> (1 - 2 * (v.y * v.y + v.z * v.z),
2 * (v.x * v.y + v.z * r),
2 * (v.z * v.x - v.y * r),
0,
2 * (v.x * v.y - v.z * r),
1 - 2 * (v.z * v.z + v.x * v.x),
2 * (v.y * v.z + v.x * r),
0,
2 * (v.z * v.x + v.y * r),
2 * (v.y * v.z - v.x * r),
1 - 2 * (v.y * v.y + v.x * v.x),
0,
0,
0,
0,
1);
}
template<class T>
inline Matrix33<T>
operator * (const Matrix33<T> &M, const Quat<T> &q)
{
return M * q.toMatrix33();
}
template<class T>
inline Matrix33<T>
operator * (const Quat<T> &q, const Matrix33<T> &M)
{
return q.toMatrix33() * M;
}
template<class T>
std::ostream &
operator << (std::ostream &o, const Quat<T> &q)
{
return o << "(" << q.r
<< " " << q.v.x
<< " " << q.v.y
<< " " << q.v.z
<< ")";
}
template<class T>
inline Quat<T>
operator * (const Quat<T> &q1, const Quat<T> &q2)
{
return Quat<T> (q1.r * q2.r - (q1.v ^ q2.v),
q1.r * q2.v + q1.v * q2.r + q1.v % q2.v);
}
template<class T>
inline Quat<T>
operator / (const Quat<T> &q1, const Quat<T> &q2)
{
return q1 * q2.inverse();
}
template<class T>
inline Quat<T>
operator / (const Quat<T> &q, T t)
{
return Quat<T> (q.r / t, q.v / t);
}
template<class T>
inline Quat<T>
operator * (const Quat<T> &q, T t)
{
return Quat<T> (q.r * t, q.v * t);
}
template<class T>
inline Quat<T>
operator * (T t, const Quat<T> &q)
{
return Quat<T> (q.r * t, q.v * t);
}
template<class T>
inline Quat<T>
operator + (const Quat<T> &q1, const Quat<T> &q2)
{
return Quat<T> (q1.r + q2.r, q1.v + q2.v);
}
template<class T>
inline Quat<T>
operator - (const Quat<T> &q1, const Quat<T> &q2)
{
return Quat<T> (q1.r - q2.r, q1.v - q2.v);
}
template<class T>
inline Quat<T>
operator ~ (const Quat<T> &q)
{
return Quat<T> (q.r, -q.v);
}
template<class T>
inline Quat<T>
operator - (const Quat<T> &q)
{
return Quat<T> (-q.r, -q.v);
}
template<class T>
inline Vec3<T>
operator * (const Vec3<T> &v, const Quat<T> &q)
{
Vec3<T> a = q.v % v;
Vec3<T> b = q.v % a;
return v + T (2) * (q.r * a + b);
}
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
#pragma warning(default:4244)
#endif
}
#endif