gfx_math_matrix.hh

Go to the documentation of this file.
00001 /*
00032  * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
00033  *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
00034  *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
00035  *****************************************************************************/
00036 
00037 #ifndef GFX_MATH_MATRIX_HH
00038 #define GFX_MATH_MATRIX_HH 1
00039 
00040 namespace gfx {
00041 
00045 
00046 // MATRIX_EXT=1 extended precision.
00047 #define MATRIX_EXT  0
00048 
00049 // A gfx matrix has 12 elements to minimize space (W elements aren't needed).
00050 // A 16 element matrix remains a compile option.
00051 #define MATRIX_ELEMS  12
00052 
00053 // Row-major or column-major.
00054 // If row-major, to go to row i, multiply i by amount of columns.
00055 #ifndef MATRIX_ROW_MAJOR
00056 #define MATRIX_ROW_MAJOR  0
00057 #endif
00058 
00059 // Matrix element offsets.
00060 #if MATRIX_ELEMS == 12
00061     #if MATRIX_ROW_MAJOR
00062 enum { Xx, Xy, Xz, Ox,
00063        Yx, Yy, Yz, Oy,
00064        Zx, Zy, Zz, Oz };
00065     #else
00066 enum { Xx, Yx, Zx,
00067        Xy, Yy, Zy,
00068        Xz, Yz, Zz,
00069        Ox, Oy, Oz };
00070     #endif // MATRIX_ROW_MAJOR
00071 #elif MATRIX_ELEMS == 16
00072     #if MATRIX_ROW_MAJOR
00073 enum { Xx, Xy, Xz, Ox,
00074        Yx, Yy, Yz, Oy,
00075        Zx, Zy, Zz, Oz,
00076        Xw, Yw, Zw, Ow };  // W elements are strongly deprecated
00077     #else
00078 enum { Xx, Yx, Zx, Xw,
00079        Xy, Yy, Zy, Yw,
00080        Xz, Yz, Zz, Zw,
00081        Ox, Oy, Oz, Ow };
00082     #endif // MATRIX_ROW_MAJOR
00083 #endif
00084 
00088 
00097 class Matrix : public Shared
00098 {
00099 
00100 public:
00101 
00102     // Matrix fp type.
00103 #if MATRIX_EXT
00104     typedef fpx FPM;        
00105 #else
00106     typedef fp FPM;         
00107 #endif
00108     typedef FPM ElemType;   
00109 
00111     Matrix( void )
00112     {
00113         Identity();
00114     }
00115 
00116     // (default copy methods suffice)
00117 
00118     // Element access.
00119     FPM&       operator[]( uint i )       { ASSERT2( i < MATRIX_ELEMS ); return m[i]; }
00120     const FPM& operator[]( uint i ) const { ASSERT2( i < MATRIX_ELEMS ); return m[i]; }
00121 
00123     friend bool operator==( const Matrix& m1, const Matrix& m2 )
00124     {
00125         for ( uint i = 0; i < MATRIX_ELEMS; ++i )
00126             if ( m1[i] != m2[i] ) return false;
00127         return true;  // each was equal
00128     }
00129 
00131     friend bool operator!=( const Matrix& m1, const Matrix& m2 )
00132     {
00133         return not (m1 == m2);
00134     }
00135 
00137     friend bool IfRotationEqual( const Matrix& m1, const Matrix& m2 )
00138     {
00139         for ( uint i = 0; i < Ox; ++i )
00140             if ( m1[i] != m2[i] ) return false;
00141         return true;  // each was equal
00142     }
00143 
00144     Vector3 GetOrigin( void ) const
00145     {
00146         return Vector3( m[Ox], m[Oy], m[Oz] );
00147     }
00148 
00149     void SetOrigin( const Vector3& origin )
00150     {
00151         m[Ox] = origin.x;
00152         m[Oy] = origin.y;
00153         m[Oz] = origin.z;
00154     }
00155 
00156     // Convert Matrix object into an OpenGL 4x4 matrix.
00157     void Convert( fp out[16] ) const
00158     {
00159         out[ 0] = m[Xx]; out[ 1] = m[Xy]; out[ 2] = m[Xz];
00160         out[ 4] = m[Yx]; out[ 5] = m[Yy]; out[ 6] = m[Yz];
00161         out[ 8] = m[Zx]; out[ 9] = m[Zy]; out[10] = m[Zz];
00162         out[12] = m[Ox]; out[13] = m[Oy]; out[14] = m[Oz];
00163 #if MATRIX_ELEMS == 12
00164         out[ 0+3] = 0.0;
00165         out[ 4+3] = 0.0;
00166         out[ 8+3] = 0.0;
00167         out[12+3] = 1.0;
00168 #else // MATRIX_ELEMS == 16
00169         out[ 0+3] = m[Xw];
00170         out[ 4+3] = m[Yw];
00171         out[ 8+3] = m[Zw];
00172         out[12+3] = m[Ow];
00173 #endif
00174     }
00175 
00179     void
00180     Identity( void )
00181     {
00182         m[Xx] = 1.0; m[Xy] = 0.0; m[Xz] = 0.0;
00183         m[Yx] = 0.0; m[Yy] = 1.0; m[Yz] = 0.0;
00184         m[Zx] = 0.0; m[Zy] = 0.0; m[Zz] = 1.0;
00185         m[Ox] = 0.0; m[Oy] = 0.0; m[Oz] = 0.0;
00186 #if MATRIX_ELEMS == 16
00187         m[Xw] = 0.0; m[Yw] = 0.0; m[Zw] = 0.0; m[Ow] = 1.0;
00188 #endif
00189     }
00190 
00194 
00198     FPM
00199     RotateX( FPM x, FPM y, FPM z ) const
00200     {
00201         return x * m[Xx] + y * m[Xy] + z * m[Xz];  // X
00202     }
00203 
00204     FPM
00205     RotateY( FPM x, FPM y, FPM z ) const
00206     {   
00207         return x * m[Yx] + y * m[Yy] + z * m[Yz];  // Y
00208     }
00209 
00210     FPM
00211     RotateZ( FPM x, FPM y, FPM z ) const
00212     {
00213         return x * m[Zx] + y * m[Zy] + z * m[Zz];  // Z
00214     }
00215 
00220     template<typename VECTOR_DEST,typename VECTOR_SRC>
00221     VECTOR_DEST
00222     Rotate( const VECTOR_SRC& v ) const
00223     {
00224         return VECTOR_DEST( v.x * m[Xx] + v.y * m[Xy] + v.z * m[Xz],    // X
00225                             v.x * m[Yx] + v.y * m[Yy] + v.z * m[Yz],    // Y
00226                             v.x * m[Zx] + v.y * m[Zy] + v.z * m[Zz] );  // Z
00227     }
00228 
00232     FPM
00233     RotateTranslateX( FPM x, FPM y, FPM z ) const
00234     {
00235         return x * m[Xx] + y * m[Xy] + z * m[Xz] + m[Ox];  // X
00236     }
00237 
00238     FPM
00239     RotateTranslateY( FPM x, FPM y, FPM z ) const
00240     {
00241         return x * m[Yx] + y * m[Yy] + z * m[Yz] + m[Oy];  // Y
00242     }
00243 
00244     FPM
00245     RotateTranslateZ( FPM x, FPM y, FPM z ) const
00246     {
00247         return x * m[Zx] + y * m[Zy] + z * m[Zz] + m[Oz];  // Z
00248     }
00249 
00253     #define CODE_RESIZE_DEST_ARRAY(dest,src,vcnt)                       \
00254         /* Ensure dest array has enough room. */                        \
00255         const uint vcnt = src.size();                                   \
00256         ASSERT( vcnt > 0 );                                             \
00257         ASSERT( vcnt < MAX_VERTEXS );                                   \
00258         dest.resize( vcnt );
00259 
00263     template<typename DEST,typename SRC>
00264     DEST
00265     RotateTranslate( const SRC& v ) const
00266     {
00267         return DEST( v.x * m[Xx] + v.y * m[Xy] + v.z * m[Xz] + m[Ox],
00268                      v.x * m[Yx] + v.y * m[Yy] + v.z * m[Yz] + m[Oy],
00269                      v.x * m[Zx] + v.y * m[Zy] + v.z * m[Zz] + m[Oz] );
00270     }
00271 
00272     #define CODE_ROTATE_TRANSLATE_ARRAY(dest,src,vcnt)                                  \
00273     {                                                                                   \
00274         for ( uint i = 0; i < vcnt; ++i )                                               \
00275         {                                                                               \
00276           /* catch memory corruption */ \
00277             dest[i].x = src[i].x * m[Xx] + src[i].y * m[Xy] + src[i].z * m[Xz] + m[Ox]; \
00278             dest[i].y = src[i].x * m[Yx] + src[i].y * m[Yy] + src[i].z * m[Yz] + m[Oy]; \
00279             dest[i].z = src[i].x * m[Zx] + src[i].y * m[Zy] + src[i].z * m[Zz] + m[Oz]; \
00280         }                                                                               \
00281     }
00282 
00284     template<typename DEST,typename SRC>
00285     void
00286     RotateTranslate( Array<DEST>& dest, const Array<SRC>& src ) const
00287     {
00288         CODE_RESIZE_DEST_ARRAY(dest,src,vcnt)
00289 #if DEBUG
00290         // Compile slower STL operator[] but handles vertex typesigs in DEBUG builds.
00291         CODE_ROTATE_TRANSLATE_ARRAY(dest,src,vcnt)
00292 #else
00293         // Compile optimal code to directly index raw array (incompatible with typesigs).
00294         Vector3* destRaw = dest.PTR(); const Vector3* srcRaw = src.CONST_PTR();  // -- CAST --
00295         CODE_ROTATE_TRANSLATE_ARRAY(destRaw,srcRaw,vcnt)
00296 #endif
00297     }
00298 
00299     #undef CODE_ROTATE_TRANSLATE_ARRAY
00300 
00304     template<typename DEST,typename SRC>
00305     DEST
00306     TranslateRotate( const SRC& src ) const
00307     {
00308         fp x = src.x + m[Ox];
00309         fp y = src.y + m[Oy];
00310         fp z = src.z + m[Oz];
00311         return DEST( x * m[Xx] + y * m[Xy] + z * m[Xz],
00312                      x * m[Yx] + y * m[Yy] + z * m[Yz],
00313                      x * m[Zx] + y * m[Zy] + z * m[Zz] );
00314     }
00315 
00316     #define CODE_TRANSLATE_ROTATE_ARRAY(dest,src,vcnt)                                  \
00317     {                                                                                   \
00318         for ( uint i = 0; i < vcnt; ++i )                                               \
00319         {                                                                               \
00320           /* catch memory corruption */ \
00321             fp x = src[i].x + m[Ox];                                                    \
00322             fp y = src[i].y + m[Oy];                                                    \
00323             fp z = src[i].z + m[Oz];                                                    \
00324             dest[i].x = x * m[Xx] + y * m[Xy] + z * m[Xz];                              \
00325             dest[i].y = x * m[Yx] + y * m[Yy] + z * m[Yz];                              \
00326             dest[i].z = x * m[Zx] + y * m[Zy] + z * m[Zz];                              \
00327         }                                                                               \
00328     }
00329 
00331     template<typename DEST,typename SRC>
00332     void
00333     TranslateRotate( Array<DEST>& dest, const Array<SRC>& src ) const
00334     {
00335         CODE_RESIZE_DEST_ARRAY(dest,src,vcnt)
00336 #if DEBUG
00337         // Compile slower STL operator[] but handles vertex typesigs in DEBUG builds.
00338         CODE_TRANSLATE_ROTATE_ARRAY(dest,src,vcnt)
00339 #else
00340         // Compile optimal code to directly index raw array (incompatible with typesigs).
00341         Vector3* destRaw = dest.PTR(); const Vector3* srcRaw = src.CONST_PTR();  // -- CAST --
00342         CODE_TRANSLATE_ROTATE_ARRAY(destRaw,srcRaw,vcnt)
00343 #endif
00344     }
00345 
00346     #undef CODE_TRANSLATE_ROTATE_ARRAY
00347 
00356 
00357     WorldVertex
00358     Transform( const LocalVertex& v ) const
00359     {
00360         return RotateTranslate<WorldVertex,LocalVertex>( v );
00361     }
00362     void
00363     Transform( Array<WorldVertex>& dest, const Array<LocalVertex>& src ) const
00364     {
00365         RotateTranslate<WorldVertex,LocalVertex>( dest, src );
00366     }
00367 
00369     EyeVertex
00370     Transform( const WorldVertex& v ) const
00371     {
00372         return TranslateRotate<EyeVertex,WorldVertex>( v );
00373     }
00374     void
00375     Transform( Array<EyeVertex>& dest, const Array<WorldVertex>& src ) const
00376     {
00377         TranslateRotate<EyeVertex,WorldVertex>( dest, src );
00378     }
00379 
00381     void
00382     Transform( Array<EyeVertex>& dest, const Array<LocalVertex>& src ) const
00383     {
00384         RotateTranslate<EyeVertex,LocalVertex>( dest, src );
00385     }
00386 
00391     template<typename VECTOR>
00392     VECTOR
00393     MoveFixed( uint axis, fp inc ) const
00394     {
00395     ASSERT( CHECK_AXIS( axis ) );
00396         return VECTOR( inc * m[MIXF(axis,XX)],
00397                        inc * m[MIXF(axis,YY)],
00398                        inc * m[MIXF(axis,ZZ)] );
00399     }
00400 
00401     template<typename VECTOR>
00402     VECTOR
00403     MoveLocal( uint axis, fp inc ) const
00404     {
00405     ASSERT( CHECK_AXIS( axis ) );
00406         return VECTOR( inc * m[MIXL(axis,XX)],
00407                        inc * m[MIXL(axis,YY)],
00408                        inc * m[MIXL(axis,ZZ)] );
00409     }
00410 
00414 
00419     void
00420     TranslateFixed( uint axis, FPM inc )
00421     {
00422     ASSERT( CHECK_AXIS( axis ) );
00423         m[Ox] += inc * m[MIXF(axis,XX)];
00424         m[Oy] += inc * m[MIXF(axis,YY)];
00425         m[Oz] += inc * m[MIXF(axis,ZZ)];
00426     }
00427 
00432     void
00433     TranslateLocal( uint axis, FPM inc )
00434     {
00435     ASSERT( CHECK_AXIS( axis ) );
00436         m[Ox] += inc * m[MIXL(axis,XX)];
00437         m[Oy] += inc * m[MIXL(axis,YY)];
00438         m[Oz] += inc * m[MIXL(axis,ZZ)];
00439     }
00440 
00447     void
00448     RotateFixed( uint axis, Radian rad )
00449     {
00450         pair<FPM,FPM> si_co = SinCos<FPM>( rad );
00451         FPM& s = si_co.first;
00452         FPM& c = si_co.second;
00453         Matrix n = *this;  // dest = src
00454         switch ( axis )
00455         {
00456             // X : Pitch
00457             case AXIS_X:
00458             n[Yx] = m[Yx]*c - m[Zx]*s;      // Y = Ycos - Zsin
00459             n[Yy] = m[Yy]*c - m[Zy]*s;
00460             n[Yz] = m[Yz]*c - m[Zz]*s;
00461 
00462             n[Zx] = m[Yx]*s + m[Zx]*c;      // Z = Ysin + Zcos
00463             n[Zy] = m[Yy]*s + m[Zy]*c;
00464             n[Zz] = m[Yz]*s + m[Zz]*c;
00465             break;
00466 
00467             // Y : Yaw
00468             case AXIS_Y:
00469             n[Xx] = m[Xx]*c - m[Zx]*s;      // X = Xcos - Zsin
00470             n[Xy] = m[Xy]*c - m[Zy]*s;
00471             n[Xz] = m[Xz]*c - m[Zz]*s;
00472 
00473             n[Zx] = m[Xx]*s + m[Zx]*c;      // Z = Xsin + Zcos
00474             n[Zy] = m[Xy]*s + m[Zy]*c;
00475             n[Zz] = m[Xz]*s + m[Zz]*c;
00476             break;
00477 
00478             // Z : Roll
00479             case AXIS_Z:
00480             n[Xx] = m[Xx]*c - m[Yx]*s;      // X = Xcos - Ysin
00481             n[Xy] = m[Xy]*c - m[Yy]*s;
00482             n[Xz] = m[Xz]*c - m[Yz]*s;
00483 
00484             n[Yx] = m[Xx]*s + m[Yx]*c;      // Y = Xsin + Ycos
00485             n[Yy] = m[Xy]*s + m[Yy]*c;
00486             n[Yz] = m[Xz]*s + m[Yz]*c;
00487             break;
00488 
00489             default: ASSERT(0); return;
00490         }
00491 
00492         *this = n;  // dest = src
00493     }
00494 
00505     void
00506     RotateLocal( uint axis, Radian rad )
00507     {
00508         // Identity (1:1) matrix r.
00509         Matrix r;
00510 
00511         // Rotate matrix r.
00512         r.RotateFixed( axis, rad );
00513 
00514         // Transform r thru m.
00515         // Ie, thru matrix m, pass r as if it were the rotated coords (1.0, 1.0, 1.0).
00516         Matrix t;
00517         t[Xx] = r.RotateTranslateX( m[Xx], m[Xy], m[Xz] );
00518         t[Xy] = r.RotateTranslateY( m[Xx], m[Xy], m[Xz] );
00519         t[Xz] = r.RotateTranslateZ( m[Xx], m[Xy], m[Xz] );
00520 
00521         t[Yx] = r.RotateTranslateX( m[Yx], m[Yy], m[Yz] );
00522         t[Yy] = r.RotateTranslateY( m[Yx], m[Yy], m[Yz] );
00523         t[Yz] = r.RotateTranslateZ( m[Yx], m[Yy], m[Yz] );
00524 
00525         t[Zx] = r.RotateTranslateX( m[Zx], m[Zy], m[Zz] );
00526         t[Zy] = r.RotateTranslateY( m[Zx], m[Zy], m[Zz] );
00527         t[Zz] = r.RotateTranslateZ( m[Zx], m[Zy], m[Zz] );
00528 
00529         // m = r excluding origin elements.
00530         m[Xx] = t[Xx];
00531         m[Xy] = t[Xy];
00532         m[Xz] = t[Xz];
00533 
00534         m[Yx] = t[Yx];
00535         m[Yy] = t[Yy];
00536         m[Yz] = t[Yz];
00537 
00538         m[Zx] = t[Zx];
00539         m[Zy] = t[Zy];
00540         m[Zz] = t[Zz];
00541     }
00542 
00543     // Limited use.
00544     FPM*             PTR( void ) const { return const_cast<FPM*>( m ); }
00545     const FPM* CONST_PTR( void ) const { return m; }
00546 
00547 private:
00548 // Access matrix elements using a (row,col) tuple independent of matrix format.
00549 // MIXF() is used for transformations relative to fixed space.
00550 // MIXL() is used for transformations relative to matrix's local space.
00551 #if MATRIX_ELEMS == 12
00552     #if MATRIX_ROW_MAJOR
00553     uint MIXF( uint i, uint j ) const  { return i*4 + j; }
00554     #else
00555     uint MIXF( uint i, uint j ) const  { return j*3 + i; }
00556     #endif
00557     #if MATRIX_ROW_MAJOR
00558     uint MIXL( uint i, uint j ) const { return j*4 + i; }
00559     #else
00560     uint MIXL( uint i, uint j ) const { return i*3 + j; }
00561     #endif
00562 #elif MATRIX_ELEMS == 16
00563     #if MATRIX_ROW_MAJOR
00564     uint MIXF( uint i, uint j ) const  { return i*4 + j; }
00565     #else
00566     uint MIXF( uint i, uint j ) const { return j*4 + i; }
00567     #endif
00568     #if MATRIX_ROW_MAJOR
00569     uint MIXL( uint i, uint j ) const { return j*4 + i; }
00570     #else
00571     uint MIXL( uint i, uint j ) const { return i*4 + j; }
00572     #endif
00573 #endif
00574 
00575     friend ostream& operator<<( ostream& strm, const Matrix& m )
00576     {
00577         ios::fmtflags savedFlags = strm.flags();
00578         strm.setf( ios::fixed, ios::floatfield );
00579         strm.precision( 6 );
00580         strm << "Xxyzw:  " << m[Xx] << "  " << m[Xy] << "  " << m[Xz] << endl
00581              << "Yxyzw:  " << m[Yx] << "  " << m[Yy] << "  " << m[Yz] << endl
00582              << "Zxyzw:  " << m[Zx] << "  " << m[Zy] << "  " << m[Zz] << endl
00583              << "Oxyzw:  " << m[Ox] << "  " << m[Oy] << "  " << m[Oz]; // << endl;
00584         strm.flags(savedFlags);
00585         return strm;
00586     }
00587 
00588 private:
00589     FPM     m[MATRIX_ELEMS];
00590 };
00591 
00595 
00639 INLINE Matrix
00640 operator*( const Matrix& m, const Matrix& n )
00641 {
00642     // Optimizations:
00643     // Calculating Xw,Yw,Zw,Ow (0,0,0,1) is bypassed as they never change.
00644     // Xw,Yw,Zw are always 0 so multiplying one factor is bypassed.
00645     // Ow is always 1 so Oxyz coefficients are added directly without multiplying it by 1.
00646     // Inefficiencies:
00647     // Some factors are re-multiplied.
00648 
00649     Matrix prod;
00650 
00651 #define MULTIPLY_MATRIX_ELEM3( i, a0,a1, b0,b1, c0,c1 )         \
00652     prod[i] =   m[a0] * n[a1]                                   \
00653               + m[b0] * n[b1]                                   \
00654               + m[c0] * n[c1];
00655 
00656 #define MULTIPLY_MATRIX_ELEM4( i, a0,a1, b0,b1, c0,c1, oi )     \
00657     prod[i] =   m[a0] * n[a1]                                   \
00658               + m[b0] * n[b1]                                   \
00659               + m[c0] * n[c1]                                   \
00660               +         n[oi];
00661 
00662 #if MATRIX_ROW_MAJOR
00663     MULTIPLY_MATRIX_ELEM3( Xx, Xx,Xx, Yx,Xy, Zx,Xz /*, Xw,Ox */      ); 
00664     MULTIPLY_MATRIX_ELEM3( Xy, Xy,Xx, Yy,Xy, Zy,Xz /*, Yw,Ox */      ); 
00665     MULTIPLY_MATRIX_ELEM3( Xz, Xz,Xx, Yz,Xy, Zz,Xz /*, Zw,Ox */      ); 
00666     MULTIPLY_MATRIX_ELEM4( Ox, Ox,Xx, Oy,Xy, Oz,Xz /*, Ow,Ox */ , Ox ); 
00667     MULTIPLY_MATRIX_ELEM3( Yx, Xx,Yx, Yx,Yy, Zx,Yz /*, Xw,Oy */      ); 
00668     MULTIPLY_MATRIX_ELEM3( Yy, Xy,Yx, Yy,Yy, Zy,Yz /*, Yw,Oy */      ); 
00669     MULTIPLY_MATRIX_ELEM3( Yz, Xz,Yx, Yz,Yy, Zz,Yz /*, Zw,Oy */      ); 
00670     MULTIPLY_MATRIX_ELEM4( Oy, Ox,Yx, Oy,Yy, Oz,Yz /*, Ow,Oy */ , Oy ); 
00671     MULTIPLY_MATRIX_ELEM3( Zx, Xx,Zx, Yx,Zy, Zx,Zz /*, Xw,Oz */      ); 
00672     MULTIPLY_MATRIX_ELEM3( Zy, Xy,Zx, Yy,Zy, Zy,Zz /*, Yw,Oz */      ); 
00673     MULTIPLY_MATRIX_ELEM3( Zz, Xz,Zx, Yz,Zy, Zz,Zz /*, Zw,Oz */      ); 
00674     MULTIPLY_MATRIX_ELEM4( Oz, Ox,Zx, Oy,Zy, Oz,Zz /*, Ow,Oz */ , Oz ); 
00675 #else
00676     MULTIPLY_MATRIX_ELEM3( Xx, Xx,Xx, Yx,Xy, Zx,Xz /*, Xw,Ox */      ); 
00677     MULTIPLY_MATRIX_ELEM3( Yx, Xx,Yx, Yx,Yy, Zx,Yz /*, Xw,Oy */      ); 
00678     MULTIPLY_MATRIX_ELEM3( Zx, Xx,Zx, Yx,Zy, Zx,Zz /*, Xw,Oz */      ); 
00679     MULTIPLY_MATRIX_ELEM3( Xy, Xy,Xx, Yy,Xy, Zy,Xz /*, Yw,Ox */      ); 
00680     MULTIPLY_MATRIX_ELEM3( Yy, Xy,Yx, Yy,Yy, Zy,Yz /*, Yw,Oy */      ); 
00681     MULTIPLY_MATRIX_ELEM3( Zy, Xy,Zx, Yy,Zy, Zy,Zz /*, Yw,Oz */      ); 
00682     MULTIPLY_MATRIX_ELEM3( Xz, Xz,Xx, Yz,Xy, Zz,Xz /*, Zw,Ox */      ); 
00683     MULTIPLY_MATRIX_ELEM3( Yz, Xz,Yx, Yz,Yy, Zz,Yz /*, Zw,Oy */      ); 
00684     MULTIPLY_MATRIX_ELEM3( Zz, Xz,Zx, Yz,Zy, Zz,Zz /*, Zw,Oz */      ); 
00685     MULTIPLY_MATRIX_ELEM4( Ox, Ox,Xx, Oy,Xy, Oz,Xz /*, Ow,Ox */ , Ox ); 
00686     MULTIPLY_MATRIX_ELEM4( Oy, Ox,Yx, Oy,Yy, Oz,Yz /*, Ow,Oy */ , Oy ); 
00687     MULTIPLY_MATRIX_ELEM4( Oz, Ox,Zx, Oy,Zy, Oz,Zz /*, Ow,Oz */ , Oz ); 
00688 #endif
00689 
00690     return prod;
00691 }
00692 
00697 INLINE void
00698 TransposeMatrix( Matrix& dest, const Matrix& src )
00699 {
00700     // Transpose rotation sub-matrix.
00701     // X = X'
00702     dest[Xx] = src[Xx];
00703     dest[Xy] = src[Yx];
00704     dest[Xz] = src[Zx];
00705     // Y = Y'
00706     dest[Yx] = src[Xy];
00707     dest[Yy] = src[Yy];
00708     dest[Yz] = src[Zy];
00709     // Z = Z'
00710     dest[Zx] = src[Xz];
00711     dest[Zy] = src[Yz];
00712     dest[Zz] = src[Zz];
00713 
00714     // Negate origin sub-matrix.
00715     dest[Ox] = -src[Ox];
00716     dest[Oy] = -src[Oy];
00717     dest[Oz] = -src[Oz];
00718 }
00719 
00720 // Served their purpose.
00721 #undef MATRIX_ELEMS
00722 #undef CODE_RESIZE_DEST_ARRAY
00723 
00724 } // namespace gfx
00725 
00726 #endif // GFX_MATH_MATRIX_HH
Palomino 3D Engine documents generated by doxygen 1.5.3 on Fri Nov 23 11:26:10 2007