"Fossies" - the Fresh Open Source Software Archive

Member "aqsis-1.8.2/include/aqsis/math/matrix.h" (24 Aug 2012, 30788 Bytes) of package /linux/privat/aqsis-1.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Aqsis
    2 // Copyright (C) 1997 - 2001, Paul C. Gregory
    3 //
    4 // Contact: pgregory@aqsis.org
    5 //
    6 // This library is free software; you can redistribute it and/or
    7 // modify it under the terms of the GNU General Public
    8 // License as published by the Free Software Foundation; either
    9 // version 2 of the License, or (at your option) any later version.
   10 //
   11 // This library is distributed in the hope that it will be useful,
   12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14 // General Public License for more details.
   15 //
   16 // You should have received a copy of the GNU General Public
   17 // License along with this library; if not, write to the Free Software
   18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19 
   20 
   21 /**
   22  * \file
   23  *
   24  * \brief Declares the CqMatrix 4D homogenous matrix class.
   25  * \author Paul C. Gregory (pgregory@aqsis.org)
   26  */
   27 
   28 #ifndef MATRIX_H_INCLUDED
   29 #define MATRIX_H_INCLUDED
   30 
   31 #include <aqsis/aqsis.h>
   32 
   33 #include <iostream>
   34 
   35 #include <aqsis/math/vector3d.h>
   36 #include <aqsis/math/vector4d.h>
   37 
   38 namespace Aqsis {
   39 
   40 //----------------------------------------------------------------------
   41 /** \brief 4x4 matrix class for homogenous coordinates.
   42  *
   43  * Access to matrix elements is always row,column from 0.
   44  *
   45  * \todo Document the assumptions about the order of element access in matrix
   46  * multiplication etc.  The convention this matrix class uses is opposite from
   47  * that used in university maths courses: From the conventional mathematical
   48  * viewpoint, multiplication of a vector by this matrix on the right is
   49  * actually multiplication by a row vector on the left...
   50  */
   51 class AQSIS_MATH_SHARE CqMatrix
   52 {
   53     public:
   54         //--------------------------------------------------
   55         // Constructors
   56 
   57         /** \brief Construct the identity matrix.
   58          */
   59         CqMatrix();
   60         /** \brief Construct a diagonal matrix
   61          *
   62          * \param xs - scale factor along x.
   63          * \param ys - scale factor along y.
   64          * \param zs - scale factor along z.
   65          */
   66         CqMatrix( const TqFloat xs, const TqFloat ys, const TqFloat zs );
   67         /** \brief Construct a translation matrix.
   68          *
   69          * \param trans - The vector by which to translate.
   70          */
   71         CqMatrix( const CqVector3D& trans );
   72         /** \brief Rotation matrix constructor
   73          *
   74          * \param angle - The angle to rotate by.
   75          * \param axis - The axis about which to rotate.
   76          */
   77         CqMatrix( const TqFloat angle, const CqVector3D axis );
   78         /** \brief Skew matrix constructor
   79          *
   80          * \param angle
   81          * \param dx1, - dy1, dz1
   82          * \param dx2, - dy2, dz2
   83          */
   84         CqMatrix( const TqFloat angle,
   85                   const TqFloat dx1, const TqFloat dy1, const TqFloat dz1,
   86                   const TqFloat dx2, const TqFloat dy2, const TqFloat dz2 );
   87         /// Copy constructor
   88         CqMatrix( const CqMatrix &from );
   89         /** \brief Construct from a list of individual matrix elements.
   90          *
   91          * Takes 16 floats for the elements of the matrix.
   92          */
   93         CqMatrix( const TqFloat r1c1, const TqFloat r1c2, const TqFloat r1c3, const TqFloat r1c4,
   94                   const TqFloat r2c1, const TqFloat r2c2, const TqFloat r2c3, const TqFloat r2c4,
   95                   const TqFloat r3c1, const TqFloat r3c2, const TqFloat r3c3, const TqFloat r3c4,
   96                   const TqFloat r4c1, const TqFloat r4c2, const TqFloat r4c3, const TqFloat r4c4 );
   97         /** \brief Constructor from a 2D float array of matrix elements
   98          *
   99          * \param from - 2D float array to copy data from.
  100          */
  101         CqMatrix( const TqFloat from[ 4 ][ 4 ] );
  102         /** \brief Constructor from a flattened array of matrix elements
  103          *
  104          * \param from - 1D float array to copy data from.
  105          */
  106         CqMatrix( const TqFloat from[ 16 ] );
  107         /** \brief Construct a scaled 4x4 identity from a float
  108          *
  109          * \param f - amount to scale the identity matrix by
  110          */
  111         CqMatrix( TqFloat f );
  112 
  113         //--------------------------------------------------
  114         /// \name Special-case identity operations
  115         //@{
  116         /// Turn this matrix into an identity.
  117         void Identity();
  118         /** \brief Mark this matrix as identity or not.
  119          *
  120          * \param f - boolean indicating whether or not this matrix should be
  121          * considered identity irespective of its contents.
  122          */
  123         void SetfIdentity( bool f );
  124         /// Return whether or not the matrix is the identity
  125         bool fIdentity() const;
  126         //@}
  127 
  128         //--------------------------------------------------
  129         /// \name Methods for concatenating transformations onto the current one.
  130         //@{
  131         /** \brief Scale matrix uniformly in all three axes.
  132          * \param S - amount to scale by.
  133          */
  134         void Scale( const TqFloat S );
  135         /** \brief Scale matrix in three axes.
  136          * \param xs - X scale factor.
  137          * \param ys - Y scale factor.
  138          * \param zs - Z scale factor.
  139          */
  140         void Scale( const TqFloat xs, const TqFloat ys, const TqFloat zs );
  141         /** \brief Rotate this matrix by an angle about an axis through the origin.
  142          * \param angle - The angle to rotate by.
  143          * \param axis - The axis about which to rotate.
  144          */
  145         void Rotate( const TqFloat angle, const CqVector3D axis );
  146         /** Translates this matrix by a given vector.
  147          * \param trans - The vector by which to translate.
  148          */
  149         void Translate( const CqVector3D& trans );
  150         /** Translates this matrix by three axis distances.
  151          * \param xt - X distance to translate.
  152          * \param yt - Y distance to translate.
  153          * \param zt - Z distance to translate.
  154          */
  155         void Translate( const TqFloat xt, const TqFloat yt, const TqFloat zt );
  156         /** Shears this matrix's X axis according to two shear factors, yh and zh
  157          * \param yh - Y shear factor.
  158          * \param zh - Z shear factor.
  159          */
  160         void ShearX( const TqFloat yh, const TqFloat zh );
  161         /** Shears this matrix's Y axis according to two shear factors, xh and zh
  162          * \param xh - X shear factor.
  163          * \param zh - Z shear factor.
  164          */
  165         void ShearY( const TqFloat xh, const TqFloat zh );
  166         /** Shears this matrix's Z axis according to two shear factors, xh and yh
  167          * \param xh - X shear factor.
  168          * \param yh - Y shear factor.
  169          */
  170         void ShearZ( const TqFloat xh, const TqFloat yh );
  171         /** Skew matrix
  172          * \param angle - The angle by which to skew the transformation.
  173          * \param dx1 
  174          * \param dy1
  175          * \param dz1 - First vector controling skew direction
  176          * \param dx2
  177          * \param dy2
  178          * \param dz2 - Second vector controling skew direction
  179          */
  180         void Skew( const TqFloat angle,
  181                    const TqFloat dx1, const TqFloat dy1, const TqFloat dz1,
  182                    const TqFloat dx2, const TqFloat dy2, const TqFloat dz2 );
  183         /** \brief Normalise the matrix, so that the homogenous part of the matrix is 1.
  184          * \todo code review might be removed since not used in codebase
  185          */
  186         void Normalise();
  187         //@}
  188 
  189         //--------------------------------------------------
  190         /// \name Access to matrix elements
  191         //@{
  192         /** \brief Get the element at the specified row and column index.
  193          * \param row - The row index.
  194          * \param col - The column index.
  195          * \return Float value.
  196          */
  197         TqFloat Element(TqInt row, TqInt col) const;
  198         /** \brief Set the element at the specified row and column index.
  199          * \param row - The row index.
  200          * \param col - The column index.
  201          * \param fValue - the value to insert.
  202          */
  203         void SetElement(TqInt row, TqInt col, TqFloat fValue);
  204         /** \brief Get a pointer to the row index specified.
  205          * \param row - The row index.
  206          * \return Pointer to array of 4 float values.
  207          */
  208         TqFloat* operator[](TqInt row);
  209         /** \brief Get a read only pointer to the row index specified.
  210          * \param row - The row index.
  211          * \return Pointer to array of 4 float values.
  212          */
  213         const TqFloat* operator[](TqInt row) const;
  214         /** \brief Get a pointer to matrix data.
  215          * \return Pointer to array of 16 float values.
  216          */
  217         TqFloat* pElements();
  218         /** \brief Get a read only pointer to matrix data.
  219          * \return Pointer to array of 16 float values.
  220          */
  221         const TqFloat* pElements() const;
  222         //@}
  223 
  224         //--------------------------------------------------
  225         /// \name Operators and functions for matrix arithmetic.
  226         //@{
  227         /** \brief Multiply two matrices together.
  228          * \param from - The matrix to multiply with this matrix.
  229          * \return The resultant multiplied matrix.
  230          */
  231         CqMatrix operator*(const CqMatrix &from) const;
  232         /** \brief Apply scale matrix uniformly in all three axes.
  233          * \param S - The amount by which to scale matrix.
  234          * \return Result of scaling this matrix by S.
  235          */
  236         CqMatrix operator*(const TqFloat S) const;
  237         /** \brief Multiply a vector by this matrix.
  238          * \param vec - The vector to multiply.
  239          * \return The result of multiplying the vector by this matrix.
  240          */
  241         CqVector4D operator*(const CqVector4D &vec) const;
  242         /** \brief Premultiplies this matrix by a vector, returning v*m.
  243          *
  244          * This is the same as postmultiply the transpose of m by a vector: T(m)*v
  245          * \param vec - The vector to multiply.
  246          */
  247         CqVector4D PreMultiply(const CqVector4D &vec) const;
  248         /** \brief Multiply a 3D vector by this matrix.
  249          *
  250          * The meaning of this is to first construct a 4D vector corresponding
  251          * to the homogeneous coordinates: [vec, 1], and multiply that by the
  252          * matrix instead.  We then rescale the result such that the fourth
  253          * component again has value 1.  This allows us to represent
  254          * perspective transformations via matrix multiplication in homogeneous
  255          * coordinates.
  256          *
  257          * \param vec - The vector to multiply.
  258          */
  259         CqVector3D operator*(const CqVector3D &vec) const;
  260         /** \brief Add two matrices.
  261          * \param from - The matrix to add.
  262          * \return Result of adding from to this matrix.
  263          */
  264         CqMatrix operator+(const CqMatrix &from) const;
  265         /** \brief Subtract two matrices.
  266          * \param from - The matrix to subtract.
  267          * \return Result of subtracting from from this matrix.
  268          */
  269         CqMatrix operator-(const CqMatrix &from) const;
  270 
  271         /** \brief Return the inverse of this matrix.
  272          *
  273          * Uses Gauss-Jordan elimination with partial pivoting (see for
  274          * example, Graphics Gems IV (p554)).
  275          */
  276         CqMatrix Inverse() const;
  277         /** \brief Returns the transpose of this matrix
  278          */
  279         CqMatrix Transpose() const;
  280         /** \brief Returns the determinant of this matrix
  281          *
  282          * The algorithm used is simple cofactor expansion.  See, for example,
  283          * Graphics Gems I (p768).
  284          */
  285         TqFloat Determinant() const;
  286 
  287         /** \brief assignment operator
  288          * \param from - matrix to copy information from.
  289          */
  290         CqMatrix& operator=( const CqMatrix &from );
  291         /** \brief Copy function.
  292          * \param from - Renderman matrix to copy information from.
  293          */
  294         CqMatrix& operator=( const TqFloat from[ 4 ][ 4 ] );
  295         /** \brief Copy function.
  296          * \param from - Renderman matrix to copy information from.
  297          */
  298         CqMatrix& operator=( const TqFloat from[ 16 ] );
  299         /** \brief Add a given matrix to this matrix.
  300          * \param from - The matrix to add.
  301          */
  302         CqMatrix& operator+=( const CqMatrix &from );
  303         /** \brief Subtract a given matrix from this matrix.
  304          * \param from - The matrix to subtract.
  305          */
  306         CqMatrix& operator-=( const CqMatrix &from );
  307         /** \brief Multiply this matrix by specified matrix.
  308          *
  309          * This takes into account the types of matrices, in an attempt to
  310          * speed it up.
  311          * \param from - The matrix to multiply with this matrix.
  312          */
  313         CqMatrix& operator*=( const CqMatrix &from );
  314         /** \brief Matrix multiplication of the form a = b * a.
  315          * \param from - The matrix to multiply with this matrix.
  316          */
  317         CqMatrix& PreMultiply( const CqMatrix &from );
  318         /** \brief Apply scale matrix uniformly in all three axes to this matrix.
  319          * \param S - The amount by which to scale this matrix.
  320          * \return The result scaling this matrix by S.
  321          */
  322         CqMatrix& operator*=( const TqFloat S );
  323         /** \brief Scale each element by the specified value.
  324          * \param S - The amount by which to scale the matrix elements.
  325          * \param a - The matrix to be scaled.
  326          * \return Result of scaling this matrix by S.
  327          */
  328         AQSIS_MATH_SHARE friend CqMatrix operator*( TqFloat S, const CqMatrix& a );
  329         //@}
  330 
  331         //--------------------------------------------------
  332         /// \name Other operators
  333         //@{
  334         /** \brief Compare two matrices.
  335          * \param A - One matrix to be compared.
  336          * \param B - Second matrix to be compared with.
  337          * \return Result if matrices are equal or not.
  338          *
  339          * \todo code review Direct floating point comparison is rarely a good
  340          * idea.  We probably need some kind of comparison tolerance in here.
  341          */
  342         AQSIS_MATH_SHARE friend bool  operator==(const CqMatrix& A, const CqMatrix& B);
  343         /// Return !(A == B)
  344         AQSIS_MATH_SHARE friend bool  operator!=(const CqMatrix& A, const CqMatrix& B);
  345         /** \brief Outputs a matrix to an output stream.
  346          * \param Stream - Stream to output the matrix to.
  347          * \param matrix - The matrix to output.
  348          * \return The new state of Stream.
  349          */
  350         AQSIS_MATH_SHARE friend std::ostream &operator<<(std::ostream &Stream,
  351                 const CqMatrix &matrix);
  352         //@}
  353 
  354     protected:
  355         /// The 4x4 array of float values.
  356         TqFloat m_elements[ 4 ][ 4 ];
  357         /** Flag indicating that this matrix should be treated as identity
  358          * irrespective of its contents.
  359          */
  360         bool m_fIdentity;
  361 };
  362 
  363 /// Premultiply matrix by vector.
  364 AQSIS_MATH_SHARE CqVector4D operator*( const CqVector4D &vec, const CqMatrix& matrix );
  365 
  366 //------------------------------------------------------------------------------
  367 /** \brief Determine whether two matrices are equal to within some tolerance
  368  *
  369  * The closeness criterion for the matrices is based on the euclidian norm -
  370  * ie, the usual distance function between two vectors (sum of squares of the
  371  * differences between m1 and m2)
  372  *
  373  * \param m1
  374  * \param m2 - matrices to compare
  375  * \param tolerance - for comparison
  376  */
  377 AQSIS_MATH_SHARE bool isClose(const CqMatrix& m1, const CqMatrix& m2,
  378         TqFloat tol = 10*std::numeric_limits<TqFloat>::epsilon());
  379 
  380 
  381 /// Get the vector transformation associated with the point transformation, m
  382 ///
  383 /// The vector transform is the point transform without the translation part
  384 /// of m.
  385 CqMatrix vectorTransform(const CqMatrix& m);
  386 
  387 /// Get the normal transformation associated with the point transformation, m
  388 ///
  389 /// The normal transform is the same as the vector transform for orthogonal
  390 /// transformations but more complicated in the general case.
  391 CqMatrix normalTransform(const CqMatrix& m);
  392 
  393 //==============================================================================
  394 // Implementation details
  395 //==============================================================================
  396 
  397 // Constructors
  398 inline CqMatrix::CqMatrix( )
  399 {
  400     Identity();
  401 }
  402 
  403 // construct a diagonal matrix
  404 inline CqMatrix::CqMatrix( const TqFloat xs, const TqFloat ys, const TqFloat zs )
  405 {
  406     Identity();
  407 
  408     if ( xs != 1.0f || ys != 1.0f || zs != 1.0f )
  409     {
  410         m_elements[ 0 ][ 0 ] = xs;
  411         m_elements[ 1 ][ 1 ] = ys;
  412         m_elements[ 2 ][ 2 ] = zs;
  413         m_elements[ 3 ][ 3 ] = 1.0;
  414 
  415         m_fIdentity = false;
  416     }
  417 }
  418 
  419 // Construct a translation matrix
  420 inline CqMatrix::CqMatrix( const CqVector3D& trans )
  421 {
  422     Identity();
  423 
  424     if ( trans.x() != 0.0f || trans.y() != 0.0f || trans.z() != 0.0f )
  425     {
  426         m_fIdentity = false;
  427 
  428         m_elements[ 3 ][ 0 ] = trans.x();
  429         m_elements[ 3 ][ 1 ] = trans.y();
  430         m_elements[ 3 ][ 2 ] = trans.z();
  431     }
  432 }
  433 
  434 // Construct a rotation matrix
  435 inline CqMatrix::CqMatrix( const TqFloat angle, const CqVector3D axis )
  436 {
  437     Identity();
  438 
  439     if ( angle != 0.0f && axis.Magnitude() != 0.0f )
  440         Rotate( angle, axis );
  441 }
  442 
  443 inline CqMatrix::CqMatrix( const CqMatrix &from )
  444 {
  445     *this = from;
  446 }
  447 
  448 inline CqMatrix::CqMatrix(
  449         const TqFloat r1c1, const TqFloat r1c2, const TqFloat r1c3, const TqFloat r1c4,
  450         const TqFloat r2c1, const TqFloat r2c2, const TqFloat r2c3, const TqFloat r2c4,
  451         const TqFloat r3c1, const TqFloat r3c2, const TqFloat r3c3, const TqFloat r3c4,
  452         const TqFloat r4c1, const TqFloat r4c2, const TqFloat r4c3, const TqFloat r4c4 )
  453     : m_fIdentity(false)
  454 {
  455     m_elements[ 0 ][ 0 ] = r1c1;
  456     m_elements[ 0 ][ 1 ] = r1c2;
  457     m_elements[ 0 ][ 2 ] = r1c3;
  458     m_elements[ 0 ][ 3 ] = r1c4;
  459     m_elements[ 1 ][ 0 ] = r2c1;
  460     m_elements[ 1 ][ 1 ] = r2c2;
  461     m_elements[ 1 ][ 2 ] = r2c3;
  462     m_elements[ 1 ][ 3 ] = r2c4;
  463     m_elements[ 2 ][ 0 ] = r3c1;
  464     m_elements[ 2 ][ 1 ] = r3c2;
  465     m_elements[ 2 ][ 2 ] = r3c3;
  466     m_elements[ 2 ][ 3 ] = r3c4;
  467     m_elements[ 3 ][ 0 ] = r4c1;
  468     m_elements[ 3 ][ 1 ] = r4c2;
  469     m_elements[ 3 ][ 2 ] = r4c3;
  470     m_elements[ 3 ][ 3 ] = r4c4;
  471 }
  472 
  473 inline CqMatrix::CqMatrix( const TqFloat from[ 4 ][ 4 ] )
  474 {
  475     *this = from;
  476 }
  477 
  478 inline CqMatrix::CqMatrix( const TqFloat from[ 16 ] )
  479 {
  480     *this = from;
  481 }
  482 
  483 inline CqMatrix::CqMatrix( TqFloat f )
  484 {
  485   Identity();
  486   if(f != 1.0)
  487   {
  488     m_elements[ 0 ][ 0 ] = f;
  489     m_elements[ 1 ][ 1 ] = f;
  490     m_elements[ 2 ][ 2 ] = f;
  491     m_elements[ 3 ][ 3 ] = f;
  492     m_fIdentity = false;
  493   }
  494 }
  495 
  496 //------------------------------------------------------------------------------
  497 // Special-case identity handling
  498 AQSIS_MATH_SHARE inline void CqMatrix::Identity()
  499 {
  500     m_fIdentity = true;
  501 
  502     m_elements[ 0 ][ 1 ]
  503         = m_elements[ 0 ][ 2 ]
  504         = m_elements[ 0 ][ 3 ]
  505         = m_elements[ 1 ][ 0 ]
  506         = m_elements[ 1 ][ 2 ]
  507         = m_elements[ 1 ][ 3 ]
  508         = m_elements[ 2 ][ 0 ]
  509         = m_elements[ 2 ][ 1 ]
  510         = m_elements[ 2 ][ 3 ]
  511         = m_elements[ 3 ][ 0 ]
  512         = m_elements[ 3 ][ 1 ]
  513         = m_elements[ 3 ][ 2 ]
  514         = 0.0f;
  515 
  516     m_elements[ 0 ][ 0 ]
  517         = m_elements[ 1 ][ 1 ]
  518         = m_elements[ 2 ][ 2 ]
  519         = m_elements[ 3 ][ 3 ]
  520         = 1.0f;
  521 }
  522 
  523 inline void CqMatrix::SetfIdentity( bool f )
  524 {
  525     m_fIdentity = f;
  526 }
  527 
  528 inline bool CqMatrix::fIdentity() const
  529 {
  530     return m_fIdentity;
  531 }
  532 
  533 //------------------------------------------------------------------------------
  534 // Methods for concatenating transformations onto the current one.
  535 inline void CqMatrix::Scale( const TqFloat S )
  536 {
  537     if ( S != 1.0f )
  538         Scale( S, S, S );
  539 }
  540 
  541 inline void CqMatrix::Scale( const TqFloat xs, const TqFloat ys, const TqFloat zs )
  542 {
  543     CqMatrix Scale( xs, ys, zs );
  544     this->PreMultiply( Scale );
  545 }
  546 
  547 inline void CqMatrix::Translate( const CqVector3D& trans )
  548 {
  549     CqMatrix matTrans( trans );
  550     this->PreMultiply( matTrans );
  551 }
  552 
  553 inline void CqMatrix::Translate( const TqFloat xt, const TqFloat yt, const TqFloat zt )
  554 {
  555     if ( xt != 0.0f || yt != 0.0f || zt != 0.0f )
  556         Translate( CqVector3D( xt, yt, zt ) );
  557 }
  558 
  559 inline void CqMatrix::ShearX( const TqFloat yh, const TqFloat zh )
  560 {
  561     CqMatrix Shear;
  562     Shear.m_fIdentity = false;
  563 
  564     Shear.m_elements[ 0 ][ 1 ] = yh;
  565     Shear.m_elements[ 0 ][ 2 ] = zh;
  566 
  567     this->PreMultiply( Shear );
  568 }
  569 
  570 inline void CqMatrix::ShearY( const TqFloat xh, const TqFloat zh )
  571 {
  572     CqMatrix Shear;
  573     Shear.m_fIdentity = false;
  574 
  575     Shear.m_elements[ 1 ][ 0 ] = xh;
  576     Shear.m_elements[ 1 ][ 2 ] = zh;
  577 
  578     this->PreMultiply( Shear );
  579 }
  580 
  581 inline void CqMatrix::ShearZ( const TqFloat xh, const TqFloat yh )
  582 {
  583     CqMatrix Shear;
  584     Shear.m_fIdentity = false;
  585 
  586     Shear.m_elements[ 2 ][ 0 ] = xh;
  587     Shear.m_elements[ 2 ][ 1 ] = yh;
  588 
  589     this->PreMultiply( Shear );
  590 }
  591 
  592 inline void CqMatrix::Skew( const TqFloat angle,
  593                      const TqFloat dx1, const TqFloat dy1, const TqFloat dz1,
  594                      const TqFloat dx2, const TqFloat dy2, const TqFloat dz2 )
  595 {
  596     CqMatrix Skew( angle, dx1, dy1, dz1, dx2, dy2, dz2 );
  597 
  598     this->PreMultiply( Skew );
  599 }
  600 
  601 //------------------------------------------------------------------------------
  602 // Access to matrix elements.
  603 inline TqFloat CqMatrix::Element( TqInt row, TqInt col ) const
  604 {
  605     return ( m_elements[ row ][ col ] );
  606 }
  607 
  608 inline void CqMatrix::SetElement( TqInt row, TqInt col, TqFloat fValue )
  609 {
  610     m_elements[ row ][ col ] = fValue;
  611 }
  612 
  613 inline TqFloat* CqMatrix::operator[] ( TqInt row )
  614 {
  615     return( &m_elements[ row ][ 0 ] );
  616 }
  617 
  618 inline const TqFloat* CqMatrix::operator[] ( TqInt row ) const
  619 {
  620     return( &m_elements[ row ][ 0 ] );
  621 }
  622 
  623 inline TqFloat* CqMatrix::pElements()
  624 {
  625     return ( &m_elements[ 0 ][ 0 ] );
  626 }
  627 
  628 inline const TqFloat* CqMatrix::pElements() const
  629 {
  630     return ( &m_elements[ 0 ][ 0 ] );
  631 }
  632 
  633 //------------------------------------------------------------------------------
  634 // Operators and functions for matrices arithmetic.
  635 
  636 inline CqMatrix CqMatrix::operator*( const CqMatrix &from ) const
  637 {
  638     CqMatrix temp( *this );
  639     temp *= from;
  640     return temp;
  641 }
  642 
  643 inline CqVector4D CqMatrix::PreMultiply( const CqVector4D &vec ) const
  644 {
  645     if ( m_fIdentity )
  646         return vec;
  647 
  648     CqVector4D  Result;
  649 
  650     Result.x( m_elements[ 0 ][ 0 ] * vec.x()
  651               + m_elements[ 0 ][ 1 ] * vec.y()
  652               + m_elements[ 0 ][ 2 ] * vec.z()
  653               + m_elements[ 0 ][ 3 ] * vec.h() );
  654 
  655     Result.y( m_elements[ 1 ][ 0 ] * vec.x()
  656               + m_elements[ 1 ][ 1 ] * vec.y()
  657               + m_elements[ 1 ][ 2 ] * vec.z()
  658               + m_elements[ 1 ][ 3 ] * vec.h() );
  659 
  660     Result.z( m_elements[ 2 ][ 0 ] * vec.x()
  661               + m_elements[ 2 ][ 1 ] * vec.y()
  662               + m_elements[ 2 ][ 2 ] * vec.z()
  663               + m_elements[ 2 ][ 3 ] * vec.h() );
  664 
  665     Result.h( m_elements[ 3 ][ 0 ] * vec.x()
  666               + m_elements[ 3 ][ 1 ] * vec.y()
  667               + m_elements[ 3 ][ 2 ] * vec.z()
  668               + m_elements[ 3 ][ 3 ] * vec.h() );
  669 
  670     return Result;
  671 }
  672 
  673 inline CqMatrix CqMatrix::operator*( const TqFloat S ) const
  674 {
  675     CqMatrix temp( *this );
  676     temp *= S;
  677     return temp;
  678 }
  679 
  680 inline CqMatrix &CqMatrix::operator*=( const TqFloat S )
  681 {
  682     CqMatrix ScaleMatrix( S, S, S );
  683     this->PreMultiply( ScaleMatrix );
  684     return *this;
  685 }
  686 
  687 inline CqVector4D CqMatrix::operator*( const CqVector4D &vec ) const
  688 {
  689     if ( m_fIdentity )
  690         return vec;
  691 
  692     CqVector4D  Result;
  693 
  694     Result.x( m_elements[ 0 ][ 0 ] * vec.x()
  695               + m_elements[ 1 ][ 0 ] * vec.y()
  696               + m_elements[ 2 ][ 0 ] * vec.z()
  697               + m_elements[ 3 ][ 0 ] * vec.h() );
  698 
  699     Result.y( m_elements[ 0 ][ 1 ] * vec.x()
  700               + m_elements[ 1 ][ 1 ] * vec.y()
  701               + m_elements[ 2 ][ 1 ] * vec.z()
  702               + m_elements[ 3 ][ 1 ] * vec.h() );
  703 
  704     Result.z( m_elements[ 0 ][ 2 ] * vec.x()
  705               + m_elements[ 1 ][ 2 ] * vec.y()
  706               + m_elements[ 2 ][ 2 ] * vec.z()
  707               + m_elements[ 3 ][ 2 ] * vec.h() );
  708 
  709     Result.h( m_elements[ 0 ][ 3 ] * vec.x()
  710               + m_elements[ 1 ][ 3 ] * vec.y()
  711               + m_elements[ 2 ][ 3 ] * vec.z()
  712               + m_elements[ 3 ][ 3 ] * vec.h() );
  713 
  714     return Result;
  715 }
  716 
  717 inline CqVector3D CqMatrix::operator*( const CqVector3D &vec ) const
  718 {
  719     if ( m_fIdentity )
  720         return vec;
  721 
  722     CqVector3D  Result;
  723     TqFloat h = ( m_elements[ 0 ][ 3 ] * vec.x()
  724                   + m_elements[ 1 ][ 3 ] * vec.y()
  725                   + m_elements[ 2 ][ 3 ] * vec.z()
  726                   + m_elements[ 3 ][ 3 ] );
  727     Result.x( ( m_elements[ 0 ][ 0 ] * vec.x()
  728                 + m_elements[ 1 ][ 0 ] * vec.y()
  729                 + m_elements[ 2 ][ 0 ] * vec.z()
  730                 + m_elements[ 3 ][ 0 ] ) );
  731     Result.y( ( m_elements[ 0 ][ 1 ] * vec.x()
  732                 + m_elements[ 1 ][ 1 ] * vec.y()
  733                 + m_elements[ 2 ][ 1 ] * vec.z()
  734                 + m_elements[ 3 ][ 1 ] ) );
  735     Result.z( ( m_elements[ 0 ][ 2 ] * vec.x()
  736                 + m_elements[ 1 ][ 2 ] * vec.y()
  737                 + m_elements[ 2 ][ 2 ] * vec.z()
  738                 + m_elements[ 3 ][ 2 ] ) );
  739 
  740     if(h != 1)
  741     {
  742         assert(h != 0);
  743         TqFloat invh = 1/h;
  744         Result.x(Result.x()*invh);
  745         Result.y(Result.y()*invh);
  746         Result.z(Result.z()*invh);
  747     }
  748 
  749     return Result;
  750 }
  751 
  752 inline CqMatrix CqMatrix::operator+( const CqMatrix &from ) const
  753 {
  754     CqMatrix temp( *this );
  755     temp += from;
  756     return temp;
  757 }
  758 
  759 inline CqMatrix &CqMatrix::operator+=( const CqMatrix &from )
  760 {
  761     m_elements[ 0 ][ 0 ] += from.m_elements[ 0 ][ 0 ];
  762     m_elements[ 1 ][ 0 ] += from.m_elements[ 1 ][ 0 ];
  763     m_elements[ 2 ][ 0 ] += from.m_elements[ 2 ][ 0 ];
  764     m_elements[ 3 ][ 0 ] += from.m_elements[ 3 ][ 0 ];
  765     m_elements[ 0 ][ 1 ] += from.m_elements[ 0 ][ 1 ];
  766     m_elements[ 1 ][ 1 ] += from.m_elements[ 1 ][ 1 ];
  767     m_elements[ 2 ][ 1 ] += from.m_elements[ 2 ][ 1 ];
  768     m_elements[ 3 ][ 1 ] += from.m_elements[ 3 ][ 1 ];
  769     m_elements[ 0 ][ 2 ] += from.m_elements[ 0 ][ 2 ];
  770     m_elements[ 1 ][ 2 ] += from.m_elements[ 1 ][ 2 ];
  771     m_elements[ 2 ][ 2 ] += from.m_elements[ 2 ][ 2 ];
  772     m_elements[ 3 ][ 2 ] += from.m_elements[ 3 ][ 2 ];
  773     m_elements[ 0 ][ 3 ] += from.m_elements[ 0 ][ 3 ];
  774     m_elements[ 1 ][ 3 ] += from.m_elements[ 1 ][ 3 ];
  775     m_elements[ 2 ][ 3 ] += from.m_elements[ 2 ][ 3 ];
  776     m_elements[ 3 ][ 3 ] += from.m_elements[ 3 ][ 3 ];
  777 
  778     m_fIdentity = false;
  779 
  780     return *this;
  781 }
  782 
  783 inline CqMatrix CqMatrix::operator-( const CqMatrix &from ) const
  784 {
  785     CqMatrix temp( *this );
  786     temp -= from;
  787     return temp;
  788 }
  789 
  790 inline CqMatrix &CqMatrix::operator-=( const CqMatrix &from )
  791 {
  792     m_elements[ 0 ][ 0 ] -= from.m_elements[ 0 ][ 0 ];
  793     m_elements[ 1 ][ 0 ] -= from.m_elements[ 1 ][ 0 ];
  794     m_elements[ 2 ][ 0 ] -= from.m_elements[ 2 ][ 0 ];
  795     m_elements[ 3 ][ 0 ] -= from.m_elements[ 3 ][ 0 ];
  796     m_elements[ 0 ][ 1 ] -= from.m_elements[ 0 ][ 1 ];
  797     m_elements[ 1 ][ 1 ] -= from.m_elements[ 1 ][ 1 ];
  798     m_elements[ 2 ][ 1 ] -= from.m_elements[ 2 ][ 1 ];
  799     m_elements[ 3 ][ 1 ] -= from.m_elements[ 3 ][ 1 ];
  800     m_elements[ 0 ][ 2 ] -= from.m_elements[ 0 ][ 2 ];
  801     m_elements[ 1 ][ 2 ] -= from.m_elements[ 1 ][ 2 ];
  802     m_elements[ 2 ][ 2 ] -= from.m_elements[ 2 ][ 2 ];
  803     m_elements[ 3 ][ 2 ] -= from.m_elements[ 3 ][ 2 ];
  804     m_elements[ 0 ][ 3 ] -= from.m_elements[ 0 ][ 3 ];
  805     m_elements[ 1 ][ 3 ] -= from.m_elements[ 1 ][ 3 ];
  806     m_elements[ 2 ][ 3 ] -= from.m_elements[ 2 ][ 3 ];
  807     m_elements[ 3 ][ 3 ] -= from.m_elements[ 3 ][ 3 ];
  808 
  809     m_fIdentity = false;
  810 
  811     return *this;
  812 }
  813 
  814 inline CqMatrix &CqMatrix::operator=( const CqMatrix &from )
  815 {
  816     m_elements[ 0 ][ 0 ] = from.m_elements[ 0 ][ 0 ];
  817     m_elements[ 1 ][ 0 ] = from.m_elements[ 1 ][ 0 ];
  818     m_elements[ 2 ][ 0 ] = from.m_elements[ 2 ][ 0 ];
  819     m_elements[ 3 ][ 0 ] = from.m_elements[ 3 ][ 0 ];
  820     m_elements[ 0 ][ 1 ] = from.m_elements[ 0 ][ 1 ];
  821     m_elements[ 1 ][ 1 ] = from.m_elements[ 1 ][ 1 ];
  822     m_elements[ 2 ][ 1 ] = from.m_elements[ 2 ][ 1 ];
  823     m_elements[ 3 ][ 1 ] = from.m_elements[ 3 ][ 1 ];
  824     m_elements[ 0 ][ 2 ] = from.m_elements[ 0 ][ 2 ];
  825     m_elements[ 1 ][ 2 ] = from.m_elements[ 1 ][ 2 ];
  826     m_elements[ 2 ][ 2 ] = from.m_elements[ 2 ][ 2 ];
  827     m_elements[ 3 ][ 2 ] = from.m_elements[ 3 ][ 2 ];
  828     m_elements[ 0 ][ 3 ] = from.m_elements[ 0 ][ 3 ];
  829     m_elements[ 1 ][ 3 ] = from.m_elements[ 1 ][ 3 ];
  830     m_elements[ 2 ][ 3 ] = from.m_elements[ 2 ][ 3 ];
  831     m_elements[ 3 ][ 3 ] = from.m_elements[ 3 ][ 3 ];
  832 
  833     m_fIdentity = from.m_fIdentity;
  834 
  835     return *this;
  836 }
  837 
  838 inline CqMatrix &CqMatrix::operator=( const TqFloat from[ 4 ][ 4 ] )
  839 {
  840     m_elements[ 0 ][ 0 ] = from[ 0 ][ 0 ];
  841     m_elements[ 1 ][ 0 ] = from[ 1 ][ 0 ];
  842     m_elements[ 2 ][ 0 ] = from[ 2 ][ 0 ];
  843     m_elements[ 3 ][ 0 ] = from[ 3 ][ 0 ];
  844     m_elements[ 0 ][ 1 ] = from[ 0 ][ 1 ];
  845     m_elements[ 1 ][ 1 ] = from[ 1 ][ 1 ];
  846     m_elements[ 2 ][ 1 ] = from[ 2 ][ 1 ];
  847     m_elements[ 3 ][ 1 ] = from[ 3 ][ 1 ];
  848     m_elements[ 0 ][ 2 ] = from[ 0 ][ 2 ];
  849     m_elements[ 1 ][ 2 ] = from[ 1 ][ 2 ];
  850     m_elements[ 2 ][ 2 ] = from[ 2 ][ 2 ];
  851     m_elements[ 3 ][ 2 ] = from[ 3 ][ 2 ];
  852     m_elements[ 0 ][ 3 ] = from[ 0 ][ 3 ];
  853     m_elements[ 1 ][ 3 ] = from[ 1 ][ 3 ];
  854     m_elements[ 2 ][ 3 ] = from[ 2 ][ 3 ];
  855     m_elements[ 3 ][ 3 ] = from[ 3 ][ 3 ];
  856 
  857     m_fIdentity = false;
  858 
  859     return *this;
  860 }
  861 
  862 inline CqMatrix &CqMatrix::operator=( const TqFloat from[ 16 ] )
  863 {
  864     m_elements[ 0 ][ 0 ] = from[ 0 ];
  865     m_elements[ 0 ][ 1 ] = from[ 1 ];
  866     m_elements[ 0 ][ 2 ] = from[ 2 ];
  867     m_elements[ 0 ][ 3 ] = from[ 3 ];
  868     m_elements[ 1 ][ 0 ] = from[ 4 ];
  869     m_elements[ 1 ][ 1 ] = from[ 5 ];
  870     m_elements[ 1 ][ 2 ] = from[ 6 ];
  871     m_elements[ 1 ][ 3 ] = from[ 7 ];
  872     m_elements[ 2 ][ 0 ] = from[ 8 ];
  873     m_elements[ 2 ][ 1 ] = from[ 9 ];
  874     m_elements[ 2 ][ 2 ] = from[ 10 ];
  875     m_elements[ 2 ][ 3 ] = from[ 11 ];
  876     m_elements[ 3 ][ 0 ] = from[ 12 ];
  877     m_elements[ 3 ][ 1 ] = from[ 13 ];
  878     m_elements[ 3 ][ 2 ] = from[ 14 ];
  879     m_elements[ 3 ][ 3 ] = from[ 15 ];
  880 
  881     m_fIdentity = false;
  882 
  883     return *this;
  884 }
  885 
  886 inline CqMatrix CqMatrix::Transpose() const
  887 {
  888     CqMatrix temp;
  889 
  890     if ( m_fIdentity )
  891     {
  892         temp = *this;
  893     }
  894     else
  895     {
  896         temp.m_elements[ 0 ][ 0 ] = m_elements[ 0 ][ 0 ];
  897         temp.m_elements[ 0 ][ 1 ] = m_elements[ 1 ][ 0 ];
  898         temp.m_elements[ 0 ][ 2 ] = m_elements[ 2 ][ 0 ];
  899         temp.m_elements[ 0 ][ 3 ] = m_elements[ 3 ][ 0 ];
  900         temp.m_elements[ 1 ][ 0 ] = m_elements[ 0 ][ 1 ];
  901         temp.m_elements[ 1 ][ 1 ] = m_elements[ 1 ][ 1 ];
  902         temp.m_elements[ 1 ][ 2 ] = m_elements[ 2 ][ 1 ];
  903         temp.m_elements[ 1 ][ 3 ] = m_elements[ 3 ][ 1 ];
  904         temp.m_elements[ 2 ][ 0 ] = m_elements[ 0 ][ 2 ];
  905         temp.m_elements[ 2 ][ 1 ] = m_elements[ 1 ][ 2 ];
  906         temp.m_elements[ 2 ][ 2 ] = m_elements[ 2 ][ 2 ];
  907         temp.m_elements[ 2 ][ 3 ] = m_elements[ 3 ][ 2 ];
  908         temp.m_elements[ 3 ][ 0 ] = m_elements[ 0 ][ 3 ];
  909         temp.m_elements[ 3 ][ 1 ] = m_elements[ 1 ][ 3 ];
  910         temp.m_elements[ 3 ][ 2 ] = m_elements[ 2 ][ 3 ];
  911         temp.m_elements[ 3 ][ 3 ] = m_elements[ 3 ][ 3 ];
  912 
  913         temp.m_fIdentity = false;
  914     }
  915 
  916     return temp;
  917 }
  918 
  919 inline CqMatrix operator*( TqFloat S, const CqMatrix& a )
  920 {
  921     CqMatrix temp( a );
  922     temp.m_elements[ 0 ][ 0 ] *= S;
  923     temp.m_elements[ 1 ][ 0 ] *= S;
  924     temp.m_elements[ 2 ][ 0 ] *= S;
  925     temp.m_elements[ 3 ][ 0 ] *= S;
  926 
  927     temp.m_elements[ 0 ][ 1 ] *= S;
  928     temp.m_elements[ 1 ][ 1 ] *= S;
  929     temp.m_elements[ 2 ][ 1 ] *= S;
  930     temp.m_elements[ 3 ][ 1 ] *= S;
  931 
  932     temp.m_elements[ 0 ][ 2 ] *= S;
  933     temp.m_elements[ 1 ][ 2 ] *= S;
  934     temp.m_elements[ 2 ][ 2 ] *= S;
  935     temp.m_elements[ 3 ][ 2 ] *= S;
  936 
  937     temp.m_elements[ 0 ][ 3 ] *= S;
  938     temp.m_elements[ 1 ][ 3 ] *= S;
  939     temp.m_elements[ 2 ][ 3 ] *= S;
  940     temp.m_elements[ 3 ][ 3 ] *= S;
  941     return temp;
  942 }
  943 
  944 inline CqVector4D operator*( const CqVector4D &vec, const CqMatrix& matrix )
  945 {
  946     return ( matrix.PreMultiply( vec ) );
  947 }
  948 
  949 inline bool  operator==(const CqMatrix& A, const CqMatrix& B)
  950 {
  951     if( (A.m_elements[ 0 ][ 0 ] == B.m_elements[ 0 ][ 0 ]) &&
  952             (A.m_elements[ 1 ][ 0 ] == B.m_elements[ 1 ][ 0 ]) &&
  953             (A.m_elements[ 2 ][ 0 ] == B.m_elements[ 2 ][ 0 ]) &&
  954             (A.m_elements[ 3 ][ 0 ] == B.m_elements[ 3 ][ 0 ]) &&
  955 
  956             (A.m_elements[ 0 ][ 1 ] == B.m_elements[ 0 ][ 1 ]) &&
  957             (A.m_elements[ 1 ][ 1 ] == B.m_elements[ 1 ][ 1 ]) &&
  958             (A.m_elements[ 2 ][ 1 ] == B.m_elements[ 2 ][ 1 ]) &&
  959             (A.m_elements[ 3 ][ 1 ] == B.m_elements[ 3 ][ 1 ]) &&
  960 
  961             (A.m_elements[ 0 ][ 2 ] == B.m_elements[ 0 ][ 2 ]) &&
  962             (A.m_elements[ 1 ][ 2 ] == B.m_elements[ 1 ][ 2 ]) &&
  963             (A.m_elements[ 2 ][ 2 ] == B.m_elements[ 2 ][ 2 ]) &&
  964             (A.m_elements[ 3 ][ 2 ] == B.m_elements[ 3 ][ 2 ]) &&
  965 
  966             (A.m_elements[ 0 ][ 3 ] == B.m_elements[ 0 ][ 3 ]) &&
  967             (A.m_elements[ 1 ][ 3 ] == B.m_elements[ 1 ][ 3 ]) &&
  968             (A.m_elements[ 2 ][ 3 ] == B.m_elements[ 2 ][ 3 ]) &&
  969             (A.m_elements[ 3 ][ 3 ] == B.m_elements[ 3 ][ 3 ]))
  970         return true;
  971     else
  972         return false;
  973 }
  974 
  975 inline bool  operator!=(const CqMatrix& A, const CqMatrix& B)
  976 {
  977     return !(A==B);
  978 }
  979 
  980 
  981 inline CqMatrix vectorTransform(const CqMatrix& m)
  982 {
  983     CqMatrix r = m;
  984     // Remove the transformation and projection parts of the transform.
  985     r[3][0] = r[3][1] = r[3][2] = 0;
  986     r[0][3] = r[1][3] = r[2][3] = 0;
  987     r[3][3] = 1.0;
  988     return r;
  989 }
  990 
  991 
  992 inline CqMatrix normalTransform(const CqMatrix& m)
  993 {
  994     return vectorTransform(m).Inverse().Transpose();
  995 }
  996 
  997 
  998 } // namespace Aqsis
  999 
 1000 #endif  // !MATRIX_H_INCLUDED