00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_QUAT_H
00027 #define NL_QUAT_H
00028
00029 #include "nel/misc/types_nl.h"
00030 #include "nel/misc/vector.h"
00031 #include "nel/misc/stream.h"
00032 #include <math.h>
00033
00034 namespace NLMISC
00035 {
00036
00037
00038
00039 const double QuatEpsilon= 0.000001;
00040
00041
00042
00043
00050 struct CAngleAxis
00051 {
00052 CVector Axis;
00053 float Angle;
00054
00055 CAngleAxis() {}
00056 CAngleAxis(CVector axis, float ang) : Axis(axis), Angle(ang) {}
00057
00059 void serial(IStream &f)
00060 {
00061 f.serial(Axis);
00062 f.serial(Angle);
00063 }
00064 };
00065
00066
00067
00074 template <class T> class CQuatT
00075 {
00076 public:
00077 T x,y,z,w;
00078
00079
00080 public:
00081
00083
00084 CQuatT() : x((T)0.0),y((T)0.0),z((T)0.0),w((T)1.0) {}
00085 CQuatT(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {}
00087 CQuatT(const CVector &axis, float angle) {setAngleAxis(axis, angle);}
00089 CQuatT(const CAngleAxis &aa) {setAngleAxis(aa);}
00090
00091
00092
00094
00095 void set(T X, T Y, T Z, T W) {x= X; y= Y; z= Z; w= W;}
00096
00097
00099
00100 bool operator==(const CQuatT& a) const {return (x==0 && y==0 && z==0 && w==1.0f);}
00101 bool equal(const CQuatT& a, float epsilon = 1E-6f) const;
00102 void identity() {x = y = z = 0.0f ; w = 1.0f; }
00103 bool isIdentity() const {return (x==0.0f && y==0.0f && z==0.0f && w==1.0f);}
00104
00105
00107
00108 CQuatT& operator+=(const CQuatT&o) {x+=o.x; y+=o.y; z+=o.z; w+=o.w; return *this;}
00109 CQuatT& operator-=(const CQuatT&o) {x-=o.x; y-=o.y; z-=o.z; w-=o.w; return *this;}
00110 CQuatT& operator*=(T f) {x*=f;y*=f;z*=f;w*=f; return *this;}
00111 CQuatT& operator/=(T f) {double oof= 1.0/f; x=(T)(x*oof); y=(T)(y*oof); z= (T)(z*oof); w=(T)(w*oof); return *this;}
00112 CQuatT operator+(const CQuatT&o) const {return CQuatT(x+o.x,y+o.y,z+o.z,w+o.w);}
00113 CQuatT operator-(const CQuatT&o) const {return CQuatT(x-o.x,y-o.y,z-o.z,w-o.w);}
00114 CQuatT operator*(T f) const {return CQuatT(x*f,y*f,z*f,w*f);}
00115 CQuatT operator/(T f) const {double oof= 1.0/f; return CQuatT(x*oof,y*oof,z*oof,w*oof);}
00116 CQuatT operator-() const {return(CQuatT(-x,-y,-z,-w)); }
00117 CQuatT operator+() const {return *this; }
00119 T sqrnorm() const {return (x*x + y*y + z*z + w*w);}
00121 T norm() const {return (T)sqrt(sqrnorm());}
00123 void normalize();
00125 CQuatT normed() const {CQuatT ret= *this; ret.normalize(); return ret;}
00126
00127
00128
00130
00132
00133 CQuatT& operator*=(const CQuatT&);
00135 void invert();
00137 CQuatT inverted() const {CQuatT ret= *this; ret.invert(); return ret;}
00139 CQuatT conjugate() const {return CQuatT(-x, -y, -z, w);}
00140
00141
00142
00144
00146
00148
00150
00151
00153 void setAngleAxis(const CVector &axis, float angle);
00155 void setAngleAxis(const CAngleAxis &angAxis) {setAngleAxis(angAxis.Axis, angAxis.Angle);}
00156
00157
00158
00160
00162
00164
00166
00168
00169 {
00170 f.serial(x,y,z,w);
00171 }
00172
00173
00174
00175 public:
00176
00178
00180
00184 static CQuatT slerp(const CQuatT<T>& q0, const CQuatT<T>& q1, float t);
00188 static CQuatT squad(const CQuatT<T>& q0, const CQuatT<T>& tgtQ0, const CQuatT<T>& tgtQ1, const CQuatT<T>& q1, float t);
00191 static CQuatT squadrev(const CAngleAxis &rot, const CQuatT<T>& q0, const CQuatT<T>& tgtQ0, const CQuatT<T>& tgtQ1, const CQuatT<T>& q1, float t);
00192
00194 static CQuatT lnDif(const CQuatT &q0, const CQuatT &q1);
00195
00196
00197
00198
00199 };
00200
00201
00202
00203
00204
00205
00207
00208
00210 template <class T>
00211 inline CQuatT<T> operator*(T f, const CQuatT<T> &o) {return o*f;}
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 template <class T>
00227 inline bool CQuatT<T>::equal(const CQuatT<T>& a, float epsilon) const
00228 {
00229 if (fabs(x-a.x)<epsilon &&
00230 fabs(y-a.y)<epsilon &&
00231 fabs(z-a.z)<epsilon &&
00232 fabs(w-a.w)<epsilon )
00233 {
00234 return true;
00235 }
00236 return false;
00237 }
00238
00239
00240
00241 template <class T>
00242 inline CQuatT<T> CQuatT<T>::operator*(const CQuatT<T>& o) const
00243 {
00244
00245
00246 return CQuatT<T>(
00247 (w*o.x) +(x*o.w) + (y*o.z)-(z*o.y),
00248 (w*o.y) +(y*o.w) + (z*o.x)-(x*o.z),
00249 (w*o.z) +(z*o.w) + (x*o.y)-(y*o.x),
00250 (w*o.w)-(x*o.x)-(y*o.y)-(z*o.z) );
00251
00252 }
00253
00254
00255 template <class T>
00256 inline CQuatT<T>& CQuatT<T>::operator*=(const CQuatT<T>& o)
00257 {
00258 *this= *this * o;
00259 return *this;
00260 }
00261
00262
00263
00264 template <class T>
00265 inline void CQuatT<T>::invert()
00266 {
00267
00268 T f= sqrnorm();
00269 if(f!=0)
00270 {
00271 *this/=f;
00272 }
00273
00274 *this= conjugate();
00275 }
00276
00277
00278
00279 template <class T>
00280 inline void CQuatT<T>::normalize()
00281 {
00282 T f= norm();
00283 if(f==0)
00284 identity();
00285 else
00286 {
00287 *this/=f;
00288 }
00289 }
00290
00291
00292
00293 template <class T>
00294 inline void CQuatT<T>::setAngleAxis(const CVector &axis, float angle)
00295 {
00296 CVector v= axis;
00297 v.normalize();
00298 double ca= cos(angle/2);
00299 double sa= sin(angle/2);
00300 x= (T)(v.x*sa);
00301 y= (T)(v.y*sa);
00302 z= (T)(v.z*sa);
00303 w= (T)(ca);
00304 }
00305
00306
00307
00308 template <class T>
00309 T CQuatT<T>::dotProduct(const CQuatT<T> &q0, const CQuatT<T> &q1)
00310 {
00311 return q0.x*q1.x + q0.y*q1.y + q0.z*q1.z + q0.w*q1.w;
00312 }
00313
00314
00315
00316 template <class T>
00317 CQuatT<T> CQuatT<T>::slerp(const CQuatT<T>& q0, const CQuatT<T>& q1, float t)
00318 {
00319
00320 double omega, cosom,sinom;
00321 T factq0= 1;
00322 T s0,s1;
00323
00324 cosom = CQuatT<T>::dotProduct(q0, q1);
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 if ( cosom < 1.0 - NLMISC::QuatEpsilon)
00335 {
00336 omega = acos(cosom);
00337 sinom = sin(omega);
00338 s0 = (T) (sin((1.0f - t)*omega) / sinom);
00339 s1 = (T) (sin(t*omega) / sinom);
00340 }
00341 else
00342 {
00343
00344 s0 = (T)(1.0 - t);
00345 s1 = t;
00346 }
00347
00348 return q0*(factq0*s0) + q1*s1;
00349
00350 }
00351
00352
00353
00354 template <class T>
00355 CQuatT<T> CQuatT<T>::squad(const CQuatT<T>& q0, const CQuatT<T>& tgtQ0, const CQuatT<T>& tgtQ1, const CQuatT<T>& q1, float t)
00356 {
00357 return CQuatT<T>::slerp(
00358 CQuatT<T>::slerp(q0, q1, t),
00359 CQuatT<T>::slerp(tgtQ0, tgtQ1, t),
00360 2.f*(1.f-t)*t);
00361 }
00362
00363
00364
00365 template <class T>
00366 CQuatT<T> CQuatT<T>::squadrev(const CAngleAxis &rot, const CQuatT<T>& q0, const CQuatT<T>& tgtQ0, const CQuatT<T>& tgtQ1, const CQuatT<T>& q1, float t)
00367 {
00368 float s,v;
00369 float omega = rot.Angle* 0.5f;
00370 float nrevs = 0.0f;
00371 CQuatT<T> ret,qaxis,pp,qq;
00372
00373
00374
00375 if (omega<Pi-QuatEpsilon)
00376 {
00377 ret = CQuatT<T>::squad(q0,tgtQ0,tgtQ1,q1,t);
00378 return ret;
00379 }
00380
00381
00382
00383
00384
00385
00386 qaxis.set(rot.Axis.x, rot.Axis.y, rot.Axis.z, 0);
00387
00388
00389 nrevs= (float)(omega/Pi);
00390
00391 s = t*2*nrevs;
00392
00393
00394
00395 if (s < 1.0f)
00396 {
00397
00398 pp = q0*qaxis;
00399 ret = CQuatT<T>::squad(q0,tgtQ0,pp,pp,s);
00400 }
00401 else
00402 {
00403 v = s - (2.0f*nrevs - 1.0f);
00404 if( v <= 0.0f)
00405 {
00406
00407 while (s >= 2.0f) s -= 2.0f;
00408 pp = q0*qaxis;
00409
00410 ret = CQuatT<T>::slerp(q0,pp,s);
00411 }
00412 else
00413 {
00414
00415 qq = - q1*qaxis;
00416 ret= CQuatT<T>::squad(qq,qq,tgtQ1,q1,v);
00417 }
00418 }
00419
00420 return ret;
00421 }
00422
00423
00424
00425
00426 template <class T>
00427 CQuatT<T> CQuatT<T>::log()
00428 {
00429 double len;
00430 len = sqrt (x*x + y*y + z*z);
00431
00432 if (len < QuatEpsilon)
00433 return CQuatT<T>(0.f, 0.f, 0.f, 0.f);
00434 else
00435 {
00436 double div = (float) acos (w) / len;
00437 return CQuatT<T>( (T)(x*div), (T)(y*div), (T)(z*div), 0.f);
00438 }
00439
00440 }
00441
00442
00443
00444 template <class T>
00445 CQuatT<T> CQuatT<T>::exp()
00446 {
00447 double len;
00448 len = sqrt (x*x + y*y + z*z);
00449
00450 if (len < QuatEpsilon)
00451 return CQuatT<T>(0.f, 0.f, 0.f, 1.f);
00452 else
00453 {
00454 double len1 = sin(len) / len;
00455 return CQuatT<T>( (T)(x*len1), (T)(y*len1), (T)(z*len1), (T)cos(len));
00456 }
00457 }
00458
00459
00460
00461 template <class T>
00462 CQuatT<T> CQuatT<T>::lnDif(const CQuatT<T> &q0, const CQuatT<T> &q1)
00463 {
00464 CQuatT<T> dif = q0.inverted()*q1;
00465 dif.normalize();
00466
00467 return dif.log();
00468 }
00469
00470
00471
00472 template <class T>
00473 void CQuatT<T>::makeClosest(const CQuatT<T> &o)
00474 {
00475 if( dotProduct(*this, o) < 0 )
00476 *this= -(*this);
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00496 class CQuat : public CQuatT<float>
00497 {
00498 public:
00499 static const CQuat Identity;
00500
00502
00503 CQuat &operator=(const CQuatT<float> &o) {x=o.x; y=o.y; z=o.z; w=o.w; return *this;}
00504 CQuat(const CQuatT<float> &o) : CQuatT<float>(o) {}
00505 CQuat() {}
00506 CQuat(float X, float Y, float Z, float W) : CQuatT<float>(X,Y,Z,W) {}
00508 CQuat(const CVector &axis, float angle) : CQuatT<float>(axis, angle) {}
00510 CQuat(const CAngleAxis &aa) : CQuatT<float>(aa) {}
00511
00512
00513 };
00514
00515
00516
00523 class CQuatD : public CQuatT<double>
00524 {
00525 public:
00526 static const CQuatD Identity;
00527
00529
00530 CQuatD &operator=(const CQuatT<double> &o) {x=o.x; y=o.y; z=o.z; w=o.w; return *this;}
00531 CQuatD(const CQuatT<double> &o) : CQuatT<double>(o) {}
00532 CQuatD() {}
00533 CQuatD(double X, double Y, double Z, double W) : CQuatT<double>(X,Y,Z,W) {}
00535 CQuatD(const CVector &axis, float angle) : CQuatT<double>(axis, angle) {}
00537 CQuatD(const CAngleAxis &aa) : CQuatT<double>(aa) {}
00538
00539
00540
00542
00543 CQuatD(const CQuat &o) {x=o.x; y=o.y; z=o.z; w=o.w;}
00544 CQuatD &operator=(const CQuatT<float> &o) {x=o.x; y=o.y; z=o.z; w=o.w; return *this;}
00545 operator CQuat() const {return CQuat((float)x, (float)y, (float)z, (float)w);}
00546
00547
00548 };
00549
00550
00551
00552
00553
00554 }
00555
00556 #endif // NL_QUAT_H
00557