Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Matrix4

Go to the documentation of this file.
00001 /* **-*-c++-*-**************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Matrix4 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.12 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #ifndef _BASE_MATRIX4_
00026 #define _BASE_MATRIX4_
00027 
00028 #include <iostream>
00029 
00030 #include <base/base>
00031 #include <base/Object>
00032 #include <base/consts>
00033 #include <base/Vector3>
00034 #include <base/Point3>
00035 #include <base/Vector4>
00036 #include <base/Matrix3>
00037 
00038 #ifdef USE_OSG
00039 #include <osg/Matrix>
00040 #endif
00041 
00042 
00043 #define MATRIX4_ACCESS(r,c) (4*(c-1)+r-1)
00044 
00045 
00046 namespace base {
00047 
00048 class Matrix4;
00049 
00050 // classes to help speed up common vector/matrix operations
00051 //  (not used directly by the user)
00052 
00053 struct M4V4mul {
00054   const Matrix4& m;
00055   const Vector4& v;
00056 
00057   M4V4mul(const Matrix4& mm, const Vector4& vv) : m(mm), v(vv) {}
00058 
00059   operator Vector4() const;
00060 };
00061 
00062 struct M4V4mulV4add {
00063   const Matrix4& m;
00064   const Vector4& v;
00065   const Vector4& v2;
00066 
00067   M4V4mulV4add(const M4V4mul& mv, const Vector4& vv) : m(mv.m), v(mv.v), v2(vv) {}
00068 
00069   operator Vector4() const;
00070 };
00071 
00072 
00073 //
00074 // The matrix
00075 //
00076 
00077 class Matrix4
00078 {
00079 
00080 public:
00081   Matrix4() { setIdentity(); }
00082   Matrix4(const Matrix4& m) { this->operator=(m); }
00083   Matrix4(const Matrix3& m) 
00084   {
00085     e(1,1)=m.e(1,1); e(1,2)=m.e(1,2); e(1,3)=m.e(1,3); e(1,4)=0;
00086     e(2,1)=m.e(2,1); e(2,2)=m.e(2,2); e(2,3)=m.e(2,3); e(2,4)=0;
00087     e(3,1)=m.e(3,1); e(3,2)=m.e(3,2); e(3,3)=m.e(3,3); e(3,4)=0;
00088     e(4,1) = e(4,2) = e(4,3) = 0; e(4,4) = 1;
00089   } 
00090   explicit Matrix4(const Real& s) { setDiag(s); }
00091   Matrix4(Real e11, Real e12, Real e13, Real e14,
00092           Real e21, Real e22, Real e23, Real e24,
00093           Real e31, Real e32, Real e33, Real e34,
00094           Real e41, Real e42, Real e43, Real e44)
00095   {
00096     e(1,1)=e11; e(1,2)=e12; e(1,3)=e13; e(1,4)=e14;
00097     e(2,1)=e21; e(2,2)=e22; e(2,3)=e23; e(2,4)=e24;
00098     e(3,1)=e31; e(3,2)=e32; e(3,3)=e33; e(3,4)=e34;
00099     e(4,1)=e41; e(4,2)=e42; e(4,3)=e43; e(4,4)=e44;
00100   }
00101   Matrix4(const Matrix3& orientation, const Point3& translation)
00102   {
00103     const Matrix3& m(orientation);
00104     e(1,1)=m.e(1,1); e(1,2)=m.e(1,2); e(1,3)=m.e(1,3); e(1,4)=translation.x;
00105     e(2,1)=m.e(2,1); e(2,2)=m.e(2,2); e(2,3)=m.e(2,3); e(2,4)=translation.y;
00106     e(3,1)=m.e(3,1); e(3,2)=m.e(3,2); e(3,3)=m.e(3,3); e(3,4)=translation.z;
00107     e(4,1) = e(4,2) = e(4,3) = 0; e(4,4) = 1;
00108   }
00109   
00110   
00111 #ifdef USE_OSG
00112   Matrix4(const osg::Matrix& matrix)
00113   {
00114 #ifdef OSG_USE_DOUBLE_MATRICES
00115     typedef double osgreal;
00116 #else
00117     typedef float osgreal;
00118 #endif
00119     // NB: This relies on both types having the same layout
00120     const osgreal* mat = matrix.ptr();
00121     for(Int e=0; e<16; e++)
00122       m[e] = mat[e];
00123   }
00124 #endif
00125   ~Matrix4() {}
00126 
00127 
00128   Matrix4& setIdentity() throw()
00129   {
00130     setDiag(Real(1)); return *this;
00131   }
00132 
00133   Matrix4& setZero() throw()
00134   {
00135     setDiag(Real(0)); return *this;
00136   }
00137 
00138 
00139   Real& e(Int row, Int col) throw()
00140   {
00141     Assertm( !((row < 1) || (row > 4) || (col < 1) || (col > 4)), "matrix row and col within bounds (debug only check)");
00142     return m[MATRIX4_ACCESS(row,col)]; 
00143   }
00144 
00145   const Real& e(Int row, Int col) const throw()
00146   {
00147     Assertm( !((row < 1) || (row > 4) || (col < 1) || (col > 4)), "matrix row and col within bounds (debug only check)");
00148     return m[MATRIX4_ACCESS(row,col)]; 
00149   }
00150 
00151   Real& at(Int row, Int col) throw(std::out_of_range)
00152   {
00153     if ((row < 1) || (row > 4) || (col < 1) || (col > 4))
00154       throw std::out_of_range(Exception("matrix row or col out of bounds"));
00155 
00156     return m[MATRIX4_ACCESS(row,col)];
00157   }
00158 
00159   const Real& at(Int row, Int col) const throw(std::out_of_range)
00160   {
00161     if ((row < 1) || (row > 4) || (col < 1) || (col > 4))
00162       throw std::out_of_range(Exception("matrix row or col out of bounds"));
00163 
00164     return m[MATRIX4_ACCESS(row,col)];
00165   }
00166 
00167   Real& operator()(Int row, Int col) throw()
00168   {
00169 #ifdef DEBUG
00170     return at(row,col);
00171 #else
00172     return e(row,col);
00173 #endif
00174   }
00175 
00176   const Real& operator()(Int row, Int col) const throw()
00177   {
00178 #ifdef DEBUG
00179     return at(row,col);
00180 #else
00181     return e(row,col);
00182 #endif
00183   }
00184 
00185 
00186   Vector4 row(Int row) const         // extract row vector
00187   { return Vector4(e(row,1),e(row,2),e(row,3),e(row,4)); }
00188 
00189   Vector4 column(Int col) const      // extract column vector
00190   { return Vector4(e(1,col),e(2,col),e(3,col),e(4,col)); }
00191 
00192   void setRow(Int row, const Vector3& r) throw()
00193   { e(row,1)=r.x; e(row,2)=r.y; e(row,3)=r.z; }
00194 
00195   void setRow(Int row, const Vector4& r) throw()
00196   { e(row,1)=r.x; e(row,2)=r.y; e(row,3)=r.z; e(row,4)=r.w; }
00197 
00198   void setColumn(Int col, const Vector3& c) throw()
00199   { e(1,col)=c.x; e(2,col)=c.y; e(3,col)=c.z; }
00200 
00201   void setColumn(Int col, const Vector4& c) throw()
00202   { e(1,col)=c.x; e(2,col)=c.y; e(3,col)=c.z; e(4,col)=c.w; }
00203 
00204   void swapColumns(Int col1, Int col2) throw(std::out_of_range)
00205   {
00206     if ((col1 < 1) || (col1 > 4) || (col2 < 1) || (col2 > 4))
00207       throw std::out_of_range(Exception("matrix col out of bounds"));
00208 
00209     Vector4 tmp(column(col1));
00210     setColumn(col1,column(col2));
00211     setColumn(col2,tmp);
00212   }
00213 
00214   void swapRows(Int row1, Int row2) throw(std::out_of_range)
00215   {
00216     if ((row1 < 1) || (row1 > 4) || (row2 < 1) || (row2 > 4))
00217       throw std::out_of_range(Exception("matrix row out of bounds"));
00218 
00219     Vector4 tmp(row(row1));
00220     setRow(row1,row(row2));
00221     setRow(row2,tmp);
00222   }
00223 
00224 
00225   Vector4 operator[](Int r) const  // row
00226   { return row(r); }
00227 
00228 
00229   int index(Int row, Int col) const throw()
00230   { return MATRIX4_ACCESS(row,col); }
00231 
00232   Matrix4& operator=(const Matrix4& src) throw()
00233   { 
00234     if (&src != this)
00235       for(int i=0; i<16; i++)
00236         m[i] = src.m[i];
00237     return *this;
00238   }
00239 
00240 
00241   bool operator==(const Matrix4& m1) const throw()
00242   {
00243     for(int i=0; i<16; i++)
00244       if (m1.m[i]!=m[i]) return false;
00245     return true;
00246   }
00247 
00248   bool equals(const Matrix4& m1, Real epsilon = consts::epsilon) const throw()
00249   {
00250     for(int i=0; i<16; i++)
00251       if (!base::equals(m1.m[i],m[i],epsilon)) return false;
00252     return true;
00253   }
00254 
00255 
00256   void setToTranslation(const Vector3& trans);
00257   void setTranslationComponent(const Vector3& trans);
00258   Vector3 getTranslationComponent() const { return Vector3(e(1,4),e(2,4),e(3,4)); }
00259   void setRotationAboutZ(Real angle);
00260 
00261   Matrix4& transpose();
00262   Matrix4& invert();
00263   Matrix4& negate() throw();
00264 
00265   // Find LUP decomposition.  P is represented by the vector Pi, where the element
00266   //  values represent the column of P containing a 1. i.e. Pi[i]=j => P[i][j]=1
00267   void decomposeLUP(Matrix4& L, Matrix4& U, Vector4& Pi) const;
00268   
00269   // Solve Ax=b for x, given b, where A=*this (returns x)
00270   Vector4  solve(const Vector4& b) const; 
00271 
00272 
00273   Matrix4& operator*=(const Matrix4& m2);
00274   Matrix4& operator+=(const Matrix4& m2);
00275   Matrix4& operator-=(const Matrix4& m2);
00276   Matrix4& operator*=(const Real& s);
00277   Matrix4& operator/=(const Real& s);
00278 
00279   operator Matrix3() const;  ///< convert to 3x3 submatrix
00280 #ifdef USE_OSG
00281   operator osg::Matrix() const; ///< convert to osg::Matrix
00282 #endif
00283 
00284   const Real* c_array() const { return m; }
00285   Real* c_array() { return m; }
00286 
00287   // Solve for xA = b, given LUP decomposition of A as L, U and Pi, and given b, returns x
00288   static Vector4 solveLUP(const Matrix4& L, const Matrix4& U, const Vector4& Pi, const Vector4& b);
00289 
00290   static void decomposeLUP(const Matrix4& A, Matrix4& L, Matrix4& U, Vector4& Pi)
00291   { A.decomposeLUP(L,U,Pi); }
00292 
00293   // best to use the operators than use these directly
00294   static Vector4 matrixMulVector(const Matrix4& m, const Vector4& v); // m x v
00295   static Vector4 matrixMulVectorAddVector(const Matrix4& m, const Vector4& v, const Vector4& v2); // m x v + v2
00296   static Vector4 matrixMulVector(const Matrix4& m, const Vector3& v); // m x v
00297 
00298   void serialize(Serializer& s); ///< read or write object state to Serializer
00299 
00300 private:
00301   Real m[16];
00302   
00303   void setDiag(const Real& d)
00304   {
00305     m[0] = d;
00306     m[1] = Real(0);
00307     m[2] = Real(0);
00308     m[3] = Real(0);
00309     m[4] = Real(0);
00310     m[5] = d;
00311     m[6] = Real(0);
00312     m[7] = Real(0);
00313     m[8] = Real(0);
00314     m[9] = Real(0);
00315     m[10] = d;
00316     m[11] = Real(0);
00317     m[12] = Real(0);
00318     m[13] = Real(0);
00319     m[14] = Real(0);
00320     m[15] = d;
00321   }
00322 
00323 };
00324 
00325 
00326 // Operations
00327 
00328 
00329 inline Matrix4 operator*(const Matrix4& m1, const Matrix4& m2) // Matrix multiplication
00330 { Matrix4 r(m1); return r *= m2; }
00331 
00332 inline Matrix4 operator+(const Matrix4& m1, const Matrix4& m2) // Addition
00333 { Matrix4 r(m1); return r += m2; }
00334 
00335 inline Matrix4 operator-(const Matrix4& m1, const Matrix4& m2) // Subtraction
00336 { Matrix4 r(m1); return r -= m2; }
00337 
00338 inline Matrix4 operator-(const Matrix4& m1) // Negation
00339 { Matrix4 r(m1); return r.negate(); }
00340 
00341 inline Matrix4 operator*(const Matrix4& m1, const Real& s) // Scalar multiplication
00342 { Matrix4 r(m1); return r *= s; }
00343 
00344 inline Matrix4 operator*(const Real& s, const Matrix4& m1) // Scalar multiplication
00345 { Matrix4 r(m1); return r *= s; }
00346 
00347 inline Matrix4 operator/(const Matrix4& m1, const Real& s) // Scalar division
00348 { Matrix4 r(m1); return r /= s; }
00349 
00350 
00351 inline Vector3 operator*(const Matrix4& m1, const Vector3& v) // Vector multiplication
00352 { Vector4 r(Matrix4::matrixMulVector(m1,v)); return Vector3(r.x,r.y,r.z); }
00353 
00354 inline Matrix4 transpose(const Matrix4& m) // Transpose
00355 { Matrix4 r(m); return r.transpose(); }
00356 
00357 inline Matrix4 inverse(const Matrix4& m) // Inverse
00358 { Matrix4 r(m); return r.invert(); }
00359 
00360 
00361 // These functions and the structs above provide closures for common vector matrix
00362 //  operations.
00363 // For example, an expression like m*v+v2 will expand to:
00364 //              Matrix4::matrixMulVectorAddVector(m,v,v2);
00365 // rather than: Vector4 r(operator*(m,v)); r.operator+=(v2), return r
00366 //   (saving a couple copies between temporaries)
00367 
00368 inline M4V4mulV4add operator+(const M4V4mul& mv, const Vector4& vv)
00369 { return M4V4mulV4add(mv,vv); }
00370 
00371 inline M4V4mul operator*(const Matrix4& mm, const Vector4& vv)
00372 { return M4V4mul(mm,vv); }
00373 
00374 inline M4V4mul::operator Vector4() const
00375 { return Matrix4::matrixMulVector(m,v); }
00376 
00377 inline M4V4mulV4add::operator Vector4() const
00378 { return Matrix4::matrixMulVectorAddVector(m,v,v2); }
00379 
00380 
00381 std::ostream& operator<<(std::ostream& out, const Matrix4& m); // Output
00382 
00383 
00384 } // base
00385 
00386 #endif
00387 

Generated on Thu Jul 29 15:56:07 2004 for OpenSim by doxygen 1.3.6