src/quat.cpp

Go to the documentation of this file.
00001 #include "quat.h"
00002 
00003 #define DELTA 0.00001
00004 
00005 void QUATERNION::LoadMultIdent()
00006 {
00007         w = 1.0f;
00008         x = y = z = 0.0f;
00009         cachematvalid = false;
00010 }
00011 
00012 QUATERNION::QUATERNION()
00013 {
00014         LoadMultIdent();
00015         cachematvalid = false;
00016 }
00017 
00018 float QUATERNION::Norm()
00019 {
00020         return sqrt(w*w+x*x+y*y+z*z);
00021 }
00022 
00023 void QUATERNION::Normalize()
00024 {
00025         cachematvalid = false;
00026         
00027         float len = Norm();
00028         w = w / len;
00029         x = x / len;
00030         y = y / len;
00031         z = z / len;
00032 }
00033 
00034 void QUATERNION::GetMat(float * destmat)
00035 {
00036         if (!cachematvalid)
00037         {
00038                 Normalize();
00039                 //NOTE:  We're assuming the quaternion is normalized here!
00040                 
00041                 float xx = x*x;
00042                 float xy = x*y;
00043                 float xz = x*z;
00044                 float xw = x*w;
00045                 
00046                 float yy = y*y;
00047                 float yz = y*z;
00048                 float yw = y*w;
00049                 
00050                 float zz = z*z;
00051                 float zw = z*w;
00052                 
00053                 destmat[0] = 1.0f - 2.0f*(yy+zz);
00054                 destmat[1] = 2.0f*(xy+zw);
00055                 destmat[2] = 2.0f*(xz-yw);
00056                 destmat[3] = 0;
00057                 
00058                 destmat[4] = 2.0f*(xy-zw);
00059                 destmat[5] = 1.0f-2.0f*(xx+zz);
00060                 destmat[6] = 2.0f*(yz+xw);
00061                 destmat[7] = 0;
00062                 
00063                 destmat[8] = 2.0f*(xz+yw);
00064                 destmat[9] = 2.0f*(yz-xw);
00065                 destmat[10] = 1.0f-2.0f*(xx+yy);
00066                 destmat[11] = 0;
00067                 
00068                 destmat[12] = 0;
00069                 destmat[13] = 0;
00070                 destmat[14] = 0;
00071                 destmat[15] = 1;
00072                 
00073                 //build cached matrix
00074                 for (int i = 0; i < 16; i++)
00075                 {
00076                         cachemat[i] = destmat[i];
00077                 }
00078                 cachematvalid = true;
00079         }
00080         else
00081         {
00082                 //send back the cached matrix
00083                 for (int i = 0; i < 16; i++)
00084                 {
00085                         destmat[i] = cachemat[i];
00086                 }
00087         }
00088         
00089         /*xx      = X * X;
00090     xy      = X * Y;
00091     xz      = X * Z;
00092     xw      = X * W;
00093 
00094     yy      = Y * Y;
00095     yz      = Y * Z;
00096     yw      = Y * W;
00097 
00098     zz      = Z * Z;
00099     zw      = Z * W;
00100 
00101     mat[0]  = 1 - 2 * ( yy + zz );
00102     mat[1]  =     2 * ( xy - zw );
00103     mat[2]  =     2 * ( xz + yw );
00104 
00105     mat[4]  =     2 * ( xy + zw );
00106     mat[5]  = 1 - 2 * ( xx + zz );
00107     mat[6]  =     2 * ( yz - xw );
00108 
00109     mat[8]  =     2 * ( xz - yw );
00110     mat[9]  =     2 * ( yz + xw );
00111     mat[10] = 1 - 2 * ( xx + yy );
00112 
00113     mat[3]  = mat[7] = mat[11 = mat[12] = mat[13] = mat[14] = 0;
00114     mat[15] = 1;*/
00115 }
00116 
00117 void QUATERNION::GetMat(GLdouble * destmat)
00118 {
00119         if (!cachematvalid)
00120         {
00121                 Normalize();
00122                 //NOTE:  We're assuming the quaternion is normalized here!
00123                 
00124                 GLdouble xx = x*x;
00125                 GLdouble xy = x*y;
00126                 GLdouble xz = x*z;
00127                 GLdouble xw = x*w;
00128                 
00129                 GLdouble yy = y*y;
00130                 GLdouble yz = y*z;
00131                 GLdouble yw = y*w;
00132                 
00133                 GLdouble zz = z*z;
00134                 GLdouble zw = z*w;
00135                 
00136                 destmat[0] = 1.0f - 2.0f*(yy+zz);
00137                 destmat[1] = 2.0f*(xy+zw);
00138                 destmat[2] = 2.0f*(xz-yw);
00139                 destmat[3] = 0;
00140                 
00141                 destmat[4] = 2.0f*(xy-zw);
00142                 destmat[5] = 1.0f-2.0f*(xx+zz);
00143                 destmat[6] = 2.0f*(yz+xw);
00144                 destmat[7] = 0;
00145                 
00146                 destmat[8] = 2.0f*(xz+yw);
00147                 destmat[9] = 2.0f*(yz-xw);
00148                 destmat[10] = 1.0f-2.0f*(xx+yy);
00149                 destmat[11] = 0;
00150                 
00151                 destmat[12] = 0;
00152                 destmat[13] = 0;
00153                 destmat[14] = 0;
00154                 destmat[15] = 1;
00155                 
00156                 //build cached matrix
00157                 for (int i = 0; i < 16; i++)
00158                 {
00159                         cachemat[i] = destmat[i];
00160                 }
00161                 cachematvalid = true;
00162         }
00163         else
00164         {
00165                 //send back the cached matrix
00166                 for (int i = 0; i < 16; i++)
00167                 {
00168                         destmat[i] = cachemat[i];
00169                 }
00170         }
00171 }
00172 
00173 void QUATERNION::GetAxisAngle(float * aangle)
00174 {
00175         //aangle is (angle of rotation, x, y, z)
00176         
00177         /*float scale = x*x+y*y+z*z;
00178         if (scale < 0.00001)
00179         {
00180                 aangle[0] = 0;
00181                 aangle[1] = 1;
00182                 aangle[2] = 0;
00183                 aangle[3] = 0;
00184         }
00185         else
00186         {
00187                 aangle[0] = 2*acos(w);
00188                 aangle[1] = x/scale;
00189                 aangle[2] = y/scale;
00190                 aangle[3] = z/scale;
00191         }*/
00192         
00193         
00194         /*float scale = x*x+y*y+z*z;
00195         
00196         float cos_angle  = w;
00197     aangle[0]      = acos( cos_angle ) * 2;
00198     float sin_angle  = sqrt( 1.0 - cos_angle * cos_angle );
00199 
00200 
00201     if ( fabs( sin_angle ) < 0.00005 )
00202       scale = 1.0f;
00203 
00204     aangle[1] = x/scale;
00205     aangle[2] = y/scale;
00206         aangle[3] = z/scale;*/
00207         
00208     GLfloat     len;
00209     GLfloat tx, ty, tz;
00210 
00211         // cache variables
00212         tx = x;
00213         ty = y;
00214         tz = z;
00215 
00216         len = tx * tx + ty * ty + tz * tz;
00217 
00218     if (len > DELTA) 
00219         {
00220                 aangle[1] = tx * (1.0f / len);
00221                 aangle[2] = ty * (1.0f / len);
00222                 aangle[3] = tz * (1.0f / len);
00223             aangle[0] = (GLfloat)(2.0 * acos(w));
00224     }
00225 
00226     else {
00227                 aangle[1] = 0.0;
00228                 aangle[2] = 0.0;
00229                 aangle[3] = 1.0;
00230             aangle[0] = 0.0;
00231     }
00232 }
00233 
00234 
00235 
00236 void QUATERNION::Multiply(QUATERNION quat2)
00237 {
00238         cachematvalid = false;
00239         
00240         //slow multiply
00241         float w2 = quat2.w;
00242         float x2 = quat2.x;
00243         float y2 = quat2.y;
00244         float z2 = quat2.z;
00245         w = w*w2 - x*x2 - y*y2 - z*z2;
00246         x = w*x2 + x*w2 + y*z2 - z*y2;
00247         y = w*y2 + y*w2 + z*x2 - x*z2;
00248         z = w*z2 + z*w2 + x*y2 - y*x2;
00249         
00250         /*//FAST multiply code
00251         float a = w;
00252         float b = x;
00253         float c = y;
00254         float d = z;
00255         float w2 = quat2.w;
00256         float x2 = quat2.x;
00257         float y2 = quat2.y;
00258         float z2 = quat2.z;
00259         
00260         float tmp_00, tmp_01, tmp_02, tmp_03, tmp_04, tmp_05, tmp_06, tmp_07, tmp_08, tmp_09;
00261         
00262         tmp_00 = (d - c) * (z2 - w2);
00263         tmp_01 = (a + b) * (x2 + y2);
00264         tmp_02 = (a - b) * (z2 + w2);
00265         tmp_03 = (c + d) * (x2 - y2);
00266         tmp_04 = (d - b) * (y2 - z2);
00267         tmp_05 = (d + b) * (y2 + z2);
00268         tmp_06 = (a + c) * (x2 - w2);
00269         tmp_07 = (a - c) * (x2 + w2);
00270         tmp_08 = tmp_05 + tmp_06 + tmp_07;
00271         tmp_09 = 0.5 * (tmp_04 + tmp_08);
00272         
00273         w = tmp_00 + tmp_09 - tmp_05;
00274         x = tmp_01 + tmp_09 - tmp_08;
00275         y = tmp_02 + tmp_09 - tmp_07;
00276         z = tmp_03 + tmp_09 - tmp_06;*/
00277 }
00278 
00279 void QUATERNION::PostMultiply(QUATERNION quat2)
00280 {
00281         cachematvalid = false;
00282         
00283         //slow multiply
00284         float w1 = quat2.w;
00285         float x1 = quat2.x;
00286         float y1 = quat2.y;
00287         float z1 = quat2.z;
00288         float w2 = w;
00289         float x2 = x;
00290         float y2 = y;
00291         float z2 = z;
00292         w = w1*w2 - x1*x2 - y1*y2 - z1*z2;
00293         x = w1*x2 + x1*w2 + y1*z2 - z1*y2;
00294         y = w1*y2 + y1*w2 + z1*x2 - x1*z2;
00295         z = w1*z2 + z1*w2 + x1*y2 - y1*x2;
00296         
00297         //FAST multiply code
00298         /*float a = quat2.w;
00299         float b = quat2.x;
00300         float c = quat2.y;
00301         float d = quat2.z;
00302         
00303         float tmp_00, tmp_01, tmp_02, tmp_03, tmp_04, tmp_05, tmp_06, tmp_07, tmp_08, tmp_09;
00304         
00305         tmp_00 = (d - c) * (z - w);
00306         tmp_01 = (a + b) * (x + y);
00307         tmp_02 = (a - b) * (z + w);
00308         tmp_03 = (c + d) * (x - y);
00309         tmp_04 = (d - b) * (y - z);
00310         tmp_05 = (d + b) * (y + z);
00311         tmp_06 = (a + c) * (x - w);
00312         tmp_07 = (a - c) * (x + w);
00313         tmp_08 = tmp_05 + tmp_06 + tmp_07;
00314         tmp_09 = 0.5 * (tmp_04 + tmp_08);
00315         
00316         w = tmp_00 + tmp_09 - tmp_05;
00317         x = tmp_01 + tmp_09 - tmp_08;
00318         y = tmp_02 + tmp_09 - tmp_07;
00319         z = tmp_03 + tmp_09 - tmp_06;*/
00320 }
00321 
00322 QUATERNION QUATERNION::operator* (const QUATERNION &quat2 )
00323 {
00324         //below line stays true since we're not actually modifying our current quat
00325         //cachematvalid = false;
00326         
00327         QUATERNION qout;
00328         
00329         //slow multiply
00330         float w2 = quat2.w;
00331         float x2 = quat2.x;
00332         float y2 = quat2.y;
00333         float z2 = quat2.z;
00334         qout.w = w*w2 - x*x2 - y*y2 - z*z2;
00335         qout.x = w*x2 + x*w2 + y*z2 - z*y2;
00336         qout.y = w*y2 + y*w2 + z*x2 - x*z2;
00337         qout.z = w*z2 + z*w2 + x*y2 - y*x2;
00338                 
00339         return qout;
00340 }
00341 
00342 //i believe a is in radians
00343 void QUATERNION::SetAxisAngle(float a, float ax, float ay, float az)
00344 {
00345         cachematvalid = false;
00346         
00347         //normalize axis
00348         float temp = ax*ax + ay*ay + az*az;
00349     float dist = (GLfloat)(1.0 / sqrt(temp));
00350 
00351     ax *= dist;
00352     ay *= dist;
00353     az *= dist;
00354         
00355         /*if (ax < 0.00001 && ay < 0.00001 && az < 0.00001)
00356         {
00357                 LoadMultIdent();
00358         }
00359         else*/
00360         {
00361                 float sina2 = sin(a/2);
00362                 
00363                 w   =   cos(a/2);
00364                 x   =   ax * sina2;
00365                 y   =   ay * sina2;
00366                 z   =   az * sina2;
00367         }
00368         
00369         
00370         /*GLfloat temp, dist;
00371 
00372         // normalize
00373         temp = ax*ax + ay*ay + az*az;
00374 
00375     dist = (GLfloat)(1.0 / sqrt(temp));
00376 
00377     ax *= dist;
00378     ay *= dist;
00379     az *= dist;
00380 
00381         x = ax;
00382         y = ay;
00383         z = az;
00384 
00385         w = (GLfloat)cos(a / 2.0f);*/
00386         
00387 }
00388 
00389 void QUATERNION::SetEuler(float a, float b, float c)
00390 {
00391         cachematvalid = false;
00392         
00393         QUATERNION qout;
00394         
00395     QUATERNION Qx, Qy, Qz;
00396         Qx.w = cos(a/2); Qx.x = sin(a/2); Qx.y = Qx.z = 0.0f;
00397     Qy.w = cos(b/2); Qy.x = Qy.z = 0.0f; Qy.y = sin(b/2);
00398     Qz.w = cos(c/2); Qz.x = Qz.y = 0.0f; Qz.z = sin(c/2);
00399 
00400         qout = Qx * Qy * Qz;
00401         
00402         *this = qout;
00403 }
00404 
00405 QUATERNION QUATERNION::ReturnConjugate()
00406 {
00407         QUATERNION qtemp;
00408         qtemp.w = w;
00409         qtemp.x = -x;
00410         qtemp.y = -y;
00411         qtemp.z = -z;
00412         return qtemp;
00413 }
00414 
00415 void QUATERNION::LookAt(float eyeX, 
00416                    float eyeY, 
00417                    float eyeZ, 
00418                    float centerX, 
00419                    float centerY, 
00420                    float centerZ, 
00421                    float upX, 
00422                    float upY, 
00423                    float upZ)
00424 {
00425         float tempmat[16];
00426         
00427         glPushMatrix();
00428         glLoadIdentity();
00429         gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
00430         glGetFloatv(GL_MODELVIEW_MATRIX , tempmat);
00431         glPopMatrix();
00432         
00433         SetMat(tempmat);
00434 }
00435 
00436 void QUATERNION::SetMat(float * mat)
00437 {
00438         float S;
00439         
00440         float T = 1 + mat[0] + mat[5] + mat[10];
00441         if ( T > 0.00000001 )
00442         {
00443                 S = sqrt(T) * 2;
00444                 x = ( mat[9] - mat[6] ) / S;
00445                 y = ( mat[2] - mat[8] ) / S;
00446                 z = ( mat[4] - mat[1] ) / S;
00447                 w = 0.25 * S;
00448         }
00449         else
00450         {
00451                 if ( mat[0] > mat[5] && mat[0] > mat[10] )  {       // Column 0: 
00452                         S  = sqrt( 1.0 + mat[0] - mat[5] - mat[10] ) * 2;
00453                         x = 0.25 * S;
00454                         y = (mat[4] + mat[1] ) / S;
00455                         z = (mat[2] + mat[8] ) / S;
00456                         w = (mat[9] - mat[6] ) / S;
00457                 } else if ( mat[5] > mat[10] ) {                    // Column 1: 
00458                         S  = sqrt( 1.0 + mat[5] - mat[0] - mat[10] ) * 2;
00459                         x = (mat[4] + mat[1] ) / S;
00460                         y = 0.25 * S;
00461                         z = (mat[9] + mat[6] ) / S;
00462                         w = (mat[2] - mat[8] ) / S;
00463                 } else {                                            // Column 2:
00464                         S  = sqrt( 1.0 + mat[10] - mat[0] - mat[5] ) * 2;
00465                         x = (mat[2] + mat[8] ) / S;
00466                         y = (mat[9] + mat[6] ) / S;
00467                         z = 0.25 * S;
00468                         w = (mat[4] - mat[1] ) / S;
00469                 }
00470         }
00471 }
00472 
00473 /*void QUATERNION::SetMat(float * m1)
00474 {
00475         w = sqrt(1.0 + m1[0] + m1[5] + m1[10]) / 2.0;
00476         double w4 = (4.0 * w);
00477         x = (m1[9] - m1[6]) / w4 ;
00478         y = (m1[2] - m1[8]) / w4 ;
00479         z = (m1[4] - m1[1]) / w4 ;
00480 }*/
00481 
00482 VERTEX QUATERNION::RotateVec(VERTEX vec)
00483 {
00484         QUATERNION dirconj;
00485         
00486         QUATERNION dir;
00487         dir.w = w;
00488         dir.x = x;
00489         dir.y = y;
00490         dir.z = z;
00491 
00492         dirconj = dir.ReturnConjugate();
00493         QUATERNION qtemp;
00494         qtemp.w = 0;
00495         qtemp.x = vec.x;
00496         qtemp.y = vec.y;
00497         qtemp.z = vec.z;
00498         QUATERNION qout;
00499         qout = dir * qtemp * dirconj;
00500         
00501         VERTEX vout;
00502         
00503         vout.x += qout.x;
00504         vout.y += qout.y;
00505         vout.z += qout.z;
00506         
00507         return vout;
00508 }
00509 
00510 float QUATERNION::GetAngleBetween(QUATERNION quat2)
00511 {
00512         //establish a forward vector
00513         VERTEX forward;
00514         forward.x = 0;
00515         forward.y = 0;
00516         forward.z = 1;
00517         
00518         //create vectors for quats
00519         VERTEX vec1, vec2;
00520         vec1 = RotateVec(forward);
00521         vec2 = quat2.RotateVec(forward);
00522         
00523         //return the angle between the vectors
00524         return acos(vec1.dot(vec2));
00525 }
00526 
00527 VERTEX QUATERNION::GetEuler()
00528 {
00529         VERTEX vout;
00530         QUATERNION q1 = *this;
00531         
00532         float sqw = q1.w*q1.w;
00533     float sqx = q1.x*q1.x;
00534     float sqy = q1.y*q1.y;
00535     float sqz = q1.z*q1.z;
00536         
00537     vout.z = atan(2.0 * (q1.x*q1.y + q1.z*q1.w)/(sqx - sqy - sqz + sqw));
00538     vout.x = atan(2.0 * (q1.y*q1.z + q1.x*q1.w)/(-sqx - sqy + sqz + sqw));
00539     vout.y = asin(-2.0 * (q1.x*q1.z - q1.y*q1.w));
00540         
00541         return vout;
00542 }
00543 
00544 QUATERNION QUATERNION::Slerp(QUATERNION quat2, float t)
00545 {
00546         QUATERNION qout, p1, p2;
00547         float theta = GetAngleBetween(quat2);
00548         
00549         //qout = (*this).MultScalar(sin((1.0f-t)*theta)).Add(quat2.MultScalar(sin(t*theta))).MultScalar(1.0f/sin(theta));
00550         
00551         p1 = (*this).MultScalar((sin((1.0f-t)*theta))/sin(theta));
00552         p2 = quat2.MultScalar(sin(theta*t)/sinh(theta));
00553         qout = p1.Add(p2);
00554         
00555         
00556         return qout;
00557 }
00558 
00559 QUATERNION QUATERNION::Add(QUATERNION quat2)
00560 {
00561         QUATERNION qout;
00562         
00563         qout.w = w + quat2.w;
00564         qout.x = x + quat2.x;
00565         qout.y = y + quat2.y;
00566         qout.z = z + quat2.z;
00567         
00568         return qout;
00569 }
00570 
00571 QUATERNION QUATERNION::MultScalar(float scalar)
00572 {
00573         QUATERNION qout;
00574         
00575         qout.w = w * scalar;
00576         qout.x = x * scalar;
00577         qout.y = y * scalar;
00578         qout.z = z * scalar;
00579         
00580         return qout;
00581 }
00582 
00583 QUATERNION QUATERNION::QuatSlerp(QUATERNION quat2, float t)
00584 {
00585         float           to1[4];
00586         float        omega, cosom, sinom, scale0, scale1;
00587 
00588 
00589         // calc cosine
00590         cosom = x * quat2.x + y * quat2.y + z * quat2.z
00591                            + w * quat2.w;
00592 
00593 
00594         // adjust signs (if necessary)
00595         if ( cosom <0.0 ){ cosom = -cosom; to1[0] = - quat2.x;
00596         to1[1] = - quat2.y;
00597         to1[2] = - quat2.z;
00598         to1[3] = - quat2.w;
00599         } else  {
00600         to1[0] = quat2.x;
00601         to1[1] = quat2.y;
00602         to1[2] = quat2.z;
00603         to1[3] = quat2.w;
00604         }
00605 
00606 
00607         // calculate coefficients
00608 
00609 
00610    if ( (1.0 - cosom) > DELTA ) {
00611                         // standard case (slerp)
00612                         omega = acos(cosom);
00613                         sinom = sin(omega);
00614                         scale0 = sin((1.0 - t) * omega) / sinom;
00615                         scale1 = sin(t * omega) / sinom;
00616 
00617 
00618         } else {        
00619 // "from" and "to" quaternions are very close 
00620         //  ... so we can do a linear interpolation
00621                         scale0 = 1.0 - t;
00622                         scale1 = t;
00623         }
00624         // calculate final values
00625         QUATERNION qout;
00626         qout.x = scale0 * x + scale1 * to1[0];
00627         qout.y = scale0 * y + scale1 * to1[1];
00628         qout.z = scale0 * z + scale1 * to1[2];
00629         qout.w = scale0 * w + scale1 * to1[3];
00630         return qout;
00631 }
00632 
00633 //i was getting angry because the quats couldn't do this, so i added it....
00634 void QUATERNION::Rotate(float a, float ax, float ay, float az)
00635 {
00636         //NOTE: ax, ay, az is assumed to be a UNIT VECTOR!!
00637         
00638         QUATERNION qtemp;
00639         qtemp.SetAxisAngle(a, ax, ay, az);
00640         PostMultiply(qtemp);
00641 }
00642 
00643 void QUATERNION::DebugPrint()
00644 {
00645         cout << x << "," << y << "," << z << "," << w << endl;
00646 }
00647 
00648 VERTEX VERTEX::operator+ (VERTEX v)
00649 {
00650         VERTEX result;
00651         
00652         result.x = x + v.x;
00653         result.y = y + v.y;
00654         result.z = z + v.z;
00655         
00656         return result;
00657 }
00658 
00659 VERTEX VERTEX::operator- (VERTEX v)
00660 {
00661         VERTEX result;
00662         
00663         result.x = x - v.x;
00664         result.y = y - v.y;
00665         result.z = z - v.z;
00666         
00667         return result;
00668 }
00669 
00670 void VERTEX::Set(float nx, float ny, float nz)
00671 {
00672         x = nx;
00673         y = ny;
00674         z = nz;
00675 }
00676 
00677 float VERTEX::len()
00678 {
00679         //optimization!
00680         if (x == 0 && y == 0 && z == 0)
00681                 return 0;
00682         
00683         float sl = x*x+y*y+z*z;
00684         
00685         if (sl < 0)
00686         {
00687                 ofstream err((settings.GetSettingsDir() + "/logs/vertex.log").c_str());
00688                 err << x << endl << y << endl << z << endl << sl << endl;
00689                 err.close();
00690                 assert(0);
00691         }
00692         else if (sl >=0 )
00693         {       
00694                 return sqrt(sl);
00695         }
00696         else
00697         {
00698                 //last ditch effort to fix the problem
00699                 if (!(x < 0 || x >= 0))
00700                         x = 1;
00701                 if (!(y < 0 || y >= 0))
00702                         y = 1;
00703                 if (!(z < 0 || z >= 0))
00704                         z = 1;
00705                 sl = x*x+y*y+z*z;
00706                 
00707                 if (!(sl >= 0))
00708                 {
00709                         ofstream err((settings.GetSettingsDir() + "/logs/vertex.log").c_str());
00710                         err << x << endl << y << endl << z << endl << sl << endl;
00711                         err.close();
00712                         assert(0);
00713                         return 0;
00714                 }
00715                 else
00716                         return sqrt(sl);
00717         }
00718 }
00719 
00720 VERTEX VERTEX::cross(VERTEX b)
00721 {
00722         VERTEX result;
00723 
00724         result.x = y*b.z - z*b.y;
00725         //result.y = x*b.z - z*b.x;
00726         result.y = z*b.x - x*b.z;
00727         result.z = x*b.y - y*b.x;
00728 
00729         return result;
00730 }
00731 
00732 VERTEX VERTEX::normalize()
00733 {
00734         VERTEX new_vec;
00735         float vec_len = len();
00736         
00737         if (vec_len == 0.0f)
00738         {
00739                 new_vec.x = 0.0f;
00740                 new_vec.y = 0.0f;
00741                 new_vec.z = 0.0f;
00742                 return new_vec;
00743         }
00744         
00745         float inv_vec_len = 1.0f/vec_len;
00746 
00747         new_vec.x = x*inv_vec_len;
00748         new_vec.y = y*inv_vec_len;
00749         new_vec.z = z*inv_vec_len;
00750 
00751         return new_vec;
00752 }
00753 
00754 VERTEX::VERTEX()
00755 {
00756         x = y = z = 0.0f;
00757 }
00758 
00759 void VERTEX::Scale(float scalar)
00760 {
00761         x = x*scalar;
00762         y = y*scalar;
00763         z = z*scalar;
00764 }
00765 
00766 VERTEX VERTEX::ScaleR(float scalar)
00767 {
00768         VERTEX result;
00769         
00770         result.x = x*scalar;
00771         result.y = y*scalar;
00772         result.z = z*scalar;
00773         
00774         return result;
00775 }
00776 
00777 VERTEX VERTEX::InvertR()
00778 {
00779         VERTEX result;
00780         
00781         result.x = -x;
00782         result.y = -y;
00783         result.z = -z;
00784         
00785         return result;
00786 }
00787 
00788 float VERTEX::dot(VERTEX b)
00789 {
00790         return x*b.x + y*b.y + z*b.z;
00791 }
00792 
00793 VERTEX VERTEX::interpolatewith(VERTEX other, float percent)
00794 {
00795         VERTEX vout;
00796         
00797         vout.x = (other.x - x)*percent + x;
00798         vout.y = (other.y - y)*percent + y;
00799         vout.z = (other.z - z)*percent + z;
00800         
00801         return vout;
00802 }
00803 
00804 float * VERTEX::v3()
00805 {
00806         float3[0] = x;
00807         float3[1] = y;
00808         float3[2] = z;
00809         
00810         return float3;
00811 }
00812 
00813 void VERTEX::DebugPrint(ostream & out)
00814 {
00815         out << x << "," << y << "," << z << endl;
00816 }
00817 
00818 void VERTEX::zero()
00819 {
00820         x = y = z = 0.0f;
00821 }
00822 
00823 void VERTEX::Set(float * f3)
00824 {
00825         x = f3[0];
00826         y = f3[1];
00827         z = f3[2];
00828 }
00829 
00830 bool VERTEX::nan()
00831 {
00832         if (!(x < 0 || x >= 0) || !(y < 0 || y >= 0) || !(z < 0 || z >= 0))
00833                 return true;
00834         
00835         return false;
00836 }
00837 
00838 bool VERTEX::equals(VERTEX other)
00839 {
00840         return (x == other.x && y == other.y && z == other.z);
00841 }
00842 
00843 VERTEX QUATERNION::RelativeMove(VERTEX input)
00844 {
00845         QUATERNION dirconj, dir;
00846         VERTEX position;
00847 
00848         dirconj = ReturnConjugate();
00849         dir.w = w;
00850         dir.x = x;
00851         dir.y = y;
00852         dir.z = z;
00853         QUATERNION qtemp;
00854         qtemp.w = 0;
00855         qtemp.x = input.x;
00856         qtemp.y = input.y;
00857         qtemp.z = input.z;
00858         QUATERNION qout;
00859         qout = dirconj * qtemp * dir;
00860         
00861         position.x = qout.x;
00862         position.y = qout.y;
00863         position.z = qout.z;
00864         return position;
00865 }
00866 
00867 void MATRIX3::ProjectionMatrix(VERTEX normal)
00868 {
00869         float a = normal.x;
00870         float b = normal.y;
00871         float c = normal.z;
00872         
00873         row[0].x = b*b+c*c;
00874         row[0].y = -a*b;
00875         row[0].z = -a*c;
00876         
00877         row[1].x = -b*a;
00878         row[1].y = a*a+c*c;
00879         row[1].z = -b*c;
00880         
00881         row[2].x = -c*a;
00882         row[2].y = -c*b;
00883         row[2].z = a*a+b*b;
00884 }
00885 
00886 VERTEX MATRIX3::Multiply(VERTEX vert)
00887 {
00888         VERTEX out;
00889         
00890         /*out.zero();
00891         out.x += row[0].x*vert.x;
00892         out.x += row[0].y*vert.y;
00893         out.x += row[0].z*vert.z;*/
00894         
00895         out.x = row[0].dot(vert);
00896         out.y = row[1].dot(vert);
00897         out.z = row[2].dot(vert);
00898         
00899         return out;
00900 }
00901 
00902 //---------- VERTEXD
00903 VERTEXD VERTEXD::operator+ (VERTEXD v)
00904 {
00905         VERTEXD result;
00906         
00907         result.x = x + v.x;
00908         result.y = y + v.y;
00909         result.z = z + v.z;
00910         
00911         return result;
00912 }
00913 
00914 VERTEXD VERTEXD::operator- (VERTEXD v)
00915 {
00916         VERTEXD result;
00917         
00918         result.x = x - v.x;
00919         result.y = y - v.y;
00920         result.z = z - v.z;
00921         
00922         return result;
00923 }
00924 
00925 void VERTEXD::Set(double nx, double ny, double nz)
00926 {
00927         x = nx;
00928         y = ny;
00929         z = nz;
00930 }
00931 
00932 double VERTEXD::len()
00933 {
00934         //optimization!
00935         if (x == 0 && y == 0 && z == 0)
00936                 return 0;
00937         
00938         double sl = x*x+y*y+z*z;
00939         
00940         if (sl < 0)
00941         {
00942                 ofstream err((settings.GetSettingsDir() + "/logs/vertex.log").c_str());
00943                 err << x << endl << y << endl << z << endl << sl << endl;
00944                 err.close();
00945                 assert(0);
00946         }
00947         else if (sl >=0 )
00948         {       
00949                 return sqrt(sl);
00950         }
00951         else
00952         {
00953                 //last ditch effort to fix the problem
00954                 if (!(x < 0 || x >= 0))
00955                         x = 1;
00956                 if (!(y < 0 || y >= 0))
00957                         y = 1;
00958                 if (!(z < 0 || z >= 0))
00959                         z = 1;
00960                 sl = x*x+y*y+z*z;
00961                 
00962                 if (!(sl >= 0))
00963                 {
00964                         ofstream err((settings.GetSettingsDir() + "/logs/vertex.log").c_str());
00965                         err << x << endl << y << endl << z << endl << sl << endl;
00966                         err.close();
00967                         assert(0);
00968                         return 0;
00969                 }
00970                 else
00971                         return sqrt(sl);
00972         }
00973 }
00974 
00975 VERTEXD VERTEXD::cross(VERTEXD b)
00976 {
00977         VERTEXD result;
00978 
00979         result.x = y*b.z - z*b.y;
00980         //result.y = x*b.z - z*b.x;
00981         result.y = z*b.x - x*b.z;
00982         result.z = x*b.y - y*b.x;
00983 
00984         return result;
00985 }
00986 
00987 VERTEXD VERTEXD::normalize()
00988 {
00989         VERTEXD new_vec;
00990         double vec_len = len();
00991         
00992         if (vec_len == 0.0f)
00993         {
00994                 new_vec.x = 0.0f;
00995                 new_vec.y = 0.0f;
00996                 new_vec.z = 0.0f;
00997                 return new_vec;
00998         }
00999 
01000         new_vec.x = x/vec_len;
01001         new_vec.y = y/vec_len;
01002         new_vec.z = z/vec_len;
01003 
01004         return new_vec;
01005 }
01006 
01007 VERTEXD::VERTEXD()
01008 {
01009         x = y = z = 0.0f;
01010 }
01011 
01012 void VERTEXD::Scale(double scalar)
01013 {
01014         x = x*scalar;
01015         y = y*scalar;
01016         z = z*scalar;
01017 }
01018 
01019 VERTEXD VERTEXD::ScaleR(double scalar)
01020 {
01021         VERTEXD result;
01022         
01023         result.x = x*scalar;
01024         result.y = y*scalar;
01025         result.z = z*scalar;
01026         
01027         return result;
01028 }
01029 
01030 VERTEXD VERTEXD::InvertR()
01031 {
01032         VERTEXD result;
01033         
01034         result.x = -x;
01035         result.y = -y;
01036         result.z = -z;
01037         
01038         return result;
01039 }
01040 
01041 double VERTEXD::dot(VERTEXD b)
01042 {
01043         return x*b.x + y*b.y + z*b.z;
01044 }
01045 
01046 VERTEXD VERTEXD::interpolatewith(VERTEXD other, double percent)
01047 {
01048         VERTEXD vout;
01049         
01050         vout.x = (other.x - x)*percent + x;
01051         vout.y = (other.y - y)*percent + y;
01052         vout.z = (other.z - z)*percent + z;
01053         
01054         return vout;
01055 }
01056 
01057 double * VERTEXD::v3()
01058 {
01059         double3[0] = x;
01060         double3[1] = y;
01061         double3[2] = z;
01062         
01063         return double3;
01064 }
01065 
01066 void VERTEXD::DebugPrint()
01067 {
01068         cout << x << "," << y << "," << z << endl;
01069 }
01070 
01071 void VERTEXD::zero()
01072 {
01073         x = y = z = 0.0f;
01074 }
01075 
01076 void VERTEXD::Set(double * f3)
01077 {
01078         x = f3[0];
01079         y = f3[1];
01080         z = f3[2];
01081 }
01082 
01083 void VERTEXD::Set(float * f3)
01084 {
01085         x = f3[0];
01086         y = f3[1];
01087         z = f3[2];
01088 }
01089 
01090 bool VERTEXD::nan()
01091 {
01092         if (!(x < 0 || x >= 0) || !(y < 0 || y >= 0) || !(z < 0 || z >= 0))
01093                 return true;
01094         
01095         return false;
01096 }
01097 
01098 VERTEXD::VERTEXD(VERTEX other)
01099 {
01100         x = other.x;
01101         y = other.y;
01102         z = other.z;
01103 }
01104 
01105 VERTEXD& VERTEXD:: operator= (const VERTEX & other)
01106 {
01107         x = other.x;
01108         y = other.y;
01109         z = other.