worldsim/3rdParts/qglviewer/quaternion.h

00001 /****************************************************************************
00002 
00003  Copyright (C) 2002-2008 Gilles Debunne. All rights reserved.
00004 
00005  This file is part of the QGLViewer library version 2.3.10.
00006 
00007  http://www.libqglviewer.com - contact@libqglviewer.com
00008 
00009  This file may be used under the terms of the GNU General Public License 
00010  versions 2.0 or 3.0 as published by the Free Software Foundation and
00011  appearing in the LICENSE file included in the packaging of this file.
00012  In addition, as a special exception, Gilles Debunne gives you certain 
00013  additional rights, described in the file GPL_EXCEPTION in this package.
00014 
00015  libQGLViewer uses dual licensing. Commercial/proprietary software must
00016  purchase a libQGLViewer Commercial License.
00017 
00018  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00019  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00020 
00021 *****************************************************************************/
00022 
00023 #ifndef QGLVIEWER_QUATERNION_H
00024 #define QGLVIEWER_QUATERNION_H
00025 
00026 #include "vec.h"
00027 #include <math.h>
00028 #include <iostream>
00029 
00030 namespace qglviewer {
00066     class QGLVIEWER_EXPORT Quaternion
00067     {
00068     public:
00072         Quaternion()
00073         { q[0]=q[1]=q[2]=0.0;  q[3]=1.0; }
00074 
00076         Quaternion(const Vec& axis, double angle)
00077         {
00078             setAxisAngle(axis, angle);
00079         }
00080 
00081         Quaternion(const Vec& from, const Vec& to);
00082 
00088         Quaternion(double q0, double q1, double q2, double q3)
00089         { q[0]=q0;    q[1]=q1;    q[2]=q2;    q[3]=q3; }
00090 
00092         Quaternion(const Quaternion& Q)
00093         { for (int i=0; i<4; ++i) q[i] = Q.q[i]; }
00094 
00096         Quaternion& operator=(const Quaternion& Q)
00097         {
00098             for (int i=0; i<4; ++i)
00099                 q[i] = Q.q[i];
00100             return (*this);
00101         }
00102 
00106         void setAxisAngle(const Vec& axis, double angle)
00107         {
00108             const double norm = axis.norm();
00109             if (norm < 1E-8)
00110             {
00111                 // Null rotation
00112                 q[0] = 0.0;      q[1] = 0.0;      q[2] = 0.0;      q[3] = 1.0;
00113             }
00114             else
00115             {
00116                 const double sin_half_angle = sin(angle / 2.0);
00117                 q[0] = sin_half_angle*axis[0]/norm;
00118                 q[1] = sin_half_angle*axis[1]/norm;
00119                 q[2] = sin_half_angle*axis[2]/norm;
00120                 q[3] = cos(angle / 2.0);
00121             }
00122         }
00123 
00125         void setValue(double q0, double q1, double q2, double q3)
00126         { q[0]=q0;    q[1]=q1;    q[2]=q2;    q[3]=q3; }
00127 
00128 #ifndef DOXYGEN
00129         void setFromRotationMatrix(const float m[3][3]);
00130         void setFromRotatedBase(const Vec& X, const Vec& Y, const Vec& Z);
00131 #endif
00132         void setFromRotationMatrix(const double m[3][3]);
00133         void setFromRotatedBasis(const Vec& X, const Vec& Y, const Vec& Z);
00135 
00136 
00139         Vec axis() const;
00140         double angle() const;
00141         void getAxisAngle(Vec& axis, float& angle) const;
00142 
00144         double operator[](int i) const { return q[i]; }
00145 
00147         double& operator[](int i) { return q[i]; }
00149 
00150 
00164         friend Quaternion operator*(const Quaternion& a, const Quaternion& b)
00165         {
00166             return Quaternion(a.q[3]*b.q[0] + b.q[3]*a.q[0] + a.q[1]*b.q[2] - a.q[2]*b.q[1],
00167                 a.q[3]*b.q[1] + b.q[3]*a.q[1] + a.q[2]*b.q[0] - a.q[0]*b.q[2],
00168                 a.q[3]*b.q[2] + b.q[3]*a.q[2] + a.q[0]*b.q[1] - a.q[1]*b.q[0],
00169                 a.q[3]*b.q[3] - b.q[0]*a.q[0] - a.q[1]*b.q[1] - a.q[2]*b.q[2]);
00170         }
00171 
00178         Quaternion& operator*=(const Quaternion &q)
00179         {
00180             *this = (*this)*q;
00181             return *this;
00182         }
00183 
00187         friend Vec operator*(const Quaternion& q, const Vec& v)
00188         {
00189             return q.rotate(v);
00190         }
00191 
00192         Vec rotate(const Vec& v) const;
00193         Vec inverseRotate(const Vec& v) const;
00195 
00196 
00205         Quaternion inverse() const { return Quaternion(-q[0], -q[1], -q[2], q[3]); }
00206 
00210         void invert() { q[0] = -q[0]; q[1] = -q[1]; q[2] = -q[2]; }
00211 
00220         void negate() { invert(); q[3] = -q[3]; }
00221 
00227         double normalize()
00228         {
00229             const double norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
00230             for (int i=0; i<4; ++i)
00231                 q[i] /= norm;
00232             return norm;
00233         }
00234 
00238         Quaternion normalized() const
00239         {
00240             double Q[4];
00241             const double norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
00242             for (int i=0; i<4; ++i)
00243                 Q[i] = q[i] / norm;
00244             return Quaternion(Q[0], Q[1], Q[2], Q[3]);
00245         }
00247 
00248 
00251         const GLdouble* matrix() const;
00252         void getMatrix(GLdouble m[4][4]) const;
00253         void getMatrix(GLdouble m[16]) const;
00254 
00255         void getRotationMatrix(float m[3][3]) const;
00256 
00257         const GLdouble* inverseMatrix() const;
00258         void getInverseMatrix(GLdouble m[4][4]) const;
00259         void getInverseMatrix(GLdouble m[16]) const;
00260 
00261         void getInverseRotationMatrix(float m[3][3]) const;
00263 
00264 
00267         static Quaternion slerp(const Quaternion& a, const Quaternion& b, float t, bool allowFlip=true);
00268         static Quaternion squad(const Quaternion& a, const Quaternion& tgA, const Quaternion& tgB, const Quaternion& b, float t);
00270         static double dot(const Quaternion& a, const Quaternion& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]; }
00271 
00272         Quaternion log();
00273         Quaternion exp();
00274         static Quaternion lnDif(const Quaternion& a, const Quaternion& b);
00275         static Quaternion squadTangent(const Quaternion& before, const Quaternion& center, const Quaternion& after);
00277 
00280         static Quaternion randomQuaternion();
00282 
00285         explicit Quaternion(const QDomElement& element);
00286         QDomElement domElement(const QString& name, QDomDocument& document) const;
00287         void initFromDOMElement(const QDomElement& element);
00289 
00290 #ifdef DOXYGEN
00291 
00298         std::ostream& operator<<(std::ostream& o, const qglviewer::Vec&);
00300 #endif
00301 
00302     private:
00304         double q[4];
00305     };
00306 
00307 } // namespace
00308 
00309 std::ostream& operator<<(std::ostream& o, const qglviewer::Quaternion&);
00310 
00311 #endif // QGLVIEWER_QUATERNION_H