glmatrix.h

00001 /*
00002 Copyright (c) 2000-2007 Lee Thomason (www.grinninglizard.com)
00003 Grinning Lizard Utilities.
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any 
00010 purpose, including commercial applications, and to alter it and 
00011 redistribute it freely, subject to the following restrictions:
00012 
00013 1. The origin of this software must not be misrepresented; you must 
00014 not claim that you wrote the original software. If you use this 
00015 software in a product, an acknowledgment in the product documentation 
00016 would be appreciated but is not required.
00017 
00018 2. Altered source versions must be plainly marked as such, and 
00019 must not be misrepresented as being the original software.
00020 
00021 3. This notice may not be removed or altered from any source 
00022 distribution.
00023 */
00024 
00025 
00026 #ifndef GRINLIZ_MATRIX_DEFINED
00027 #define GRINLIZ_MATRIX_DEFINED
00028 
00029 #include "gldebug.h"
00030 #include "glvector.h"
00031 
00032 namespace grinliz {
00033 
00045 class Matrix4
00046 {
00047   public:
00048         inline static int INDEX( int row, int col ) { return col*4+row; }
00049 
00051         Matrix4()                                               {       SetIdentity();  }
00052         Matrix4( const Matrix4& rhs )                   {       memcpy( x, rhs.x, sizeof(float)*16 ); }
00053         void operator=( const Matrix4& rhs )    {       memcpy( x, rhs.x, sizeof(float)*16 ); }
00054 
00056         void SetIdentity()              {       x[0] = x[5] = x[10] = x[15] = 1.0f;
00057                                                                 x[1] = x[2] = x[3] = x[4] = x[6] = x[7] = x[8] = x[9] = x[11] = x[12] = x[13] = x[14] = 0.0f; 
00058                                                         }
00059         
00061         void SetTranslation( float _x, float _y, float _z )
00062                                                         {       x[12] = _x;     x[13] = _y;     x[14] = _z;     }
00064         void SetTranslation( const Vector3F& vec )
00065                                                         {   x[12] = vec.x;      x[13] = vec.y;  x[14] = vec.z;  }
00066 
00068         void SetXRotation( float thetaDegree );
00070         void SetYRotation( float thetaDegree );
00072         void SetZRotation( float thetaDegree );
00073 
00075         float CalcRotationAroundAxis( int axis ) const;
00076 
00078         void SetScale( float scale )    { x[0] = x[5] = x[10] = scale; }
00079 
00081         void SetAxisAngle( const Vector3F& axis, float angle );
00082 
00083         void StripTrans()               {       x[12] = x[13] = x[14] = 0.0f;
00084                                                                 x[15] = 1.0f;
00085                                                         }
00086 
00088         bool IsRotation() const;
00089 
00090         bool operator==( const Matrix4& rhs ) const     { 
00091                 for( int i=0; i<16; ++i )
00092                         if ( x[i] != rhs.x[i] )
00093                                 return false;
00094                 return true;
00095         }
00096 
00097         bool operator!=( const Matrix4& rhs ) const     { 
00098                 int match = 0;
00099                 for( int i=0; i<16; ++i )
00100                         if ( x[i] == rhs.x[i] )
00101                                 ++match;
00102                 if ( match == 16 ) return false;
00103                 return true;
00104         }
00105 
00107         void Row( unsigned i, Vector3F *row ) const     { row->x=x[INDEX(i,0)]; row->y=x[INDEX(i,1)]; row->z=x[INDEX(i,2)]; }
00109         void Col( unsigned i, Vector3F *col ) const     { col->x=x[INDEX(0,i)]; col->y=x[INDEX(1,i)]; col->z=x[INDEX(2,i)]; }
00110 
00112         void Transpose( Matrix4* transpose ) const;
00114         float Determinant() const;
00116         void Adjoint( Matrix4* adjoint ) const;
00118         void Invert( Matrix4* inverse ) const;
00120         void Cofactor( Matrix4* cofactor ) const;
00121 
00122         float SubDeterminant(int excludeRow, int excludeCol) const;
00123 
00125         void ApplyScalar( float v ) {
00126                 for( int i=0; i<16; ++i )
00127                         x[i] *= v;
00128         }
00129 
00130         // Assumes this is a homogenous matrix.
00131         bool IsTranslationOnly() const {
00132                 if ( x[0] == 1.0f && x[5] == 1.0f && x[10] == 1.0f ) {
00133                         if (    x[4] == 0.0f && x[8] == 0.0f && x[9] == 0.0f 
00134                              && x[1] == 0.0f && x[2] == 0.0f && x[6] == 0.0f ) {
00135                                 return true;
00136                         }
00137                 }
00138                 return false;
00139         }
00140 
00141         friend void MultMatrix4( const Matrix4& a, const Matrix4& b, Matrix4* c );
00142         friend void MultMatrix4( const Matrix4& a, const Vector3F& b, Vector3F* c );
00143         
00144         #ifdef DEBUG
00145         void Dump( const char* name ) const
00146         {
00147                 GLOUTPUT(( "Mat%4s: %6.2f %6.2f %6.2f %6.2f\n"
00148                                   "         %6.2f %6.2f %6.2f %6.2f\n"                  
00149                                   "         %6.2f %6.2f %6.2f %6.2f\n"                  
00150                                   "         %6.2f %6.2f %6.2f %6.2f\n",
00151                                   name,
00152                                   x[0], x[4], x[8], x[12], 
00153                                   x[1], x[5], x[9], x[13],                      
00154                                   x[2], x[6], x[10], x[14], 
00155                                   x[3], x[7], x[11], x[15] ));
00156         }
00157         #endif
00158         
00159         // Row-Column notation is backwards from x,y regrettably. Very
00160         // confusing. Just uses array. Increment by one moves down to the next
00161         // row, so that the next columnt is at +4.
00162         union
00163         {
00164                 float x[16];
00165                 struct
00166                 {
00167                         // row-column
00168                         float m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44;
00169                 };
00170         };
00171 
00172         friend Matrix4 operator*( const Matrix4& a, const Matrix4& b )
00173         {       
00174                 Matrix4 result;
00175                 MultMatrix4( a, b, &result );
00176                 return result;
00177         }
00178         friend Vector3F operator*( const Matrix4& a, const Vector3F& b )
00179         {
00180                 Vector3F result;
00181                 MultMatrix4( a, b, &result );
00182                 return result;
00183         }
00184 
00185         friend bool Equal( const Matrix4& a, const Matrix4& b, float epsilon = 0.001f )
00186         {
00187                 for( unsigned i=0; i<16; ++i )
00188                         if ( !grinliz::Equal( a.x[i], b.x[i], epsilon ) )
00189                                 return false;
00190                 return true;
00191         }
00192 
00193 
00194 };
00195 
00196 
00201 inline void MultMatrix4( const Matrix4& a, const Matrix4& b, Matrix4* c )
00202 {
00203         // This does not support the target being one of the sources.
00204         GLASSERT( c != &a && c != &b && &a != &b );
00205 
00206         // The counters are rows and columns of 'c'
00207         for( int i=0; i<4; ++i ) 
00208         {
00209                 for( int j=0; j<4; ++j ) 
00210                 {
00211                         // for c:
00212                         //      j increments the row
00213                         //      i increments the column
00214                         *( c->x + i +4*j )      =   a.x[i+0]  * b.x[j*4+0] 
00215                                                                   + a.x[i+4]  * b.x[j*4+1] 
00216                                                                   + a.x[i+8]  * b.x[j*4+2] 
00217                                                                   + a.x[i+12] * b.x[j*4+3];
00218                 }
00219         }
00220 }
00221 
00222 
00225 inline void MultMatrix4( const Matrix4& m, const Vector3F& v, Vector3F* w )
00226 {
00227         GLASSERT( w != &v );
00228         for( int i=0; i<3; ++i )                        // target row
00229         {
00230                 *( &w->x + i )  =               m.x[i+0]  * v.x 
00231                                                           + m.x[i+4]  * v.y 
00232                                                           + m.x[i+8]  * v.z
00233                                                           + m.x[i+12];                  // assume 1.0
00234         }
00235 }
00236 
00237 //
00239 //inline void MultMatrix4Odd( const Vector3F& b, const Matrix4& a, Vector3F* c )
00240 //{
00241 //      GLASSERT( c != &b );
00242 //
00243 //      for( int i=0; i<3; ++i )                        // target row
00244 //      {
00245 //              *( &c->x + i )  =               a.x[i*4+0]  * b.x 
00246 //                                                        + a.x[i*4+1]  * b.y 
00247 //                                                        + a.x[i*4+2]  * b.z
00248 //                                                        + a.x[i*4+3];                 // assume 1.0
00249 //      }
00250 //}
00251 //
00252 //
00253 
00254 };      // namespace grinliz
00255 
00256 #endif

Generated on Fri Mar 23 19:36:21 2007 for Lilith3D by  doxygen 1.5.1-p1