00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef CQuaternionH
00023 #define CQuaternionH
00024
00025 #include "CMatrix3d.h"
00026 #include "CVector3d.h"
00027
00028
00029
00037
00038
00039
00048
00049 struct cQuaternion
00050 {
00051 public:
00052
00053
00054
00055
00057 double w;
00058
00060 double x;
00061
00063 double y;
00064
00066 double z;
00067
00068
00069
00070
00071
00073 cQuaternion() {}
00074
00076 cQuaternion(double nw, double nx, double ny, double nz) : w(nw), x(nx), y(ny), z(nz) {}
00077
00079 cQuaternion(double const* in) : w(in[0]), x(in[1]), y(in[2]), z(in[3]) {}
00080
00081
00082
00083
00084
00086 operator double*() {return &w;}
00087
00089 operator double const*() const { return &w;}
00090
00092 void zero() { w=0.0; x=0.0; y=0.0; z=0.0; }
00093
00095 void negate() { w=-w; x=-x; y=-y; z=-z; }
00096
00098 double magsq() const { return (w*w) + (x*x) + (y*y) + (z*z); }
00099
00101 double lengthsq() const { return magsq(); }
00102
00104 double mag() const { return sqrt(magsq()); }
00105
00107 double length() const { return mag(); }
00108
00110 void normalize()
00111 {
00112 double m = mag();
00113 w /= m;
00114 x /= m;
00115 y /= m;
00116 z /= m;
00117 }
00118
00119
00121
00124
00125 void toRotMat(cMatrix3d& a_mat) const
00126 {
00127 double x2 = 2.0*x*x;
00128 double y2 = 2.0*y*y;
00129 double z2 = 2.0*z*z;
00130 double xy = 2.0*x*y;
00131 double wz = 2.0*w*z;
00132 double xz = 2.0*x*z;
00133 double wy = 2.0*w*y;
00134 double yz = 2.0*y*z;
00135 double wx = 2.0*w*x;
00136
00137 a_mat.m[0][0] = 1.0 - y2 - z2;
00138 a_mat.m[0][1] = xy - wz;
00139 a_mat.m[0][2] = xz + wy;
00140 a_mat.m[1][0] = xy + wz;
00141 a_mat.m[1][1] = 1.0 - x2 - z2;
00142 a_mat.m[1][2] = yz - wx;
00143 a_mat.m[2][0] = xz - wy;
00144 a_mat.m[2][1] = yz + wx;
00145 a_mat.m[2][2] = 1.0 - x2 - y2;
00146 }
00147
00148
00149
00155
00156 void fromRotMat(cMatrix3d const& a_mat)
00157 {
00158 double trace = 1.0 + a_mat[0][0] + a_mat[1][1] + a_mat[2][2];
00159
00160 if (trace>0.00000001) {
00161 double s = 2.0*sqrt(trace);
00162 x = (a_mat[2][1] - a_mat[1][2])/s;
00163 y = (a_mat[0][2] - a_mat[2][0])/s;
00164 z = (a_mat[1][0] - a_mat[0][1])/s;
00165 w = 0.25*s;
00166 } else if ((a_mat[0][0] > a_mat[1][1]) && (a_mat[0][0] > a_mat[2][2])) {
00167
00168 double s = 2.0*sqrt(1.0+a_mat[0][0]-a_mat[1][1]-a_mat[2][2]);
00169 x = 0.25*s;
00170 y = (a_mat[1][0] + a_mat[0][1])/s;
00171 z = (a_mat[0][2] + a_mat[2][0])/s;
00172 w = (a_mat[2][1] - a_mat[1][2])/s;
00173 } else if (a_mat[1][1] > a_mat[2][2]) {
00174
00175 double s = 2.0*sqrt(1.0+a_mat[1][1]-a_mat[0][0]-a_mat[2][2]);
00176 x = (a_mat[1][0] + a_mat[0][1])/s;
00177 y = 0.25*s;
00178 z = (a_mat[2][1] + a_mat[1][2])/s;
00179 w = (a_mat[0][2] - a_mat[2][0])/s;
00180 } else {
00181
00182 double s = 2.0*sqrt(1.0+a_mat[2][2]-a_mat[0][0]-a_mat[1][1]);
00183 x = (a_mat[0][2] + a_mat[2][0])/s;
00184 y = (a_mat[2][1] + a_mat[1][2])/s;
00185 z = 0.25*s;
00186 w = (a_mat[1][0] - a_mat[0][1])/s;
00187 }
00188 }
00189
00190
00191
00198
00199 void fromAxisAngle(cVector3d a_axis, double a_angle)
00200 {
00201
00202 a_axis.normalize();
00203 double sina = sin(a_angle/2.0);
00204 double cosa = cos(a_angle/2.0);
00205 w = cosa;
00206 x = a_axis[0]*sina;
00207 y = a_axis[1]*sina;
00208 z = a_axis[2]*sina;
00209 }
00210
00211
00212
00219
00220 void toAxisAngle(cVector3d& a_axis, double& a_angle) const
00221 {
00222 double cosa = w/mag();
00223 a_angle = acos(cosa);
00224 a_axis[0] = x;
00225 a_axis[1] = y;
00226 a_axis[2] = z;
00227 }
00228
00230 void conj()
00231 {
00232 x = -x;
00233 y = -y;
00234 z = -z;
00235 }
00236
00238 void invert()
00239 {
00240 double m2 = magsq();
00241 w = w/m2;
00242 x = -x/m2;
00243 y = -y/m2;
00244 z = -z/m2;
00245 }
00246
00248 cQuaternion& operator*= (cQuaternion const& a_otherQ)
00249 {
00250 double neww = w*a_otherQ.w - x*a_otherQ.x - y*a_otherQ.y - z*a_otherQ.z;
00251 double newx = w*a_otherQ.x + x*a_otherQ.w + y*a_otherQ.z - z*a_otherQ.y;
00252 double newy = w*a_otherQ.y - x*a_otherQ.z + y*a_otherQ.w + z*a_otherQ.x;
00253 double newz = w*a_otherQ.z + x*a_otherQ.y - y*a_otherQ.x + z*a_otherQ.w;
00254 w = neww;
00255 x = newx;
00256 y = newy;
00257 z = newz;
00258
00259 return *this;
00260 }
00261
00262
00263
00270
00271 void mul(cQuaternion const& a_otherQ)
00272 {
00273 operator*=(a_otherQ);
00274 }
00275
00276
00278 cQuaternion& operator*= (double a_scale)
00279 {
00280 w *= a_scale; x *= a_scale; y *= a_scale; z *= a_scale;
00281 return *this;
00282 }
00283
00285 void mul(double s)
00286 {
00287 operator*=(s);
00288 }
00289
00291 bool operator==(cQuaternion const& a_otherQ) const
00292 {
00293 return (w==a_otherQ.w && x==a_otherQ.x && y==a_otherQ.y && z==a_otherQ.z);
00294 }
00295
00296
00304
00305 double dot(cQuaternion const& a_otherQ) const
00306 {
00307 return (w*a_otherQ.w + x*a_otherQ.x + y*a_otherQ.y + z*a_otherQ.z);
00308 }
00309
00311 cQuaternion& operator+= (cQuaternion const& a_otherQ)
00312 {
00313 w+=a_otherQ.w; x+=a_otherQ.x; y+=a_otherQ.y; z+=a_otherQ.z;
00314 return *this;
00315 }
00316
00317
00324
00325 void add(cQuaternion const& a_otherQ)
00326 {
00327 operator+=(a_otherQ);
00328 }
00329
00330
00340
00341 void slerp(double a_level, cQuaternion const& a_q1, cQuaternion a_q2)
00342 {
00343
00344
00345 double costheta = a_q1.dot(a_q2);
00346 if ((costheta-1.0) < 1e-4 && (costheta-1.0) > -1e-4)
00347 {
00348
00349
00350 *this = a_q1;
00351 this->mul(1.0-a_level);
00352 a_q2.mul(a_level);
00353 this->operator +=(a_q2);
00354 this->normalize();
00355 }
00356 else
00357 {
00358 double ratio1, ratio2;
00359 if ((costheta+1.0) > -1e-4 && (costheta+1.0) < 1e-4) {
00360
00361
00362 a_q2.w = a_q1.z;
00363 a_q2.x = -a_q1.y;
00364 a_q2.y = a_q1.x;
00365 a_q2.z = -a_q1.w;
00366 ratio1 = sin(CHAI_PI*(0.5-a_level));
00367 ratio2 = sin(CHAI_PI*a_level);
00368 } else {
00369 if (costheta < 0.0) {
00370 costheta = -costheta;
00371 a_q2.negate();
00372 }
00373 double theta = acos(costheta);
00374 double sintheta = sin(theta);
00375
00376 ratio1 = sin(theta*(1.0-a_level))/sintheta;
00377 ratio2 = sin(theta*a_level)/sintheta;
00378 }
00379 *this = a_q1;
00380 this->mul(ratio1);
00381 a_q2.mul(ratio2);
00382 this->operator +=(a_q2);
00383 }
00384 }
00385 };
00386
00387
00388
00389 #endif
00390