m3math.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 //#include "vmath.h"
00035 #include "v3math.h"
00036 #include "v3dmath.h"
00037 #include "v4math.h"
00038 #include "m4math.h"
00039 #include "m3math.h"
00040 #include "llquaternion.h"
00041 
00042 // LLMatrix3
00043 
00044 //              ji  
00045 // LLMatrix3 = |00 01 02 |
00046 //             |10 11 12 |
00047 //             |20 21 22 |
00048 
00049 // LLMatrix3 = |fx fy fz |  forward-axis
00050 //             |lx ly lz |  left-axis
00051 //             |ux uy uz |  up-axis
00052 
00053 
00054 // Constructors
00055 
00056 
00057 LLMatrix3::LLMatrix3(const LLQuaternion &q)
00058 {
00059         setRot(q);
00060 }
00061 
00062 
00063 LLMatrix3::LLMatrix3(const F32 angle, const LLVector3 &vec)
00064 {
00065         LLQuaternion    quat(angle, vec);
00066         setRot(quat);
00067 }
00068 
00069 LLMatrix3::LLMatrix3(const F32 angle, const LLVector3d &vec)
00070 {
00071         LLVector3 vec_f;
00072         vec_f.setVec(vec);
00073         LLQuaternion    quat(angle, vec_f);
00074         setRot(quat);
00075 }
00076 
00077 LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec)
00078 {
00079         LLQuaternion    quat(angle, vec);
00080         setRot(quat);
00081 }
00082 
00083 LLMatrix3::LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z)
00084 {
00085         LLVector3 vec(x, y, z);
00086         LLQuaternion    quat(angle, vec);
00087         setRot(quat);
00088 }
00089 
00090 LLMatrix3::LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw)
00091 {
00092         setRot(roll,pitch,yaw);
00093 }
00094 
00095 // From Matrix and Quaternion FAQ
00096 void LLMatrix3::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
00097 {
00098         F64 angle_x, angle_y, angle_z;
00099         F64 cx, cy, cz;                                 // cosine of angle_x, angle_y, angle_z
00100         F64 sx,     sz;                                 // sine of angle_x, angle_y, angle_z
00101 
00102         angle_y = asin(llclamp(mMatrix[2][0], -1.f, 1.f));
00103         cy = cos(angle_y);
00104 
00105         if (fabs(cy) > 0.005)           // non-zero
00106         {
00107                 // no gimbal lock
00108                 cx = mMatrix[2][2] / cy;
00109                 sx = - mMatrix[2][1] / cy;
00110 
00111                 angle_x = (F32) atan2(sx, cx);
00112 
00113                 cz = mMatrix[0][0] / cy;
00114                 sz = - mMatrix[1][0] / cy;
00115 
00116                 angle_z = (F32) atan2(sz, cz);
00117         }
00118         else
00119         {
00120                 // yup, gimbal lock
00121                 angle_x = 0;
00122 
00123                 // some tricky math thereby avoided, see article
00124 
00125                 cz = mMatrix[1][1];
00126                 sz = mMatrix[0][1];
00127 
00128                 angle_z = atan2(sz, cz);
00129         }
00130 
00131         *roll = (F32)angle_x;
00132         *pitch = (F32)angle_y;
00133         *yaw = (F32)angle_z;
00134 }
00135         
00136 
00137 // Clear and Assignment Functions
00138 
00139 const LLMatrix3&        LLMatrix3::setIdentity()
00140 {
00141         mMatrix[0][0] = 1.f;
00142         mMatrix[0][1] = 0.f;
00143         mMatrix[0][2] = 0.f;
00144 
00145         mMatrix[1][0] = 0.f;
00146         mMatrix[1][1] = 1.f;
00147         mMatrix[1][2] = 0.f;
00148 
00149         mMatrix[2][0] = 0.f;
00150         mMatrix[2][1] = 0.f;
00151         mMatrix[2][2] = 1.f;
00152         return (*this);
00153 }
00154 
00155 const LLMatrix3&        LLMatrix3::clear()
00156 {
00157         mMatrix[0][0] = 0.f;
00158         mMatrix[0][1] = 0.f;
00159         mMatrix[0][2] = 0.f;
00160 
00161         mMatrix[1][0] = 0.f;
00162         mMatrix[1][1] = 0.f;
00163         mMatrix[1][2] = 0.f;
00164 
00165         mMatrix[2][0] = 0.f;
00166         mMatrix[2][1] = 0.f;
00167         mMatrix[2][2] = 0.f;
00168         return (*this);
00169 }
00170 
00171 const LLMatrix3&        LLMatrix3::setZero()
00172 {
00173         mMatrix[0][0] = 0.f;
00174         mMatrix[0][1] = 0.f;
00175         mMatrix[0][2] = 0.f;
00176 
00177         mMatrix[1][0] = 0.f;
00178         mMatrix[1][1] = 0.f;
00179         mMatrix[1][2] = 0.f;
00180 
00181         mMatrix[2][0] = 0.f;
00182         mMatrix[2][1] = 0.f;
00183         mMatrix[2][2] = 0.f;
00184         return (*this);
00185 }
00186 
00187 // various useful mMatrix functions
00188 
00189 const LLMatrix3&        LLMatrix3::transpose() 
00190 {
00191         // transpose the matrix
00192         F32 temp;
00193         temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp;
00194         temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp;
00195         temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp;
00196         return *this;
00197 }
00198 
00199 
00200 F32             LLMatrix3::determinant() const
00201 {
00202         // Is this a useful method when we assume the matrices are valid rotation
00203         // matrices throughout this implementation?
00204         return  mMatrix[0][0] * (mMatrix[1][1] * mMatrix[2][2] - mMatrix[1][2] * mMatrix[2][1]) +
00205                         mMatrix[0][1] * (mMatrix[1][2] * mMatrix[2][0] - mMatrix[1][0] * mMatrix[2][2]) +
00206                         mMatrix[0][2] * (mMatrix[1][0] * mMatrix[2][1] - mMatrix[1][1] * mMatrix[2][0]); 
00207 }
00208 
00209 // inverts this matrix
00210 void LLMatrix3::invert()
00211 {
00212         // fails silently if determinant is zero too small
00213         F32 det = determinant();
00214         const F32 VERY_SMALL_DETERMINANT = 0.000001f;
00215         if (fabs(det) > VERY_SMALL_DETERMINANT)
00216         {
00217                 // invertiable
00218                 LLMatrix3 t(*this);
00219                 mMatrix[VX][VX] = ( t.mMatrix[VY][VY] * t.mMatrix[VZ][VZ] - t.mMatrix[VY][VZ] * t.mMatrix[VZ][VY] ) / det;
00220                 mMatrix[VY][VX] = ( t.mMatrix[VY][VZ] * t.mMatrix[VZ][VX] - t.mMatrix[VY][VX] * t.mMatrix[VZ][VZ] ) / det;
00221                 mMatrix[VZ][VX] = ( t.mMatrix[VY][VX] * t.mMatrix[VZ][VY] - t.mMatrix[VY][VY] * t.mMatrix[VZ][VX] ) / det;
00222                 mMatrix[VX][VY] = ( t.mMatrix[VZ][VY] * t.mMatrix[VX][VZ] - t.mMatrix[VZ][VZ] * t.mMatrix[VX][VY] ) / det;
00223                 mMatrix[VY][VY] = ( t.mMatrix[VZ][VZ] * t.mMatrix[VX][VX] - t.mMatrix[VZ][VX] * t.mMatrix[VX][VZ] ) / det;
00224                 mMatrix[VZ][VY] = ( t.mMatrix[VZ][VX] * t.mMatrix[VX][VY] - t.mMatrix[VZ][VY] * t.mMatrix[VX][VX] ) / det;
00225                 mMatrix[VX][VZ] = ( t.mMatrix[VX][VY] * t.mMatrix[VY][VZ] - t.mMatrix[VX][VZ] * t.mMatrix[VY][VY] ) / det;
00226                 mMatrix[VY][VZ] = ( t.mMatrix[VX][VZ] * t.mMatrix[VY][VX] - t.mMatrix[VX][VX] * t.mMatrix[VY][VZ] ) / det;
00227                 mMatrix[VZ][VZ] = ( t.mMatrix[VX][VX] * t.mMatrix[VY][VY] - t.mMatrix[VX][VY] * t.mMatrix[VY][VX] ) / det;
00228         }
00229 }
00230 
00231 // does not assume a rotation matrix, and does not divide by determinant, assuming results will be renormalized
00232 const LLMatrix3&        LLMatrix3::adjointTranspose()
00233 {
00234         LLMatrix3 adjoint_transpose;
00235         adjoint_transpose.mMatrix[VX][VX] = mMatrix[VY][VY] * mMatrix[VZ][VZ] - mMatrix[VY][VZ] * mMatrix[VZ][VY] ;
00236         adjoint_transpose.mMatrix[VY][VX] = mMatrix[VY][VZ] * mMatrix[VZ][VX] - mMatrix[VY][VX] * mMatrix[VZ][VZ] ;
00237         adjoint_transpose.mMatrix[VZ][VX] = mMatrix[VY][VX] * mMatrix[VZ][VY] - mMatrix[VY][VY] * mMatrix[VZ][VX] ;
00238         adjoint_transpose.mMatrix[VX][VY] = mMatrix[VZ][VY] * mMatrix[VX][VZ] - mMatrix[VZ][VZ] * mMatrix[VX][VY] ;
00239         adjoint_transpose.mMatrix[VY][VY] = mMatrix[VZ][VZ] * mMatrix[VX][VX] - mMatrix[VZ][VX] * mMatrix[VX][VZ] ;
00240         adjoint_transpose.mMatrix[VZ][VY] = mMatrix[VZ][VX] * mMatrix[VX][VY] - mMatrix[VZ][VY] * mMatrix[VX][VX] ;
00241         adjoint_transpose.mMatrix[VX][VZ] = mMatrix[VX][VY] * mMatrix[VY][VZ] - mMatrix[VX][VZ] * mMatrix[VY][VY] ;
00242         adjoint_transpose.mMatrix[VY][VZ] = mMatrix[VX][VZ] * mMatrix[VY][VX] - mMatrix[VX][VX] * mMatrix[VY][VZ] ;
00243         adjoint_transpose.mMatrix[VZ][VZ] = mMatrix[VX][VX] * mMatrix[VY][VY] - mMatrix[VX][VY] * mMatrix[VY][VX] ;
00244 
00245         *this = adjoint_transpose;
00246         return *this;
00247 }
00248 
00249 // SJB: This code is correct for a logicly stored (non-transposed) matrix;
00250 //              Our matrices are stored transposed, OpenGL style, so this generates the
00251 //              INVERSE quaternion (-x, -y, -z, w)!
00252 //              Because we use similar logic in LLQuaternion::getMatrix3,
00253 //              we are internally consistant so everything works OK :)
00254 LLQuaternion    LLMatrix3::quaternion() const
00255 {
00256         LLQuaternion    quat;
00257         F32             tr, s, q[4];
00258         U32             i, j, k;
00259         U32             nxt[3] = {1, 2, 0};
00260 
00261         tr = mMatrix[0][0] + mMatrix[1][1] + mMatrix[2][2];
00262 
00263         // check the diagonal
00264         if (tr > 0.f) 
00265         {
00266                 s = (F32)sqrt (tr + 1.f);
00267                 quat.mQ[VS] = s / 2.f;
00268                 s = 0.5f / s;
00269                 quat.mQ[VX] = (mMatrix[1][2] - mMatrix[2][1]) * s;
00270                 quat.mQ[VY] = (mMatrix[2][0] - mMatrix[0][2]) * s;
00271                 quat.mQ[VZ] = (mMatrix[0][1] - mMatrix[1][0]) * s;
00272         } 
00273         else
00274         {               
00275                 // diagonal is negative
00276                 i = 0;
00277                 if (mMatrix[1][1] > mMatrix[0][0]) 
00278                         i = 1;
00279                 if (mMatrix[2][2] > mMatrix[i][i]) 
00280                         i = 2;
00281 
00282                 j = nxt[i];
00283                 k = nxt[j];
00284 
00285 
00286                 s = (F32)sqrt ((mMatrix[i][i] - (mMatrix[j][j] + mMatrix[k][k])) + 1.f);
00287 
00288                 q[i] = s * 0.5f;
00289 
00290                 if (s != 0.f) 
00291                         s = 0.5f / s;
00292 
00293                 q[3] = (mMatrix[j][k] - mMatrix[k][j]) * s;
00294                 q[j] = (mMatrix[i][j] + mMatrix[j][i]) * s;
00295                 q[k] = (mMatrix[i][k] + mMatrix[k][i]) * s;
00296 
00297                 quat.setQuat(q);
00298         }
00299         return quat;
00300 }
00301 
00302 
00303 // These functions take Rotation arguments
00304 const LLMatrix3&        LLMatrix3::setRot(const F32 angle, const F32 x, const F32 y, const F32 z)
00305 {
00306         setRot(LLQuaternion(angle,x,y,z));
00307         return *this;
00308 }
00309 
00310 const LLMatrix3&        LLMatrix3::setRot(const F32 angle, const LLVector3 &vec)
00311 {
00312         setRot(LLQuaternion(angle, vec));
00313         return *this;
00314 }
00315 
00316 const LLMatrix3&        LLMatrix3::setRot(const F32 roll, const F32 pitch, const F32 yaw)
00317 {
00318         // Rotates RH about x-axis by 'roll'  then
00319         // rotates RH about the old y-axis by 'pitch' then
00320         // rotates RH about the original z-axis by 'yaw'.
00321         //                .
00322         //               /|\ yaw axis
00323         //                |     __.
00324         //   ._        ___|      /| pitch axis
00325         //  _||\       \\ |-.   /
00326         //  \|| \_______\_|__\_/_______
00327         //   | _ _   o o o_o_o_o o   /_\_  ________\ roll axis
00328         //   //  /_______/    /__________>         /   
00329         //  /_,-'       //   /
00330         //             /__,-'
00331 
00332         F32             cx, sx, cy, sy, cz, sz;
00333         F32             cxsy, sxsy;
00334 
00335     cx = (F32)cos(roll); //A
00336     sx = (F32)sin(roll); //B
00337     cy = (F32)cos(pitch); //C
00338     sy = (F32)sin(pitch); //D
00339     cz = (F32)cos(yaw); //E
00340     sz = (F32)sin(yaw); //F
00341 
00342     cxsy = cx * sy; //AD
00343     sxsy = sx * sy; //BD 
00344 
00345     mMatrix[0][0] =  cy * cz;
00346     mMatrix[1][0] = -cy * sz;
00347     mMatrix[2][0] = sy;
00348     mMatrix[0][1] = sxsy * cz + cx * sz;
00349     mMatrix[1][1] = -sxsy * sz + cx * cz;
00350     mMatrix[2][1] = -sx * cy;
00351     mMatrix[0][2] =  -cxsy * cz + sx * sz;
00352     mMatrix[1][2] =  cxsy * sz + sx * cz;
00353     mMatrix[2][2] =  cx * cy;
00354         return *this;
00355 }
00356 
00357 
00358 const LLMatrix3&        LLMatrix3::setRot(const LLQuaternion &q)
00359 {
00360         *this = q.getMatrix3();
00361         return *this;
00362 }
00363 
00364 const LLMatrix3&        LLMatrix3::setRows(const LLVector3 &fwd, const LLVector3 &left, const LLVector3 &up)
00365 {
00366         mMatrix[0][0] = fwd.mV[0];
00367         mMatrix[0][1] = fwd.mV[1];
00368         mMatrix[0][2] = fwd.mV[2];
00369 
00370         mMatrix[1][0] = left.mV[0];
00371         mMatrix[1][1] = left.mV[1];
00372         mMatrix[1][2] = left.mV[2];
00373 
00374         mMatrix[2][0] = up.mV[0];
00375         mMatrix[2][1] = up.mV[1];
00376         mMatrix[2][2] = up.mV[2];
00377 
00378         return *this;
00379 }
00380 
00381 const LLMatrix3& LLMatrix3::setRow( U32 rowIndex, const LLVector3& row )
00382 {
00383         llassert( rowIndex >= 0 && rowIndex < NUM_VALUES_IN_MAT3 );
00384 
00385         mMatrix[rowIndex][0] = row[0];
00386         mMatrix[rowIndex][1] = row[1];
00387         mMatrix[rowIndex][2] = row[2];
00388 
00389         return *this;
00390 }
00391 
00392 const LLMatrix3& LLMatrix3::setCol( U32 colIndex, const LLVector3& col )
00393 {
00394         llassert( colIndex >= 0 && colIndex < NUM_VALUES_IN_MAT3 );
00395 
00396         mMatrix[0][colIndex] = col[0];
00397         mMatrix[1][colIndex] = col[1];
00398         mMatrix[2][colIndex] = col[2];
00399 
00400         return *this;
00401 }
00402                 
00403 // Rotate exisitng mMatrix
00404 const LLMatrix3&        LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z)
00405 {
00406         LLMatrix3       mat(angle, x, y, z);
00407         *this *= mat;
00408         return *this;
00409 }
00410 
00411 
00412 const LLMatrix3&        LLMatrix3::rotate(const F32 angle, const LLVector3 &vec)
00413 {
00414         LLMatrix3       mat(angle, vec);
00415         *this *= mat;
00416         return *this;
00417 }
00418 
00419 
00420 const LLMatrix3&        LLMatrix3::rotate(const F32 roll, const F32 pitch, const F32 yaw)
00421 {
00422         LLMatrix3       mat(roll, pitch, yaw); 
00423         *this *= mat;
00424         return *this;
00425 }
00426 
00427 
00428 const LLMatrix3&        LLMatrix3::rotate(const LLQuaternion &q)
00429 {
00430         LLMatrix3       mat(q);
00431         *this *= mat;
00432         return *this;
00433 }
00434 
00435 void LLMatrix3::add(const LLMatrix3& other_matrix)
00436 {
00437         for (S32 i = 0; i < 3; ++i)
00438         {
00439                 for (S32 j = 0; j < 3; ++j)
00440                 {
00441                         mMatrix[i][j] += other_matrix.mMatrix[i][j];
00442                 }
00443         }
00444 }
00445 
00446 LLVector3       LLMatrix3::getFwdRow() const
00447 {
00448         return LLVector3(mMatrix[VX]);
00449 }
00450 
00451 LLVector3       LLMatrix3::getLeftRow() const
00452 {
00453         return LLVector3(mMatrix[VY]);
00454 }
00455 
00456 LLVector3       LLMatrix3::getUpRow() const
00457 {
00458         return LLVector3(mMatrix[VZ]);
00459 }
00460 
00461 
00462 
00463 const LLMatrix3&        LLMatrix3::orthogonalize()
00464 {
00465         LLVector3 x_axis(mMatrix[VX]);
00466         LLVector3 y_axis(mMatrix[VY]);
00467         LLVector3 z_axis(mMatrix[VZ]);
00468 
00469         x_axis.normVec();
00470         y_axis -= x_axis * (x_axis * y_axis);
00471         y_axis.normVec();
00472         z_axis = x_axis % y_axis;
00473         setRows(x_axis, y_axis, z_axis);
00474         return (*this);
00475 }
00476 
00477 
00478 // LLMatrix3 Operators
00479 
00480 LLMatrix3 operator*(const LLMatrix3 &a, const LLMatrix3 &b)
00481 {
00482         U32             i, j;
00483         LLMatrix3       mat;
00484         for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
00485         {
00486                 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
00487                 {
00488                         mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + 
00489                                                             a.mMatrix[j][1] * b.mMatrix[1][i] + 
00490                                                             a.mMatrix[j][2] * b.mMatrix[2][i];
00491                 }
00492         }
00493         return mat;
00494 }
00495 
00496 /* Not implemented to help enforce code consistency with the syntax of 
00497    row-major notation.  This is a Good Thing.
00498 LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b)
00499 {
00500         LLVector3       vec;
00501         // matrix operates "from the left" on column vector
00502         vec.mV[VX] = a.mMatrix[VX][VX] * b.mV[VX] + 
00503                                  a.mMatrix[VX][VY] * b.mV[VY] + 
00504                                  a.mMatrix[VX][VZ] * b.mV[VZ];
00505         
00506         vec.mV[VY] = a.mMatrix[VY][VX] * b.mV[VX] + 
00507                                  a.mMatrix[VY][VY] * b.mV[VY] + 
00508                                  a.mMatrix[VY][VZ] * b.mV[VZ];
00509         
00510         vec.mV[VZ] = a.mMatrix[VZ][VX] * b.mV[VX] + 
00511                                  a.mMatrix[VZ][VY] * b.mV[VY] + 
00512                                  a.mMatrix[VZ][VZ] * b.mV[VZ];
00513         return vec;
00514 }
00515 */
00516 
00517 
00518 LLVector3 operator*(const LLVector3 &a, const LLMatrix3 &b)
00519 {
00520         // matrix operates "from the right" on row vector
00521         return LLVector3(
00522                                 a.mV[VX] * b.mMatrix[VX][VX] + 
00523                                 a.mV[VY] * b.mMatrix[VY][VX] + 
00524                                 a.mV[VZ] * b.mMatrix[VZ][VX],
00525         
00526                                 a.mV[VX] * b.mMatrix[VX][VY] + 
00527                                 a.mV[VY] * b.mMatrix[VY][VY] + 
00528                                 a.mV[VZ] * b.mMatrix[VZ][VY],
00529         
00530                                 a.mV[VX] * b.mMatrix[VX][VZ] + 
00531                                 a.mV[VY] * b.mMatrix[VY][VZ] + 
00532                                 a.mV[VZ] * b.mMatrix[VZ][VZ] );
00533 }
00534 
00535 LLVector3d operator*(const LLVector3d &a, const LLMatrix3 &b)
00536 {
00537         // matrix operates "from the right" on row vector
00538         return LLVector3d(
00539                                 a.mdV[VX] * b.mMatrix[VX][VX] + 
00540                                 a.mdV[VY] * b.mMatrix[VY][VX] + 
00541                                 a.mdV[VZ] * b.mMatrix[VZ][VX],
00542         
00543                                 a.mdV[VX] * b.mMatrix[VX][VY] + 
00544                                 a.mdV[VY] * b.mMatrix[VY][VY] + 
00545                                 a.mdV[VZ] * b.mMatrix[VZ][VY],
00546         
00547                                 a.mdV[VX] * b.mMatrix[VX][VZ] + 
00548                                 a.mdV[VY] * b.mMatrix[VY][VZ] + 
00549                                 a.mdV[VZ] * b.mMatrix[VZ][VZ] );
00550 }
00551 
00552 bool operator==(const LLMatrix3 &a, const LLMatrix3 &b)
00553 {
00554         U32             i, j;
00555         for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
00556         {
00557                 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
00558                 {
00559                         if (a.mMatrix[j][i] != b.mMatrix[j][i])
00560                                 return FALSE;
00561                 }
00562         }
00563         return TRUE;
00564 }
00565 
00566 bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b)
00567 {
00568         U32             i, j;
00569         for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
00570         {
00571                 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
00572                 {
00573                         if (a.mMatrix[j][i] != b.mMatrix[j][i])
00574                                 return TRUE;
00575                 }
00576         }
00577         return FALSE;
00578 }
00579 
00580 const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b)
00581 {
00582         U32             i, j;
00583         LLMatrix3       mat;
00584         for (i = 0; i < NUM_VALUES_IN_MAT3; i++)
00585         {
00586                 for (j = 0; j < NUM_VALUES_IN_MAT3; j++)
00587                 {
00588                         mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + 
00589                                                             a.mMatrix[j][1] * b.mMatrix[1][i] + 
00590                                                             a.mMatrix[j][2] * b.mMatrix[2][i];
00591                 }
00592         }
00593         a = mat;
00594         return a;
00595 }
00596 
00597 const LLMatrix3& operator*=(LLMatrix3 &a, F32 scalar )
00598 {
00599         for( U32 i = 0; i < NUM_VALUES_IN_MAT3; ++i )
00600         {
00601                 for( U32 j = 0; j < NUM_VALUES_IN_MAT3; ++j )
00602                 {
00603                         a.mMatrix[i][j] *= scalar;
00604                 }
00605         }
00606 
00607         return a;
00608 }
00609 
00610 std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a) 
00611 {
00612         s << "{ " 
00613                 << a.mMatrix[VX][VX] << ", " << a.mMatrix[VX][VY] << ", " << a.mMatrix[VX][VZ] << "; "
00614                 << a.mMatrix[VY][VX] << ", " << a.mMatrix[VY][VY] << ", " << a.mMatrix[VY][VZ] << "; "
00615                 << a.mMatrix[VZ][VX] << ", " << a.mMatrix[VZ][VY] << ", " << a.mMatrix[VZ][VZ] 
00616           << " }";
00617         return s;
00618 }
00619 

Generated on Fri May 16 08:32:18 2008 for SecondLife by  doxygen 1.5.5