1 #ifndef INCLUDE_AL_QUAT_HPP 
    2 #define INCLUDE_AL_QUAT_HPP 
   47 #include "al/math/al_Constants.hpp" 
   48 #include "al/math/al_Mat.hpp" 
   49 #include "al/math/al_Vec.hpp" 
   62 template <
typename T = 
double>
 
   76   Quat(
const T& 
w = T(1), 
const T& 
x = T(0), 
const T& 
y = T(0),
 
   97       : 
w(
w), 
x(xyz[0]), 
y(xyz[1]), 
z(xyz[2]) {}
 
  161     return (
w == v.
w) && (
x == v.
x) && (
y == v.
y) && (
z == v.
z);
 
  168   Quat operator+(
const Quat& v)
 const { 
return Quat(*
this) += v; }
 
  169   Quat operator+(
const T& v)
 const { 
return Quat(*
this) += v; }
 
  170   Quat operator-(
const Quat& v)
 const { 
return Quat(*
this) -= v; }
 
  171   Quat operator-(
const T& v)
 const { 
return Quat(*
this) -= v; }
 
  172   Quat operator/(
const Quat& v)
 const { 
return Quat(*
this) /= v; }
 
  173   Quat operator/(
const T& v)
 const { 
return Quat(*
this) /= v; }
 
  174   Quat operator*(
const Quat& v)
 const { 
return Quat(*
this) *= v; }
 
  175   Quat operator*(
const T& v)
 const { 
return Quat(*
this) *= v; }
 
  178   Quat& operator=(
const Quat<U>& v) {
 
  181   Quat& operator=(
const T& v) { 
return set(v); }
 
  189   Quat& operator+=(
const T& v) {
 
  203   Quat& operator-=(
const T& v) {
 
  210   Quat& operator*=(
const Quat& v) { 
return set(multiply(v)); }
 
  211   Quat& operator*=(
const T& v) {
 
  218   Quat& operator/=(
const Quat& v) { 
return (*
this) *= v.recip(); }
 
  219   Quat& operator/=(
const T& v) {
 
  252   Quat multiply(
const Quat& q2) 
const;
 
  253   Quat reverseMultiply(
const Quat& q2) 
const;
 
  270     return set(q.
w, q.
x, q.
y, q.
z);
 
  285     return set(cos(t2), sin(t2), T(0), T(0));
 
  291     return set(cos(t2), T(0), sin(t2), T(0));
 
  297     return set(cos(t2), T(0), T(0), sin(t2));
 
  302     return fromEuler(aeb[0], aeb[1], aeb[2]);
 
  328   template <
typename T2>
 
  332   template <
typename T2>
 
  352   template <
typename T2>
 
  354   template <
typename T2>
 
  356     toVectorX(v[0], v[1], v[2]);
 
  358   template <
typename T2 = T>
 
  366   template <
typename T2>
 
  368   template <
typename T2>
 
  370     toVectorY(v[0], v[1], v[2]);
 
  372   template <
typename T2 = T>
 
  380   template <
typename T2>
 
  382   template <
typename T2>
 
  384     toVectorZ(v[0], v[1], v[2]);
 
  386   template <
typename T2 = T>
 
  402     return slerp(*
this, target, amt);
 
  413   void print(std::ostream& stream) 
const;
 
  415   static T accuracyMax() { 
return 1.000001; }
 
  416   static T accuracyMin() { 
return 0.999999; }
 
  417   static T eps() { 
return 0.0000001; }
 
  420   static T abs(T v) { 
return v > T(0) ? v : -v; }
 
  424 Quat<T> operator+(T r, 
const Quat<T>& q) {
 
  428 Quat<T> operator-(T r, 
const Quat<T>& q) {
 
  432 Quat<T> operator*(T r, 
const Quat<T>& q) {
 
  436 Quat<T> operator/(T r, 
const Quat<T>& q) {
 
  437   return q.conjugate() * (r / q.magSqr());
 
  442 template <
typename T>
 
  445   if (unit * unit < eps()) {
 
  448   } 
else if (unit > accuracyMax() || unit < accuracyMin()) {
 
  449     (*this) *= 1. / sqrt(unit);
 
  455 template <
typename T>
 
  457   return Quat(w * q.
w - x * q.
x - y * q.
y - z * q.
z,
 
  458               w * q.
x + x * q.
w + y * q.
z - z * q.
y,
 
  459               w * q.
y + y * q.
w + z * q.
x - x * q.
z,
 
  460               w * q.
z + z * q.
w + x * q.
y - y * q.
x);
 
  463 template <
typename T>
 
  464 inline Quat<T> Quat<T>::reverseMultiply(
const Quat<T>& q)
 const {
 
  472 inline T justUnder1();
 
  474 float inline justUnder1() {
 
  478 double inline justUnder1() {
 
  479   return 0.999999999999999;
 
  483 template <
typename T>
 
  490   if (w_m > justUnder1<T>() || w_m < -justUnder1<T>()) {
 
  491     return Quat<T>((w >= T(0) ? T(1) : T(-1)) * ::pow(m, expo), 0, 0, 0);
 
  494   T theta = ::acos(w_m);
 
  496   imag *= ::sin(expo * theta);
 
  497   return Quat(::cos(expo * theta), imag) * ::pow(m, expo);
 
  500 template <
typename T>
 
  502   return fromAxisAngle(
angle, axis[0], axis[1], axis[2]);
 
  505 template <
typename T>
 
  508   T t2 = 
angle * T(0.5);
 
  517 template <
typename T>
 
  536   T c1 = cos(az * T(0.5));
 
  537   T c2 = cos(el * T(0.5));
 
  538   T c3 = cos(ba * T(0.5));
 
  539   T s1 = sin(az * T(0.5));
 
  540   T s2 = sin(el * T(0.5));
 
  541   T s3 = sin(ba * T(0.5));
 
  569   w = tw * c3 - tz * s3;
 
  570   x = tx * c3 + ty * s3;
 
  571   y = ty * c3 - tx * s3;
 
  572   z = tw * s3 + tz * c3;
 
  578 template <
typename T>
 
  580   T trace = m[0] + m[5] + m[10];
 
  581   w = sqrt(1. + trace) * 0.5;
 
  584     x = (m[9] - m[6]) / (4. * w);
 
  585     y = (m[2] - m[8]) / (4. * w);
 
  586     z = (m[4] - m[1]) / (4. * w);
 
  588     if (m[0] > m[5] && m[0] > m[10]) {
 
  590       x = sqrt(1. + m[0] - m[5] - m[10]) * 0.5;
 
  591       w = (m[9] - m[6]) / (4. * x);
 
  592       y = (m[4] + m[1]) / (4. * x);
 
  593       z = (m[8] + m[2]) / (4. * x);
 
  594     } 
else if (m[5] > m[0] && m[5] > m[10]) {
 
  596       y = sqrt(1. + m[5] - m[0] - m[10]) * 0.5;
 
  597       w = (m[2] - m[8]) / (4. * y);
 
  598       x = (m[4] + m[1]) / (4. * y);
 
  599       z = (m[9] + m[6]) / (4. * y);
 
  602       z = sqrt(1. + m[10] - m[0] - m[5]) * 0.5;
 
  603       w = (m[4] - m[1]) / (4. * z);
 
  604       x = (m[8] + m[2]) / (4. * z);
 
  605       y = (m[9] + m[6]) / (4. * z);
 
  611 template <
typename T>
 
  613   T trace = m[0] + m[5] + m[10];
 
  614   w = sqrt(1. + trace) * 0.5;
 
  617     x = (m[6] - m[9]) / (4. * w);
 
  618     y = (m[8] - m[2]) / (4. * w);
 
  619     z = (m[1] - m[4]) / (4. * w);
 
  621     if (m[0] > m[5] && m[0] > m[10]) {
 
  623       x = sqrt(1. + m[0] - m[5] - m[10]) * 0.5;
 
  624       w = (m[6] - m[9]) / (4. * x);
 
  625       y = (m[1] + m[4]) / (4. * x);
 
  626       z = (m[2] + m[8]) / (4. * x);
 
  627     } 
else if (m[5] > m[0] && m[5] > m[10]) {
 
  629       y = sqrt(1. + m[5] - m[0] - m[10]) * 0.5;
 
  630       w = (m[8] - m[2]) / (4. * y);
 
  631       x = (m[1] + m[4]) / (4. * y);
 
  632       z = (m[6] + m[9]) / (4. * y);
 
  635       z = sqrt(1. + m[10] - m[0] - m[5]) * 0.5;
 
  636       w = (m[1] - m[4]) / (4. * z);
 
  637       x = (m[2] + m[8]) / (4. * z);
 
  638       y = (m[6] + m[9]) / (4. * z);
 
  644 template <
typename T>
 
  649     T invSinAngle = 1. / sqrt(1. - unit);  
 
  651     aa = ::acos(w) * T(2);
 
  652     ax = x * invSinAngle;
 
  653     ay = y * invSinAngle;
 
  654     az = z * invSinAngle;
 
  657     if (x == T(0) && y == T(0) && z == T(0)) {
 
  674 template <
typename T>
 
  683   T a = w, b = y, c = x, d = z, e = -1;  
 
  688   T test = a * c + e * b * d;
 
  689   if (test > 0.49999) {  
 
  695   if (test < -0.49999) {  
 
  706   az = ::atan2(2 * (a * b - e * c * d), 1 - 2 * (bsq + csq));
 
  707   el = ::asin(2 * test);
 
  708   ba = ::atan2(2 * (a * d - e * b * c), 1 - 2 * (csq + dsq));
 
  723 template <
typename T>
 
  726   static const T _2 = T(2);
 
  727   static const T _1 = T(1);
 
  728   T _2w = _2 * w, _2x = _2 * x, _2y = _2 * y;
 
  729   T wx = _2w * x, wy = _2w * y, wz = _2w * z, xx = _2x * x, xy = _2x * y,
 
  730     xz = _2x * z, yy = _2y * y, yz = _2y * z, zz = _2 * z * z;
 
  732   ux[0] = -zz - yy + _1;
 
  737   uy[1] = -zz - xx + _1;
 
  742   uz[2] = -yy - xx + _1;
 
  762 template <
typename T>
 
  763 template <
typename T2>
 
  766   toCoordinateFrame(ux, uy, uz);
 
  787 template <
typename T>
 
  788 template <
typename T2>
 
  791   toCoordinateFrame(ux, uy, uz);
 
  811 template <
typename T>
 
  812 template <
typename T2>
 
  814   ax = 1.0 - 2.0 * y * y - 2.0 * z * z;
 
  815   ay = 2.0 * x * y + 2.0 * z * w;
 
  816   az = 2.0 * x * z - 2.0 * y * w;
 
  819 template <
typename T>
 
  820 template <
typename T2>
 
  822   ax = 2.0 * x * y - 2.0 * z * w;
 
  823   ay = 1.0 - 2.0 * x * x - 2.0 * z * z;
 
  824   az = 2.0 * y * z + 2.0 * x * w;
 
  827 template <
typename T>
 
  828 template <
typename T2>
 
  830   ax = 2.0 * x * z + 2.0 * y * w;
 
  831   ay = 2.0 * y * z - 2.0 * x * w;
 
  832   az = 1.0 - 2.0 * x * x - 2.0 * y * y;
 
  840 template <
typename T>
 
  845   Quat p(-x * v.x - y * v.y - z * v.z, w * v.x + y * v.z - z * v.y,
 
  846          w * v.y - x * v.z + z * v.x, w * v.z + x * v.y - y * v.x);
 
  851                    p.
y * w - p.
w * y + p.
x * z - p.
z * x,
 
  852                    p.
z * w - p.
w * z + p.
y * x - p.
x * y);
 
  857 template <
typename T>
 
  862 template <
typename T>
 
  868   } 
else if (amt == T(1)) {
 
  873   T dot_prod = input.
dot(target);
 
  877   dot_prod = (dot_prod < -1) ? -1 : ((dot_prod > 1) ? 1 : dot_prod);
 
  880   if (dot_prod < 0.0) {
 
  881     dot_prod = -dot_prod;
 
  885   T cos_angle = acos(dot_prod);
 
  886   if (Quat::abs(cos_angle) > eps()) {
 
  887     T sine = sin(cos_angle);
 
  888     T inv_sine = 1. / sine;
 
  890     a = sin(cos_angle * (1. - amt)) * inv_sine;
 
  891     b = sin(cos_angle * amt) * inv_sine;
 
  903   result.
w = a * input.
w + b * target.
w;
 
  904   result.
x = a * input.
x + b * target.
x;
 
  905   result.
y = a * input.
y + b * target.
y;
 
  906   result.
z = a * input.
z + b * target.
z;
 
  912 template <
typename T>
 
  914                           Quat<T>* buffer, 
int numFrames) {
 
  918     RSin(
const T& frq = T(0), 
const T& phs = T(0), 
const T& amp = T(1))
 
  921       mul = (T)2 * (T)cos(f);
 
  922       val2 = (T)sin(p - f * T(2)) * amp;
 
  923       val = (T)sin(p - f) * amp;
 
  927     T operator()()
 const {
 
  928       T v0 = mul * val - val2;
 
  939   T dot_prod = input.
dot(target);
 
  942   dot_prod = (dot_prod < -1) ? -1 : ((dot_prod > 1) ? 1 : dot_prod);
 
  945   if (dot_prod < 0.0) {
 
  946     dot_prod = -dot_prod;
 
  950   const T cos_angle = acos(dot_prod);
 
  951   const T inv_frames = 1. / ((T)numFrames);
 
  953   if (Quat::abs(cos_angle) > eps()) {
 
  954     const T sine = sin(cos_angle);
 
  955     const T inv_sine = 1. / sine;
 
  956     RSin sinA(-cos_angle * inv_frames, cos_angle, inv_sine);
 
  957     RSin sinB(cos_angle * inv_frames, 0, inv_sine * bflip);
 
  959     for (
int i = 0; i < numFrames; i++) {
 
  964       buffer[i].
w = a * input.
w + b * target.
w;
 
  965       buffer[i].
x = a * input.
x + b * target.
x;
 
  966       buffer[i].
y = a * input.
y + b * target.
y;
 
  967       buffer[i].
z = a * input.
z + b * target.
z;
 
  971     for (
int i = 0; i < numFrames; i++) {
 
  972       T a = i * inv_frames;
 
  975       buffer[i].
w = a * input.
w + b * target.
w;
 
  976       buffer[i].
x = a * input.
x + b * target.
x;
 
  977       buffer[i].
y = a * input.
y + b * target.
y;
 
  978       buffer[i].
z = a * input.
z + b * target.
z;
 
  984 template <
typename T>
 
  999   if (d < -0.999999999) {
 
 1003     if (axis.
magSqr() < 0.00000000001) {
 
 1019     T s = sqrt((d + 1.) * 2);
 
 1030 template <
typename T>
 
 1046   T num8 = (m00 + m11) + m22;
 
 1049     T num = sqrt(num8 + 1);
 
 1052     q.
x = (m12 - m21) * num;
 
 1053     q.
y = (m20 - m02) * num;
 
 1054     q.
z = (m01 - m10) * num;
 
 1057   if ((m00 >= m11) && (m00 >= m22)) {
 
 1058     T num7 = sqrt(((1 + m00) - m11) - m22);
 
 1059     T num4 = 0.5 / num7;
 
 1061     q.
y = (m01 + m10) * num4;
 
 1062     q.
z = (m02 + m20) * num4;
 
 1063     q.
w = (m12 - m21) * num4;
 
 1067     T num6 = sqrt(((1 + m11) - m00) - m22);
 
 1068     T num3 = 0.5 / num6;
 
 1069     q.
x = (m10 + m01) * num3;
 
 1071     q.
z = (m21 + m12) * num3;
 
 1072     q.
w = (m20 - m02) * num3;
 
 1075   T num5 = sqrt(((1 + m22) - m00) - m11);
 
 1076   T num2 = 0.5 / num5;
 
 1077   q.
x = (m20 + m02) * num2;
 
 1078   q.
y = (m21 + m12) * num2;
 
 1080   q.
w = (m01 - m10) * num2;
 
 1087 template <
typename T>
 
 1101   cross(axis, zaxis, diff);
 
 1105   float axis_mag_sqr = axis.
dot(axis);
 
 1106   float along = zaxis.
dot(diff);  
 
 1108   if (axis_mag_sqr < 0.001 && along < 0) {
 
 1113     if (axis_mag_sqr < 0.001) {
 
 1119     axis_mag_sqr = axis.
dot(axis);  
 
 1122   if (along < 0.9995 && axis_mag_sqr > 0.001) {
 
 1123     float theta = Quat::abs(amt) * acos(along);
 
 1125     fromAxisAngle(theta, axis[0], axis[1], axis[2]);
 
 1133 template <
typename T>
 
 1143   T dotmag = v1.
dot(v2);
 
 1144   T theta = acos(dotmag) * 0.5;
 
 1148   Quat<T> q(cos(theta), bivec[0], bivec[1], bivec[2]);
 
 1153 template <
typename T>
 
 1155   stream << 
"Quat(" << w << 
", " << x << 
", " << y << 
", " << z << 
")" 
Fixed-size n-by-n square matrix.
 
Quat & set(const T &w, const T &x, const T &y, const T &z)
Set components.
 
T magSqr() const
Get magnitude squared.
 
static Quat getBillboardRotation(const Vec< 3, T > &forward, const Vec< 3, T > &up)
 
Quat slerp(const Quat &target, T amt) const
Spherical interpolation.
 
Quat & fromAxisAngle(const T &angle, const Vec< 3, T > &axis)
Set as versor rotated by angle, in radians, around unit vector.
 
bool operator==(const Quat &v) const
Returns true if all components are equal.
 
Quat & setIdentity()
Set to identity.
 
static Quat rotor(const Vec< 3, T > &v1, const Vec< 3, T > &v2)
Get rotor from two unit vectors.
 
Quat & fromMatrix(const Mat< 4, T > &v)
 
Quat & set(const Quat< U > &q)
Set from other quaternion.
 
void slerpTo(const Quat &target, T amt)
In-place spherical interpolation.
 
void toEuler(T &az, T &el, T &ba) const
Convert to YXZ Euler angles (azimuth, elevation, bank), in radians.
 
Quat & fromMatrixTransposed(const Mat< 4, T > &v)
Set as versor from row-major 4-by-4 projective space transformation matrix.
 
Vec< 3, T > rotate(const Vec< 3, T > &v) const
 
Quat & fromAxisZ(const T &angle)
Set as versor rotated by angle, in radians, around z-axis.
 
Quat & fromMatrix(const T *matrix)
 
Quat pow(T v) const
Return quaternion raised to a power.
 
void print(std::ostream &stream) const
utility for debug printing:
 
Quat inverse() const
Returns inverse (same as conjugate if normalized as q^-1 = q_conj/q_mag^2)
 
Quat sgn() const
Returns signum, q/|q|, the closest point on unit 3-sphere.
 
Quat(const Vec< 3, U > &xyz)
Construct 'pure imaginary' quaternion.
 
Quat conj() const
Returns the conjugate.
 
void toMatrix(T2 *matrix) const
Convert to column-major 4-by-4 projective space transformation matrix.
 
void toEuler(Vec< 3, T > &aeb) const
Convert to YXZ Euler angle vector (azimuth, elevation, bank), in radians.
 
Quat(const T &w, const Vec< 3, U > &xyz)
Construct quaternion from real and imaginary parts.
 
void toCoordinateFrame(Vec< 3, T > &ux, Vec< 3, T > &uy, Vec< 3, T > &uz) const
Convert to coordinate frame unit vectors.
 
void toMatrixTransposed(T2 *matrix) const
Convert to row-major 4-by-4 projective space transformation matrix.
 
Quat & fromMatrixTransposed(const T *matrix)
Set as versor from row-major 4-by-4 projective space transformation matrix.
 
void towardPoint(const Vec< 3, T > &pos, const Quat< T > &q, const Vec< 3, T > &v, float amt)
Get the quaternion from a given point and quaterion toward another point.
 
T components[4]
component vector
 
Quat recip() const
Returns multiplicative inverse.
 
Quat & fromEuler(const Vec< 3, T > &aeb)
Set as versor rotated by YXZ Euler angles, in radians.
 
T mag() const
Get magnitude.
 
void toAxisAngle(T &angle, T &ax, T &ay, T &az) const
Convert to axis-angle form, in radians.
 
Quat & fromAxisY(const T &angle)
Set as versor rotated by angle, in radians, around y-axis.
 
Vec< 3, T > rotateTransposed(const Vec< 3, T > &v) const
This is rotation by the quaternion's conjugate.
 
static Quat getRotationTo(const Vec< 3, T > &usrc, const Vec< 3, T > &udst)
 
void toEuler(T *aeb) const
Convert to YXZ Euler angle vector (azimuth, elevation, bank), in radians.
 
T & operator[](int i)
Set component with index.
 
Quat & normalize()
Normalize magnitude to one.
 
static void slerpBuffer(const Quat &from, const Quat &to, Quat< T > *buffer, int numFrames)
Fill an array of Quats with a full spherical interpolation.
 
static Quat slerp(const Quat &from, const Quat &to, T amt)
Spherical linear interpolation of a quaternion.
 
Quat & fromAxisAngle(const T &angle, const T &ux, const T &uy, const T &uz)
Set as versor rotated by angle, in radians, around unit vector (ux,uy,uz)
 
Quat & fromEuler(const T &az, const T &el, const T &ba)
Set as versor rotated by YXZ Euler angles, in radians.
 
void toVectorX(T2 &ax, T2 &ay, T2 &az) const
Get local x unit vector (1,0,0) in absolute coordinates.
 
static Quat identity()
Returns identity.
 
Quat & fromAxisX(const T &angle)
Set as versor rotated by angle, in radians, around x-axis.
 
Quat(const T &w=T(1), const T &x=T(0), const T &y=T(0), const T &z=T(0))
Default constructor creates an identity quaternion.
 
const T & operator[](int i) const
Get component with index.
 
void toVectorZ(T2 &ax, T2 &ay, T2 &az) const
Get local z unit vector (0,0,1) in absolute coordinates.
 
bool operator!=(const Quat &v) const
Returns true if any components are not equal.
 
void toVectorY(T2 &ax, T2 &ay, T2 &az) const
Get local y unit vector (0,1,0) in absolute coordinates.
 
T dot(const Quat &v) const
Returns dot product with another quaternion.
 
Vec & normalize(T scale=T(1))
Set magnitude to one without changing direction.
 
T magSqr() const
Returns magnitude squared.
 
T dot(const Vec< N, U > &v) const
Returns dot (inner) product between vectors.
 
T angle(const Vec< N, T > &a, const Vec< N, T > &b)
Returns angle, in interval [0, pi], between two vectors.
 
Quat< double > Quatd
Double-precision quaternion.
 
Quat< float > Quatf
Single-precision quaternion.
 
void cross(Vec< 3, T > &r, const Vec< 3, T > &a, const Vec< 3, T > &b)
Sets r to cross product, a x b.