matrix44.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: matrix44.h,v 1.55.14.1 2007/03/25 21:23:45 oliver Exp $
00005 //
00006 
00007 #ifndef BALL_MATHS_MATRIX44_H
00008 #define BALL_MATHS_MATRIX44_H
00009 
00010 #ifndef BALL_COMMON_EXCEPTION_H
00011 # include <BALL/COMMON/exception.h>
00012 #endif
00013 
00014 #include <math.h>
00015 #include <iostream>
00016 #include <stdlib.h>
00017 
00018 #ifndef BALL_MATHS_ANGLE_H
00019 # include <BALL/MATHS/angle.h>
00020 #endif
00021 
00022 #ifndef BALL_MATHS_VECTOR3_H
00023 # include <BALL/MATHS/vector3.h>
00024 #endif
00025 
00026 #ifndef BALL_MATHS_VECTOR4_H
00027 # include <BALL/MATHS/vector4.h>
00028 #endif
00029 
00030 namespace BALL 
00031 {
00038 
00039   template <typename T>
00040   class TMatrix4x4;
00041 
00050   template <typename T>
00051   std::istream& operator >> (std::istream& s, TMatrix4x4<T>& m)
00052     ;
00053 
00059   template <typename T>
00060   std::ostream& operator << (std::ostream& s, const TMatrix4x4<T>& m)
00061     ;
00063   
00066   template <typename T>
00067   class TMatrix4x4
00068   {
00069     public:
00070   
00071     BALL_CREATE(TMatrix4x4)
00072 
00073     
00076 
00081     TMatrix4x4()
00082       ;
00083 
00090     TMatrix4x4(const T* ptr)
00091       throw(Exception::NullPointer);
00092 
00099     TMatrix4x4(const T ptr[4][4])
00100       throw(Exception::NullPointer);
00101 
00107     TMatrix4x4(const TMatrix4x4& m)
00108       ;
00109 
00118     TMatrix4x4
00119       (const TVector4<T>& col1, const TVector4<T>& col2,
00120        const TVector4<T>& col3, const TVector4<T>& col4)
00121       ;
00122 
00127     TMatrix4x4
00128       (const T& m11, const T& m12, const T& m13, const T& m14, 
00129        const T& m21, const T& m22, const T& m23, const T& m24, 
00130        const T& m31, const T& m32, const T& m33, const T& m34, 
00131        const T& m41, const T& m42, const T& m43, const T& m44)
00132       ;
00133 
00138     virtual ~TMatrix4x4()
00139       
00140     {
00141     }
00142 
00146     virtual void clear() 
00147       ;
00148 
00150 
00153 
00159     void set(const T* ptr)
00160       throw(Exception::NullPointer);
00161 
00167     void set(const T ptr[4][4])
00168       throw(Exception::NullPointer);
00169 
00173     void set(const TMatrix4x4& m)
00174       ;
00175 
00182     void set
00183       (const TVector4<T>& col1, const TVector4<T>& col2,
00184        const TVector4<T>& col3, const TVector4<T>& col4)
00185       ;
00186 
00190     void set
00191       (const T& m11, const T& m12, const T& m13, const T& m14, 
00192        const T& m21, const T& m22, const T& m23, const T& m24, 
00193        const T& m31, const T& m32, const T& m33, const T& m34, 
00194        const T& m41, const T& m42, const T& m43, const T& m44)
00195       ;
00196 
00201     TMatrix4x4& operator = (const T* ptr)
00202       throw(Exception::NullPointer);
00203 
00208     TMatrix4x4& operator = (const T ptr[4][4])
00209       throw(Exception::NullPointer);
00210 
00215     TMatrix4x4& operator = (const TMatrix4x4& m)
00216       ;
00217 
00223     void get(T* ptr) const
00224       throw(Exception::NullPointer);
00225 
00231     void get(T ptr[4][4]) const
00232       throw(Exception::NullPointer);
00233 
00238     void get(TMatrix4x4& m) const
00239       ;
00240 
00247     void get
00248       (TVector4<T>& col1, TVector4<T>& col2,
00249        TVector4<T>& col3, TVector4<T>& col4) const
00250       ;
00251 
00255     void get
00256       (T& m11, T& m12, T& m13, T& m14, 
00257        T& m21, T& m22, T& m23, T& m24, 
00258        T& m31, T& m32, T& m33, T& m34, 
00259        T& m41, T& m42, T& m43, T& m44) const
00260       ;
00261 
00265     void swap(TMatrix4x4& m)
00266       ;
00267 
00269 
00272 
00277     T getTrace() const ;
00278 
00282     static const TMatrix4x4& getZero() ;
00283 
00288     static const TMatrix4x4& getIdentity() ;
00289 
00294     void setIdentity() ;
00295 
00300     void set(const T& t = (T)1) ;
00301 
00306     void transpose() ;
00307 
00313     TVector4<T> getRow(Position row) const
00314       throw(Exception::IndexOverflow);
00315 
00321     TVector4<T> getColumn(Position col) const
00322       throw(Exception::IndexOverflow);
00323 
00329     void setRow(Position row, const TVector4<T>& row_value)
00330       throw(Exception::IndexOverflow);
00331 
00337     void setColumn(Position col, const TVector4<T>& col_value)
00338       throw(Exception::IndexOverflow);
00339 
00346     bool isEqual(const TMatrix4x4& m) const ;
00347 
00351     TVector4<T> getDiagonal() const ;
00352     
00359     T& operator () (Position row, Position col)
00360       throw(Exception::IndexOverflow);
00361 
00368     const T& operator () (Position row, Position col) const
00369       throw(Exception::IndexOverflow);
00370 
00377     const T& operator [] (Position position) const
00378       throw(Exception::IndexOverflow);
00379 
00383     T& operator [] (Position position)
00384       throw(Exception::IndexOverflow);
00385 
00388     TMatrix4x4 operator + () const ;
00389 
00392     TMatrix4x4 operator - () const ;
00393 
00399     TMatrix4x4 operator + (const TMatrix4x4& m) const ;
00400 
00406     TMatrix4x4& operator += (const TMatrix4x4& m) ;
00407 
00413     TMatrix4x4 operator - (const TMatrix4x4& m) const ;
00414 
00420     TMatrix4x4& operator -= (const TMatrix4x4& m) ;
00421 
00426     TMatrix4x4 operator * (const T& scalar) const ;
00427 
00432     TMatrix4x4& operator *= (const T& scalar) ;
00433 
00439     TMatrix4x4 operator / (const T& scalar) const
00440       throw(Exception::DivisionByZero);
00441 
00447     TMatrix4x4& operator /= (const T& scalar)
00448       throw(Exception::DivisionByZero);
00449 
00453     TMatrix4x4 operator * (const TMatrix4x4& m) const ;
00454 
00458     TMatrix4x4& operator *= (const TMatrix4x4& m) ;
00459 
00463     TVector4<T> operator * (const TVector4<T>& vector) const ;
00464 
00471     bool invert(TMatrix4x4& inverse) const ;
00472 
00478     bool invert() ;
00479 
00483     T getDeterminant() const ;
00484 
00490     void translate(const T &x, const T &y, const T &z) ;
00491 
00495     void translate(const TVector3<T>& v) ;
00496 
00502     void setTranslation(const T& x, const T& y, const T& z) ;
00503 
00507     void setTranslation(const TVector3<T>& v) ;
00508 
00514     void scale(const T& x_scale, const T& y_scale, const T& z_scale) ;
00515 
00519     void scale(const T& scale) ;
00520 
00524     void scale(const TVector3<T>& v) ;
00525 
00531     void setScale(const T& x_scale, const T& y_scale, const T& z_scale) ;
00532 
00536     void setScale(const T& scale) ;
00537 
00541     void setScale(const TVector3<T>& v) ;
00542 
00546     void rotateX(const TAngle<T>& phi) ;
00547 
00551     void setRotationX(const TAngle<T>& phi) ;
00552 
00556     void rotateY(const TAngle<T>& phi) ;
00557 
00561     void setRotationY(const TAngle<T>& phi) ;
00562 
00566     void rotateZ(const TAngle<T>& phi) ;
00567 
00571     void setRotationZ(const TAngle<T>& phi) ;
00572 
00579     void rotate(const TAngle<T>& phi, const T& axis_x, const T& axis_y, const T& axis_z) ;
00580 
00585     void rotate(const TAngle<T>& phi, const TVector3<T>& axis) ;
00586 
00591     void rotate(const TAngle<T>& phi, const TVector4<T>& axis) ;
00592 
00599     void setRotation(const TAngle<T>& phi, const T& axis_x, const T& axis_y, const T& axis_z) ;
00600 
00605     void setRotation(const TAngle<T>& phi, const TVector3<T>& axis) ;
00606 
00611     void setRotation(const TAngle<T>& phi, const TVector4<T>& axis) ;
00613 
00617 
00623     bool operator == (const TMatrix4x4& m) const ; 
00624 
00630     bool operator != (const TMatrix4x4& m) const ;
00631 
00636     bool isIdentity() const ;
00637 
00641     bool isRegular() const ;
00642 
00646     bool isSingular() const ;
00647 
00652     bool isSymmetric() const ;
00653 
00657     bool isLowerTriangular() const ;
00658 
00662     bool isUpperTriangular() const ;
00663 
00667     bool isDiagonal() const ;
00669 
00673 
00678     bool isValid() const ;
00679 
00686     void dump(std::ostream& s = std::cout, Size depth = 0) const ;
00688 
00692 
00694     T m11;
00695 
00697     T m12;
00698 
00700     T m13;
00701 
00703     T m14;
00704 
00706     T m21;
00707 
00709     T m22;
00710 
00712     T m23;
00713 
00715     T m24;
00716 
00718     T m31;
00719 
00721     T m32;
00722 
00724     T m33;
00725 
00727     T m34;
00728 
00730     T m41;
00731 
00733     T m42;
00734 
00736     T m43;
00737 
00739     T m44;
00741 
00742     private:
00743 
00744     void initializeComponentPointers_()
00745       
00746     {
00747       T **ptr = (T **)comp_ptr_;
00748 
00749       *ptr++ = &m11; *ptr++ = &m12; *ptr++ = &m13; *ptr++ = &m14;
00750       *ptr++ = &m21; *ptr++ = &m22; *ptr++ = &m23; *ptr++ = &m24;
00751       *ptr++ = &m31; *ptr++ = &m32; *ptr++ = &m33; *ptr++ = &m34;
00752       *ptr++ = &m41; *ptr++ = &m42; *ptr++ = &m43; *ptr   = &m44;
00753     }
00754 
00755     // pointers to the components of the matrix 
00756     T* comp_ptr_[16];
00757   };
00759 
00760   template <typename T>
00761   TMatrix4x4<T>::TMatrix4x4()
00762     
00763     : m11(0), m12(0), m13(0), m14(0), 
00764       m21(0), m22(0), m23(0), m24(0), 
00765       m31(0), m32(0), m33(0), m34(0), 
00766       m41(0), m42(0), m43(0), m44(0)
00767   {
00768     initializeComponentPointers_();
00769   }
00770 
00771   template <typename T>
00772   TMatrix4x4<T>::TMatrix4x4( const T* ptr)
00773     throw(Exception::NullPointer)
00774   {
00775     if (ptr == 0)
00776     {
00777       throw Exception::NullPointer(__FILE__, __LINE__);
00778     }
00779     
00780     m11 = *ptr++; m12 = *ptr++; m13 = *ptr++; m14 = *ptr++; 
00781     m21 = *ptr++; m22 = *ptr++; m23 = *ptr++; m24 = *ptr++; 
00782     m31 = *ptr++; m32 = *ptr++; m33 = *ptr++; m34 = *ptr++; 
00783     m41 = *ptr++; m42 = *ptr++; m43 = *ptr++; m44 = *ptr; 
00784 
00785     initializeComponentPointers_();
00786   }
00787 
00788   template <typename T>
00789   TMatrix4x4<T>::TMatrix4x4(const T array_ptr[4][4])
00790     throw(Exception::NullPointer)
00791   {
00792     if (array_ptr == 0)
00793     {
00794       throw Exception::NullPointer(__FILE__, __LINE__);
00795     }
00796     
00797     const T *ptr = *array_ptr;
00798       
00799     m11 = *ptr++; m12 = *ptr++; m13 = *ptr++; m14 = *ptr++; 
00800     m21 = *ptr++; m22 = *ptr++; m23 = *ptr++; m24 = *ptr++; 
00801     m31 = *ptr++; m32 = *ptr++; m33 = *ptr++; m34 = *ptr++; 
00802     m41 = *ptr++; m42 = *ptr++; m43 = *ptr++; m44 = *ptr; 
00803 
00804     initializeComponentPointers_();
00805   }
00806 
00807   template <typename T>
00808   TMatrix4x4<T>::TMatrix4x4(const TMatrix4x4<T>& m)
00809     
00810     : m11(m.m11), m12(m.m12), m13(m.m13), m14(m.m14), 
00811       m21(m.m21), m22(m.m22), m23(m.m23), m24(m.m24), 
00812       m31(m.m31), m32(m.m32), m33(m.m33), m34(m.m34), 
00813       m41(m.m41), m42(m.m42), m43(m.m43), m44(m.m44)
00814   {
00815     initializeComponentPointers_();
00816   }
00817 
00818 
00819   template <typename T>
00820   TMatrix4x4<T>::TMatrix4x4
00821     (const TVector4<T>& col1, const TVector4<T>& col2,
00822      const TVector4<T>& col3,const TVector4<T>& col4)
00823     
00824     : m11(col1.x), m12(col1.y), m13(col1.z), m14(col1.h), 
00825       m21(col2.x), m22(col2.y), m23(col2.z), m24(col2.h), 
00826       m31(col3.x), m32(col3.y), m33(col3.z), m34(col3.h), 
00827       m41(col4.x), m42(col4.y), m43(col4.z), m44(col4.h)
00828   {
00829     initializeComponentPointers_();
00830   }
00831 
00832   template <typename T>
00833   TMatrix4x4<T>::TMatrix4x4
00834     (const T& m11, const T& m12, const T& m13, const T& m14, 
00835      const T& m21, const T& m22, const T& m23, const T& m24, 
00836      const T& m31, const T& m32, const T& m33, const T& m34, 
00837      const T& m41, const T& m42, const T& m43, const T& m44)
00838     
00839     : m11(m11), m12(m12), m13(m13), m14(m14), 
00840       m21(m21), m22(m22), m23(m23), m24(m24), 
00841       m31(m31), m32(m32), m33(m33), m34(m34), 
00842       m41(m41), m42(m42), m43(m43), m44(m44)
00843   {
00844     initializeComponentPointers_();
00845   }
00846 
00847   template <typename T>
00848   void TMatrix4x4<T>::clear()
00849     
00850   {
00851     set((T)0);
00852   }
00853 
00854   template <typename T>
00855   void TMatrix4x4<T>::set(const T* ptr)
00856     throw(Exception::NullPointer)
00857   {
00858     if (ptr == 0) 
00859     {
00860       throw Exception::NullPointer(__FILE__, __LINE__);
00861     }
00862 
00863     m11 = *ptr++; m12 = *ptr++; m13 = *ptr++; m14 = *ptr++; 
00864     m21 = *ptr++; m22 = *ptr++; m23 = *ptr++; m24 = *ptr++; 
00865     m31 = *ptr++; m32 = *ptr++; m33 = *ptr++; m34 = *ptr++; 
00866     m41 = *ptr++; m42 = *ptr++; m43 = *ptr++; m44 = *ptr; 
00867   }
00868 
00869   template <typename T>
00870   void TMatrix4x4<T>::set(const T array_ptr[4][4])
00871     throw(Exception::NullPointer)
00872   {
00873     if (array_ptr == 0)
00874     {
00875       throw Exception::NullPointer(__FILE__, __LINE__);
00876     }
00877     
00878     const T *ptr = *array_ptr;
00879 
00880     m11 = *ptr++; m12 = *ptr++; m13 = *ptr++; m14 = *ptr++; 
00881     m21 = *ptr++; m22 = *ptr++; m23 = *ptr++; m24 = *ptr++; 
00882     m31 = *ptr++; m32 = *ptr++; m33 = *ptr++; m34 = *ptr++; 
00883     m41 = *ptr++; m42 = *ptr++; m43 = *ptr++; m44 = *ptr; 
00884   }
00885 
00886   template <typename T>
00887   void TMatrix4x4<T>::set(const TMatrix4x4<T>& m)
00888     
00889   {
00890     m11 = m.m11; m12 = m.m12; m13 = m.m13; m14 = m.m14; 
00891     m21 = m.m21; m22 = m.m22; m23 = m.m23; m24 = m.m24; 
00892     m31 = m.m31; m32 = m.m32; m33 = m.m33; m34 = m.m34; 
00893     m41 = m.m41; m42 = m.m42; m43 = m.m43; m44 = m.m44;
00894   }
00895 
00896   template <typename T>
00897   void TMatrix4x4<T>::set
00898     (const TVector4<T>& col1, const TVector4<T>& col2,
00899      const TVector4<T>& col3, const TVector4<T>& col4)
00900     
00901   {
00902     m11 = col1.x; m12 = col1.y; m13 = col1.z; m14 = col1.h; 
00903     m21 = col2.x; m22 = col2.y; m23 = col2.z; m24 = col2.h; 
00904     m31 = col3.x; m32 = col3.y; m33 = col3.z; m34 = col3.h; 
00905     m41 = col4.x; m42 = col4.y; m43 = col4.z; m44 = col4.h;
00906   }
00907 
00908   template <typename T>
00909   void TMatrix4x4<T>::set
00910     (const T& c11, const T& c12, const T& c13, const T& c14, 
00911      const T& c21, const T& c22, const T& c23, const T& c24, 
00912      const T& c31, const T& c32, const T& c33, const T& c34, 
00913      const T& c41, const T& c42, const T& c43, const T& c44)
00914     
00915   {
00916     m11 = c11; m12 = c12; m13 = c13; m14 = c14;
00917     m21 = c21; m22 = c22; m23 = c23; m24 = c24;
00918     m31 = c31; m32 = c32; m33 = c33; m34 = c34;
00919     m41 = c41; m42 = c42; m43 = c43; m44 = c44;
00920   }
00921 
00922   template <typename T>
00923   BALL_INLINE 
00924   TMatrix4x4<T>& TMatrix4x4<T>::operator = (const T* ptr)
00925     throw(Exception::NullPointer)
00926   {
00927     set(ptr);
00928     return *this;
00929   }
00930 
00931   template <typename T>
00932   BALL_INLINE 
00933   TMatrix4x4<T>& TMatrix4x4<T>::operator = (const T array_ptr[4][4])
00934     throw(Exception::NullPointer)
00935   {
00936     set(array_ptr);
00937     return *this;
00938   }
00939 
00940   template <typename T>
00941   BALL_INLINE 
00942   TMatrix4x4<T>& TMatrix4x4<T>::operator = (const TMatrix4x4<T>& m)
00943     
00944   {
00945     set(m);
00946     return *this;
00947   }
00948 
00949   template <typename T>
00950   void TMatrix4x4<T>::get(T* ptr) const
00951     throw(Exception::NullPointer)
00952   {
00953     if (ptr == 0)
00954     {
00955       throw Exception::NullPointer(__FILE__, __LINE__);
00956     }
00957 
00958     *ptr++ = m11; *ptr++ = m12; *ptr++ = m13; *ptr++ = m14; 
00959     *ptr++ = m21; *ptr++ = m22; *ptr++ = m23; *ptr++ = m24; 
00960     *ptr++ = m31; *ptr++ = m32; *ptr++ = m33; *ptr++ = m34; 
00961     *ptr++ = m41; *ptr++ = m42; *ptr++ = m43; *ptr   = m44; 
00962   }
00963 
00964   template <typename T>
00965   void TMatrix4x4<T>::get(T array_ptr[4][4]) const
00966     throw(Exception::NullPointer)
00967   {
00968     if (array_ptr == 0)
00969     {
00970        throw Exception::NullPointer(__FILE__, __LINE__);
00971     }
00972  
00973     T *ptr = *array_ptr;
00974 
00975     *ptr++ = m11; *ptr++ = m12; *ptr++ = m13; *ptr++ = m14; 
00976     *ptr++ = m21; *ptr++ = m22; *ptr++ = m23; *ptr++ = m24; 
00977     *ptr++ = m31; *ptr++ = m32; *ptr++ = m33; *ptr++ = m34; 
00978     *ptr++ = m41; *ptr++ = m42; *ptr++ = m43; *ptr   = m44; 
00979   }
00980 
00981   template <typename T>
00982   void TMatrix4x4<T>::get(TMatrix4x4<T>& m) const
00983     
00984   {
00985     m.set(*this);
00986   }
00987 
00988   template <typename T>
00989   void TMatrix4x4<T>::get
00990     (TVector4<T>& col1, TVector4<T>& col2,
00991      TVector4<T>& col3, TVector4<T>& col4) const
00992     
00993   {
00994     col1.x = m11; col1.y = m12; col1.z = m13; col1.h = m14; 
00995     col2.x = m21; col2.y = m22; col2.z = m23; col2.h = m24; 
00996     col3.x = m31; col3.y = m32; col3.z = m33; col3.h = m34; 
00997     col4.x = m41; col4.y = m42; col4.z = m43; col4.h = m44;
00998   }
00999 
01000   template <typename T>
01001   void TMatrix4x4<T>::get
01002     (T& c11, T& c12, T& c13, T& c14, 
01003      T& c21, T& c22, T& c23, T& c24, 
01004      T& c31, T& c32, T& c33, T& c34, 
01005      T& c41, T& c42, T& c43, T& c44) const
01006     
01007   {
01008     c11 = m11; c12 = m12; c13 = m13; c14 = m14;
01009     c21 = m21; c22 = m22; c23 = m23; c24 = m24;
01010     c31 = m31; c32 = m32; c33 = m33; c34 = m34;
01011     c41 = m41; c42 = m42; c43 = m43; c44 = m44;
01012   }
01013 
01014   template <typename T>
01015   BALL_INLINE 
01016   T TMatrix4x4<T>::getTrace() const
01017     
01018   {
01019     return (m11 + m22 + m33 + m44);
01020   }
01021 
01022   template <typename T>
01023   BALL_INLINE 
01024   const TMatrix4x4<T>& TMatrix4x4<T>::getZero()
01025     
01026   {
01027     static TMatrix4x4<T> null_matrix
01028       (0, 0, 0, 0,
01029        0, 0, 0, 0,
01030        0, 0, 0, 0,
01031        0, 0, 0, 0);
01032     
01033     return null_matrix;
01034   }
01035 
01036 
01037   template <typename T>
01038   BALL_INLINE
01039   void TMatrix4x4<T>::setIdentity()
01040     
01041   {
01042     m12 = m13 = m14 = m21 = m23 = m24 = m31 = m32 = m34 = m41 = m42 = m43 = 0;
01043     m11 = m22 = m33 = m44 = (T)1;
01044   }
01045   template <typename T>
01046   BALL_INLINE 
01047   const TMatrix4x4<T>& TMatrix4x4<T>::getIdentity()
01048     
01049   {
01050     static TMatrix4x4<T> identity
01051       (1, 0, 0, 0,
01052        0, 1, 0, 0,
01053        0, 0, 1, 0,
01054        0, 0, 0, 1);
01055 
01056     return identity;
01057   }
01058 
01059   template <typename T>
01060   void TMatrix4x4<T>::set(const T& t)
01061     
01062   {
01063       m11 = m12 = m13 = m14 
01064     = m21 = m22 = m23 = m24 
01065     = m31 = m32 = m33 = m34
01066     = m41 = m42 = m43 = m44
01067     = t;
01068   }
01069 
01070   template <typename T>
01071   void TMatrix4x4<T>::swap(TMatrix4x4<T>& m)
01072     
01073   {
01074     T tmp = m11; m11 = m.m11; m.m11 = tmp;
01075       tmp = m12; m12 = m.m12; m.m12 = tmp;
01076       tmp = m13; m13 = m.m13; m.m13 = tmp;
01077       tmp = m14; m14 = m.m14; m.m14 = tmp;
01078       tmp = m21; m21 = m.m21; m.m21 = tmp;
01079       tmp = m22; m22 = m.m22; m.m22 = tmp;
01080       tmp = m23; m23 = m.m23; m.m23 = tmp;
01081       tmp = m24; m24 = m.m24; m.m24 = tmp;
01082       tmp = m31; m31 = m.m31; m.m31 = tmp;
01083       tmp = m32; m32 = m.m32; m.m32 = tmp;
01084       tmp = m33; m33 = m.m33; m.m33 = tmp;
01085       tmp = m34; m34 = m.m34; m.m34 = tmp;
01086       tmp = m41; m41 = m.m41; m.m41 = tmp;
01087       tmp = m42; m42 = m.m42; m.m42 = tmp;
01088       tmp = m43; m43 = m.m43; m.m43 = tmp;
01089       tmp = m44; m44 = m.m44; m.m44 = tmp;
01090   }
01091 
01092   template <typename T>
01093   void TMatrix4x4<T>::transpose()
01094     
01095   {
01096     T tmp = m12;
01097     m12 = m21;
01098     m21 = tmp;
01099 
01100     tmp  = m13;
01101     m13 = m31;
01102     m31 = tmp;
01103 
01104     tmp  = m14;
01105     m14 = m41;
01106     m41 = tmp;
01107 
01108     tmp  = m23;
01109     m23 = m32;
01110     m32 = tmp;
01111 
01112     tmp  = m24;
01113     m24 = m42;
01114     m42 = tmp;
01115 
01116     tmp  = m34;
01117     m34 = m43;
01118     m43 = tmp;
01119   }
01120 
01121   template <typename T>
01122   TVector4<T> TMatrix4x4<T>::getRow(Position row) const
01123     throw(Exception::IndexOverflow)
01124   {
01125     if (row > 3)
01126     {
01127       throw Exception::IndexOverflow(__FILE__, __LINE__, row, 3);
01128     }
01129 
01130     // calculate the start of the row in the array
01131     const T* ptr = comp_ptr_[4 * row];
01132     return TVector4<T> (ptr[0], ptr[1], ptr[2], ptr[3]);
01133   }
01134 
01135   template <typename T>
01136   TVector4<T> TMatrix4x4<T>::getColumn(Position col) const
01137     throw(Exception::IndexOverflow)
01138   {
01139     if (col > 3)
01140     {
01141       throw Exception::IndexOverflow(__FILE__, __LINE__, col, 3);
01142     }
01143     
01144     const T* ptr = comp_ptr_[col];
01145 
01146     return TVector4<T> (ptr[0], ptr[4], ptr[8], ptr[12]);
01147   }
01148 
01149 
01150   template <typename T>
01151   void TMatrix4x4<T>::setRow(Position row, const TVector4<T>& row_value)
01152     throw(Exception::IndexOverflow)
01153   {
01154     if (row > 3)
01155     {
01156       throw Exception::IndexOverflow(__FILE__, __LINE__, row, 3);
01157     }
01158 
01159     // calculate a pointer to the start of the row
01160     T* ptr = comp_ptr_[4 * row];
01161 
01162     ptr[0] = row_value.x;
01163     ptr[1] = row_value.y;
01164     ptr[2] = row_value.z;
01165     ptr[3] = row_value.h;
01166   }
01167 
01168   template <typename T>
01169   void TMatrix4x4<T>::setColumn(Position col, const TVector4<T>& col_value)
01170     throw(Exception::IndexOverflow)
01171   {
01172     if (col > 3)
01173     {
01174       throw Exception::IndexOverflow(__FILE__, __LINE__, col, 3);
01175     }
01176 
01177     // calculate a pointer to the start of the column
01178     T* ptr = comp_ptr_[col];
01179 
01180     ptr[0] = col_value.x;
01181     ptr[4] = col_value.y;
01182     ptr[8] = col_value.z;
01183     ptr[12] = col_value.h;
01184   }
01185 
01186   template <typename T>
01187   bool TMatrix4x4<T>::isEqual(const TMatrix4x4<T>& m) const
01188     
01189   {
01190     // iterate over all component pointers
01191     // and compare the elements for approximate equality
01192     for (Position i = 0; i < 16; i++)
01193     {
01194       if (Maths::isEqual(*comp_ptr_[i], *m.comp_ptr_[i]) == false)
01195       {
01196         return false;
01197       } 
01198     }
01199 
01200     return true;
01201   }
01202 
01203   template <typename T>
01204   TVector4<T>TMatrix4x4<T>::getDiagonal() const
01205     
01206   {
01207     return TVector4<T>(m11, m22, m33, m44);
01208   }
01209 
01210   template <typename T>
01211   BALL_INLINE  
01212   T& TMatrix4x4<T>::operator () (Position row, Position col)
01213     throw(Exception::IndexOverflow)
01214   {
01215     if ((row > 3) || (col > 3))
01216     {
01217       throw Exception::IndexOverflow(__FILE__, __LINE__, row + col, 3);
01218     }
01219 
01220     return *comp_ptr_[4 * row + col];
01221   }
01222 
01223   template <typename T>
01224   BALL_INLINE 
01225   const T& TMatrix4x4<T>::operator () (Position row, Position col) const
01226     throw(Exception::IndexOverflow)
01227   {
01228     if ((row > 3) || (col > 3))
01229     {
01230       throw Exception::IndexOverflow(__FILE__, __LINE__, row + col, 3);
01231     }
01232 
01233     return *comp_ptr_[4 * row + col];
01234   }
01235 
01236   template <typename T>
01237   BALL_INLINE
01238   const T& TMatrix4x4<T>::operator [] (Position position) const
01239     throw(Exception::IndexOverflow)
01240   {
01241     if (position > 15)
01242     {
01243       throw Exception::IndexOverflow(__FILE__, __LINE__, position, 15);
01244     }
01245     return *comp_ptr_[position];
01246   }
01247 
01248   template <typename T>
01249   BALL_INLINE
01250   T& TMatrix4x4<T>::operator [] (Position position)
01251     throw(Exception::IndexOverflow)
01252   {
01253     if (position > 15)
01254     {
01255       throw Exception::IndexOverflow(__FILE__, __LINE__, position, 15);
01256     }
01257     return *comp_ptr_[position];
01258   }
01259 
01260   template <typename T>
01261   BALL_INLINE 
01262   TMatrix4x4<T> TMatrix4x4<T>::operator + () const
01263     
01264   {
01265     return *this;
01266   }
01267 
01268   template <typename T>
01269   BALL_INLINE TMatrix4x4<T>
01270   TMatrix4x4<T>::operator - () const
01271     
01272   {
01273     return TMatrix4x4<T>
01274       (-m11, -m12, -m13, -m14,
01275        -m21, -m22, -m23, -m24,
01276        -m31, -m32, -m33, -m34,
01277        -m41, -m42, -m43, -m44);
01278   }
01279 
01280   template <typename T>
01281   TMatrix4x4<T> TMatrix4x4<T>::operator + (const TMatrix4x4<T>& m) const
01282     
01283   {
01284     return TMatrix4x4<T>
01285       (m11 + m.m11, m12 + m.m12, m13 + m.m13, m14 + m.m14,
01286        m21 + m.m21, m22 + m.m22, m23 + m.m23, m24 + m.m24,
01287        m31 + m.m31, m32 + m.m32, m33 + m.m33, m34 + m.m34,
01288        m41 + m.m41, m42 + m.m42, m43 + m.m43, m44 + m.m44);
01289   }
01290 
01291   template <typename T>
01292   TMatrix4x4<T>& TMatrix4x4<T>::operator += (const TMatrix4x4<T>& m)
01293     
01294   {
01295     m11 += m.m11;
01296     m12 += m.m12;
01297     m13 += m.m13;
01298     m14 += m.m14;
01299     m21 += m.m21;
01300     m22 += m.m22;
01301     m23 += m.m23;
01302     m24 += m.m24;
01303     m31 += m.m31;
01304     m32 += m.m32;
01305     m33 += m.m33;
01306     m34 += m.m34;
01307     m41 += m.m41;
01308     m42 += m.m42;
01309     m43 += m.m43;
01310     m44 += m.m44;
01311 
01312     return *this;
01313   }
01314 
01315   template <typename T>
01316   TMatrix4x4<T> TMatrix4x4<T>::operator - (const TMatrix4x4<T>& m) const
01317     
01318   {
01319     return TMatrix4x4<T>
01320       (m11 - m.m11, m12 - m.m12, m13 - m.m13, m14 - m.m14,
01321        m21 - m.m21, m22 - m.m22, m23 - m.m23, m24 - m.m24,
01322        m31 - m.m31, m32 - m.m32, m33 - m.m33, m34 - m.m34,
01323        m41 - m.m41, m42 - m.m42, m43 - m.m43, m44 - m.m44);
01324   }
01325 
01326   template <typename T>
01327   TMatrix4x4<T>& TMatrix4x4<T>::operator -= (const TMatrix4x4<T>& m)
01328     
01329   {
01330     m11 -= m.m11;
01331     m12 -= m.m12;
01332     m13 -= m.m13;
01333     m14 -= m.m14;
01334     m21 -= m.m21;
01335     m22 -= m.m22;
01336     m23 -= m.m23;
01337     m24 -= m.m24;
01338     m31 -= m.m31;
01339     m32 -= m.m32;
01340     m33 -= m.m33;
01341     m34 -= m.m34;
01342     m41 -= m.m41;
01343     m42 -= m.m42;
01344     m43 -= m.m43;
01345     m44 -= m.m44;
01346 
01347     return *this;
01348   }
01349 
01350   template <typename T>
01351   TMatrix4x4<T> TMatrix4x4<T>::operator * (const T& scalar) const
01352     
01353   {
01354     return TMatrix4x4<T>
01355       (m11 * scalar, m12 * scalar, m13 * scalar, m14 * scalar,
01356        m21 * scalar, m22 * scalar, m23 * scalar, m24 * scalar,
01357        m31 * scalar, m32 * scalar, m33 * scalar, m34 * scalar,
01358        m41 * scalar, m42 * scalar, m43 * scalar, m44 * scalar);
01359   }
01360 
01361   template <typename T>
01362   TMatrix4x4<T> operator * (const T& scalar, const TMatrix4x4<T>& m)
01363     
01364   {
01365     return TMatrix4x4<T>
01366       (scalar * m.m11, scalar * m.m12, scalar * m.m13, scalar * m.m14,
01367        scalar * m.m21, scalar * m.m22, scalar * m.m23, scalar * m.m24,
01368        scalar * m.m31, scalar * m.m32, scalar * m.m33, scalar * m.m34,
01369        scalar * m.m41, scalar * m.m42, scalar * m.m43, scalar * m.m44);
01370   }
01371 
01372   template <typename T>
01373   TMatrix4x4<T>& TMatrix4x4<T>::operator *= (const T& scalar)
01374     
01375   {
01376     m11 *= scalar;
01377     m12 *= scalar;
01378     m13 *= scalar;
01379     m14 *= scalar;
01380     m21 *= scalar;
01381     m22 *= scalar;
01382     m23 *= scalar;
01383     m24 *= scalar;
01384     m31 *= scalar;
01385     m32 *= scalar;
01386     m33 *= scalar;
01387     m34 *= scalar;
01388     m41 *= scalar;
01389     m42 *= scalar;
01390     m43 *= scalar;
01391     m44 *= scalar;
01392 
01393     return *this;
01394   }
01395 
01396   template <typename T>
01397   TVector3<T> operator *(const TMatrix4x4<T>& matrix, const TVector3<T>& vector)
01398     
01399   {
01400     return TVector3<T>
01401       (matrix.m11 * vector.x + matrix.m12 * vector.y + matrix.m13 * vector.z + matrix.m14,
01402        matrix.m21 * vector.x + matrix.m22 * vector.y + matrix.m23 * vector.z + matrix.m24,
01403        matrix.m31 * vector.x + matrix.m32 * vector.y + matrix.m33 * vector.z + matrix.m34);
01404   }
01405 
01406   template <typename T>
01407   BALL_INLINE 
01408   TMatrix4x4<T>TMatrix4x4<T>::operator / (const T& scalar) const
01409     throw(Exception::DivisionByZero)
01410   {
01411     if (scalar == (T)0)
01412     {
01413       throw Exception::DivisionByZero(__FILE__, __LINE__);
01414     }
01415     
01416     return (*this * ((T)1 / scalar));
01417   }
01418 
01419   template <typename T>
01420   BALL_INLINE 
01421   TMatrix4x4<T>& TMatrix4x4<T>::operator /= (const T& scalar)
01422     throw(Exception::DivisionByZero)
01423   {
01424     if (scalar == (T)0)
01425     {
01426       throw Exception::DivisionByZero(__FILE__, __LINE__);
01427     }
01428     
01429     return (*this *= (T)1 / scalar);
01430   }
01431 
01432   template <typename T>
01433   TMatrix4x4<T> TMatrix4x4<T>::operator * (const TMatrix4x4<T>& m) const
01434     
01435   {
01436     return TMatrix4x4<T>
01437         (m11 * m.m11 + m12 * m.m21 + m13 * m.m31 + m14 * m.m41,
01438          m11 * m.m12 + m12 * m.m22 + m13 * m.m32 + m14 * m.m42,
01439          m11 * m.m13 + m12 * m.m23 + m13 * m.m33 + m14 * m.m43,
01440          m11 * m.m14 + m12 * m.m24 + m13 * m.m34 + m14 * m.m44,
01441 
01442          m21 * m.m11 + m22 * m.m21 + m23 * m.m31 + m24 * m.m41,
01443          m21 * m.m12 + m22 * m.m22 + m23 * m.m32 + m24 * m.m42,
01444          m21 * m.m13 + m22 * m.m23 + m23 * m.m33 + m24 * m.m43,
01445          m21 * m.m14 + m22 * m.m24 + m23 * m.m34 + m24 * m.m44,
01446      
01447          m31 * m.m11 + m32 * m.m21 + m33 * m.m31 + m34 * m.m41,
01448          m31 * m.m12 + m32 * m.m22 + m33 * m.m32 + m34 * m.m42,
01449          m31 * m.m13 + m32 * m.m23 + m33 * m.m33 + m34 * m.m43,
01450          m31 * m.m14 + m32 * m.m24 + m33 * m.m34 + m34 * m.m44,
01451      
01452          m41 * m.m11 + m42 * m.m21 + m43 * m.m31 + m44 * m.m41,
01453          m41 * m.m12 + m42 * m.m22 + m43 * m.m32 + m44 * m.m42,
01454          m41 * m.m13 + m42 * m.m23 + m43 * m.m33 + m44 * m.m43,
01455          m41 * m.m14 + m42 * m.m24 + m43 * m.m34 + m44 * m.m44);
01456   }
01457 
01458   template <typename T>
01459   TMatrix4x4<T>& TMatrix4x4<T>::operator *= (const TMatrix4x4<T>& m)
01460     
01461   {
01462     set(m11 * m.m11 + m12 * m.m21 + m13 * m.m31 + m14 * m.m41,
01463         m11 * m.m12 + m12 * m.m22 + m13 * m.m32 + m14 * m.m42,
01464         m11 * m.m13 + m12 * m.m23 + m13 * m.m33 + m14 * m.m43,
01465         m11 * m.m14 + m12 * m.m24 + m13 * m.m34 + m14 * m.m44,
01466  
01467         m21 * m.m11 + m22 * m.m21 + m23 * m.m31 + m24 * m.m41,
01468         m21 * m.m12 + m22 * m.m22 + m23 * m.m32 + m24 * m.m42,
01469         m21 * m.m13 + m22 * m.m23 + m23 * m.m33 + m24 * m.m43,
01470         m21 * m.m14 + m22 * m.m24 + m23 * m.m34 + m24 * m.m44,
01471 
01472         m31 * m.m11 + m32 * m.m21 + m33 * m.m31 + m34 * m.m41,
01473         m31 * m.m12 + m32 * m.m22 + m33 * m.m32 + m34 * m.m42,
01474         m31 * m.m13 + m32 * m.m23 + m33 * m.m33 + m34 * m.m43,
01475         m31 * m.m14 + m32 * m.m24 + m33 * m.m34 + m34 * m.m44,
01476 
01477         m41 * m.m11 + m42 * m.m21 + m43 * m.m31 + m44 * m.m41,
01478         m41 * m.m12 + m42 * m.m22 + m43 * m.m32 + m44 * m.m42,
01479         m41 * m.m13 + m42 * m.m23 + m43 * m.m33 + m44 * m.m43,
01480         m41 * m.m14 + m42 * m.m24 + m43 * m.m34 + m44 * m.m44);
01481 
01482     return *this;
01483   }
01484 
01485   template <typename T>
01486   TVector4<T> TMatrix4x4<T>::operator * (const TVector4<T>& v) const
01487     
01488   {
01489     return TVector4<T>
01490       (m11 * v.x + m12 * v.y + m13 * v.z + m14 * v.h,
01491        m21 * v.x + m22 * v.y + m23 * v.z + m24 * v.h,
01492        m31 * v.x + m32 * v.y + m33 * v.z + m34 * v.h,
01493        m41 * v.x + m42 * v.y + m43 * v.z + m44 * v.h);
01494   }
01495 
01496   template <typename T>
01497   bool TMatrix4x4<T>::invert(TMatrix4x4<T>& inverse) const
01498     
01499   {
01507     Index i, j, k;
01508 
01509     T a[4][4] = // holds the matrix we want to invert
01510     {
01511       { m11, m12, m13, m14 },
01512       { m21, m22, m23, m24 },
01513       { m31, m32, m33, m34 },
01514       { m41, m42, m43, m44 }
01515     };
01516   
01517     // holds the maximum in the part of A we still have to work with
01518     T scale, sum_of_squares, sigma, tau;
01519     T c[4], d[4];
01520     for (k=0; k<3; k++)
01521     {
01522       scale = (T)0;
01523       // find the maximum in a
01524       for (i=k; i<4; i++)
01525         scale = Maths::max((T)fabs(a[i][k]), scale);
01526 
01527       // is the matrix singular?
01528       if (scale == (T)0)
01529         return false;
01530 
01531       // nope. we can normalize the remaining rows
01532       for (i=k; i<4; i++)
01533         a[i][k] /= scale;
01534       
01535       sum_of_squares = (T)0;
01536       for (i=k; i<4; i++)
01537         sum_of_squares += a[i][k]*a[i][k];
01538 
01539       // shift the diagonal element
01540       sigma = (a[k][k] >= 0) ? sqrt(sum_of_squares) : -sqrt(sum_of_squares);
01541       a[k][k] += sigma;
01542 
01543       c[k] =  sigma*a[k][k];
01544       d[k] = -scale*sigma;
01545 
01546       for (j = k+1; j<4; j++)
01547       {
01548         // store the scalar product of a_[k] and a_[j]
01549         sum_of_squares = (T)0;
01550         for (i = k; i<4; i++)
01551           sum_of_squares += a[i][k] * a[i][j];
01552 
01553         tau = sum_of_squares / c[k];
01554 
01555         // prepare the matrix
01556         for (i=k; i<4; i++)
01557           a[i][j] -= tau*a[i][k];
01558       }
01559     }
01560     d[3] = a[3][3];
01561     
01562     // is the matrix singular?
01563     if (d[3] == (T)0)
01564       return 1;
01565 
01566     // now we have the QR decomposition. The upper triangle of A contains
01567     // R, except for the diagonal elements, which are stored in d. c contains
01568     // the values needed to compute the Householder matrices Q, and the vectors
01569     // u needed for the determination of the Qs are stored in the lower triangle
01570     // of A
01571     //
01572     // now we need to solve four linear systems of equations, one for each column
01573     // of the resulting matrix
01574     T result[4][4];
01575     result[0][0] = 1; result[0][1] = 0; result[0][2] = 0; result[0][3] = 0;
01576     result[1][0] = 0; result[1][1] = 1; result[1][2] = 0; result[1][3] = 0;
01577     result[2][0] = 0; result[2][1] = 0; result[2][2] = 1; result[2][3] = 0;
01578     result[3][0] = 0; result[3][1] = 0; result[3][2] = 0; result[3][3] = 1;
01579 
01580     for (k=0; k<4; k++) // k generates the k-th column of the inverse
01581     {
01582       // form the vector Q^t * b, which is simple, since b = e_k
01583       for (j=0; j<3; j++)
01584       {
01585         sum_of_squares = (T)0;
01586         for (i=j; i<4; i++)
01587           sum_of_squares += a[i][j]*result[i][k];
01588         
01589         tau = sum_of_squares / c[j];
01590         
01591         for (i=j; i<4; i++)
01592           result[i][k] -= tau*a[i][j];
01593       }
01594 
01595       // and solve the resulting system
01596       result[3][k] /= d[3];
01597       for (i=2; i>=0; i--)
01598       {
01599         sum_of_squares = (T)0;
01600         for (j=i+1; j<4; j++)
01601           sum_of_squares += a[i][j] * result[j][k];
01602 
01603         result[i][k] = (result[i][k] - sum_of_squares) / d[i];
01604       }
01605     }
01606     
01607     T* k_ptr = *result;
01608     inverse.m11 = *k_ptr++;
01609     inverse.m12 = *k_ptr++;
01610     inverse.m13 = *k_ptr++;
01611     inverse.m14 = *k_ptr++;
01612     inverse.m21 = *k_ptr++;
01613     inverse.m22 = *k_ptr++;
01614     inverse.m23 = *k_ptr++;
01615     inverse.m24 = *k_ptr++;
01616     inverse.m31 = *k_ptr++;
01617     inverse.m32 = *k_ptr++;
01618     inverse.m33 = *k_ptr++;
01619     inverse.m34 = *k_ptr++;
01620     inverse.m41 = *k_ptr++;
01621     inverse.m42 = *k_ptr++;
01622     inverse.m43 = *k_ptr++;
01623     inverse.m44 = *k_ptr;
01624 
01625     return true;
01626   }
01627 
01628   template <typename T>
01629   BALL_INLINE bool TMatrix4x4<T>::invert()
01630     
01631   {
01632     return invert(*this);
01633   }
01634 
01635   template <typename T>
01636   T TMatrix4x4<T>::getDeterminant() const
01637     
01638   {
01639     Position i;
01640     Position j;
01641     Position k;
01642     T submatrix[3][3];
01643     T matrix[4][4] =
01644     {
01645       { m11, m12, m13, m14 },
01646       { m21, m22, m23, m24 },
01647       { m31, m32, m33, m34 },
01648       { m41, m42, m43, m44 }
01649     };
01650     T determinant = 0;
01651       
01652     for (i = 0; i < 4; i++)
01653     {
01654       for (j = 0; j < 3; j++)
01655       {
01656         for (k = 0; k < 3; k++)
01657         {
01658           submatrix[j][k] =
01659           matrix[j + 1][(k < i) ? k : k + 1];
01660         }
01661       }
01662       
01663       determinant += matrix[0][i] * (T)(i / 2.0 == (i >> 1) ? 1 : -1)
01664                   * (submatrix[0][0] * submatrix[1][1] * submatrix[2][2] 
01665                      + submatrix[0][1] * submatrix[1][2] * submatrix[2][0] 
01666                      + submatrix[0][2] * submatrix[1][0] * submatrix[2][1] 
01667                      - submatrix[0][2] * submatrix[1][1] * submatrix[2][0] 
01668                      - submatrix[0][0] * submatrix[1][2] * submatrix[2][1] 
01669                      - submatrix[0][1] * submatrix[1][0] * submatrix[2][2]);
01670     }
01671 
01672     return determinant;
01673   }
01674 
01675   template <typename T>
01676   void TMatrix4x4<T>::translate(const T& x, const T& y, const T& z)
01677     
01678   {
01679     m14 += m11 * x + m12 * y + m13 * z;
01680     m24 += m21 * x + m22 * y + m23 * z;
01681     m34 += m31 * x + m32 * y + m33 * z;
01682     m44 += m41 * x + m42 * y + m43 * z;
01683   }
01684 
01685   template <typename T>
01686   void TMatrix4x4<T>::translate(const TVector3<T>& v)
01687     
01688   {
01689     m14 += m11 * v.x + m12 * v.y + m13 * v.z;
01690     m24 += m21 * v.x + m22 * v.y + m23 * v.z;
01691     m34 += m31 * v.x + m32 * v.y + m33 * v.z;
01692     m44 += m41 * v.x + m42 * v.y + m43 * v.z;
01693   }
01694 
01695   template <typename T>
01696   void TMatrix4x4<T>::setTranslation(const T& x, const T& y, const T& z)
01697     
01698   {
01699     m11 = m22 = m33 = m44 = 1;
01700 
01701     m12 = m13 = 
01702     m21 = m23 = 
01703     m31 = m32 =  
01704     m41 = m42 = m43 = 0;
01705 
01706     m14 = x;
01707     m24 = y;
01708     m34 = z;
01709   }
01710 
01711   template <typename T>
01712   void TMatrix4x4<T>::setTranslation(const TVector3<T>& v)
01713     
01714   {
01715     m11 = m22 = m33 = m44 = 1;
01716 
01717     m12 = m13 = 
01718     m21 = m23 = 
01719     m31 = m32 =  
01720     m41 = m42 = m43 = 0;
01721 
01722     m14 = v.x;
01723     m24 = v.y;
01724     m34 = v.z;
01725   }
01726 
01727   template <typename T>
01728   void TMatrix4x4<T>::scale(const T& x_scale, const T& y_scale, const T& z_scale)
01729     
01730   {
01731     m11 *= x_scale;
01732     m21 *= x_scale;
01733     m31 *= x_scale;
01734     m41 *= x_scale;
01735 
01736     m12 *= y_scale;
01737     m22 *= y_scale;
01738     m32 *= y_scale;
01739     m42 *= y_scale;
01740 
01741     m13 *= z_scale;
01742     m23 *= z_scale;
01743     m33 *= z_scale;
01744     m43 *= z_scale;
01745   }
01746 
01747   template <typename T>
01748   void TMatrix4x4<T>::scale(const T& scale)
01749     
01750   {
01751     m11 *= scale;
01752     m21 *= scale;
01753     m31 *= scale;
01754     m41 *= scale;
01755 
01756     m12 *= scale;
01757     m22 *= scale;
01758     m32 *= scale;
01759     m42 *= scale;
01760 
01761     m13 *= scale;
01762     m23 *= scale;
01763     m33 *= scale;
01764     m43 *= scale;
01765   }
01766 
01767   template <typename T>
01768   void TMatrix4x4<T>::scale(const TVector3<T>& v)
01769     
01770   {
01771     m11 *= v.x;
01772     m21 *= v.x;
01773     m31 *= v.x;
01774     m41 *= v.x;
01775 
01776     m12 *= v.y;
01777     m22 *= v.y;
01778     m32 *= v.y;
01779     m42 *= v.y;
01780 
01781     m13 *= v.z;
01782     m23 *= v.z;
01783     m33 *= v.z;
01784     m43 *= v.z;
01785   }
01786 
01787   template <typename T>
01788   void TMatrix4x4<T>::setScale(const T& x_scale, const T& y_scale, const T& z_scale)
01789     
01790   {
01791     m11 = x_scale;
01792     m22 = y_scale;
01793     m33 = z_scale;
01794     m44 = 1;
01795 
01796     m12 = m13 = m14 =
01797     m21 = m23 = m24 =
01798     m31 = m32 = m34 = 
01799     m41 = m42 = m43 = 0;
01800   }
01801 
01802   template <typename T>
01803   void TMatrix4x4<T>::setScale(const T& scale)
01804     
01805   {
01806     m11 = scale;
01807     m22 = scale;
01808     m33 = scale;
01809     m44 = 1;
01810 
01811     m12 = m13 = m14 =
01812     m21 = m23 = m24 =
01813     m31 = m32 = m34 = 
01814     m41 = m42 = m43 = 0;
01815   }
01816 
01817   template <typename T>
01818   void TMatrix4x4<T>::setScale(const TVector3<T>& v)
01819     
01820   {
01821     m11 = v.x;
01822     m22 = v.y;
01823     m33 = v.z;
01824     m44 = 1;
01825 
01826     m12 = m13 = m14 =
01827     m21 = m23 = m24 =
01828     m31 = m32 = m34 = 
01829     m41 = m42 = m43 = 0;
01830   }
01831 
01832   template <typename T>
01833   BALL_INLINE 
01834   void TMatrix4x4<T>::rotateX(const TAngle<T>& phi)
01835     
01836   {
01837     TMatrix4x4<T> rotation;
01838 
01839     rotation.setRotationX(phi);
01840     *this *= rotation;
01841   }
01842 
01843   template <typename T>
01844   void TMatrix4x4<T>::setRotationX(const TAngle<T>& phi)
01845     
01846   {
01847     m11 = m44 = 1;
01848 
01849       m12 = m13 = m14 
01850     = m21 = m24 
01851     = m31 = m34  
01852     = m41 = m42 = m43 
01853     = 0;
01854 
01855     m22 = m33 = cos(phi);
01856     m23 = -(m32 = sin(phi));
01857   }
01858 
01859   template <typename T>
01860   BALL_INLINE 
01861   void TMatrix4x4<T>::rotateY(const TAngle<T>& phi)
01862     
01863   {
01864     TMatrix4x4<T> rotation;
01865 
01866     rotation.setRotationY(phi);
01867     *this *= rotation;
01868   }
01869 
01870   template <typename T>
01871   void TMatrix4x4<T>::setRotationY(const TAngle<T>& phi)
01872     
01873   {
01874     m22 = m44 = 1;
01875 
01876       m12 = m14 
01877     = m21 = m23 = m24 
01878     = m32 = m34 
01879     = m41 = m42 = m43 
01880     = 0;
01881 
01882     m11 = m33 = cos(phi);
01883     m31 = -(m13 = sin(phi));
01884   }
01885 
01886   template <typename T>
01887   BALL_INLINE 
01888   void TMatrix4x4<T>::rotateZ(const TAngle<T>& phi)
01889     
01890   {
01891     TMatrix4x4<T> rotation;
01892 
01893     rotation.setRotationZ(phi);
01894     *this *= rotation;
01895   }
01896 
01897   template <typename T>
01898   void TMatrix4x4<T>::setRotationZ(const TAngle<T>& phi)
01899     
01900   {
01901     m33 = m44 = 1;
01902 
01903     m13 = m14 = m23 = m24 = m31 = 
01904     m32 = m34 = m41 = m42 = m43 = 0;
01905 
01906     m11 =  m22 = cos(phi);
01907     m12 = -(m21 = sin(phi));
01908   }
01909 
01910   template <typename T>
01911   BALL_INLINE 
01912   void TMatrix4x4<T>::rotate(const TAngle<T>& phi, const TVector3<T>& v)
01913     
01914   {
01915     rotate(phi, v.x, v.y, v.z);
01916   }
01917 
01918   template <typename T>
01919   BALL_INLINE 
01920   void TMatrix4x4<T>::rotate(const TAngle<T>& phi, const TVector4<T>& v)
01921     
01922   {
01923     rotate(phi, v.x, v.y, v.z);
01924   }
01925 
01926   //
01927   //     Arbitrary axis rotation matrix.
01928   //
01929   //  [Taken from the MESA-Library. But modified for additional Speed-Up.]
01930   //
01931   //  This function was contributed by Erich Boleyn (erich@uruk.org).
01932   //
01933   //  This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
01934   //  like so:  Rz * Ry * T * Ry' * Rz'.  T is the final rotation
01935   //  (which is about the X-axis), and the two composite transforms
01936   //  Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
01937   //  from the arbitrary axis to the X-axis then back.  They are
01938   //  all elementary rotations.
01939   //
01940   //  Rz' is a rotation about the Z-axis, to bring the axis vector
01941   //  into the x-z plane.  Then Ry' is applied, rotating about the
01942   //  Y-axis to bring the axis vector parallel with the X-axis.  The
01943   //  rotation about the X-axis is then performed.  Ry and Rz are
01944   //  simply the respective inverse transforms to bring the arbitrary
01945   //  axis back to it's original orientation.  The first transforms
01946   //  Rz' and Ry' are considered inverses, since the data from the
01947   //  arbitrary axis gives you info on how to get to it, not how
01948   //  to get away from it, and an inverse must be applied.
01949   //
01950   //  The basic calculation used is to recognize that the arbitrary
01951   //  axis vector (x, y, z), since it is of unit length, actually
01952   //  represents the sines and cosines of the angles to rotate the
01953   //  X-axis to the same orientation, with theta being the angle about
01954   //  Z and phi the angle about Y (in the order described above)
01955   //  as follows:
01956   //
01957   //  cos ( theta ) = x / sqrt ( 1 - z^2 )
01958   //  sin ( theta ) = y / sqrt ( 1 - z^2 )
01959   //
01960   //  cos ( phi ) = sqrt ( 1 - z^2 )
01961   //  sin ( phi ) = z
01962   //
01963   //  Note that cos ( phi ) can further be inserted to the above
01964   //  formulas:
01965   //
01966   //  cos ( theta ) = x / cos ( phi )
01967   //  sin ( theta ) = y / sin ( phi )
01968   //
01969   //  ...etc.  Because of those relations and the standard trigonometric
01970   //  relations, it is pssible to reduce the transforms down to what
01971   //  is used below.  It may be that any primary axis chosen will give the
01972   //  same results (modulo a sign convention) using thie method.
01973   //
01974   //  Particularly nice is to notice that all divisions that might
01975   //  have caused trouble when parallel to certain planes or
01976   //  axis go away with care paid to reducing the expressions.
01977   //  After checking, it does perform correctly under all cases, since
01978   //  in all the cases of division where the denominator would have
01979   //  been zero, the numerator would have been zero as well, giving
01980   //  the expected result.
01981 
01982   template <typename T>
01983   void TMatrix4x4<T>::rotate(const TAngle<T>& phi, const T& ax, const T& ay, const T& az)
01984     
01985   {
01986     T xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
01987     T x = ax;
01988     T y = ay;
01989     T z = az;
01990 
01991     double sin_angle = sin(phi);
01992     double cos_angle = cos(phi);
01993 
01994     xx = x * x;
01995     yy = y * y;
01996     zz = z * z;
01997 
01998     T mag = sqrt(xx + yy + zz);
01999     
02000     if (mag == (T)0) 
02001     {
02002       m12 = m13 = m14 = m21 = m23 = m24 = m31 = m32 = m34 = m41 = m42 = m43 = 0;
02003       m11 = m22 = m33 = m44 = (T)1;
02004     }
02005 
02006     x /= mag;
02007     y /= mag;
02008     z /= mag;
02009 
02010     // we need to recalculate xx, yy, zz due to the
02011     // normalization. recalculation is probably faster
02012     // than normalizing xx, yy, zz
02013     xx = x*x;
02014     yy = y*y;
02015     zz = z*z;
02016 
02017     xy = x * y;
02018     yz = y * z;
02019     zx = z * x;
02020     xs = (T) (x * sin_angle);
02021     ys = (T) (y * sin_angle);
02022     zs = (T) (z * sin_angle);
02023     one_c = (T) (1 - cos_angle);
02024 
02025     m11 = (T)( (one_c * xx) + cos_angle );
02026     m12 = (one_c * xy) - zs;
02027     m13 = (one_c * zx) + ys;
02028     m14 = 0;
02029     
02030     m21 = (one_c * xy) + zs;
02031     m22 = (T) ((one_c * yy) + cos_angle);
02032     m23 = (one_c * yz) - xs;
02033     m24 = 0;
02034     
02035     m31 = (one_c * zx) - ys;
02036     m32 = (one_c * yz) + xs;
02037     m33 = (T) ((one_c * zz) + cos_angle);
02038     m34 = 0;
02039      
02040     m41 = 0;
02041     m42 = 0;
02042     m43 = 0;
02043     m44 = 1;
02044   }
02045 
02046   template <typename T>
02047   void TMatrix4x4<T>::setRotation(const TAngle<T>& phi, const T& x, const T& y, const T& z)
02048     
02049   {
02050     m12 = m13 = m14 = m21 = m23 = m24 = m31 = m32 = m34 = m41 = m42 = m43 = 0;
02051     m11 = m22 = m33 = m44 = (T)1;
02052     rotate(phi, x, y, z);
02053   }
02054 
02055   template <typename T>
02056   BALL_INLINE 
02057   void TMatrix4x4<T>::setRotation(const TAngle<T>& phi, const TVector3<T>& v)
02058     
02059   {
02060     m12 = m13 = m14 = m21 = m23 = m24 = m31 = m32 = m34 = m41 = m42 = m43 = 0;
02061     m11 = m22 = m33 = m44 = (T)1;
02062     rotate(phi, v.x, v.y, v.z);
02063   }
02064 
02065   template <typename T>
02066   BALL_INLINE 
02067   void TMatrix4x4<T>::setRotation(const TAngle<T>& phi, const TVector4<T>& v)
02068     
02069   {
02070     m12 = m13 = m14 = m21 = m23 = m24 = m31 = m32 = m34 = m41 = m42 = m43 = 0;
02071     m11 = m22 = m33 = m44 = (T)1;
02072     rotate(phi, v.x, v.y, v.z);
02073   }
02074 
02075   template <typename T>
02076   bool TMatrix4x4<T>::operator == (const TMatrix4x4<T>& m) const
02077     
02078   {
02079     return 
02080       (   m11 == m.m11
02081        && m12 == m.m12
02082        && m13 == m.m13
02083        && m14 == m.m14
02084        && m21 == m.m21
02085        && m22 == m.m22
02086        && m23 == m.m23
02087        && m24 == m.m24
02088        && m31 == m.m31
02089        && m32 == m.m32
02090        && m33 == m.m33
02091        && m34 == m.m34
02092        && m41 == m.m41
02093        && m42 == m.m42
02094        && m43 == m.m43
02095        && m44 == m.m44);
02096   }
02097 
02098   template <typename T>
02099   bool TMatrix4x4<T>::operator != (const TMatrix4x4<T>& m) const
02100     
02101   {
02102     return 
02103       (   m11 != m.m11
02104        || m12 != m.m12
02105        || m13 != m.m13
02106        || m14 != m.m14
02107        || m21 != m.m21
02108        || m22 != m.m22
02109        || m23 != m.m23
02110        || m24 != m.m24
02111        || m31 != m.m31
02112        || m32 != m.m32
02113        || m33 != m.m33
02114        || m34 != m.m34
02115        || m41 != m.m41
02116        || m42 != m.m42
02117        || m43 != m.m43
02118        || m44 != m.m44);
02119   }
02120 
02121   template <typename T>
02122   bool TMatrix4x4<T>::isIdentity() const
02123     
02124   {
02125     return 
02126       (   m11 == (T)1
02127        && m12 == (T)0
02128        && m13 == (T)0
02129        && m14 == (T)0
02130        && m21 == (T)0
02131        && m22 == (T)1
02132        && m23 == (T)0
02133        && m24 == (T)0
02134        && m31 == (T)0
02135        && m32 == (T)0
02136        && m33 == (T)1
02137        && m34 == (T)0
02138        && m41 == (T)0
02139        && m42 == (T)0
02140        && m43 == (T)0
02141        && m44 == (T)1);
02142   }
02143 
02144   template <typename T>
02145   BALL_INLINE 
02146   bool TMatrix4x4<T>::isRegular() const
02147     
02148   {
02149     return (getDeterminant() != (T)0);
02150   }
02151 
02152   template <typename T>
02153   BALL_INLINE
02154   bool TMatrix4x4<T>::isSingular() const
02155     
02156   {
02157     return (getDeterminant() == (T)0);
02158   }
02159 
02160   template <typename T>
02161   bool TMatrix4x4<T>::isSymmetric() const
02162     
02163   {
02164     return (   m12 == m21 && m13 == m31
02165             && m14 == m41 && m23 == m32
02166             && m24 == m42 && m34 == m43);
02167   }
02168 
02169   template <typename T>
02170   bool TMatrix4x4<T>::isLowerTriangular() const
02171     
02172   {
02173     return (   m12 == (T)0
02174             && m13 == (T)0
02175             && m14 == (T)0
02176             && m23 == (T)0
02177             && m24 == (T)0
02178             && m34 == (T)0);
02179   }
02180 
02181   template <typename T>
02182   bool TMatrix4x4<T>::isUpperTriangular() const
02183     
02184   {
02185     return (   m21 == (T)0
02186             && m31 == (T)0
02187             && m32 == (T)0
02188             && m41 == (T)0
02189             && m42 == (T)0
02190             && m43 == (T)0);
02191   }
02192 
02193   template <typename T>
02194   BALL_INLINE 
02195   bool TMatrix4x4<T>::isDiagonal() const
02196     
02197   {
02198     return (   m12 == (T)0
02199             && m13 == (T)0
02200             && m14 == (T)0
02201             && m21 == (T)0
02202             && m23 == (T)0
02203             && m24 == (T)0
02204             && m31 == (T)0
02205             && m32 == (T)0
02206             && m34 == (T)0
02207             && m41 == (T)0
02208             && m42 == (T)0
02209             && m43 == (T)0);
02210   }
02211 
02212   template <typename T>
02213   bool TMatrix4x4<T>::isValid() const
02214     
02215   {
02216     T **ptr = (T **)comp_ptr_;
02217     
02218     return (   *ptr++ == &m11
02219             && *ptr++ == &m12
02220             && *ptr++ == &m13
02221             && *ptr++ == &m14
02222             && *ptr++ == &m21
02223             && *ptr++ == &m22
02224             && *ptr++ == &m23
02225             && *ptr++ == &m24
02226             && *ptr++ == &m31
02227             && *ptr++ == &m32
02228             && *ptr++ == &m33
02229             && *ptr++ == &m34
02230             && *ptr++ == &m41
02231             && *ptr++ == &m42
02232             && *ptr++ == &m43
02233             && *ptr   == &m44);
02234   }
02235 
02236   template <typename T>
02237   std::istream& operator >> (std::istream& s, TMatrix4x4<T>& m)
02238     
02239   {   
02240     char c;
02241     s >> c
02242       >> m.m11 >> m.m12 >> m.m13 >> m.m14 >> c >> c
02243       >> m.m21 >> m.m22 >> m.m23 >> m.m24 >> c >> c
02244       >> m.m31 >> m.m32 >> m.m33 >> m.m34 >> c >> c
02245       >> m.m41 >> m.m42 >> m.m43 >> m.m44 >> c;
02246     
02247     return s;
02248   }
02249 
02250   template <typename T>
02251   std::ostream& operator << (std::ostream& s, const TMatrix4x4<T>& m)
02252     
02253   { 
02254     s << '/'  <<  std::setw(14) << m.m11 << ' ' << std::setw(14) << m.m12 << ' ' << std::setw(14) << m.m13 << ' ' << std::setw(14) << m.m14 << " \\" << std::endl
02255       << '|'  <<  std::setw(14) << m.m21 << ' ' << std::setw(14) << m.m22 << ' ' << std::setw(14) << m.m23 << ' ' << std::setw(14) << m.m24 << " |"  << std::endl
02256       << '|'  <<  std::setw(14) << m.m31 << ' ' << std::setw(14) << m.m32 << ' ' << std::setw(14) << m.m33 << ' ' << std::setw(14) << m.m34 << " |"  << std::endl
02257       << '\\' <<  std::setw(14) << m.m41 << ' ' << std::setw(14) << m.m42 << ' ' << std::setw(14) << m.m43 << ' ' << std::setw(14) << m.m44 << " /" << std::endl;
02258 
02259     return s;
02260   }
02261 
02262   template <typename T>
02263   void TMatrix4x4<T>::dump(std::ostream& s, Size depth) const
02264     
02265   {
02266     BALL_DUMP_STREAM_PREFIX(s);
02267 
02268     BALL_DUMP_HEADER(s, this, this);
02269 
02270     BALL_DUMP_DEPTH(s, depth);
02271     s << m11 << " " << m12 << " " << m13 << " " << m14 << std::endl;
02272 
02273     BALL_DUMP_DEPTH(s, depth);
02274     s << m21 << " " << m22 << " " << m23 << " " << m24 << std::endl;
02275 
02276     BALL_DUMP_DEPTH(s, depth);
02277     s << m31 << " " << m32 << " " << m33 << " " << m34 << std::endl;
02278 
02279     BALL_DUMP_DEPTH(s, depth);
02280     s << m41 << " " << m42 << " " << m43 << " " << m44 << std::endl;
02281 
02282     BALL_DUMP_STREAM_SUFFIX(s);
02283   }
02284 
02286   template <typename T>
02287   TMatrix4x4<T> operator * (const T& scalar, const TMatrix4x4<T>& m)
02288     ;
02289 
02291   template <typename T>
02292   TVector3<T> operator * (const TMatrix4x4<T>& matrix, const TVector3<T>& vector)
02293     ;
02294 
02299   typedef TMatrix4x4<float> Matrix4x4;
02300 
02301 } // namespace BALL
02302 
02303 #endif // BALL_MATHS_MATRIX44_H