include/cinder/Matrix44.h
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2011, The Cinder Project: http://libcinder.org All rights reserved.
00003  This code is intended for use with the Cinder C++ library: http://libcinder.org
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 */
00022 
00023 
00024 #pragma once
00025 
00026 #include "cinder/Cinder.h"
00027 #include "cinder/CinderMath.h"
00028 #include "cinder/Vector.h"
00029 
00030 #include "cinder/Matrix22.h"
00031 #include "cinder/Matrix33.h"
00032 #include "cinder/MatrixAffine2.h"
00033 
00034 #include <iomanip>
00035 
00036 namespace cinder { 
00037 
00039 // Matrix44
00040 template< typename T >
00041 class Matrix44 
00042 {
00043 public:
00044     typedef T   TYPE;
00045     typedef T   value_type;
00046     //
00047     static const size_t DIM     = 4;
00048     static const size_t DIM_SQ  = DIM*DIM;
00049     static const size_t MEM_LEN = sizeof(T)*DIM_SQ;
00050 
00051     //
00052     // This class is OpenGL friendly and stores the m as how OpenGL would expect it.
00053     // m[i,j]:
00054     // | m[0,0] m[0,1] m[0,2] m[0,2] |
00055     // | m[1,0] m[1,1] m[1,2] m[1,2] |
00056     // | m[2,0] m[2,1] m[2,2] m[2,2] |
00057     // | m[3,0] m[3,1] m[3,2] m[3,2] |
00058     //
00059     // m[idx]
00060     // | m[ 0] m[ 4] m[ 8] m[12] |
00061     // | m[ 1] m[ 5] m[ 9] m[13] |
00062     // | m[ 2] m[ 6] m[10] m[14] |
00063     // | m[ 3] m[ 7] m[11] m[15] |
00064     //
00065     union {
00066         T m[16];
00067         struct {
00068             // This looks like it's transposed from the above, but it's really not.
00069             // It just has to be written this way so it follows the right ordering
00070             // in the memory layout as well as being mathematically correct.
00071             T m00, m10, m20, m30;
00072             T m01, m11, m21, m31;
00073             T m02, m12, m22, m32;
00074             T m03, m13, m23, m33;
00075         };
00076         // [Cols][Rows]
00077         T mcols[4][4];
00078     };
00079 
00080     Matrix44();
00081     
00082     Matrix44( T s );
00083 
00084     // OpenGL layout - unless srcIsRowMajor is true
00085     Matrix44( const T *dt, bool srcIsRowMajor = false );
00086 
00087     // OpenGL layout: m[0]=d0, m[1]=d1, m[2]=d2 ... m[13]=d13, m[14]=d14, m[15]=d15 - unless srcIsRowMajor is true
00088     Matrix44( T d0, T d1, T d2, T d3, T d4, T d5, T d6, T d7, T d8, T d9, T d10, T d11, T d12, T d13, T d14, T d15, bool srcIsRowMajor = false );
00089 
00090     // Creates matrix with column vectors vx, vy, vz and vw
00091     Matrix44( const Vec3<T> &vx, const Vec3<T> &vy, const Vec3<T> &vz ); 
00092     Matrix44( const Vec4<T> &vx, const Vec4<T> &vy, const Vec4<T> &vz, const Vec4<T> &vw = Vec4<T>( 0, 0, 0, 1 ) ); 
00093 
00094     template< typename FromT >
00095     Matrix44( const Matrix44<FromT>& src );
00096 
00097     Matrix44( const Matrix22<T>& src );
00098     explicit Matrix44( const MatrixAffine2<T> &src );
00099     Matrix44( const Matrix33<T>& src );
00100 
00101     Matrix44( const Matrix44<T>& src );
00102 
00103                         operator T*() { return (T*)m; }
00104                         operator const T*() const { return (const T*)m; }
00105 
00106     Matrix44<T>&        operator=( const Matrix44<T>& rhs );
00107     Matrix44<T>&        operator=( T rhs );
00108     
00109     template< typename FromT >
00110     Matrix44<T>&        operator=( const Matrix44<FromT>& rhs );
00111     
00112     // remaining columns and rows will be filled with identity values
00113     Matrix44<T>&        operator=( const Matrix22<T>& rhs );
00114     Matrix44<T>&        operator=( const MatrixAffine2<T>& rhs );
00115     Matrix44<T>&        operator=( const Matrix33<T>& rhs );
00116 
00117     bool                equalCompare( const Matrix44<T>& rhs, T epsilon ) const;
00118     bool                operator==( const Matrix44<T> &rhs ) const { return equalCompare( rhs, (T)EPSILON ); }
00119     bool                operator!=( const Matrix44<T> &rhs ) const { return ! ( *this == rhs ); }
00120 
00121     Matrix44<T>&        operator*=( const Matrix44<T> &rhs );
00122     Matrix44<T>&        operator+=( const Matrix44<T> &rhs );
00123     Matrix44<T>&        operator-=( const Matrix44<T> &rhs );
00124 
00125     Matrix44<T>&        operator*=( T rhs );
00126     Matrix44<T>&        operator/=( T rhs );
00127     Matrix44<T>&        operator+=( T rhs );
00128     Matrix44<T>&        operator-=( T rhs );
00129 
00130     const Matrix44<T>   operator*( const Matrix44<T> &rhs ) const;
00131     const Matrix44<T>   operator+( const Matrix44<T> &rhs ) const;
00132     const Matrix44<T>   operator-( const Matrix44<T> &rhs ) const;
00133 
00134     // post-multiplies column vector [rhs.x rhs.y rhs.z 1] and divides by w
00135     const Vec3<T>       operator*( const Vec3<T> &rhs ) const;
00136 
00137     // post-multiplies column vector [rhs.x rhs.y rhs.z rhs.w]
00138     const Vec4<T>       operator*( const Vec4<T> &rhs ) const;
00139 
00140     const Matrix44<T>   operator*( T rhs ) const;
00141     const Matrix44<T>   operator/( T rhs ) const;
00142     const Matrix44<T>   operator+( T rhs ) const;
00143     const Matrix44<T>   operator-( T rhs ) const;
00144 
00145     // Accessors
00146     T&                  at( int row, int col );
00147     const T&            at( int row, int col ) const;
00148 
00149     // OpenGL layout - unless srcIsRowMajor is true
00150     void                set( const T *dt, bool srcIsRowMajor = false );
00151     // OpenGL layout: m[0]=d0, m[1]=d1, m[2]=d2 ... m[13]=d13, m[14]=d14, m[15]=d15 - unless srcIsRowMajor is true
00152     void                set( T d0, T d1, T d2, T d3, T d4, T d5, T d6, T d7, T d8, T d9, T d10, T d11, T d12, T d13, T d14, T d15, bool srcIsRowMajor = false );
00153 
00154     Vec4<T>             getColumn( int col ) const;
00155     void                setColumn( int col, const Vec4<T> &v );
00156     
00157     Vec4<T>             getRow( int row ) const;
00158     void                setRow( int row, const Vec4<T> &v );
00159 
00160     void                getColumns( Vec4<T> *c0, Vec4<T> *c1, Vec4<T> *c2, Vec4<T> *c3 ) const;
00161     void                setColumns( const Vec4<T> &c0, const Vec4<T> &c1, const Vec4<T> &c2, const Vec4<T> &c3 );
00162 
00163     void                getRows( Vec4<T> *r0, Vec4<T> *r1, Vec4<T> *r2, Vec4<T> *r3 ) const;
00164     void                setRows( const Vec4<T> &r0, const Vec4<T> &r1, const Vec4<T> &r2, const Vec4<T> &r3 );
00165 
00166     // returns a sub-matrix starting at row, col
00167     Matrix22<T>         subMatrix22( int row, int col ) const;
00168     Matrix33<T>         subMatrix33( int row, int col ) const;
00169 
00170     void                setToNull();
00171     void                setToIdentity();
00172 
00173     T                   determinant() const;
00174     // returns trace of 3x3 submatrix if fullTrace == false, otherwise returns trace of full 4x4 matrix
00175     T                   trace( bool fullTrace = false ) const;
00176 
00177     Matrix44<T>         diagonal() const;
00178 
00179     Matrix44<T>         lowerTriangular() const;
00180     Matrix44<T>         upperTriangular() const;
00181 
00182     void                transpose();
00183     Matrix44<T>         transposed() const;
00184 
00185     void                invert (T epsilon = EPSILON ) { *this = inverted( epsilon ); }
00186     Matrix44<T>         inverted( T epsilon = EPSILON ) const;
00187 
00188     // pre-multiplies row vector v - no divide by w
00189     Vec3<T>             preMultiply( const Vec3<T> &v ) const;
00190     Vec4<T>             preMultiply( const Vec4<T> &v ) const;
00191 
00192     // post-multiplies column vector v - no divide by w
00193     Vec3<T>             postMultiply( const Vec3<T> &v ) const;
00194     Vec4<T>             postMultiply( const Vec4<T> &v ) const;
00195 
00197     void                affineInvert(){ *this = affineInverted(); } 
00198     Matrix44<T>         affineInverted() const;
00199     
00201     void                orthonormalInvert();
00202     Matrix44<T>         orthonormalInverted() const { Matrix44<T> result( *this ); result.orthonormalInvert(); return result; }
00203     
00204     // post-multiplies column vector [rhs.x rhs.y rhs.z 1] and divides by w - same as operator*( const Vec3<T>& )
00205     Vec3<T>             transformPoint( const Vec3<T> &rhs ) const;
00206     
00207     // post-multiplies column vector [rhs.x rhs.y rhs.z 1] but omits divide by w
00208     Vec3<T>             transformPointAffine( const Vec3<T> &rhs ) const;
00209     
00210     // post-multiplies column vector [rhs.x rhs.y rhs.z 0]
00211     Vec3<T>             transformVec( const Vec3<T> &rhs ) const;
00212     Vec4<T>             transformVec( const Vec4<T> &rhs ) const { return transformVec( rhs.xyz() ); }
00213 
00214     // returns the translation values from the last column
00215     Vec4<T>             getTranslate() const { return Vec4<T>( m03, m13, m23, m33 ); }
00216     // sets the translation values in the last column
00217     void                setTranslate( const Vec3<T>& v ) { m03 = v.x; m13 = v.y; m23 = v.z; }
00218     void                setTranslate( const Vec4<T>& v ) { setTranslate( v.xyz() ); }
00219 
00220     // multiplies the current matrix by a translation matrix derived from tr
00221     void                translate( const Vec3<T> &tr ) { *this *= createTranslation( tr ); }
00222     void                translate( const Vec4<T> &tr ) { *this *= createTranslation( tr ); }
00223 
00224     // multiplies the current matrix by the rotation matrix derived using axis and radians
00225     void                rotate( const Vec3<T> &axis, T radians ) { *this *= createRotation( axis, radians ); }
00226     void                rotate( const Vec4<T> &axis, T radians ) { *this *= createRotation( axis, radians ); }
00227     // multiplies the current matrix by the rotation matrix derived using eulerRadians
00228     void                rotate( const Vec3<T> &eulerRadians ) { *this *= createRotation( eulerRadians ); }
00229     void                rotate( const Vec4<T> &eulerRadians ) { *this *= createRotation( eulerRadians ); }
00230     // multiplies the current matrix by the rotation matrix derived using from, to, worldUp
00231     void                rotate( const Vec3<T> &from, const Vec3<T> &to, const Vec3<T> &worldUp ) { *this *= createRotation( from, to, worldUp ); }
00232     void                rotate( const Vec4<T> &from, const Vec4<T> &to, const Vec4<T> &worldUp ) { *this *= createRotation( from, to, worldUp ); }
00233 
00234     // multiplies the current matrix by the scale matrix derived from supplies parameters
00235     void                scale( T s ) { Matrix44 op = createScale( s ); Matrix44 mat = *this; *this = op*mat; }
00236     void                scale( const Vec2<T> &v ) { *this *= createScale( v ); }
00237     void                scale( const Vec3<T> &v ) { *this *= createScale( v ); }
00238     void                scale( const Vec4<T> &v ) { *this *= createScale( v ); }
00239 
00240     // transposes rotation sub-matrix and inverts translation
00241     Matrix44<T>         invertTransform() const;
00242         
00243     // returns an identity matrix
00244     static Matrix44<T>  identity() { return Matrix44( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); }
00245     // returns 1 filled matrix
00246     static Matrix44<T>  one() { return Matrix44( (T)1 ); }
00247     // returns 0 filled matrix
00248     static Matrix44<T>  zero() { return Matrix44( (T)0 ); }
00249 
00250     // creates translation matrix
00251     static Matrix44<T>  createTranslation( const Vec3<T> &v, T w = 1 );
00252     static Matrix44<T>  createTranslation( const Vec4<T> &v ) { return createTranslation( v.xyz(), v.w );}
00253 
00254     // creates rotation matrix
00255     static Matrix44<T>  createRotation( const Vec3<T> &axis, T radians );
00256     static Matrix44<T>  createRotation( const Vec4<T> &axis, T radians ) { return createRotation( axis.xyz(), radians ); }
00257     static Matrix44<T>  createRotation( const Vec3<T> &from, const Vec3<T> &to, const Vec3<T> &worldUp );
00258     static Matrix44<T>  createRotation( const Vec4<T> &from, const Vec4<T> &to, const Vec4<T> &worldUp ) { return createRotation( from.xyz(), to.xyz(), worldUp.xyz() ); }
00259     // equivalent to rotate( zAxis, z ), then rotate( yAxis, y ) then rotate( xAxis, x )
00260     static Matrix44<T>  createRotation( const Vec3<T> &eulerRadians );
00261     static Matrix44<T>  createRotation( const Vec4<T> &eulerRadians ) { return createRotation( eulerRadians.xyz() ); }
00262     // creates rotation matrix from ortho normal basis (u, v, n)
00263     static Matrix44<T>  createRotationOnb( const Vec3<T>& u, const Vec3<T>& v, const Vec3<T>& w );
00264     static Matrix44<T>  createRotationOnb( const Vec4<T>& u, const Vec4<T>& v, const Vec4<T>& w ) { return createRotationOnb( u.xyz(), v.xyz(), w.xyz() ); }
00265 
00266     // creates scale matrix
00267     static Matrix44<T>  createScale( T s );
00268     static Matrix44<T>  createScale( const Vec2<T> &v );
00269     static Matrix44<T>  createScale( const Vec3<T> &v );
00270     static Matrix44<T>  createScale( const Vec4<T> &v );
00271 
00272     // creates a rotation matrix with z-axis aligned to targetDir   
00273     static Matrix44<T>  alignZAxisWithTarget( Vec3<T> targetDir, Vec3<T> upDir );
00274     static Matrix44<T>  alignZAxisWithTarget( Vec4<T> targetDir, Vec4<T> upDir ) { return alignZAxisWithTarget( targetDir.xyz(), upDir.xyz() ); }
00275 
00276     friend std::ostream& operator<<( std::ostream &lhs, const Matrix44<T> &rhs ) {
00277         for( int i = 0; i < 4; i++) {
00278             lhs << " |";
00279             for( int j = 0; j < 4; j++) {
00280                 lhs << std::setw( 12 ) << std::setprecision( 6 ) << rhs.m[j*4+i];
00281             }
00282             lhs << "|" << std::endl;
00283         }
00284         
00285         return lhs;
00286     }
00287 };
00288 
00289 template< typename T >
00290 Matrix44<T>::Matrix44()
00291 {
00292     setToIdentity();
00293 }
00294 
00295 template< typename T >
00296 Matrix44<T>::Matrix44( T s )
00297 {
00298     for( int i = 0; i < DIM_SQ; ++i ) {
00299         m[i] = s;
00300     }
00301 }
00302 
00303 template< typename T >
00304 Matrix44<T>::Matrix44( const T *dt, bool srcIsRowMajor )
00305 {
00306     set( dt, srcIsRowMajor );
00307 }
00308 
00309 template< typename T >
00310 Matrix44<T>::Matrix44( T d0, T d1, T d2, T d3, T d4, T d5, T d6, T d7, T d8, T d9, T d10, T d11, T d12, T d13, T d14, T d15, bool srcIsRowMajor )
00311 {
00312     set(  d0,  d1,  d2,  d3, 
00313         d4,  d5,  d6,  d7, 
00314         d8,  d9, d10, d11, 
00315         d12, d13, d14, d15, srcIsRowMajor );
00316 }
00317 
00318 template< typename T >
00319 Matrix44<T>::Matrix44( const Vec3<T> &vx, const Vec3<T> &vy, const Vec3<T> &vz )
00320 {
00321     m[0] = vx.x; m[4] = vy.x; m[ 8] = vz.x; m[12] = 0;
00322     m[1] = vx.y; m[5] = vy.y; m[ 9] = vz.y; m[13] = 0;
00323     m[2] = vx.z; m[6] = vy.z; m[10] = vz.z; m[14] = 0;
00324     m[3] =    0; m[7] =    0; m[11] =    0; m[15] = 1;
00325 }
00326 
00327 template< typename T >
00328 Matrix44<T>::Matrix44( const Vec4<T> &vx, const Vec4<T> &vy, const Vec4<T> &vz, const Vec4<T> &vw )
00329 {
00330     m[0] = vx.x; m[4] = vy.x; m[ 8] = vz.x; m[12] = vw.x;
00331     m[1] = vx.y; m[5] = vy.y; m[ 9] = vz.y; m[13] = vw.y;
00332     m[2] = vx.z; m[6] = vy.z; m[10] = vz.z; m[14] = vw.z;
00333     m[3] = vx.w; m[7] = vy.w; m[11] = vz.w; m[15] = vw.w;
00334 }
00335 
00336 template< typename T >
00337 template< typename FromT >
00338 Matrix44<T>::Matrix44( const Matrix44<FromT>& src )
00339 {
00340     for( int i = 0; i < DIM_SQ; ++i ) {
00341         m[i] = static_cast<T>( src.m[i] );
00342     }
00343 }
00344 
00345 template< typename T >
00346 Matrix44<T>::Matrix44( const Matrix22<T>& src )
00347 {
00348     setToIdentity();
00349     m00 = src.m00; m01 = src.m01;
00350     m10 = src.m10; m11 = src.m11;
00351 }
00352 
00353 template< typename T >
00354 Matrix44<T>::Matrix44( const MatrixAffine2<T>& src )
00355 {
00356     m[ 0] = src.m[0]; m[ 4] = src.m[2]; m[ 8] = 0; m[12] = src.m[4];
00357     m[ 1] = src.m[1]; m[ 5] = src.m[3]; m[ 9] = 0; m[13] = src.m[5];
00358     m[ 2] = 0;        m[ 6] = 0;        m[10] = 1; m[14] = 0;
00359     m[ 3] = 0;        m[ 7] = 0;        m[11] = 0; m[15] = 1;
00360 }
00361 
00362 template< typename T >
00363 Matrix44<T>::Matrix44( const Matrix33<T>& src )
00364 {
00365     setToIdentity();
00366     m00 = src.m00; m01 = src.m01; m02 = src.m02;
00367     m10 = src.m10; m11 = src.m11; m12 = src.m12;
00368     m20 = src.m20; m21 = src.m21; m22 = src.m22;
00369 }
00370 
00371 template< typename T >
00372 Matrix44<T>::Matrix44( const Matrix44<T>& src )
00373 {
00374     std::memcpy( m, src.m, MEM_LEN );
00375 }
00376 
00377 template< typename T >
00378 Matrix44<T>& Matrix44<T>::operator=( const Matrix44<T>& rhs )
00379 {
00380     std::memcpy( m, rhs.m, MEM_LEN );
00381     return *this;
00382 }
00383 
00384 template< typename T >
00385 Matrix44<T>& Matrix44<T>::operator=( T rhs )
00386 {
00387     for( int i = 0; i < DIM_SQ; i++ ) {
00388         m[i] = rhs;
00389     }
00390     return *this;
00391 }
00392 
00393 template< typename T >
00394 template< typename FromT >
00395 Matrix44<T>& Matrix44<T>::operator=( const Matrix44<FromT>& rhs )
00396 {
00397     for( int i = 0; i < DIM_SQ; i++ ) {
00398         m[i] = static_cast<T>(rhs.m[i]);
00399     }
00400     return *this;
00401 }
00402 
00403 template< typename T >
00404 Matrix44<T>& Matrix44<T>::operator=( const Matrix22<T>& rhs )
00405 {
00406     setToIdentity();
00407     m00 = rhs.m00; m01 = rhs.m01;
00408     m10 = rhs.m10; m11 = rhs.m11;
00409     return *this;
00410 }
00411 
00412 template< typename T >
00413 Matrix44<T>& Matrix44<T>::operator=( const MatrixAffine2<T>& rhs )
00414 {
00415     m[ 0] = rhs.m[0]; m[ 4] = rhs.m[2]; m[ 8] = 0; m[12] = rhs.m[4];
00416     m[ 1] = rhs.m[1]; m[ 5] = rhs.m[3]; m[ 9] = 0; m[13] = rhs.m[5];
00417     m[ 2] = 0;        m[ 6] = 0;        m[10] = 1; m[14] = 0;
00418     m[ 3] = 0;        m[ 7] = 0;        m[11] = 0; m[15] = 1;
00419     return *this;
00420 }
00421 
00422 
00423 
00424 template< typename T >
00425 Matrix44<T>& Matrix44<T>::operator=( const Matrix33<T>& rhs )
00426 {
00427     setToIdentity();
00428     m00 = rhs.m00; m01 = rhs.m01; m02 = rhs.m02;
00429     m10 = rhs.m10; m11 = rhs.m11; m12 = rhs.m12;
00430     m20 = rhs.m20; m21 = rhs.m21; m22 = rhs.m22;
00431     return *this;
00432 }
00433 
00434 template< typename T >
00435 bool Matrix44<T>::equalCompare( const Matrix44<T>& rhs, T epsilon ) const
00436 {
00437     for( int i = 0; i < DIM_SQ; ++i ) {
00438         if( math<T>::abs(m[i] - rhs.m[i]) >= epsilon )
00439             return false;
00440     }
00441     return true;
00442 }
00443 
00444 template< typename T >
00445 inline Matrix44<T>& Matrix44<T>::operator*=( const Matrix44<T> &rhs )
00446 {
00447     Matrix44<T> ret;
00448 
00449     ret.m[ 0] = m[ 0]*rhs.m[ 0] + m[ 4]*rhs.m[ 1] + m[ 8]*rhs.m[ 2] + m[12]*rhs.m[ 3];
00450     ret.m[ 1] = m[ 1]*rhs.m[ 0] + m[ 5]*rhs.m[ 1] + m[ 9]*rhs.m[ 2] + m[13]*rhs.m[ 3];
00451     ret.m[ 2] = m[ 2]*rhs.m[ 0] + m[ 6]*rhs.m[ 1] + m[10]*rhs.m[ 2] + m[14]*rhs.m[ 3];
00452     ret.m[ 3] = m[ 3]*rhs.m[ 0] + m[ 7]*rhs.m[ 1] + m[11]*rhs.m[ 2] + m[15]*rhs.m[ 3];
00453 
00454     ret.m[ 4] = m[ 0]*rhs.m[ 4] + m[ 4]*rhs.m[ 5] + m[ 8]*rhs.m[ 6] + m[12]*rhs.m[ 7];
00455     ret.m[ 5] = m[ 1]*rhs.m[ 4] + m[ 5]*rhs.m[ 5] + m[ 9]*rhs.m[ 6] + m[13]*rhs.m[ 7];
00456     ret.m[ 6] = m[ 2]*rhs.m[ 4] + m[ 6]*rhs.m[ 5] + m[10]*rhs.m[ 6] + m[14]*rhs.m[ 7];
00457     ret.m[ 7] = m[ 3]*rhs.m[ 4] + m[ 7]*rhs.m[ 5] + m[11]*rhs.m[ 6] + m[15]*rhs.m[ 7];
00458 
00459     ret.m[ 8] = m[ 0]*rhs.m[ 8] + m[ 4]*rhs.m[ 9] + m[ 8]*rhs.m[10] + m[12]*rhs.m[11];
00460     ret.m[ 9] = m[ 1]*rhs.m[ 8] + m[ 5]*rhs.m[ 9] + m[ 9]*rhs.m[10] + m[13]*rhs.m[11];
00461     ret.m[10] = m[ 2]*rhs.m[ 8] + m[ 6]*rhs.m[ 9] + m[10]*rhs.m[10] + m[14]*rhs.m[11];
00462     ret.m[11] = m[ 3]*rhs.m[ 8] + m[ 7]*rhs.m[ 9] + m[11]*rhs.m[10] + m[15]*rhs.m[11];
00463 
00464     ret.m[12] = m[ 0]*rhs.m[12] + m[ 4]*rhs.m[13] + m[ 8]*rhs.m[14] + m[12]*rhs.m[15];
00465     ret.m[13] = m[ 1]*rhs.m[12] + m[ 5]*rhs.m[13] + m[ 9]*rhs.m[14] + m[13]*rhs.m[15];
00466     ret.m[14] = m[ 2]*rhs.m[12] + m[ 6]*rhs.m[13] + m[10]*rhs.m[14] + m[14]*rhs.m[15];
00467     ret.m[15] = m[ 3]*rhs.m[12] + m[ 7]*rhs.m[13] + m[11]*rhs.m[14] + m[15]*rhs.m[15];
00468 
00469     for( int i = 0; i < DIM_SQ; ++i ) {
00470         m[i] = ret.m[i];
00471     }
00472 
00473     return *this;
00474 }
00475 
00476 template< typename T >
00477 Matrix44<T>& Matrix44<T>::operator+=( const Matrix44<T> &rhs )
00478 {
00479     for( int i = 0; i < DIM_SQ; ++i ) {
00480         m[i] += rhs.m[i];
00481     }
00482     return *this;
00483 }
00484 
00485 template< typename T >
00486 Matrix44<T>& Matrix44<T>::operator-=( const Matrix44<T> &rhs )
00487 {
00488     for( int i = 0; i < DIM_SQ; ++i ) {
00489         m[i] -= rhs.m[i];
00490     }
00491     return *this;
00492 }
00493 
00494 template< typename T >
00495 Matrix44<T>& Matrix44<T>::operator*=( T rhs )
00496 {
00497     for( int i = 0; i < DIM_SQ; ++i ) {
00498         m[i] *= rhs;
00499     }
00500     return *this;
00501 }
00502 
00503 template< typename T >
00504 Matrix44<T>& Matrix44<T>::operator/=( T rhs )
00505 {
00506     T invS = (T)1/rhs;
00507     for( int i = 0; i < DIM_SQ; ++i ) {
00508         m[i] *= invS;
00509     }
00510     return *this;
00511 }
00512 
00513 template< typename T >
00514 Matrix44<T>& Matrix44<T>::operator+=( T rhs )
00515 {
00516     for( int i = 0; i < DIM_SQ; ++i ) {
00517         m[i] += rhs;
00518     }
00519     return *this;
00520 }
00521 
00522 template< typename T >
00523 Matrix44<T>& Matrix44<T>::operator-=( T rhs )
00524 {
00525     for( int i = 0; i < DIM_SQ; ++i ) {
00526         m[i] -= rhs;
00527     }
00528     return *this;
00529 }
00530 
00531 template< typename T >
00532 inline const Matrix44<T> Matrix44<T>::operator*( const Matrix44<T> &rhs ) const
00533 {
00534     Matrix44<T> ret;
00535 
00536     ret.m[ 0] = m[ 0]*rhs.m[ 0] + m[ 4]*rhs.m[ 1] + m[ 8]*rhs.m[ 2] + m[12]*rhs.m[ 3];
00537     ret.m[ 1] = m[ 1]*rhs.m[ 0] + m[ 5]*rhs.m[ 1] + m[ 9]*rhs.m[ 2] + m[13]*rhs.m[ 3];
00538     ret.m[ 2] = m[ 2]*rhs.m[ 0] + m[ 6]*rhs.m[ 1] + m[10]*rhs.m[ 2] + m[14]*rhs.m[ 3];
00539     ret.m[ 3] = m[ 3]*rhs.m[ 0] + m[ 7]*rhs.m[ 1] + m[11]*rhs.m[ 2] + m[15]*rhs.m[ 3];
00540 
00541     ret.m[ 4] = m[ 0]*rhs.m[ 4] + m[ 4]*rhs.m[ 5] + m[ 8]*rhs.m[ 6] + m[12]*rhs.m[ 7];
00542     ret.m[ 5] = m[ 1]*rhs.m[ 4] + m[ 5]*rhs.m[ 5] + m[ 9]*rhs.m[ 6] + m[13]*rhs.m[ 7];
00543     ret.m[ 6] = m[ 2]*rhs.m[ 4] + m[ 6]*rhs.m[ 5] + m[10]*rhs.m[ 6] + m[14]*rhs.m[ 7];
00544     ret.m[ 7] = m[ 3]*rhs.m[ 4] + m[ 7]*rhs.m[ 5] + m[11]*rhs.m[ 6] + m[15]*rhs.m[ 7];
00545 
00546     ret.m[ 8] = m[ 0]*rhs.m[ 8] + m[ 4]*rhs.m[ 9] + m[ 8]*rhs.m[10] + m[12]*rhs.m[11];
00547     ret.m[ 9] = m[ 1]*rhs.m[ 8] + m[ 5]*rhs.m[ 9] + m[ 9]*rhs.m[10] + m[13]*rhs.m[11];
00548     ret.m[10] = m[ 2]*rhs.m[ 8] + m[ 6]*rhs.m[ 9] + m[10]*rhs.m[10] + m[14]*rhs.m[11];
00549     ret.m[11] = m[ 3]*rhs.m[ 8] + m[ 7]*rhs.m[ 9] + m[11]*rhs.m[10] + m[15]*rhs.m[11];
00550 
00551     ret.m[12] = m[ 0]*rhs.m[12] + m[ 4]*rhs.m[13] + m[ 8]*rhs.m[14] + m[12]*rhs.m[15];
00552     ret.m[13] = m[ 1]*rhs.m[12] + m[ 5]*rhs.m[13] + m[ 9]*rhs.m[14] + m[13]*rhs.m[15];
00553     ret.m[14] = m[ 2]*rhs.m[12] + m[ 6]*rhs.m[13] + m[10]*rhs.m[14] + m[14]*rhs.m[15];
00554     ret.m[15] = m[ 3]*rhs.m[12] + m[ 7]*rhs.m[13] + m[11]*rhs.m[14] + m[15]*rhs.m[15];
00555 
00556     return ret;
00557 }
00558 
00559 template< typename T >
00560 const Matrix44<T> Matrix44<T>::operator+( const Matrix44<T> &rhs ) const
00561 {
00562     Matrix44<T> ret;
00563     for( int i = 0; i < DIM_SQ; ++i ) {
00564         ret.m[i] = m[i] + rhs.m[i];
00565     }
00566     return ret;
00567 }
00568 
00569 template< typename T >
00570 const Matrix44<T> Matrix44<T>::operator-( const Matrix44<T> &rhs ) const
00571 {
00572     Matrix44<T> ret;
00573     for( int i = 0; i < DIM_SQ; ++i ) {
00574         ret.m[i] = m[i] - rhs.m[i];
00575     }
00576     return ret;
00577 }
00578 
00579 template< typename T >
00580 const Vec3<T> Matrix44<T>::operator*( const Vec3<T> &rhs ) const
00581 {
00582     T x = m[ 0]*rhs.x + m[ 4]*rhs.y + m[ 8]*rhs.z + m[12];
00583     T y = m[ 1]*rhs.x + m[ 5]*rhs.y + m[ 9]*rhs.z + m[13];
00584     T z = m[ 2]*rhs.x + m[ 6]*rhs.y + m[10]*rhs.z + m[14];
00585     T w = m[ 3]*rhs.x + m[ 7]*rhs.y + m[11]*rhs.z + m[15];
00586 
00587     return Vec3<T>( x/w, y/w, z/w );
00588 }
00589 
00590 template< typename T >
00591 const Vec4<T> Matrix44<T>::operator*( const Vec4<T> &rhs ) const
00592 {
00593     return Vec4<T>(
00594         m[ 0]*rhs.x + m[ 4]*rhs.y + m[ 8]*rhs.z + m[12]*rhs.w,
00595         m[ 1]*rhs.x + m[ 5]*rhs.y + m[ 9]*rhs.z + m[13]*rhs.w,
00596         m[ 2]*rhs.x + m[ 6]*rhs.y + m[10]*rhs.z + m[14]*rhs.w,
00597         m[ 3]*rhs.x + m[ 7]*rhs.y + m[11]*rhs.z + m[15]*rhs.w
00598         );
00599 }
00600 
00601 template< typename T >
00602 const Matrix44<T> Matrix44<T>::operator*( T rhs ) const
00603 {
00604     Matrix44<T> ret;
00605     for( int i = 0; i < DIM_SQ; ++i ) {
00606         ret.m[i] = m[i]*rhs;
00607     }
00608     return ret;
00609 }
00610 
00611 template< typename T >
00612 const Matrix44<T> Matrix44<T>::operator/( T rhs ) const
00613 {
00614     Matrix44<T> ret;
00615     T s = (T)1/rhs;
00616     for( int i = 0; i < DIM_SQ; ++i ) {
00617         ret.m[i] = m[i]*s;
00618     }
00619     return ret;
00620 }
00621 
00622 template< typename T >
00623 const Matrix44<T> Matrix44<T>::operator+( T rhs ) const
00624 {
00625     Matrix44<T> ret;
00626     for( int i = 0; i < DIM_SQ; ++i ) {
00627         ret.m[i] = m[i] + rhs;
00628     }
00629     return ret;
00630 }
00631 
00632 template< typename T >
00633 const Matrix44<T> Matrix44<T>::operator-( T rhs ) const
00634 {
00635     Matrix44<T> ret;
00636     for( int i = 0; i < DIM_SQ; ++i ) {
00637         ret.m[i] = m[i] - rhs;
00638     }
00639     return ret;
00640 }
00641 
00642 template< typename T >
00643 T& Matrix44<T>::at( int row, int col ) 
00644 {
00645     assert(row >= 0 && row < DIM);
00646     assert(col >= 0 && col < DIM);
00647     return m[col*DIM + row];
00648 }
00649 
00650 template< typename T >
00651 const T& Matrix44<T>::at( int row, int col ) const 
00652 {
00653     assert(row >= 0 && row < DIM);
00654     assert(col >= 0 && col < DIM);
00655     return m[col*DIM + row];
00656 }
00657 
00658 template< typename T >
00659 void Matrix44<T>::set( const T *dt, bool srcIsRowMajor )
00660 {
00661     if( srcIsRowMajor ) {
00662         m[0] = dt[ 0]; m[4] = dt[ 1]; m[ 8] = dt[ 2]; m[12] = dt[ 3];
00663         m[1] = dt[ 4]; m[5] = dt[ 5]; m[ 9] = dt[ 6]; m[13] = dt[ 7];
00664         m[2] = dt[ 8]; m[6] = dt[ 9]; m[10] = dt[10]; m[14] = dt[11];
00665         m[3] = dt[12]; m[7] = dt[13]; m[11] = dt[14]; m[15] = dt[15];
00666     }
00667     else {
00668         std::memcpy( m, dt, MEM_LEN );
00669     }
00670 }
00671 
00672 template< typename T >
00673 void Matrix44<T>::set( T d0, T d1, T d2, T d3, T d4, T d5, T d6, T d7, T d8, T d9, T d10, T d11, T d12, T d13, T d14, T d15, bool srcIsRowMajor )
00674 {
00675     if( srcIsRowMajor ) {
00676         m[0] =  d0; m[4] =  d1; m[ 8] =  d2; m[12] =  d3;
00677         m[1] =  d4; m[5] =  d5; m[ 9] =  d6; m[13] =  d7;
00678         m[2] =  d8; m[6] =  d9; m[10] = d10; m[14] = d11;
00679         m[3] = d12; m[7] = d13; m[11] = d14; m[15] = d15;
00680     }
00681     else {
00682         m[0] =  d0; m[4] =  d4; m[ 8] =  d8; m[12] = d12;
00683         m[1] =  d1; m[5] =  d5; m[ 9] =  d9; m[13] = d13;
00684         m[2] =  d2; m[6] =  d6; m[10] = d10; m[14] = d14;
00685         m[3] =  d3; m[7] =  d7; m[11] = d11; m[15] = d15;
00686     }
00687 }
00688 
00689 template< typename T >
00690 Vec4<T> Matrix44<T>::getColumn( int col ) const
00691 {
00692     size_t i = col*DIM;
00693     return Vec4<T>( 
00694         m[i + 0], 
00695         m[i + 1], 
00696         m[i + 2], 
00697         m[i + 3]
00698     );
00699 }
00700 
00701 template< typename T >
00702 void Matrix44<T>::setColumn( int col, const Vec4<T> &v )
00703 {
00704     size_t i = col*DIM;
00705     m[i + 0] = v.x;
00706     m[i + 1] = v.y;
00707     m[i + 2] = v.z;
00708     m[i + 3] = v.w;
00709 }
00710 
00711 template< typename T >
00712 Vec4<T> Matrix44<T>::getRow( int row ) const 
00713 { 
00714     return Vec4<T>( 
00715         m[row +  0], 
00716         m[row +  4], 
00717         m[row +  8], 
00718         m[row + 12] 
00719     ); 
00720 }
00721 
00722 template< typename T >
00723 void Matrix44<T>::setRow( int row, const Vec4<T> &v ) 
00724 { 
00725     m[row +  0] = v.x; 
00726     m[row +  4] = v.y; 
00727     m[row +  8] = v.z; 
00728     m[row + 12] = v.w; 
00729 }
00730 
00731 template< typename T >
00732 void Matrix44<T>::getColumns( Vec4<T> *c0, Vec4<T> *c1, Vec4<T> *c2, Vec4<T> *c3 ) const
00733 {
00734     *c0 = getColumn( 0 );
00735     *c1 = getColumn( 1 );
00736     *c2 = getColumn( 2 );
00737     *c3 = getColumn( 3 );
00738 }
00739 
00740 template< typename T >
00741 void Matrix44<T>::setColumns( const Vec4<T> &c0, const Vec4<T> &c1, const Vec4<T> &c2, const Vec4<T> &c3 )
00742 {
00743     setColumn( 0, c0 );
00744     setColumn( 1, c1 );
00745     setColumn( 2, c2 );
00746     setColumn( 3, c3 );
00747 }
00748 
00749 template< typename T >
00750 void Matrix44<T>::getRows( Vec4<T> *r0, Vec4<T> *r1, Vec4<T> *r2, Vec4<T> *r3 ) const
00751 {
00752     *r0 = getRow( 0 );
00753     *r1 = getRow( 1 );
00754     *r2 = getRow( 2 );
00755     *r3 = getRow( 3 );
00756 }
00757 
00758 template< typename T >
00759 void Matrix44<T>::setRows( const Vec4<T> &r0, const Vec4<T> &r1, const Vec4<T> &r2, const Vec4<T> &r3 )
00760 {
00761     setRow( 0, r0 );
00762     setRow( 1, r1 );
00763     setRow( 2, r2 );
00764     setRow( 3, r3 );
00765 }
00766 
00767 template< typename T >
00768 Matrix22<T> Matrix44<T>::subMatrix22( int row, int col ) const
00769 {
00770     Matrix22<T> ret;
00771     ret.setToNull();
00772 
00773     for( int i = 0; i < 2; ++i ) {
00774         int r = row + i;
00775         if( r >= 4 ) {
00776             continue;
00777         }
00778         for( int j = 0; j < 2; ++j ) {
00779             int c = col + j;
00780             if( c >= 4 ) {
00781                 continue;
00782             }
00783             ret.at( i, j ) = at( r, c );
00784         }
00785     }
00786 
00787     return ret;
00788 }
00789 
00790 template< typename T >
00791 Matrix33<T> Matrix44<T>::subMatrix33( int row, int col ) const
00792 {
00793     Matrix33<T> ret;
00794     ret.setToNull();
00795 
00796     for( int i = 0; i < 3; ++i ) {
00797         int r = row + i;
00798         if( r >= 4 ) {
00799             continue;
00800         }
00801         for( int j = 0; j < 3; ++j ) {
00802             int c = col + j;
00803             if( c >= 4 ) {
00804                 continue;
00805             }
00806             ret.at( i, j ) = at( r, c );
00807         }
00808     }
00809 
00810     return ret;
00811 }
00812 
00813 template< typename T >
00814 void Matrix44<T>::setToNull()
00815 {
00816     std::memset( m, 0, MEM_LEN );
00817 }
00818 
00819 template< typename T >
00820 void Matrix44<T>::setToIdentity()
00821 {
00822     m[ 0] = 1; m[ 4] = 0; m[ 8] = 0; m[12] = 0;
00823     m[ 1] = 0; m[ 5] = 1; m[ 9] = 0; m[13] = 0;
00824     m[ 2] = 0; m[ 6] = 0; m[10] = 1; m[14] = 0;
00825     m[ 3] = 0; m[ 7] = 0; m[11] = 0; m[15] = 1;
00826 }
00827 
00828 template< typename T >
00829 T Matrix44<T>::determinant() const
00830 {
00831     T a0 = m[ 0]*m[ 5] - m[ 1]*m[ 4];
00832     T a1 = m[ 0]*m[ 6] - m[ 2]*m[ 4];
00833     T a2 = m[ 0]*m[ 7] - m[ 3]*m[ 4];
00834     T a3 = m[ 1]*m[ 6] - m[ 2]*m[ 5];
00835     T a4 = m[ 1]*m[ 7] - m[ 3]*m[ 5];
00836     T a5 = m[ 2]*m[ 7] - m[ 3]*m[ 6];
00837     T b0 = m[ 8]*m[13] - m[ 9]*m[12];
00838     T b1 = m[ 8]*m[14] - m[10]*m[12];
00839     T b2 = m[ 8]*m[15] - m[11]*m[12];
00840     T b3 = m[ 9]*m[14] - m[10]*m[13];
00841     T b4 = m[ 9]*m[15] - m[11]*m[13];
00842     T b5 = m[10]*m[15] - m[11]*m[14];
00843 
00844     T det = a0*b5 - a1*b4 + a2*b3 + a3*b2 - a4*b1 + a5*b0;
00845 
00846     return det;
00847 }
00848 
00849 template< typename T >
00850 T Matrix44<T>::trace( bool fullTrace ) const
00851 {
00852     if( fullTrace ) {
00853         return m00 + m11 + m22 + m33;
00854     }
00855 
00856     return m00 + m11 + m22;
00857 }
00858 
00859 template< typename T >
00860 Matrix44<T> Matrix44<T>::diagonal() const
00861 {
00862     Matrix44 ret;
00863     ret.m00 = m00; ret.m01 =   0; ret.m02 =   0; ret.m03 =   0;
00864     ret.m10 =   0; ret.m11 = m11; ret.m12 =   0; ret.m13 =   0;
00865     ret.m20 =   0; ret.m21 =   0; ret.m22 = m22; ret.m23 =   0;
00866     ret.m30 =   0; ret.m31 =   0; ret.m32 =   0; ret.m33 = m33;
00867     return ret;
00868 }
00869 
00870 template< typename T >
00871 Matrix44<T> Matrix44<T>::lowerTriangular() const
00872 {
00873     Matrix44 ret;
00874     ret.m00 = m00; ret.m01 =   0; ret.m02 =   0; ret.m03 =   0;
00875     ret.m10 = m10; ret.m11 = m11; ret.m12 =   0; ret.m13 =   0;
00876     ret.m20 = m20; ret.m21 = m21; ret.m22 = m22; ret.m23 =   0;
00877     ret.m30 = m30; ret.m31 = m31; ret.m32 = m32; ret.m33 = m33;
00878     return ret;
00879 }
00880 
00881 template< typename T >
00882 Matrix44<T> Matrix44<T>::upperTriangular() const
00883 {
00884     Matrix44 ret;
00885     ret.m00 = m00; ret.m01 = m01; ret.m02 = m02; ret.m03 = m03;
00886     ret.m10 =   0; ret.m11 = m11; ret.m12 = m12; ret.m13 = m13;
00887     ret.m20 =   0; ret.m21 =   0; ret.m22 = m22; ret.m23 = m23;
00888     ret.m30 =   0; ret.m31 =   0; ret.m32 =   0; ret.m33 = m33;
00889     return ret;
00890 }
00891 
00892 template< typename T >
00893 void Matrix44<T>::transpose()
00894 {
00895     T t;
00896     t = m01; m01 = m10; m10 = t;
00897     t = m02; m02 = m20; m20 = t;
00898     t = m03; m03 = m30; m30 = t;
00899     t = m12; m12 = m21; m21 = t;
00900     t = m13; m13 = m31; m31 = t;
00901     t = m23; m23 = m32; m32 = t;
00902 }
00903 
00904 template< typename T >
00905 Matrix44<T> Matrix44<T>::transposed() const
00906 {
00907     return Matrix44<T>( 
00908         m[ 0], m[ 4], m[ 8], m[12],
00909         m[ 1], m[ 5], m[ 9], m[13],
00910         m[ 2], m[ 6], m[10], m[14],
00911         m[ 3], m[ 7], m[11], m[15] 
00912     );
00913 }
00914 
00915 template< typename T >
00916 inline Matrix44<T> Matrix44<T>::inverted( T epsilon ) const
00917 {
00918     Matrix44<T> inv( (T)0 );
00919 
00920     T a0 = m[ 0]*m[ 5] - m[ 1]*m[ 4];
00921     T a1 = m[ 0]*m[ 6] - m[ 2]*m[ 4];
00922     T a2 = m[ 0]*m[ 7] - m[ 3]*m[ 4];
00923     T a3 = m[ 1]*m[ 6] - m[ 2]*m[ 5];
00924     T a4 = m[ 1]*m[ 7] - m[ 3]*m[ 5];
00925     T a5 = m[ 2]*m[ 7] - m[ 3]*m[ 6];
00926     T b0 = m[ 8]*m[13] - m[ 9]*m[12];
00927     T b1 = m[ 8]*m[14] - m[10]*m[12];
00928     T b2 = m[ 8]*m[15] - m[11]*m[12];
00929     T b3 = m[ 9]*m[14] - m[10]*m[13];
00930     T b4 = m[ 9]*m[15] - m[11]*m[13];
00931     T b5 = m[10]*m[15] - m[11]*m[14];
00932 
00933     T det = a0*b5 - a1*b4 + a2*b3 + a3*b2 - a4*b1 + a5*b0;
00934 
00935     if( fabs( det ) > epsilon ) {
00936         inv.m[ 0] = + m[ 5]*b5 - m[ 6]*b4 + m[ 7]*b3;
00937         inv.m[ 4] = - m[ 4]*b5 + m[ 6]*b2 - m[ 7]*b1;
00938         inv.m[ 8] = + m[ 4]*b4 - m[ 5]*b2 + m[ 7]*b0;
00939         inv.m[12] = - m[ 4]*b3 + m[ 5]*b1 - m[ 6]*b0;
00940         inv.m[ 1] = - m[ 1]*b5 + m[ 2]*b4 - m[ 3]*b3;
00941         inv.m[ 5] = + m[ 0]*b5 - m[ 2]*b2 + m[ 3]*b1;
00942         inv.m[ 9] = - m[ 0]*b4 + m[ 1]*b2 - m[ 3]*b0;
00943         inv.m[13] = + m[ 0]*b3 - m[ 1]*b1 + m[ 2]*b0;
00944         inv.m[ 2] = + m[13]*a5 - m[14]*a4 + m[15]*a3;
00945         inv.m[ 6] = - m[12]*a5 + m[14]*a2 - m[15]*a1;
00946         inv.m[10] = + m[12]*a4 - m[13]*a2 + m[15]*a0;
00947         inv.m[14] = - m[12]*a3 + m[13]*a1 - m[14]*a0;
00948         inv.m[ 3] = - m[ 9]*a5 + m[10]*a4 - m[11]*a3;
00949         inv.m[ 7] = + m[ 8]*a5 - m[10]*a2 + m[11]*a1;
00950         inv.m[11] = - m[ 8]*a4 + m[ 9]*a2 - m[11]*a0;
00951         inv.m[15] = + m[ 8]*a3 - m[ 9]*a1 + m[10]*a0;
00952 
00953         T invDet = ((T)1)/det;
00954         inv.m[ 0] *= invDet;
00955         inv.m[ 1] *= invDet;
00956         inv.m[ 2] *= invDet;
00957         inv.m[ 3] *= invDet;
00958         inv.m[ 4] *= invDet;
00959         inv.m[ 5] *= invDet;
00960         inv.m[ 6] *= invDet;
00961         inv.m[ 7] *= invDet;
00962         inv.m[ 8] *= invDet;
00963         inv.m[ 9] *= invDet;
00964         inv.m[10] *= invDet;
00965         inv.m[11] *= invDet;
00966         inv.m[12] *= invDet;
00967         inv.m[13] *= invDet;
00968         inv.m[14] *= invDet;
00969         inv.m[15] *= invDet;
00970     }
00971 
00972     return inv;
00973 }
00974 
00975 template< typename T >
00976 Vec3<T> Matrix44<T>::preMultiply( const Vec3<T> &v ) const
00977 {
00978     return Vec3<T>(
00979         v.x*m00 + v.y*m10 + v.z*m20,
00980         v.x*m01 + v.y*m11 + v.z*m21,
00981         v.x*m02 + v.y*m12 + v.z*m22
00982         );
00983 }
00984 
00985 template< typename T >
00986 Vec4<T> Matrix44<T>::preMultiply( const Vec4<T> &v ) const
00987 {
00988     return Vec4<T>(
00989         v.x*m00 + v.y*m10 + v.z*m20 + v.w*m30,
00990         v.x*m01 + v.y*m11 + v.z*m21 + v.w*m31,
00991         v.x*m02 + v.y*m12 + v.z*m22 + v.w*m32,
00992         v.x*m03 + v.y*m13 + v.z*m23 + v.w*m33
00993         );
00994 }
00995 
00996 template< typename T >
00997 Vec3<T> Matrix44<T>::postMultiply( const Vec3<T> &v ) const
00998 {
00999     return Vec3<T>(
01000         m00*v.x + m01*v.y + m02*v.z,
01001         m10*v.x + m11*v.y + m12*v.z,
01002         m20*v.x + m21*v.y + m22*v.z
01003         );
01004 }
01005 
01006 template< typename T >
01007 Vec4<T> Matrix44<T>::postMultiply( const Vec4<T> &v ) const
01008 {
01009     return Vec4<T>(
01010         m00*v.x + m01*v.y + m02*v.z + m03*v.w,
01011         m10*v.x + m11*v.y + m12*v.z + m13*v.w,
01012         m20*v.x + m21*v.y + m22*v.z + m23*v.w,
01013         m30*v.x + m31*v.y + m32*v.z + m33*v.w
01014         );
01015 }
01016 
01017 template< typename T >
01018 Matrix44<T> Matrix44<T>::affineInverted() const
01019 {
01020     Matrix44<T> ret;
01021 
01022     // compute upper left 3x3 matrix determinant
01023     T cofactor0 = m[ 5]*m[10] - m[6]*m[ 9];
01024     T cofactor4 = m[ 2]*m[ 9] - m[1]*m[10];
01025     T cofactor8 = m[ 1]*m[ 6] - m[2]*m[ 5];
01026     T det = m[0]*cofactor0 + m[4]*cofactor4 + m[8]*cofactor8;
01027     if( fabs( det ) <= EPSILON ) {
01028         return ret;
01029     }
01030 
01031     // create adjunct matrix and multiply by 1/det to get upper 3x3
01032     T invDet = ((T)1.0) / det;
01033     ret.m[ 0] = invDet*cofactor0;
01034     ret.m[ 1] = invDet*cofactor4;
01035     ret.m[ 2] = invDet*cofactor8;
01036 
01037     ret.m[ 4] = invDet*(m[ 6]*m[ 8] - m[ 4]*m[10]);
01038     ret.m[ 5] = invDet*(m[ 0]*m[10] - m[ 2]*m[ 8]);
01039     ret.m[ 6] = invDet*(m[ 2]*m[ 4] - m[ 0]*m[ 6]);
01040 
01041     ret.m[ 8] = invDet*(m[ 4]*m[ 9] - m[ 5]*m[ 8]);
01042     ret.m[ 9] = invDet*(m[ 1]*m[ 8] - m[ 0]*m[ 9]);
01043     ret.m[10] = invDet*(m[ 0]*m[ 5] - m[ 1]*m[ 4]);
01044 
01045     // multiply -translation by inverted 3x3 to get its inverse     
01046     ret.m[12] = -ret.m[ 0]*m[12] - ret.m[ 4]*m[13] - ret.m[ 8]*m[14];
01047     ret.m[13] = -ret.m[ 1]*m[12] - ret.m[ 5]*m[13] - ret.m[ 9]*m[14];
01048     ret.m[14] = -ret.m[ 2]*m[12] - ret.m[ 6]*m[13] - ret.m[10]*m[14];
01049 
01050     return ret;
01051 }
01052 
01053 template< typename T >
01054 Vec3<T> Matrix44<T>::transformPoint( const Vec3<T> &rhs ) const
01055 {
01056     T x = m00*rhs.x + m01*rhs.y + m02*rhs.z + m03;
01057     T y = m10*rhs.x + m11*rhs.y + m12*rhs.z + m13;
01058     T z = m20*rhs.x + m21*rhs.y + m22*rhs.z + m23;
01059     T w = m30*rhs.x + m31*rhs.y + m32*rhs.z + m33;
01060 
01061     return Vec3<T>( x / w, y / w, z / w );
01062 }
01063 
01064 template< typename T >
01065 Vec3<T> Matrix44<T>::transformPointAffine( const Vec3<T> &rhs ) const
01066 {
01067     T x = m00*rhs.x + m01*rhs.y + m02*rhs.z + m03;
01068     T y = m10*rhs.x + m11*rhs.y + m12*rhs.z + m13;
01069     T z = m20*rhs.x + m21*rhs.y + m22*rhs.z + m23;
01070 
01071     return Vec3<T>( x, y, z );
01072 }
01073 
01074 template< typename T >
01075 Vec3<T> Matrix44<T>::transformVec( const Vec3<T> &rhs ) const
01076 {
01077     T x = m00*rhs.x + m01*rhs.y + m02*rhs.z;
01078     T y = m10*rhs.x + m11*rhs.y + m12*rhs.z;
01079     T z = m20*rhs.x + m21*rhs.y + m22*rhs.z;
01080 
01081     return Vec3<T>( x, y, z );
01082 }
01083 
01084 template< typename T > // thanks to @juj/MathGeoLib for fix
01085 void Matrix44<T>::orthonormalInvert()
01086 {
01087     // transpose upper 3x3 (R->R^t)
01088     std::swap( at(0,1), at(1,0) );
01089     std::swap( at(0,2), at(2,0) );
01090     std::swap( at(1,2), at(2,1) );
01091 
01092     // replace translation (T) with R^t(-T).
01093     Vec3f newT( transformVec( Vec3f(-at(0,3),-at(1,3),-at(2,3)) ) );
01094     at(0,3) = newT.x;
01095     at(1,3) = newT.y;
01096     at(2,3) = newT.z;
01097 }
01098 
01099 template<typename T>
01100 Matrix44<T> Matrix44<T>::createTranslation( const Vec3<T> &v, T w )
01101 {
01102     Matrix44 ret;
01103     ret.m[12] = v.x;
01104     ret.m[13] = v.y;
01105     ret.m[14] = v.z;
01106     ret.m[15] = w;
01107 
01108     return ret;
01109 }
01110 
01112 // Matrix44
01113 template<typename T>
01114 Matrix44<T> Matrix44<T>::createRotation( const Vec3<T> &from, const Vec3<T> &to, const Vec3<T> &worldUp )
01115 {
01116     // The goal is to obtain a rotation matrix that takes 
01117     // "fromDir" to "toDir".  We do this in two steps and 
01118     // compose the resulting rotation matrices; 
01119     //    (a) rotate "fromDir" into the z-axis
01120     //    (b) rotate the z-axis into "toDir"
01121  
01122     // The from direction must be non-zero; but we allow zero to and up dirs.
01123     if( from.lengthSquared() == 0 ) {
01124         return Matrix44<T>();
01125     }
01126     else {
01127         Matrix44<T> zAxis2FromDir = alignZAxisWithTarget( from, Vec3<T>::yAxis() );
01128         Matrix44<T> fromDir2zAxis = zAxis2FromDir.transposed();
01129         Matrix44<T> zAxis2ToDir = alignZAxisWithTarget( to, worldUp );
01130         return fromDir2zAxis * zAxis2ToDir;
01131     }
01132 }
01133 
01134 template<typename T>
01135 Matrix44<T> Matrix44<T>::createRotation( const Vec3<T> &axis, T angle )
01136 {
01137     Vec3<T> unit( axis.normalized() );
01138     T sine   = math<T>::sin( angle );
01139     T cosine = math<T>::cos( angle );
01140 
01141     Matrix44<T> ret;
01142 
01143     ret.m[ 0] = unit.x * unit.x * (1 - cosine) + cosine;
01144     ret.m[ 1] = unit.x * unit.y * (1 - cosine) + unit.z * sine;
01145     ret.m[ 2] = unit.x * unit.z * (1 - cosine) - unit.y * sine;
01146     ret.m[ 3] = 0;
01147 
01148     ret.m[ 4] = unit.x * unit.y * (1 - cosine) - unit.z * sine;
01149     ret.m[ 5] = unit.y * unit.y * (1 - cosine) + cosine;
01150     ret.m[ 6] = unit.y * unit.z * (1 - cosine) + unit.x * sine;
01151     ret.m[ 7] = 0;
01152 
01153     ret.m[ 8] = unit.x * unit.z * (1 - cosine) + unit.y * sine;
01154     ret.m[ 9] = unit.y * unit.z * (1 - cosine) - unit.x * sine;
01155     ret.m[10] = unit.z * unit.z * (1 - cosine) + cosine;
01156     ret.m[11] = 0;
01157 
01158     ret.m[12] = 0;
01159     ret.m[13] = 0;
01160     ret.m[14] = 0;
01161     ret.m[15] = 1;
01162 
01163     return ret;
01164 }
01165 
01166 template<typename T>
01167 Matrix44<T> Matrix44<T>::createRotation( const Vec3<T> &eulerRadians )
01168 {
01169     // The ordering for this is XYZ. In OpenGL, the ordering
01170     // is the same, but the operations needs to happen in
01171     // reverse: 
01172     //
01173     //     glRotatef( eulerRadians.z, 0.0f, 0.0f 1.0f );
01174     //     glRotatef( eulerRadians.y, 0.0f, 1.0f 0.0f );
01175     //     glRotatef( eulerRadians.x, 1.0f, 0.0f 0.0f );
01176     //
01177 
01178     Matrix44<T> ret;
01179     T cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx;
01180 
01181     cos_rx = math<T>::cos( eulerRadians.x );
01182     cos_ry = math<T>::cos( eulerRadians.y );
01183     cos_rz = math<T>::cos( eulerRadians.z );
01184 
01185     sin_rx = math<T>::sin( eulerRadians.x );
01186     sin_ry = math<T>::sin( eulerRadians.y );
01187     sin_rz = math<T>::sin( eulerRadians.z );
01188 
01189     ret.m[ 0] =  cos_rz*cos_ry;
01190     ret.m[ 1] =  sin_rz*cos_ry;
01191     ret.m[ 2] = -sin_ry;
01192     ret.m[ 3] =  0;
01193 
01194     ret.m[ 4] = -sin_rz*cos_rx + cos_rz*sin_ry*sin_rx;
01195     ret.m[ 5] =  cos_rz*cos_rx + sin_rz*sin_ry*sin_rx;
01196     ret.m[ 6] =  cos_ry*sin_rx;
01197     ret.m[ 7] =  0;
01198 
01199     ret.m[ 8] =  sin_rz*sin_rx + cos_rz*sin_ry*cos_rx;
01200     ret.m[ 9] = -cos_rz*sin_rx + sin_rz*sin_ry*cos_rx;
01201     ret.m[10] =  cos_ry*cos_rx;
01202     ret.m[11] =  0;
01203 
01204     ret.m[12] =  0;
01205     ret.m[13] =  0;
01206     ret.m[14] =  0;
01207     ret.m[15] =  1;
01208 
01209     return ret;
01210 }
01211 
01212 template<typename T>
01213 Matrix44<T> Matrix44<T>::createRotationOnb( const Vec3<T>& u, const Vec3<T>& v, const Vec3<T>& w )
01214 {
01215     return Matrix44<T>(
01216         u.x,  u.y, u.z, 0,
01217         v.x,  v.y, v.z, 0,
01218         w.x,  w.y, w.z, 0,
01219         0,    0,   0, 1
01220         );
01221 }
01222 
01223 template<typename T>
01224 Matrix44<T> Matrix44<T>::createScale( T s )
01225 {
01226     Matrix44<T> ret;
01227     ret.setToIdentity();
01228     ret.at(0,0) = s;
01229     ret.at(1,1) = s;
01230     ret.at(2,2) = s;
01231     ret.at(3,3) = s;
01232     return ret;
01233 }
01234 
01235 template<typename T>
01236 Matrix44<T> Matrix44<T>::createScale( const Vec2<T> &v )
01237 {
01238     Matrix44<T> ret;
01239     ret.setToIdentity();
01240     ret.at(0,0) = v.x;
01241     ret.at(1,1) = v.y;
01242     ret.at(2,2) = 1;
01243     ret.at(3,3) = 1;
01244     return ret;
01245 }
01246 
01247 template<typename T>
01248 Matrix44<T> Matrix44<T>::createScale( const Vec3<T> &v )
01249 {
01250     Matrix44<T> ret;
01251     ret.setToIdentity();
01252     ret.at(0,0) = v.x;
01253     ret.at(1,1) = v.y;
01254     ret.at(2,2) = v.z;
01255     ret.at(3,3) = 1;
01256     return ret;
01257 }
01258 
01259 template<typename T>
01260 Matrix44<T> Matrix44<T>::createScale( const Vec4<T> &v )
01261 {
01262     Matrix44<T> ret;
01263     ret.setToIdentity();
01264     ret.at(0,0) = v.x;
01265     ret.at(1,1) = v.y;
01266     ret.at(2,2) = v.z;
01267     ret.at(3,3) = v.w;
01268     return ret;
01269 }
01270 
01271 template<typename T>
01272 Matrix44<T> Matrix44<T>::alignZAxisWithTarget( Vec3<T> targetDir, Vec3<T> upDir )
01273 {
01274     // Ensure that the target direction is non-zero.
01275     if( targetDir.lengthSquared() == 0 )
01276         targetDir = Vec3<T>::zAxis();
01277 
01278     // Ensure that the up direction is non-zero.
01279     if( upDir.lengthSquared() == 0 )
01280         upDir = Vec3<T>::yAxis();
01281 
01282     // Check for degeneracies.  If the upDir and targetDir are parallel 
01283     // or opposite, then compute a new, arbitrary up direction that is
01284     // not parallel or opposite to the targetDir.
01285     if( upDir.cross( targetDir ).lengthSquared() == 0 ) {
01286         upDir = targetDir.cross( Vec3<T>::xAxis() );
01287     if( upDir.lengthSquared() == 0 )
01288         upDir = targetDir.cross( Vec3<T>::zAxis() );
01289     }
01290 
01291     // Compute the x-, y-, and z-axis vectors of the new coordinate system.
01292     Vec3<T> targetPerpDir = upDir.cross( targetDir );    
01293     Vec3<T> targetUpDir = targetDir.cross( targetPerpDir );
01294     
01295 
01296     // Rotate the x-axis into targetPerpDir (row 0),
01297     // rotate the y-axis into targetUpDir   (row 1),
01298     // rotate the z-axis into targetDir     (row 2).
01299     Vec3<T> row[3];
01300     row[0] = targetPerpDir.normalized();
01301     row[1] = targetUpDir.normalized();
01302     row[2] = targetDir.normalized();
01303     
01304     Matrix44<T> mat( row[0].x,  row[0].y,  row[0].z,  0,
01305                      row[1].x,  row[1].y,  row[1].z,  0,
01306                      row[2].x,  row[2].y,  row[2].z,  0,
01307                             0,          0,        0,  1 );
01308     
01309     return mat;
01310 }
01311 
01313 // Typedefs
01314 typedef Matrix44<float>  Matrix44f;
01315 typedef Matrix44<double> Matrix44d;
01316 
01317 } // namespace cinder