Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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 }
00308
00309 std::ostream& operator<<(std::ostream& o, const qglviewer::Quaternion&);
00310
00311 #endif // QGLVIEWER_QUATERNION_H