- Main Page
- Classes
- Files
- Directories
- Related Pages

# 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