00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef QGLVIEWER_QUATERNION_H
00026 #define QGLVIEWER_QUATERNION_H
00027
00028 #include "vec.h"
00029 #include <math.h>
00030 #include <iostream>
00031
00032 namespace qglviewer {
00060 class QGLVIEWER_EXPORT Quaternion
00061 {
00062 public:
00065
00066 explicit Quaternion()
00067 { q[0]=q[1]=q[2]=0.0; q[3]=1.0; }
00068
00070 explicit Quaternion(const Vec& axis, const double angle)
00071 {
00072 setAxisAngle(axis, angle);
00073 }
00074
00076 explicit Quaternion(const Vec& v, const double sin_ha, const double cos_ha)
00077 {
00078 q[0] = v[0]*sin_ha ;
00079 q[1] = v[1]*sin_ha ;
00080 q[2] = v[2]*sin_ha ;
00081 q[3] = cos_ha ;
00082 }
00083
00085 explicit Quaternion(const double q0, const double q1, const double q2, const double q3)
00086 { q[0]=q0; q[1]=q1; q[2]=q2; q[3]=q3; }
00087
00089 explicit Quaternion(const Vec& from, const Vec& to);
00090
00092 Quaternion& operator=(const Quaternion& Q)
00093 {
00094 for (int i=0; i<4; ++i)
00095 q[i] = Q.q[i];
00096 return (*this);
00097 }
00098
00100 Quaternion(const Quaternion& Q)
00101 { for (int i=0; i<4; ++i) q[i] = Q.q[i]; }
00103
00104 void setAxisAngle(const Vec& v, const double angle)
00105 {
00106 const double norm = v.norm();
00107 if (norm < 1E-9)
00108 {
00109
00110 q[0] = 0.0; q[1] = 0.0; q[2] = 0.0; q[3] = 1.0;
00111 }
00112 else
00113 {
00114 const double sin_half_angle = sin(angle / 2.0);
00115 q[0] = sin_half_angle*v[0]/norm;
00116 q[1] = sin_half_angle*v[1]/norm;
00117 q[2] = sin_half_angle*v[2]/norm;
00118 q[3] = cos(angle / 2.0);
00119 }
00120 }
00121
00123 void setValue(const double q0, const double q1, const double q2, const double q3)
00124 { q[0]=q0; q[1]=q1; q[2]=q2; q[3]=q3; }
00125
00126 void setFromRotationMatrix(const float m[3][3]);
00127 void setFromRotatedBase(const Vec& X,
00128 const Vec& Y,
00129 const Vec& Z);
00131
00132
00135 Vec axis() const;
00136 float angle() const;
00137 void getAxisAngle(Vec& axis, float& angle) const;
00138
00140 double operator[](int i) const { return q[i]; }
00141
00143 double& operator[](int i) { return q[i]; }
00145
00146
00149
00150
00151
00152 friend const Quaternion operator*(const Quaternion& a, const Quaternion& b)
00153 {
00154 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],
00155 a.q[3]*b.q[1] + b.q[3]*a.q[1] + a.q[2]*b.q[0] - a.q[0]*b.q[2],
00156 a.q[3]*b.q[2] + b.q[3]*a.q[2] + a.q[0]*b.q[1] - a.q[1]*b.q[0],
00157 a.q[3]*b.q[3] - b.q[0]*a.q[0] - a.q[1]*b.q[1] - a.q[2]*b.q[2]);
00158 }
00159
00163 Quaternion& operator*=(const Quaternion &q)
00164 {
00165 *this = (*this)*q;
00166 return *this;
00167 }
00168
00170 friend const Vec operator*(const Quaternion& a, const Vec& b)
00171 {
00172 return a.rotate(b);
00173 }
00174
00175 Vec inverseRotate(const Vec& v) const;
00176 Vec rotate(const Vec& v) const;
00178
00179
00182
00183 Quaternion inverse() const { return Quaternion(-q[0], -q[1], -q[2], q[3]); }
00184
00186 void invert() { q[0] = -q[0]; q[1] = -q[1]; q[2] = -q[2]; }
00187
00191 void negate() { invert(); q[3] = -q[3]; }
00192
00194 double normalize()
00195 {
00196 const double norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
00197 for (int i=0; i<4; ++i)
00198 q[i] /= norm;
00199 return norm;
00200 }
00202
00203
00206 const GLdouble* matrix() const;
00207 void getMatrix(GLdouble m[4][4]) const;
00208 void getMatrix(GLdouble m[16]) const;
00209
00210 void getRotationMatrix(float m[3][3]) const;
00212
00213
00216 static Quaternion slerp(const Quaternion& a, const Quaternion& b, float t, bool allowFlip=true);
00217 static Quaternion squad(const Quaternion& a, const Quaternion& tgA, const Quaternion& tgB, const Quaternion& b, float t);
00219 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]; }
00220
00221 Quaternion log();
00222 Quaternion exp();
00223 static Quaternion lnDif(const Quaternion& a, const Quaternion& b);
00224 static Quaternion squadTangent(const Quaternion& a, const Quaternion& b, const Quaternion& c);
00226
00229 static Quaternion randomOrientation();
00231
00234 QDomElement domElement(const QString& name, QDomDocument& doc) const;
00235 void initFromDOMElement(const QDomElement& de);
00237
00238 private:
00240 double q[4];
00241 };
00242
00243 }
00244
00245 std::ostream& operator<<(std::ostream& o, const qglviewer::Quaternion&);
00246
00247 #endif // QGLVIEWER_QUATERNION_H