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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #ifndef ACG_QUATERNION_HH
00052 #define ACG_QUATERNION_HH
00053
00054
00055
00056
00057 #include "VectorT.hh"
00058 #include "Matrix4x4T.hh"
00059
00060
00061
00062
00063 namespace ACG {
00064
00065
00066
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
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 }
00322
00323 #endif // ACG_QUATERNION_HH defined
00324
00325