quaternion.H

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #ifndef ARCHON_MATH_QUATERNION_H
00021 #define ARCHON_MATH_QUATERNION_H
00022 
00023 #include <cmath>
00024 #include <algorithm>
00025 #include <iostream>
00026 
00027 #include <archon/math/rotation.H>
00028 
00029 namespace Archon
00030 {
00031   namespace Math
00032   {
00033     struct Quaternion
00034     {
00035       double w;
00036       Vector3 v;
00037 
00038       static const Quaternion zero()
00039       {
00040         static Quaternion q = makeZero();
00041         return q;
00042       }
00043 
00044       static const Quaternion one()
00045       {
00046         static Quaternion q = makeOne();
00047         return q;
00048       }
00049 
00050       Quaternion() {}
00051       Quaternion(double w, const Vector3 &v): w(w), v(v) {}
00052 
00053       double squareSum() const                        { return w*w + v.squareSum(); }
00054       double length() const                           { return sqrt(squareSum()); }
00055 
00056       Quaternion operator+(const Quaternion &q) const { Quaternion r(*this); return r += q; }
00057       Quaternion operator-(const Quaternion &q) const { Quaternion r(*this); return r -= q; }
00058       Quaternion operator*(const Quaternion &q) const { Quaternion r(*this); return r *= q; }
00059       Quaternion operator*(double f) const            { Quaternion q(*this); return q *= f; }
00060       Quaternion operator/(double f) const            { Quaternion q(*this); return q /= f; }
00061       Quaternion operator-() const                    { Quaternion q(*this); q.negate(); return q; }
00062 
00063       Quaternion &operator+=(const Quaternion &q)     { w += q.w; v += q.v; return *this; }
00064       Quaternion &operator-=(const Quaternion &q)     { w -= q.w; v -= q.v; return *this; }
00065 
00081       Quaternion &operator*=(const Quaternion &q)
00082       {
00083         Vector3 w1 = v;
00084         w1 *= q.v;
00085         Vector3 w2 = v;
00086         w2 *= q.w;
00087         w1 += w2;
00088         w2 = q.v;
00089         w2 *= w;
00090         w1 += w2;
00091         w = w*q.w - dot(v,q.v);
00092         v = w1;
00093         return *this;
00094       }
00095 
00096       Quaternion &operator/=(const Quaternion &q)  { Quaternion r(q); r.inverse(); *this *= r; return *this; }
00097 
00098       Quaternion &operator*=(double f)             { w *= f; v *= f; return *this; }
00099       Quaternion &operator/=(double f)             { w /= f; v /= f; return *this; }
00100 
00101       bool operator==(const Quaternion &q) const   { return w == q.w && v == q.v; }
00102       bool operator!=(const Quaternion &q) const   { return w != q.w || v != q.v; }
00103 
00104       void set(const Vector3 &v, double w)         { this->w = w; this->v = v; }
00105       void negate()                                { w = -w; v.negate(); }
00106       void normalize()                             { *this /= length(); }
00107       void conjugate()                             { v.negate(); }
00108       void inverse()                               { *this /= squareSum(); v.negate(); }
00109 
00116       void setRotation(const Rotation3 &r)
00117       {
00118         v = r.axis;
00119         double a = r.angle / 2;
00120         v *= sin(a);
00121         w = cos(a);
00122       }
00123 
00130       void setRotation(const Vector3 &axis, double cosineOfAngle)
00131       {
00132         v = axis;
00133         double k = (cosineOfAngle + 1)/2;
00134         v *= sqrt(k-cosineOfAngle);
00135         w = sqrt(k);
00136       }
00137 
00143       void getRotation(Rotation3 &r) const
00144       {
00145         double l = v.squareSum();
00146         if(l==0)
00147         {
00148           r.axis = Vector3(0, 1 ,0);
00149           r.angle = 0;
00150           return;
00151         }
00152         l = sqrt(l + sq(w));
00153         double a = acos(w/l);
00154         l *= sin(a);
00155         if(l==0)
00156         {
00157           r.axis = Vector3(0, 1 ,0);
00158           r.angle = 0;
00159           return;
00160         }
00161         r.angle = 2*a;
00162         r.axis = v;
00163         r.axis /= l;
00164       }
00165 
00166     private:
00167       static Quaternion makeZero()
00168       {
00169         return Quaternion(0, Vector3::zero());
00170       }
00171 
00172       static Quaternion makeOne()
00173       {
00174         return Quaternion(1, Vector3::zero());
00175       }
00176     };
00177 
00178     inline Quaternion operator*(double f, const Quaternion &q)
00179     {
00180       Quaternion r = q; return r *= f;
00181     }
00182 
00183     inline Quaternion operator/(double f, const Quaternion &q)
00184     {
00185       Quaternion r = q; r.inverse(); return r *= f;
00186     }
00187 
00188     inline Quaternion normalize(const Quaternion &q)
00189     {
00190       Quaternion r = q; r.normalize(); return r;
00191     }
00192 
00193     inline Quaternion conjugate(const Quaternion &q)
00194     {
00195       Quaternion r = q; r.conjugate(); return r;
00196     }
00197 
00198     inline Quaternion inverse(const Quaternion &q)
00199     {
00200       Quaternion r = q; r.inverse(); return r;
00201     }
00202 
00203     std::ostream &operator<<(std::ostream &, const Quaternion &);
00204   }
00205 }
00206 
00207 #endif // ARCHON_MATH_QUATERNION_H

Generated on Sun Jul 30 22:55:43 2006 for Archon by  doxygen 1.4.4