00001
00032
00033
00034
00035
00036
00037 #ifndef GFX_MATH_MATRIX_HH
00038 #define GFX_MATH_MATRIX_HH 1
00039
00040 namespace gfx {
00041
00045
00046
00047 #define MATRIX_EXT 0
00048
00049
00050
00051 #define MATRIX_ELEMS 12
00052
00053
00054
00055 #ifndef MATRIX_ROW_MAJOR
00056 #define MATRIX_ROW_MAJOR 0
00057 #endif
00058
00059
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 };
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
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
00117
00118
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;
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;
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
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];
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];
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];
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],
00225 v.x * m[Yx] + v.y * m[Yy] + v.z * m[Yz],
00226 v.x * m[Zx] + v.y * m[Zy] + v.z * m[Zz] );
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];
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];
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];
00248 }
00249
00253 #define CODE_RESIZE_DEST_ARRAY(dest,src,vcnt) \
00254 \
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 \
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
00291 CODE_ROTATE_TRANSLATE_ARRAY(dest,src,vcnt)
00292 #else
00293
00294 Vector3* destRaw = dest.PTR(); const Vector3* srcRaw = src.CONST_PTR();
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 \
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
00338 CODE_TRANSLATE_ROTATE_ARRAY(dest,src,vcnt)
00339 #else
00340
00341 Vector3* destRaw = dest.PTR(); const Vector3* srcRaw = src.CONST_PTR();
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;
00454 switch ( axis )
00455 {
00456
00457 case AXIS_X:
00458 n[Yx] = m[Yx]*c - m[Zx]*s;
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;
00463 n[Zy] = m[Yy]*s + m[Zy]*c;
00464 n[Zz] = m[Yz]*s + m[Zz]*c;
00465 break;
00466
00467
00468 case AXIS_Y:
00469 n[Xx] = m[Xx]*c - m[Zx]*s;
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;
00474 n[Zy] = m[Xy]*s + m[Zy]*c;
00475 n[Zz] = m[Xz]*s + m[Zz]*c;
00476 break;
00477
00478
00479 case AXIS_Z:
00480 n[Xx] = m[Xx]*c - m[Yx]*s;
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;
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;
00493 }
00494
00505 void
00506 RotateLocal( uint axis, Radian rad )
00507 {
00508
00509 Matrix r;
00510
00511
00512 r.RotateFixed( axis, rad );
00513
00514
00515
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
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
00544 FPM* PTR( void ) const { return const_cast<FPM*>( m ); }
00545 const FPM* CONST_PTR( void ) const { return m; }
00546
00547 private:
00548
00549
00550
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];
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
00643
00644
00645
00646
00647
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 );
00664 MULTIPLY_MATRIX_ELEM3( Xy, Xy,Xx, Yy,Xy, Zy,Xz );
00665 MULTIPLY_MATRIX_ELEM3( Xz, Xz,Xx, Yz,Xy, Zz,Xz );
00666 MULTIPLY_MATRIX_ELEM4( Ox, Ox,Xx, Oy,Xy, Oz,Xz , Ox );
00667 MULTIPLY_MATRIX_ELEM3( Yx, Xx,Yx, Yx,Yy, Zx,Yz );
00668 MULTIPLY_MATRIX_ELEM3( Yy, Xy,Yx, Yy,Yy, Zy,Yz );
00669 MULTIPLY_MATRIX_ELEM3( Yz, Xz,Yx, Yz,Yy, Zz,Yz );
00670 MULTIPLY_MATRIX_ELEM4( Oy, Ox,Yx, Oy,Yy, Oz,Yz , Oy );
00671 MULTIPLY_MATRIX_ELEM3( Zx, Xx,Zx, Yx,Zy, Zx,Zz );
00672 MULTIPLY_MATRIX_ELEM3( Zy, Xy,Zx, Yy,Zy, Zy,Zz );
00673 MULTIPLY_MATRIX_ELEM3( Zz, Xz,Zx, Yz,Zy, Zz,Zz );
00674 MULTIPLY_MATRIX_ELEM4( Oz, Ox,Zx, Oy,Zy, Oz,Zz , Oz );
00675 #else
00676 MULTIPLY_MATRIX_ELEM3( Xx, Xx,Xx, Yx,Xy, Zx,Xz );
00677 MULTIPLY_MATRIX_ELEM3( Yx, Xx,Yx, Yx,Yy, Zx,Yz );
00678 MULTIPLY_MATRIX_ELEM3( Zx, Xx,Zx, Yx,Zy, Zx,Zz );
00679 MULTIPLY_MATRIX_ELEM3( Xy, Xy,Xx, Yy,Xy, Zy,Xz );
00680 MULTIPLY_MATRIX_ELEM3( Yy, Xy,Yx, Yy,Yy, Zy,Yz );
00681 MULTIPLY_MATRIX_ELEM3( Zy, Xy,Zx, Yy,Zy, Zy,Zz );
00682 MULTIPLY_MATRIX_ELEM3( Xz, Xz,Xx, Yz,Xy, Zz,Xz );
00683 MULTIPLY_MATRIX_ELEM3( Yz, Xz,Yx, Yz,Yy, Zz,Yz );
00684 MULTIPLY_MATRIX_ELEM3( Zz, Xz,Zx, Yz,Zy, Zz,Zz );
00685 MULTIPLY_MATRIX_ELEM4( Ox, Ox,Xx, Oy,Xy, Oz,Xz , Ox );
00686 MULTIPLY_MATRIX_ELEM4( Oy, Ox,Yx, Oy,Yy, Oz,Yz , Oy );
00687 MULTIPLY_MATRIX_ELEM4( Oz, Ox,Zx, Oy,Zy, Oz,Zz , Oz );
00688 #endif
00689
00690 return prod;
00691 }
00692
00697 INLINE void
00698 TransposeMatrix( Matrix& dest, const Matrix& src )
00699 {
00700
00701
00702 dest[Xx] = src[Xx];
00703 dest[Xy] = src[Yx];
00704 dest[Xz] = src[Zx];
00705
00706 dest[Yx] = src[Xy];
00707 dest[Yy] = src[Yy];
00708 dest[Yz] = src[Zy];
00709
00710 dest[Zx] = src[Xz];
00711 dest[Zy] = src[Yz];
00712 dest[Zz] = src[Zz];
00713
00714
00715 dest[Ox] = -src[Ox];
00716 dest[Oy] = -src[Oy];
00717 dest[Oz] = -src[Oz];
00718 }
00719
00720
00721 #undef MATRIX_ELEMS
00722 #undef CODE_RESIZE_DEST_ARRAY
00723
00724 }
00725
00726 #endif // GFX_MATH_MATRIX_HH