QuaternionT.hh

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 8521 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2010-02-10 15:57:35 +0100 (Mi, 10. Feb 2010) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 //=============================================================================
00046 //
00047 //  CLASS Quaternion
00048 //
00049 //=============================================================================
00050 
00051 #ifndef ACG_QUATERNION_HH
00052 #define ACG_QUATERNION_HH
00053 
00054 
00055 //== INCLUDES =================================================================
00056 
00057 #include "VectorT.hh"
00058 #include "Matrix4x4T.hh"
00059 
00060 
00061 //== NAMESPACES  ==============================================================
00062 
00063 namespace ACG {
00064 
00065 
00066 //== CLASS DEFINITION =========================================================
00067 
00068 
00073 template <class Scalar>
00074 class QuaternionT : public VectorT<Scalar,4>
00075 {
00076 public:
00077 
00078 #define W Base::values_[0]
00079 #define X Base::values_[1]
00080 #define Y Base::values_[2]
00081 #define Z Base::values_[3]
00082 
00083 
00084   typedef VectorT<Scalar,4>    Base;
00085   typedef QuaternionT<Scalar>  Quaternion;
00086   typedef VectorT<Scalar,3>    Vec3;
00087   typedef VectorT<Scalar,4>    Vec4;
00088   typedef Matrix4x4T<Scalar>   Matrix;
00089 
00090 
00092   QuaternionT(Scalar _w=1.0, Scalar _x=0.0, Scalar _y=0.0, Scalar _z=0.0)
00093     : Vec4(_w, _x, _y, _z) {}
00094 
00096   QuaternionT(const Vec3& _p)
00097     : Vec4(0, _p[0], _p[1], _p[2]) {}
00098 
00100   QuaternionT(const Vec4& _p)
00101     : Vec4(_p[0], _p[1], _p[2], _p[3]) {}
00102 
00104   QuaternionT(Vec3 _axis, Scalar _angle)
00105   {
00106     _axis.normalize();
00107     Scalar theta = 0.5 * _angle;
00108     Scalar sin_theta = sin(theta);
00109     W = cos(theta);
00110     X = sin_theta * _axis[0];
00111     Y = sin_theta * _axis[1];
00112     Z = sin_theta * _axis[2];
00113   }
00114 
00116   template <class MatrixT>
00117   QuaternionT(const MatrixT& _rot)
00118   { init_from_matrix( _rot); }
00119   
00120 
00122   void identity() { W=1.0; X=Y=Z=0.0; }
00123 
00124 
00126   Quaternion conjugate() const
00127   { return Quaternion(W, -X, -Y, -Z); }
00128 
00129 
00131   Quaternion invert() const
00132   { return conjugate()/Base::sqrnorm(); }
00133 
00134 
00136   Quaternion operator*(const Quaternion& _q) const
00137   { return Quaternion(W*_q.W - X*_q.X - Y*_q.Y - Z*_q.Z,
00138                       W*_q.X + X*_q.W + Y*_q.Z - Z*_q.Y,
00139                       W*_q.Y - X*_q.Z + Y*_q.W + Z*_q.X,
00140                       W*_q.Z + X*_q.Y - Y*_q.X + Z*_q.W); }
00141 
00142 
00144   Quaternion& operator*=(const Quaternion& _q)
00145   { return *this = *this * _q; }
00146 
00147 
00149   Vec3 rotate(const Vec3& _v)
00150   { 
00151     Quaternion q = *this * Quaternion(_v) * conjugate();
00152     return Vec3(q[1], q[2], q[3]);
00153   }
00154 
00155 
00157   void axis_angle(Vec3& _axis, Scalar& _angle) const
00158   {
00159     if (fabs(W) > 0.999999)
00160     {
00161       _axis  = Vec3(1,0,0);
00162       _angle = 0;
00163     }
00164     else
00165     {
00166       _angle = 2.0 * acos(W);
00167       _axis  = Vec3(X, Y, Z).normalize();
00168     }
00169   }
00170 
00171 
00172 
00174   Matrix rotation_matrix() const
00175   {
00176     Scalar
00177       ww(W*W), xx(X*X), yy(Y*Y), zz(Z*Z), wx(W*X),
00178       wy(W*Y), wz(W*Z), xy(X*Y), xz(X*Z), yz(Y*Z);
00179 
00180     Matrix m;
00181 
00182     m(0,0) = ww + xx - yy - zz;
00183     m(1,0) = 2.0*(xy + wz);
00184     m(2,0) = 2.0*(xz - wy);
00185 
00186     m(0,1) = 2.0*(xy - wz);
00187     m(1,1) = ww - xx + yy - zz;
00188     m(2,1) = 2.0*(yz + wx);
00189 
00190     m(0,2) = 2.0*(xz + wy);
00191     m(1,2) = 2.0*(yz - wx);
00192     m(2,2) = ww - xx - yy + zz;
00193 
00194     m(0,3) = m(1,3) = m(2,3) = m(3,0) = m(3,1) = m(3,2) = 0.0;
00195     m(3,3) = 1.0;
00196 
00197     return m;
00198   }
00199 
00200 
00201 
00203   Matrix right_mult_matrix() const
00204   {
00205     Matrix m;
00206     m(0,0) =  W; m(0,1) = -X; m(0,2) = -Y; m(0,3) = -Z;
00207     m(1,0) =  X; m(1,1) =  W; m(1,2) = -Z; m(1,3) =  Y;
00208     m(2,0) =  Y; m(2,1) =  Z; m(2,2) =  W; m(2,3) = -X;
00209     m(3,0) =  Z; m(3,1) = -Y; m(3,2) =  X; m(3,3) =  W;
00210     return m;
00211   }
00212 
00213 
00215   Matrix left_mult_matrix() const
00216   {
00217     Matrix m;
00218     m(0,0) =  W; m(0,1) = -X; m(0,2) = -Y; m(0,3) = -Z;
00219     m(1,0) =  X; m(1,1) =  W; m(1,2) =  Z; m(1,3) = -Y;
00220     m(2,0) =  Y; m(2,1) = -Z; m(2,2) =  W; m(2,3) =  X;
00221     m(3,0) =  Z; m(3,1) =  Y; m(3,2) = -X; m(3,3) =  W;
00222     return m;
00223   }
00224 
00225 
00227   template<class MatrixT>
00228   void init_from_matrix( const MatrixT& _rot)
00229   {
00230     Scalar trace = _rot(0,0) + _rot(1,1) + _rot(2,2); 
00231     if( trace > 0.0 ) 
00232     {
00233       Scalar s = 0.5 / sqrt(trace + 1.0);
00234       W = 0.25 / s;
00235       X = ( _rot(2,1) - _rot(1,2) ) * s;
00236       Y = ( _rot(0,2) - _rot(2,0) ) * s;
00237       Z = ( _rot(1,0) - _rot(0,1) ) * s;
00238     } 
00239     else
00240     {
00241       if ( _rot(0,0) > _rot(1,1) && _rot(0,0) > _rot(2,2) )
00242       {
00243         Scalar s = 2.0 * sqrt( 1.0 + _rot(0,0) - _rot(1,1) - _rot(2,2));
00244         W = (_rot(2,1) - _rot(1,2) ) / s;
00245         X = 0.25 * s;
00246         Y = (_rot(0,1) + _rot(1,0) ) / s;
00247         Z = (_rot(0,2) + _rot(2,0) ) / s;
00248       } 
00249       else 
00250         if (_rot(1,1) > _rot(2,2))
00251         {
00252           Scalar s = 2.0 * sqrt( 1.0 + _rot(1,1) - _rot(0,0) - _rot(2,2));
00253           W = (_rot(0,2) - _rot(2,0) ) / s;
00254           X = (_rot(0,1) + _rot(1,0) ) / s;
00255           Y = 0.25 * s;
00256           Z = (_rot(1,2) + _rot(2,1) ) / s;
00257         } 
00258         else
00259         {
00260           Scalar s = 2.0 * sqrt( 1.0 + _rot(2,2) - _rot(0,0) - _rot(1,1) );
00261           W = (_rot(1,0) - _rot(0,1) ) / s;
00262           X = (_rot(0,2) + _rot(2,0) ) / s;
00263           Y = (_rot(1,2) + _rot(2,1) ) / s;
00264           Z = 0.25 * s;
00265         }
00266     }
00267   }
00268 
00269 
00271   Quaternion exponential() const
00272   {
00273     Vec3   n(X,Y,Z);
00274     Scalar theta( n.norm());
00275     Scalar sin_theta = sin(theta);
00276     Scalar cos_theta = cos(theta);
00277 
00278     if( theta > 1e-6 )
00279       n *= sin_theta/theta;
00280     else
00281       n = Vec3(0,0,0);
00282 
00283     return Quaternion( cos_theta, n[0], n[1], n[2]);
00284   }
00285 
00286 
00288   Quaternion logarithm() const
00289   {
00290     // clamp to valid input
00291     double w = W;
00292     if( w > 1.0) w = 1.0;
00293     else if( w < -1.0) w = -1.0;
00294 
00295     Scalar theta_half = acos(w);
00296 
00297     Vec3   n(X,Y,Z);
00298     Scalar n_norm( n.norm());
00299     
00300     if( n_norm > 1e-6 )
00301       n *= theta_half/n_norm;
00302     else
00303       n = Vec3(0,0,0);
00304 
00305     return Quaternion( 0, n[0], n[1], n[2]);
00306   }
00307 
00308 
00309 #undef W
00310 #undef X
00311 #undef Y
00312 #undef Z
00313 };
00314 
00315 
00316 typedef QuaternionT<float>  Quaternionf;
00317 typedef QuaternionT<double> Quaterniond;
00318 
00319 
00320 //=============================================================================
00321 } // namespace ACG
00322 //=============================================================================
00323 #endif // ACG_QUATERNION_HH defined
00324 //=============================================================================
00325 

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .