Matrix44r.h

Go to the documentation of this file.
00001 /*************************************************************************
00002 *                                                                       *
00003 * Open Physics Abstraction Layer                                        *
00004 * Copyright (C) 2004-2005                                               *
00005 * Alan Fischer  alan.fischer@gmail.com                                  *
00006 * Andres Reinot  andres@reinot.com                                      *
00007 * Tyler Streeter  tylerstreeter@gmail.com                               *
00008 * All rights reserved.                                                  *
00009 * Web: opal.sourceforge.net                                             *
00010 *                                                                       *
00011 * This library is free software; you can redistribute it and/or         *
00012 * modify it under the terms of EITHER:                                  *
00013 *   (1) The GNU Lesser General Public License as published by the Free  *
00014 *       Software Foundation; either version 2.1 of the License, or (at  *
00015 *       your option) any later version. The text of the GNU Lesser      *
00016 *       General Public License is included with this library in the     *
00017 *       file license-LGPL.txt.                                          *
00018 *   (2) The BSD-style license that is included with this library in     *
00019 *       the file license-BSD.txt.                                       *
00020 *                                                                       *
00021 * This library is distributed in the hope that it will be useful,       *
00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
00024 * license-LGPL.txt and license-BSD.txt for more details.                *
00025 *                                                                       *
00026 *************************************************************************/
00027 
00028 #ifndef OPAL_MATRIX44R_H
00029 #define OPAL_MATRIX44R_H
00030 
00031 // project headers
00032 #include "Quaternion.h"
00033 #include "OpalMath.h"
00034 #include "Point3r.h"
00035 #include "Rayr.h"
00036 #include "Vec3r.h"
00037 
00038 namespace opal
00039 {
00040         // Internally the matrix is column major order (openGL)
00041         // the accessors are (row, col), but the set(16 x real) function
00042         // is column, row order because then it is easier to write
00043         // the 16 real out.
00044 
00045         class Matrix44r;
00046         inline Matrix44r operator*( const Matrix44r & lhs, const Matrix44r & rhs );
00047         inline Vec3r operator*( const Matrix44r & m, const Vec3r &v );
00048         inline Matrix44r operator+( const Matrix44r & lhs, const Matrix44r & rhs );
00049         inline Matrix44r operator-( const Matrix44r & lhs, const Matrix44r & rhs );
00050         inline Point3r operator*( const Matrix44r & m, const Point3r &p );
00051         inline Rayr operator*( const Matrix44r & m, const Rayr &r );
00052 
00055         inline bool inverse( Matrix44r & dest, const Matrix44r & src );
00056 
00058         inline void fastInverse( Matrix44r & dest, const Matrix44r & src );
00059 
00061         inline std::ostream& operator<<( std::ostream& o, const Matrix44r& m );
00062 
00064 
00067         class Matrix44r
00068         {
00069                 private:
00070                         real mData[ 16 ];
00071 
00072                 public:
00073                         inline friend Matrix44r operator*( real scalar, Matrix44r m );
00074 
00076                         Matrix44r()
00077                         {
00078                                 makeIdentity();
00079                         }
00080 
00082                         Matrix44r( const Matrix44r & src )
00083                         {
00084                                 memcpy( mData, src.mData, 16 * sizeof( real ) );
00085                         }
00086 
00088                         Matrix44r( real _00, real _10, real _20, real _30,
00089                                    real _01, real _11, real _21, real _31,
00090                                    real _02, real _12, real _22, real _32,
00091                                    real _03, real _13, real _23, real _33 )
00092                         {
00093                                 mData[ 0 ] = _00;
00094                                 mData[ 1 ] = _01;
00095                                 mData[ 2 ] = _02;
00096                                 mData[ 3 ] = _03;
00097 
00098                                 mData[ 4 ] = _10;
00099                                 mData[ 5 ] = _11;
00100                                 mData[ 6 ] = _12;
00101                                 mData[ 7 ] = _13;
00102 
00103                                 mData[ 8 ] = _20;
00104                                 mData[ 9 ] = _21;
00105                                 mData[ 10 ] = _22;
00106                                 mData[ 11 ] = _23;
00107 
00108                                 mData[ 12 ] = _30;
00109                                 mData[ 13 ] = _31;
00110                                 mData[ 14 ] = _32;
00111                                 mData[ 15 ] = _33;
00112                         }
00113 
00115                         Matrix44r( const real * data )
00116                         {
00117                                 memcpy( mData, data, 16 * sizeof( real ) );
00118                         }
00119 
00121                         inline void setPosition( real x, real y, real z )
00122                         {
00123                                 mData[ 12 ] = x;
00124                                 mData[ 13 ] = y;
00125                                 mData[ 14 ] = z;
00126                         }
00127 
00129                         inline Point3r getPosition() const
00130                         {
00131                                 return Point3r( mData[ 12 ], mData[ 13 ], mData[ 14 ] );
00132                         }
00133 
00135                         inline Vec3r getTranslation() const
00136                         {
00137                                 return Vec3r( mData[ 12 ], mData[ 13 ], mData[ 14 ] );
00138                         }
00139 
00141                         inline void set( real _00, real _10, real _20, real _30,
00142                                                  real _01, real _11, real _21, real _31,
00143                                                  real _02, real _12, real _22, real _32,
00144                                                  real _03, real _13, real _23, real _33 )
00145                         {
00146                                 mData[ 0 ] = _00;
00147                                 mData[ 1 ] = _01;
00148                                 mData[ 2 ] = _02;
00149                                 mData[ 3 ] = _03;
00150 
00151                                 mData[ 4 ] = _10;
00152                                 mData[ 5 ] = _11;
00153                                 mData[ 6 ] = _12;
00154                                 mData[ 7 ] = _13;
00155 
00156                                 mData[ 8 ] = _20;
00157                                 mData[ 9 ] = _21;
00158                                 mData[ 10 ] = _22;
00159                                 mData[ 11 ] = _23;
00160 
00161                                 mData[ 12 ] = _30;
00162                                 mData[ 13 ] = _31;
00163                                 mData[ 14 ] = _32;
00164                                 mData[ 15 ] = _33;
00165                         }
00166 
00168                         inline void set( const real * data )
00169                         {
00170                                 memcpy( mData, data, 16 * sizeof( real ) );
00171                         }
00172 
00174                         inline void makeZero()
00175                         {
00176                                 memset( mData, 0, 16 * sizeof( real ) );
00177                         }
00178 
00180                         inline void makeIdentity()
00181                         {
00182                                 mData[ 0 ] = 1;
00183                                 mData[ 1 ] = 0;
00184                                 mData[ 2 ] = 0;
00185                                 mData[ 3 ] = 0;
00186 
00187                                 mData[ 4 ] = 0;
00188                                 mData[ 5 ] = 1;
00189                                 mData[ 6 ] = 0;
00190                                 mData[ 7 ] = 0;
00191 
00192                                 mData[ 8 ] = 0;
00193                                 mData[ 9 ] = 0;
00194                                 mData[ 10 ] = 1;
00195                                 mData[ 11 ] = 0;
00196 
00197                                 mData[ 12 ] = 0;
00198                                 mData[ 13 ] = 0;
00199                                 mData[ 14 ] = 0;
00200                                 mData[ 15 ] = 1;
00201                         }
00202 
00204                         inline void makeScale( real s )
00205                         {
00206                                 set( s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1 );
00207                         }
00208 
00210                         inline void makeScale( real x, real y, real z )
00211                         {
00212                                 set( x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 );
00213                         }
00214 
00216 
00222                         inline void makeRotation( real degrees, real x, real y, real z )
00223                         {
00224                                 Vec3r axis( x, y, z );
00225                                 axis.normalize();
00226                                 x = axis[ 0 ];
00227                                 y = axis[ 1 ];
00228                                 z = axis[ 2 ];
00229 
00230                                 // source: http://www.euclideanspace.com/maths/geometry/rotations/
00231                                 // conversions/angleToMatrix/
00232                                 real radians = degToRad( degrees );
00233                                 real c = cos( radians );
00234                                 real s = sin( radians );
00235                                 real t = ( real ) 1.0 - c;
00236 
00237                                 ( *this ) ( 0, 0 ) = c + x * x * t;
00238                                 ( *this ) ( 1, 1 ) = c + y * y * t;
00239                                 ( *this ) ( 2, 2 ) = c + z * z * t;
00240 
00241                                 real tmp1 = x * y * t;
00242                                 real tmp2 = z * s;
00243                                 ( *this ) ( 1, 0 ) = tmp1 + tmp2;
00244                                 ( *this ) ( 0, 1 ) = tmp1 - tmp2;
00245 
00246                                 tmp1 = x * z * t;
00247                                 tmp2 = y * s;
00248                                 ( *this ) ( 2, 0 ) = tmp1 - tmp2;
00249                                 ( *this ) ( 0, 2 ) = tmp1 + tmp2;
00250 
00251                                 tmp1 = y * z * t;
00252                                 tmp2 = x * s;
00253                                 ( *this ) ( 2, 1 ) = tmp1 + tmp2;
00254                                 ( *this ) ( 1, 2 ) = tmp1 - tmp2;
00255 
00256                                 ( *this ) ( 0, 3 ) = 0;
00257                                 ( *this ) ( 1, 3 ) = 0;
00258                                 ( *this ) ( 2, 3 ) = 0;
00259 
00260                                 ( *this ) ( 3, 0 ) = 0;
00261                                 ( *this ) ( 3, 1 ) = 0;
00262                                 ( *this ) ( 3, 2 ) = 0;
00263                                 ( *this ) ( 3, 3 ) = 1;
00264                         }
00265 
00267                         inline void setQuaternion( real w, real x, real y, real z )
00268                         {
00269                                 real angle;
00270                                 Vec3r axis;
00271                                 Quaternion q( w, x, y, z );
00272                                 q.getAngleAxis( angle, axis );
00273 
00274                                 setRotation( angle, axis.x, axis.y, axis.z );
00275                         }
00276 
00278                         inline void setQuaternion( const Quaternion & q )
00279                         {
00280                                 real angle;
00281                                 Vec3r axis;
00282                                 q.getAngleAxis( angle, axis );
00283 
00284                                 setRotation( angle, axis.x, axis.y, axis.z );
00285                         }
00286 
00288 
00294                         inline void setRotation( real degrees, real x, real y, real z )
00295                         {
00296                                 opal::Point3r p = getPosition();
00297                                 makeRotation( degrees, x, y, z );
00298                                 ( *this ) ( 0, 3 ) = p[ 0 ];
00299                                 ( *this ) ( 1, 3 ) = p[ 1 ];
00300                                 ( *this ) ( 2, 3 ) = p[ 2 ];
00301                         }
00302 
00303                         inline void makeTranslation( real x, real y, real z )
00304                         {
00305                                 set( 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 );
00306                         }
00307 
00309                         inline void scale( real s )
00310                         {
00311                                 Matrix44r m( s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1 );
00312                                 ( *this ) = ( *this ) * m;
00313                         }
00314 
00315                         inline void scale( real x, real y, real z )
00316                         {
00317                                 Matrix44r m( x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 );
00318                                 ( *this ) = ( *this ) * m;
00319                         }
00320 
00321                         // The following function is from
00322                         // http://www.euclideanspace.com/maths/geometry/rotations/
00323                         // conversions/matrixToQuaternion/
00324                         inline Quaternion getQuaternion() const
00325                         {
00326                                 Quaternion q;
00327                                 real trace = ( *this ) ( 0, 0 ) + ( *this ) ( 1, 1 ) + ( *this ) ( 2, 2 ) + 1.0f;
00328 
00329                                 if ( !areEqual( trace, 0 ) )
00330                                 {
00331                                         real s = 0.5f / sqrt( trace );
00332                                         q[ 0 ] = 0.25f / s;
00333                                         q[ 1 ] = ( ( *this ) ( 2, 1 ) - ( *this ) ( 1, 2 ) ) * s;
00334                                         q[ 2 ] = ( ( *this ) ( 0, 2 ) - ( *this ) ( 2, 0 ) ) * s;
00335                                         q[ 3 ] = ( ( *this ) ( 1, 0 ) - ( *this ) ( 0, 1 ) ) * s;
00336                                 }
00337                                 else
00338                                 {
00339                                         if ( ( *this ) ( 0, 0 ) > ( *this ) ( 1, 1 ) && ( *this ) ( 0, 0 ) > ( *this ) ( 2, 2 ) )
00340                                         {
00341                                                 real s = 2 * sqrt( static_cast<real>( 1 + ( *this ) ( 0, 0 ) -
00342                                                                                       ( *this ) ( 1, 1 ) - ( *this ) ( 2, 2 ) ) );
00343                                                 q[ 1 ] = 0.25f * s;
00344                                                 q[ 2 ] = ( ( *this ) ( 0, 1 ) + ( *this ) ( 1, 0 ) ) / s;
00345                                                 q[ 3 ] = ( ( *this ) ( 0, 2 ) + ( *this ) ( 2, 0 ) ) / s;
00346                                                 q[ 0 ] = ( ( *this ) ( 1, 2 ) - ( *this ) ( 2, 1 ) ) / s;
00347                                         }
00348                                         else if ( ( *this ) ( 1, 1 ) > ( *this ) ( 2, 2 ) )
00349                                         {
00350                                                 real s = 2 * sqrt( static_cast<real>( 1 + ( *this ) ( 1, 1 ) -
00351                                                                                       ( *this ) ( 0, 0 ) - ( *this ) ( 2, 2 ) ) );
00352                                                 q[ 1 ] = ( ( *this ) ( 0, 1 ) + ( *this ) ( 1, 0 ) ) / s;
00353                                                 q[ 2 ] = 0.25f * s;
00354                                                 q[ 3 ] = ( ( *this ) ( 1, 2 ) + ( *this ) ( 2, 1 ) ) / s;
00355                                                 q[ 0 ] = ( ( *this ) ( 0, 2 ) - ( *this ) ( 2, 0 ) ) / s;
00356                                         }
00357                                         else
00358                                         {
00359                                                 real s = 2 * sqrt( static_cast<real>( 1 + ( *this ) ( 2, 2 ) -
00360                                                                                       ( *this ) ( 0, 0 ) - ( *this ) ( 1, 1 ) ) );
00361                                                 q[ 1 ] = ( ( *this ) ( 0, 2 ) + ( *this ) ( 2, 0 ) ) / s;
00362                                                 q[ 2 ] = ( ( *this ) ( 1, 2 ) + ( *this ) ( 2, 1 ) ) / s;
00363                                                 q[ 3 ] = 0.25f * s;
00364                                                 q[ 0 ] = ( ( *this ) ( 0, 1 ) - ( *this ) ( 1, 0 ) ) / s;
00365                                         }
00366                                 }
00367 
00368                                 return q;
00369                         }
00370 
00372 
00375                         inline Vec3r getEulerXYZ() const
00376                         {
00377                                 Vec3r angles;
00378 
00379                                 angles[ 1 ] = asin( ( *this ) ( 0, 2 ) );
00380                                 if ( angles[ 1 ] < globals::OPAL_HALF_PI )
00381                                 {
00382                                         if ( angles[ 1 ] > -globals::OPAL_HALF_PI )
00383                                         {
00384                                                 angles[ 0 ] = atan2( -( *this ) ( 1, 2 ), ( *this ) ( 2, 2 ) );
00385                                                 angles[ 2 ] = atan2( -( *this ) ( 0, 1 ), ( *this ) ( 0, 0 ) );
00386                                         }
00387                                         else
00388                                         {
00389                                                 // This is not a unique solution.
00390                                                 real value = atan2( ( *this ) ( 1, 0 ), ( *this ) ( 1, 1 ) );
00391                                                 angles[ 2 ] = 0;
00392                                                 angles[ 0 ] = angles[ 2 ] - value;
00393                                         }
00394                                 }
00395                                 else
00396                                 {
00397                                         // This is not a unique solution.
00398                                         real value = atan2( ( *this ) ( 1, 0 ), ( *this ) ( 1, 1 ) );
00399                                         angles[ 2 ] = 0;
00400                                         angles[ 0 ] = value - angles[ 2 ];
00401                                 }
00402 
00403                                 // convert to degrees
00404                                 angles[ 0 ] = radToDeg( angles[ 0 ] );
00405                                 angles[ 1 ] = radToDeg( angles[ 1 ] );
00406                                 angles[ 2 ] = radToDeg( angles[ 2 ] );
00407 
00408                                 // normalize to (-180,180]
00409                                 angles[ 0 ] = normalizeDegrees( angles[ 0 ] );
00410                                 angles[ 1 ] = normalizeDegrees( angles[ 1 ] );
00411                                 angles[ 2 ] = normalizeDegrees( angles[ 2 ] );
00412 
00413                                 return angles;
00414                         }
00415 
00417                         inline void preScale( real s )
00418                         {
00419                                 Matrix44r m( s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1 );
00420                                 ( *this ) = m * ( *this );
00421                         }
00422 
00423                         inline void preScale( real x, real y, real z )
00424                         {
00425                                 Matrix44r m( x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 );
00426                                 ( *this ) = m * ( *this );
00427                         }
00428 
00430 
00438                         inline void rotate( real degrees, real x, real y, real z )
00439                         {
00440                                 Matrix44r m;
00441                                 m.makeRotation( degrees, x, y, z );
00442                                 ( *this ) = ( *this ) * m;
00443                         }
00444 
00446 
00454                         inline void preRotate( real degrees, real x, real y, real z )
00455                         {
00456                                 Matrix44r m;
00457                                 m.makeRotation( degrees, x, y, z );
00458                                 ( *this ) = m * ( *this );
00459                         }
00460 
00461                         inline void translate( real x, real y, real z )
00462                         {
00463                                 Matrix44r m( 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 );
00464                                 ( *this ) = ( *this ) * m;
00465                         }
00466 
00467                         inline void preTranslate( real x, real y, real z )
00468                         {
00469                                 Matrix44r m( 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 );
00470                                 ( *this ) = m * ( *this );
00471                         }
00472 
00473                         inline real * getData()
00474                         {
00475                                 return mData;
00476                         }
00477 
00478                         inline const real * getData() const
00479                         {
00480                                 return mData;
00481                         }
00482 
00483                         inline real & operator[] ( unsigned int i )
00484                         {
00485                                 return mData[ i ];
00486                         }
00487 
00488                         inline const real & operator[] ( unsigned int i ) const
00489                         {
00490                                 return mData[ i ];
00491                         }
00492 
00493                         inline real & operator() ( unsigned int row, unsigned int col )
00494                         {
00495                                 return mData[ 4 * col + row ];
00496                         }
00497 
00498                         inline const real & operator() ( unsigned int row, unsigned int col ) const
00499                         {
00500                                 return mData[ 4 * col + row ];
00501                         }
00502 
00503                         inline void operator*=( const Matrix44r &m )
00504                         {
00505                                 ( *this ) = ( *this ) * m;
00506                         }
00507 
00508                         inline bool operator==( const Matrix44r & m ) const
00509                         {
00510                                 for ( int i = 0; i < 16; ++i )
00511                                 {
00512                                         if ( mData[ i ] != m[ i ] ) return false;
00513                                 }
00514 
00515                                 return true;
00516                         }
00517 
00518                         inline bool operator!=( const Matrix44r & m ) const
00519                         {
00520                                 for ( int i = 0; i < 16; ++i )
00521                                 {
00522                                         if ( mData[ i ] != m[ i ] ) return true;
00523                                 }
00524 
00525                                 return false;
00526                         }
00527 
00528                         inline void swap( real & a, real & b )
00529                         {
00530                                 real temp = a;
00531                                 a = b;
00532                                 b = temp;
00533                         }
00534 
00535                         inline void transpose()
00536                         {
00537                                 swap( mData[ 1 ], mData[ 4 ] );
00538                                 swap( mData[ 2 ], mData[ 8 ] );
00539                                 swap( mData[ 3 ], mData[ 12 ] );
00540 
00541                                 swap( mData[ 6 ], mData[ 9 ] );
00542                                 swap( mData[ 7 ], mData[ 13 ] );
00543                                 swap( mData[ 11 ], mData[ 14 ] );
00544                         }
00545 
00546                         inline real determinant() const
00547                         {
00548                                 real det1 = ( *this ) ( 1, 2 ) * ( *this ) ( 2, 3 ) - ( *this ) ( 2, 2 ) *
00549                                             ( *this ) ( 1, 3 );
00550                                 real det2 = ( *this ) ( 1, 1 ) * ( *this ) ( 2, 3 ) - ( *this ) ( 2, 1 ) *
00551                                             ( *this ) ( 1, 3 );
00552                                 real det3 = ( *this ) ( 1, 1 ) * ( *this ) ( 2, 2 ) - ( *this ) ( 2, 1 ) *
00553                                             ( *this ) ( 1, 2 );
00554                                 real det4 = ( *this ) ( 1, 0 ) * ( *this ) ( 2, 3 ) - ( *this ) ( 2, 0 ) *
00555                                             ( *this ) ( 1, 3 );
00556                                 real det5 = ( *this ) ( 1, 0 ) * ( *this ) ( 2, 2 ) - ( *this ) ( 2, 0 ) *
00557                                             ( *this ) ( 1, 2 );
00558                                 real det6 = ( *this ) ( 1, 0 ) * ( *this ) ( 2, 1 ) - ( *this ) ( 2, 0 ) *
00559                                             ( *this ) ( 1, 1 );
00560 
00561                                 return -( *this ) ( 3, 0 ) * ( ( *this ) ( 0, 1 ) * det1 - ( *this ) ( 0, 2 ) *
00562                                                                det2 + ( *this ) ( 0, 3 ) * det3 ) + ( *this ) ( 3, 1 ) * ( ( *this ) ( 0, 0 ) *
00563                                                                        det1 - ( *this ) ( 0, 2 ) * det4 + ( *this ) ( 0, 3 ) * det5 ) -
00564                                        ( *this ) ( 3, 2 ) * ( ( *this ) ( 0, 0 ) * det2 - ( *this ) ( 0, 1 ) * det4 +
00565                                                               ( *this ) ( 0, 3 ) * det6 ) + ( *this ) ( 3, 3 ) * ( ( *this ) ( 0, 0 ) * det3 -
00566                                                                       ( *this ) ( 0, 1 ) * det5 + ( *this ) ( 0, 2 ) * det6 );
00567                         }
00568 
00569                         inline bool invert()
00570                         {
00571                                 return inverse( *this, *this );
00572                         }
00573 
00574                         inline void fastInvert()
00575                         {
00576                                 fastInverse( *this, *this );
00577                         }
00578 
00580                         inline Vec3r getForward() const
00581                         {
00582                                 return ( *this ) * Vec3r( 0, 0, -1 );
00583                         }
00584 
00586                         inline Vec3r getUp() const
00587                         {
00588                                 return ( *this ) * Vec3r( 0, 1, 0 );
00589                         }
00590 
00592                         inline Vec3r getRight() const
00593                         {
00594                                 return ( *this ) * Vec3r( 1, 0, 0 );
00595                         }
00596         };
00597 
00598         inline bool inverse( Matrix44r & dest, const Matrix44r & src )
00599         {
00600                 real det = src.determinant();
00601                 if ( areEqual( det, 0 ) )
00602                 {
00603                         return false;
00604                 }
00605                 dest = ( ( real ) 1.0 / det ) * src;
00606                 return true;
00607         }
00608 
00609         inline void fastInverse( Matrix44r & result, const Matrix44r & source )
00610         {
00611                 // source: stolen straight from GMTL
00612                 // in case &dest is == &source... :(
00613                 Matrix44r src = source;
00614 
00615                 // The rotational part of the matrix is simply the transpose of the
00616                 // original matrix.
00617                 for ( int x = 0; x < 3; ++x )
00618                 {
00619                         for ( int y = 0; y < 3; ++y )
00620                         {
00621                                 result( x, y ) = src( y, x );
00622                         }
00623                 }
00624 
00625                 real l0 = Vec3r( result( 0, 0 ), result( 0, 1 ),
00626                                  result( 0, 2 ) ).lengthSquared();
00627                 real l1 = Vec3r( result( 1, 0 ), result( 1, 1 ),
00628                                  result( 1, 2 ) ).lengthSquared();
00629                 real l2 = Vec3r( result( 2, 0 ), result( 2, 1 ),
00630                                  result( 2, 2 ) ).lengthSquared();
00631 
00632                 if ( !areEqual( l0, 0 ) )
00633                 {
00634                         l0 = 1.0f / l0;
00635                 }
00636 
00637                 if ( !areEqual( l1, 0 ) )
00638                 {
00639                         l1 = 1.0f / l1;
00640                 }
00641 
00642                 if ( !areEqual( l2, 0 ) )
00643                 {
00644                         l2 = 1.0f / l2;
00645                 }
00646 
00647                 // apply the inverse scale to the 3x3
00648                 // for each axis: normalize it (1/length), and then mult by inverse
00649                 // scale (1/length)
00650                 result( 0, 0 ) *= l0;
00651                 result( 0, 1 ) *= l0;
00652                 result( 0, 2 ) *= l0;
00653                 result( 1, 0 ) *= l1;
00654                 result( 1, 1 ) *= l1;
00655                 result( 1, 2 ) *= l1;
00656                 result( 2, 0 ) *= l2;
00657                 result( 2, 1 ) *= l2;
00658                 result( 2, 2 ) *= l2;
00659 
00660                 // The right column vector of the matrix should always be [ 0 0 0 s ]
00661                 // this represents some shear values
00662                 result( 3, 0 ) = result( 3, 1 ) = result( 3, 2 ) = 0;
00663 
00664                 // The translation components of the original matrix.
00665                 const real& tx = src( 0, 3 );
00666                 const real& ty = src( 1, 3 );
00667                 const real& tz = src( 2, 3 );
00668 
00669                 // invert scale.
00670 
00671                 const real tw = !areEqual( src( 3, 3 ), 0 )
00672                                 ? 1.0f / src( 3, 3 ) : 0.0f;
00673 
00674                 // handle uniform scale in Nx4 matrices
00675                 result( 0, 3 ) = -( result( 0, 0 ) * tx + result( 0, 1 ) * ty +
00676                                     result( 0, 2 ) * tz ) * tw;
00677                 result( 1, 3 ) = -( result( 1, 0 ) * tx + result( 1, 1 ) * ty +
00678                                     result( 1, 2 ) * tz ) * tw;
00679                 result( 2, 3 ) = -( result( 2, 0 ) * tx + result( 2, 1 ) * ty +
00680                                     result( 2, 2 ) * tz ) * tw;
00681                 result( 3, 3 ) = tw;
00682         }
00683 
00684         inline Matrix44r operator*( real scalar, Matrix44r m )
00685         {
00686                 for ( unsigned int i = 0; i < 16; ++i )
00687                 {
00688                         m.mData[ i ] *= scalar;
00689                 }
00690 
00691                 return m;
00692         }
00693 
00694         inline Matrix44r operator*( const Matrix44r & lhs, const Matrix44r & rhs )
00695         {
00696                 Matrix44r res; // prevent aliasing
00697                 res.makeZero();
00698 
00699                 // source: p. 150 Numerical Analysis (second ed.)
00700                 // if A is m x p, and B is p x n, then AB is m x n
00701                 // (AB)ij = [k = 1 to p] (a)ik (b)kj (where:  1 <= i <= m, 1 <= j <= n)
00702                 for ( unsigned int i = 0; i < 4; ++i )          // 1 <= i <= m
00703                         for ( unsigned int j = 0; j < 4; ++j )          // 1 <= j <= n
00704                                 for ( unsigned int k = 0; k < 4; ++k )          // [k = 1 to p]
00705                                         res( i, j ) += lhs( i, k ) * rhs( k, j );
00706                 return res;
00707         }
00708 
00709         inline Vec3r operator*( const Matrix44r & m, const Vec3r &v )
00710         {
00711                 return Vec3r( m( 0, 0 ) * v[ 0 ] + m( 0, 1 ) * v[ 1 ] + m( 0, 2 ) * v[ 2 ],
00712                               m( 1, 0 ) * v[ 0 ] + m( 1, 1 ) * v[ 1 ] + m( 1, 2 ) * v[ 2 ],
00713                               m( 2, 0 ) * v[ 0 ] + m( 2, 1 ) * v[ 1 ] + m( 2, 2 ) * v[ 2 ] );
00714         }
00715 
00716         inline Point3r operator*( const Matrix44r & m, const Point3r &p )
00717         {
00718                 return Point3r(
00719                            m( 0, 0 ) * p[ 0 ] + m( 0, 1 ) * p[ 1 ] + m( 0, 2 ) * p[ 2 ] + m( 0, 3 ),
00720                            m( 1, 0 ) * p[ 0 ] + m( 1, 1 ) * p[ 1 ] + m( 1, 2 ) * p[ 2 ] + m( 1, 3 ),
00721                            m( 2, 0 ) * p[ 0 ] + m( 2, 1 ) * p[ 1 ] + m( 2, 2 ) * p[ 2 ] + m( 2, 3 ) );
00722         }
00723 
00724         inline Matrix44r operator+( const Matrix44r & lhs, const Matrix44r & rhs )
00725         {
00726                 Matrix44r res;
00727                 for ( unsigned int i = 0; i < 16; ++i )
00728                 {
00729                         res[ i ] = lhs[ i ] + rhs[ i ];
00730                 }
00731                 return res;
00732         }
00733 
00734         inline Matrix44r operator-( const Matrix44r & lhs, const Matrix44r & rhs )
00735         {
00736                 Matrix44r res;
00737                 for ( unsigned int i = 0; i < 16; ++i )
00738                 {
00739                         res[ i ] = lhs[ i ] - rhs[ i ];
00740                 }
00741                 return res;
00742         }
00743 
00744         inline Rayr operator*( const Matrix44r & m, const Rayr & r )
00745         {
00746                 Rayr ray( m * r.getOrigin(), m * r.getDir() );
00747                 return ray;
00748         }
00749 
00750         inline std::ostream& operator<<( std::ostream& o, const Matrix44r& m )
00751         {
00752                 return o
00753                        << "[" << m[ 0 ] << " " << m[ 1 ] << " " << m[ 2 ] << " " << m[ 3 ]
00754                        << "]" << std::endl
00755                        << "[" << m[ 4 ] << " " << m[ 5 ] << " " << m[ 6 ] << " " << m[ 7 ]
00756                        << "]" << std::endl
00757                        << "[" << m[ 8 ] << " " << m[ 9 ] << " " << m[ 10 ] << " " << m[ 11 ]
00758                        << "]" << std::endl
00759                        << "[" << m[ 12 ] << " " << m[ 13 ] << " " << m[ 14 ] << " " << m[ 15 ]
00760                        << "]";
00761         }
00762 }
00763 
00764 #endif

Generated on Tue May 16 17:49:51 2006 for OPAL by  doxygen 1.4.6-NO