glmatrix.h

00001 /*
00002 Copyright (c) 2000-2003 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 
00050         Matrix4()                               {       SetIdentity();  }
00051         void SetIdentity()              {       x[0] = x[5] = x[10] = x[15] = 1.0f;
00052                                                                 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; 
00053                                                         }
00054         void SetTranslation( float _x, float _y, float _z )
00055                                                         {       x[12] = _x;     x[13] = _y;     x[14] = _z;     }
00056         void SetTranslation( const Vector3F& vec )
00057                                                         {   x[12] = vec.x;      x[13] = vec.y;  x[14] = vec.z;  }
00058 
00059         void SetXRotation( float thetaDegree );
00060         void SetYRotation( float thetaDegree );
00061         void SetZRotation( float thetaDegree );
00062 
00063         void SetScale( float scale )    { x[0] = x[5] = x[10] = scale; }
00064 
00065         void SetAxisAngle( const Vector3F& axis, float angle );
00066 
00067         void StripTrans()               {       x[12] = x[13] = x[14] = 0.0f;
00068                                                                 x[15] = 1.0f;
00069                                                         }
00070 
00071         // Is this probably a rotation matrix?
00072         bool IsRotation() const;
00073 
00074         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)]; }
00075         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)]; }
00076 
00077         void Transpose( Matrix4* transpose ) const;
00078         float Determinant() const;
00079         void Adjoint( Matrix4* adjoint ) const;
00080         void Invert( Matrix4* inverse ) const;
00081         void Cofactor( Matrix4* cofactor ) const;
00082         float SubDeterminant(int excludeRow, int excludeCol) const;
00083 
00084         void ApplyScalar( float v ) {
00085                 for( int i=0; i<16; ++i )
00086                         x[i] *= v;
00087         }
00088 
00089         // Assumes this is a homogenous matrix.
00090         bool IsTranslationOnly() const {
00091                 if ( x[0] == 1.0f && x[5] == 1.0f && x[10] == 1.0f ) {
00092                         if (    x[4] == 0.0f && x[8] == 0.0f && x[9] == 0.0f 
00093                              && x[1] == 0.0f && x[2] == 0.0f && x[6] == 0.0f ) {
00094                                 return true;
00095                         }
00096                 }
00097                 return false;
00098         }
00099 
00100         friend void MultMatrix4( const Matrix4& a, const Matrix4& b, Matrix4* c );
00101         friend void MultMatrix4( const Matrix4& a, const Vector3F& b, Vector3F* c );
00102         
00103         #ifdef DEBUG
00104         void Dump( const char* name ) const
00105         {
00106                 GLOUTPUT(( "Mat%4s: %6.2f %6.2f %6.2f %6.2f\n"
00107                                   "         %6.2f %6.2f %6.2f %6.2f\n"                  
00108                                   "         %6.2f %6.2f %6.2f %6.2f\n"                  
00109                                   "         %6.2f %6.2f %6.2f %6.2f\n",
00110                                   name,
00111                                   x[0], x[4], x[8], x[12], 
00112                                   x[1], x[5], x[9], x[13],                      
00113                                   x[2], x[6], x[10], x[14], 
00114                                   x[3], x[7], x[11], x[15] ));
00115         }
00116         #endif
00117         
00118         // Row-Column notation is backwards from x,y regrettably. Very
00119         // confusing. Just uses array. Increment by one moves down to the next
00120         // row, so that the next columnt is at +4.
00121         union
00122         {
00123                 float x[16];
00124                 struct
00125                 {
00126                         // row-column
00127                         float m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44;
00128                 };
00129         };
00130 
00131         friend Matrix4 operator*( const Matrix4& a, const Matrix4& b )
00132         {       
00133                 Matrix4 result;
00134                 MultMatrix4( a, b, &result );
00135                 return result;
00136         }
00137         friend Vector3F operator*( const Matrix4& a, const Vector3F& b )
00138         {
00139                 Vector3F result;
00140                 MultMatrix4( a, b, &result );
00141                 return result;
00142         }
00143 
00144         friend bool Equal( const Matrix4& a, const Matrix4& b, float epsilon = 0.001f )
00145         {
00146                 for( unsigned i=0; i<16; ++i )
00147                         if ( !grinliz::Equal( a.x[i], b.x[i], epsilon ) )
00148                                 return false;
00149                 return true;
00150         }
00151 };
00152 
00153 
00158 inline void MultMatrix4( const Matrix4& a, const Matrix4& b, Matrix4* c )
00159 {
00160         // This does not support the target being one of the sources.
00161         GLASSERT( c != &a && c != &b && &a != &b );
00162 
00163         // The counters are rows and columns of 'c'
00164         for( int i=0; i<4; ++i ) 
00165         {
00166                 for( int j=0; j<4; ++j ) 
00167                 {
00168                         // for c:
00169                         //      j increments the row
00170                         //      i increments the column
00171                         *( c->x + i +4*j )      =   a.x[i+0]  * b.x[j*4+0] 
00172                                                                   + a.x[i+4]  * b.x[j*4+1] 
00173                                                                   + a.x[i+8]  * b.x[j*4+2] 
00174                                                                   + a.x[i+12] * b.x[j*4+3];
00175                 }
00176         }
00177 }
00178 
00179 
00182 inline void MultMatrix4( const Matrix4& m, const Vector3F& v, Vector3F* w )
00183 {
00184         GLASSERT( w != &v );
00185         for( int i=0; i<3; ++i )                        // target row
00186         {
00187                 *( &w->x + i )  =               m.x[i+0]  * v.x 
00188                                                           + m.x[i+4]  * v.y 
00189                                                           + m.x[i+8]  * v.z
00190                                                           + m.x[i+12];                  // assume 1.0
00191         }
00192 }
00193 
00194 //
00196 //inline void MultMatrix4Odd( const Vector3F& b, const Matrix4& a, Vector3F* c )
00197 //{
00198 //      GLASSERT( c != &b );
00199 //
00200 //      for( int i=0; i<3; ++i )                        // target row
00201 //      {
00202 //              *( &c->x + i )  =               a.x[i*4+0]  * b.x 
00203 //                                                        + a.x[i*4+1]  * b.y 
00204 //                                                        + a.x[i*4+2]  * b.z
00205 //                                                        + a.x[i*4+3];                 // assume 1.0
00206 //      }
00207 //}
00208 //
00209 //
00210 
00211 };      // namespace grinliz
00212 
00213 #endif

Generated on Thu Jul 20 20:45:31 2006 for Kyra by  doxygen 1.4.7