glc_matrix4x4.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  Version 2.0.0 Beta 1, packaged on April 2010.
00006 
00007  http://glc-lib.sourceforge.net
00008 
00009  GLC-lib is free software; you can redistribute it and/or modify
00010  it under the terms of the GNU General Public License as published by
00011  the Free Software Foundation; either version 2 of the License, or
00012  (at your option) any later version.
00013 
00014  GLC-lib is distributed in the hope that it will be useful,
00015  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  GNU General Public License for more details.
00018 
00019  You should have received a copy of the GNU General Public License
00020  along with GLC-lib; if not, write to the Free Software
00021  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023 *****************************************************************************/
00024 
00026 
00027 #ifndef GLC_MATRIX4X4_H_
00028 #define GLC_MATRIX4X4_H_
00029 
00030 #include <QVector>
00031 #include "glc_vector3d.h"
00032 
00033 #include "../glc_config.h"
00034 
00037 
00042 
00043 class GLC_LIB_EXPORT GLC_Matrix4x4
00044 {
00045         friend class GLC_Vector3d;
00046 
00048 // Constructor
00050 public:
00052 
00053 
00054         inline GLC_Matrix4x4();
00055 
00057         inline GLC_Matrix4x4(const GLC_Matrix4x4 &matrix)
00058         {memcpy(m_Matrix, matrix.m_Matrix, sizeof(double) * 16);}
00059 
00061         inline GLC_Matrix4x4(const double *pArray)
00062         {memcpy(m_Matrix, pArray, sizeof(double) * 16);}
00063 
00065         inline GLC_Matrix4x4(const float *);
00066 
00068         inline GLC_Matrix4x4(const GLC_Vector3d &Vect, const double &dAngleRad);
00069 
00071         inline GLC_Matrix4x4(const GLC_Vector3d &Vect1, const GLC_Vector3d &Vect2);
00072 
00074         inline GLC_Matrix4x4(const GLC_Vector3d &Vect)
00075         {setMatTranslate(Vect);}
00076 
00078         inline GLC_Matrix4x4(const double Tx, const double Ty, const double Tz)
00079         {setMatTranslate(Tx, Ty, Tz);}
00081 
00083 
00085 
00086 public:
00088         inline GLC_Matrix4x4 operator * (const GLC_Matrix4x4 &Mat) const;
00089 
00091         inline GLC_Vector3d operator * (const GLC_Vector3d &Vect) const;
00092 
00094         inline bool operator==(const GLC_Matrix4x4& mat) const;
00095 
00097         inline bool operator!=(const GLC_Matrix4x4& mat) const
00098         {return !operator==(mat);}
00099 
00101 
00103 
00105 
00106 public:
00108         inline double determinant(void) const;
00109 
00111         inline const double* data(void) const
00112         {return m_Matrix;}
00113 
00115         inline double* data(void)
00116         {return m_Matrix;}
00117 
00119         QVector<double> toEuler(void) const;
00120 
00122         QString toString() const;
00123 
00125         inline GLC_Matrix4x4 rotationMatrix() const;
00126 
00128         inline GLC_Matrix4x4 isometricMatrix() const;
00129 
00131         inline double scalingX() const
00132         {return GLC_Vector3d(m_Matrix[0], m_Matrix[1], m_Matrix[2]).length();}
00133 
00135         inline double scalingY() const
00136         {return GLC_Vector3d(m_Matrix[4], m_Matrix[5], m_Matrix[6]).length();}
00137 
00139         inline double scalingZ() const
00140         {return GLC_Vector3d(m_Matrix[8], m_Matrix[9], m_Matrix[10]).length();}
00141 
00143         inline GLC_Matrix4x4 inverted() const
00144         {return GLC_Matrix4x4(*this).invert();}
00145 
00147 
00149 
00151 
00152 public:
00154         inline GLC_Matrix4x4& setMatRot(const GLC_Vector3d &, const double &);
00155 
00157         inline GLC_Matrix4x4& setMatRot(const GLC_Vector3d &, const GLC_Vector3d &);
00158 
00160         inline GLC_Matrix4x4& setMatTranslate(const GLC_Vector3d &);
00161 
00163         inline GLC_Matrix4x4& setMatTranslate(const double, const double, const double);
00164 
00166         inline GLC_Matrix4x4& setMatScaling(const double, const double, const double);
00167 
00169         inline GLC_Matrix4x4& invert(void);
00170 
00172         inline GLC_Matrix4x4& setToIdentity();
00173 
00175         inline GLC_Matrix4x4& transpose(void);
00176 
00178         GLC_Matrix4x4& fromEuler(const double, const double, const double);
00179 
00181         GLC_Matrix4x4& setColumn(int index, const GLC_Vector3d& vector);
00182 
00184 
00188 private:
00189 
00191         inline bool isInDiagonal(const int index) const
00192         {
00193                 if ((index == 0) || (index == 5) || (index == 10) || (index == 15))
00194                         return true;
00195                 else
00196                         return false;
00197         }
00198 
00200         inline double getDeterminantLC(const int, const int) const;
00201 
00203         inline void getSubMat(const int, const int, double *) const;
00204 
00206         inline GLC_Matrix4x4 getTranspose(void) const;
00207 
00209         inline GLC_Matrix4x4 getCoMat4x4(void) const;
00210 
00211 
00212 
00214 // Private members
00216 private:
00217 
00219         enum {TAILLEMAT4X4 = 16};
00221         enum {DIMMAT4X4 = 4};
00223         double m_Matrix[TAILLEMAT4X4];
00224 /*
00225 the matrix :
00226                                         a[00] a[04] a[08] a[12]
00227 
00228                                         a[01] a[05] a[09] a[13]
00229 
00230                                         a[02] a[06] a[10] a[14]
00231 
00232                                         a[03] a[07] a[11] a[15]
00233  */
00234 //                                      Tx = 12,        Ty = 13,        Tz = 14
00235 };
00236 
00238 inline double getDeterminant3x3(const double *Mat3x3)
00239 {
00240         double Determinant;
00241 
00242         Determinant= Mat3x3[0] * ( Mat3x3[4] * Mat3x3[8] - Mat3x3[7] * Mat3x3[5]);
00243         Determinant+= - Mat3x3[3] * ( Mat3x3[1] * Mat3x3[8] - Mat3x3[7] * Mat3x3[2]);
00244         Determinant+= Mat3x3[6] * ( Mat3x3[1] * Mat3x3[5] - Mat3x3[4] * Mat3x3[2]);
00245 
00246         return Determinant;
00247 }
00248 
00250 // Constructor/Destructor
00252 
00253 GLC_Matrix4x4::GLC_Matrix4x4()
00254 {
00255         setToIdentity();
00256 }
00257 
00258 GLC_Matrix4x4::GLC_Matrix4x4(const float *Tableau)
00259 {
00260 
00261         for (int i=0; i < TAILLEMAT4X4; i++)
00262         {
00263                 m_Matrix[i]= static_cast<double>(Tableau[i]);
00264         }
00265 }
00266 GLC_Matrix4x4::GLC_Matrix4x4(const GLC_Vector3d &Vect, const double &dAngleRad)
00267 {
00268         setToIdentity();
00269         setMatRot(Vect, dAngleRad);
00270 }
00271 
00272 GLC_Matrix4x4::GLC_Matrix4x4(const GLC_Vector3d &Vect1, const GLC_Vector3d &Vect2)
00273 {
00274         setToIdentity();
00275         setMatRot(Vect1, Vect2);
00276 }
00277 
00278 GLC_Matrix4x4 GLC_Matrix4x4::operator * (const GLC_Matrix4x4 &Mat) const
00279 {
00280         int Colonne;
00281         int Ligne;
00282         int i;
00283         double ValInt;
00284 
00285         int IndexInt;
00286 
00287         GLC_Matrix4x4 MatResult;
00288         for (Ligne= 0; Ligne < DIMMAT4X4; Ligne++)
00289         {
00290                 for (Colonne=0; Colonne < DIMMAT4X4; Colonne++)
00291                 {
00292                         ValInt= 0.0;
00293                         IndexInt= Colonne * DIMMAT4X4;
00294 
00295                         for (i= 0; i < DIMMAT4X4; i++)
00296                         {
00297                                 ValInt+= m_Matrix[ (i * DIMMAT4X4) + Ligne] * Mat.m_Matrix[ IndexInt + i];
00298                         }
00299                         MatResult.m_Matrix[ IndexInt + Ligne]= ValInt;
00300                 }
00301         }
00302         return MatResult;
00303 }
00304 
00305 GLC_Vector3d GLC_Matrix4x4::operator * (const GLC_Vector3d &Vect) const
00306 {
00307         double ValInt;
00308         int i;
00309         GLC_Vector3d VectResult;
00310         double mat[4];
00311 
00312         for (int Index= 0; Index < DIMMAT4X4; Index++)
00313         {
00314                 ValInt= 0.0;
00315                 for (i= 0; i < DIMMAT4X4 - 1; i++)
00316                 {
00317                         ValInt+= m_Matrix[(i * DIMMAT4X4) + Index] * Vect.m_Vector[i];
00318                 }
00319                 ValInt+= m_Matrix[(3 * DIMMAT4X4) + Index];
00320                 mat[Index]= ValInt;
00321         }
00322 
00323         double invW= 1.0;
00324         if (fabs(mat[3]) > 0.00001)
00325         {
00326                 invW/= mat[3];
00327         }
00328         VectResult.m_Vector[0]= mat[0] * invW;
00329         VectResult.m_Vector[1]= mat[1] * invW;
00330         VectResult.m_Vector[2]= mat[2] * invW;
00331 
00332 
00333         return VectResult;
00334 }
00335 
00336 bool GLC_Matrix4x4::operator==(const GLC_Matrix4x4& mat) const
00337 {
00338         bool result= true;
00339         int i= 0;
00340         while (result && (i < TAILLEMAT4X4))
00341         {
00342                 result= (qFuzzyCompare(m_Matrix[i], mat.m_Matrix[i]));
00343                 ++i;
00344         }
00345         return result;
00346 }
00347 
00348 GLC_Matrix4x4 GLC_Matrix4x4::rotationMatrix() const
00349 {
00350         GLC_Matrix4x4 result(*this);
00351         const double invScaleX= 1.0 / scalingX();
00352         const double invScaleY= 1.0 / scalingY();
00353         const double invScaleZ= 1.0 / scalingZ();
00354         result.m_Matrix[0]= result.m_Matrix[0] * invScaleX;
00355         result.m_Matrix[1]= result.m_Matrix[1] * invScaleX;
00356         result.m_Matrix[2]= result.m_Matrix[2] * invScaleX;
00357 
00358         result.m_Matrix[4]= result.m_Matrix[4] * invScaleY;
00359         result.m_Matrix[5]= result.m_Matrix[5] * invScaleY;
00360         result.m_Matrix[6]= result.m_Matrix[6] * invScaleY;
00361 
00362         result.m_Matrix[8]= result.m_Matrix[8] * invScaleZ;
00363         result.m_Matrix[9]= result.m_Matrix[9] * invScaleZ;
00364         result.m_Matrix[10]= result.m_Matrix[10] * invScaleZ;
00365 
00366         result.m_Matrix[12]= 0.0; result.m_Matrix[13]= 0.0; result.m_Matrix[14]= 0.0;
00367         result.m_Matrix[3]= 0.0; result.m_Matrix[7]= 0.0; result.m_Matrix[11]= 0.0;
00368         result.m_Matrix[15]= 1.0;
00369         return result;
00370 }
00371 
00372 GLC_Matrix4x4 GLC_Matrix4x4::isometricMatrix() const
00373 {
00374         GLC_Matrix4x4 result(*this);
00375         const double invScaleX= 1.0 / scalingX();
00376         const double invScaleY= 1.0 / scalingY();
00377         const double invScaleZ= 1.0 / scalingZ();
00378         result.m_Matrix[0]= result.m_Matrix[0] * invScaleX;
00379         result.m_Matrix[1]= result.m_Matrix[1] * invScaleX;
00380         result.m_Matrix[2]= result.m_Matrix[2] * invScaleX;
00381 
00382         result.m_Matrix[4]= result.m_Matrix[4] * invScaleY;
00383         result.m_Matrix[5]= result.m_Matrix[5] * invScaleY;
00384         result.m_Matrix[6]= result.m_Matrix[6] * invScaleY;
00385 
00386         result.m_Matrix[8]= result.m_Matrix[8] * invScaleZ;
00387         result.m_Matrix[9]= result.m_Matrix[9] * invScaleZ;
00388         result.m_Matrix[10]= result.m_Matrix[10] * invScaleZ;
00389         return result;
00390 }
00391 
00392 GLC_Matrix4x4& GLC_Matrix4x4::setMatRot(const GLC_Vector3d &Vect, const double &dAngleRad)
00393 {
00394         // Normalize the vector
00395         GLC_Vector3d VectRot(Vect);
00396         VectRot.normalize();
00397 
00398         // Code optimisation
00399         const double SinAngleSur2= sin(dAngleRad / 2.0);
00400 
00401         // Quaternion computation
00402         const double q0= cos(dAngleRad / 2);
00403         const double q1= VectRot.m_Vector[0] * SinAngleSur2;
00404         const double q2= VectRot.m_Vector[1] * SinAngleSur2;
00405         const double q3= VectRot.m_Vector[2] * SinAngleSur2;
00406 
00407         // Code optimisation
00408         const double q0Carre= (q0 * q0);
00409         const double q1Carre= (q1 * q1);
00410         const double q2Carre= (q2 * q2);
00411         const double q3Carre= (q3 * q3);
00412 
00413         m_Matrix[0]= q0Carre + q1Carre - q2Carre - q3Carre;
00414         m_Matrix[1]= 2.0 * (q1 *q2 + q0 * q3);
00415         m_Matrix[2]= 2.0 * (q1 * q3 - q0 * q2);
00416         m_Matrix[3]= 0.0;
00417         m_Matrix[4]= 2.0 * (q1 * q2 - q0 * q3);
00418         m_Matrix[5]= q0Carre + q2Carre - q3Carre - q1Carre;
00419         m_Matrix[6]= 2.0 * (q2 * q3 + q0 * q1);
00420         m_Matrix[7]= 0.0;
00421         m_Matrix[8]= 2.0 * (q1 * q3 + q0 * q2);
00422         m_Matrix[9]= 2.0 * (q2 * q3 - q0 * q1);
00423         m_Matrix[10]= q0Carre + q3Carre - q1Carre - q2Carre;
00424         m_Matrix[11]= 0.0;
00425 
00426         m_Matrix[12]= 0.0;      //TX
00427         m_Matrix[13]= 0.0;      //TY
00428         m_Matrix[14]= 0.0;      //TZ
00429         m_Matrix[15]= 1.0;
00430 
00431         return *this;
00432 }
00433 
00434 GLC_Matrix4x4& GLC_Matrix4x4::setMatRot(const GLC_Vector3d &Vect1, const GLC_Vector3d &Vect2)
00435 {
00436 
00437         // Compute rotation matrix
00438         const GLC_Vector3d VectAxeRot(Vect1 ^ Vect2);
00439         // Check if rotation vector axis is not null
00440         if (!VectAxeRot.isNull())
00441         {  // Ok, vector not null
00442                 const double Angle= acos(Vect1 * Vect2);
00443                 setMatRot(VectAxeRot, Angle);
00444         }
00445 
00446         return *this;
00447 }
00448 
00449 GLC_Matrix4x4& GLC_Matrix4x4::setMatTranslate(const GLC_Vector3d &Vect)
00450 {
00451         m_Matrix[0]= 1.0; m_Matrix[4]= 0.0; m_Matrix[8]=  0.0; m_Matrix[12]= Vect.m_Vector[0];
00452         m_Matrix[1]= 0.0; m_Matrix[5]= 1.0; m_Matrix[9]=  0.0; m_Matrix[13]= Vect.m_Vector[1];
00453         m_Matrix[2]= 0.0; m_Matrix[6]= 0.0; m_Matrix[10]= 1.0; m_Matrix[14]= Vect.m_Vector[2];
00454         m_Matrix[3]= 0.0; m_Matrix[7]= 0.0; m_Matrix[11]= 0.0; m_Matrix[15]= 1.0;
00455 
00456         return *this;
00457 }
00458 
00459 GLC_Matrix4x4& GLC_Matrix4x4::setMatTranslate(const double Tx, const double Ty, const double Tz)
00460 {
00461         m_Matrix[0]= 1.0; m_Matrix[4]= 0.0; m_Matrix[8]=  0.0; m_Matrix[12]= Tx;
00462         m_Matrix[1]= 0.0; m_Matrix[5]= 1.0; m_Matrix[9]=  0.0; m_Matrix[13]= Ty;
00463         m_Matrix[2]= 0.0; m_Matrix[6]= 0.0; m_Matrix[10]= 1.0; m_Matrix[14]= Tz;
00464         m_Matrix[3]= 0.0; m_Matrix[7]= 0.0; m_Matrix[11]= 0.0; m_Matrix[15]= 1.0;
00465 
00466         return *this;
00467 }
00468 
00469 GLC_Matrix4x4& GLC_Matrix4x4::setMatScaling(const double sX, const double sY, const double sZ)
00470 {
00471         m_Matrix[0]= sX; m_Matrix[4]= 0.0; m_Matrix[8]=  0.0; m_Matrix[12]= 0.0;
00472         m_Matrix[1]= 0.0; m_Matrix[5]= sY; m_Matrix[9]=  0.0; m_Matrix[13]= 0.0;
00473         m_Matrix[2]= 0.0; m_Matrix[6]= 0.0; m_Matrix[10]= sZ; m_Matrix[14]= 0.0;
00474         m_Matrix[3]= 0.0; m_Matrix[7]= 0.0; m_Matrix[11]= 0.0; m_Matrix[15]= 1.0;
00475 
00476         return *this;
00477 }
00478 
00479 
00480 GLC_Matrix4x4& GLC_Matrix4x4::invert(void)
00481 {
00482         const double det= determinant();
00483 
00484         // Test if the inverion is possible
00485         if (det == 0.0f) return *this;
00486 
00487         const double invDet = 1.0 / det;
00488         GLC_Matrix4x4 TCoMat= getCoMat4x4().getTranspose();
00489 
00490         for (int i= 0; i < TAILLEMAT4X4; i++)
00491         {
00492                 m_Matrix[i]= TCoMat.m_Matrix[i] * invDet;
00493         }
00494 
00495         return *this;
00496 }
00497 
00498 GLC_Matrix4x4& GLC_Matrix4x4::setToIdentity()
00499 {
00500         m_Matrix[0]= 1.0; m_Matrix[4]= 0.0; m_Matrix[8]=  0.0; m_Matrix[12]= 0.0;
00501         m_Matrix[1]= 0.0; m_Matrix[5]= 1.0; m_Matrix[9]=  0.0; m_Matrix[13]= 0.0;
00502         m_Matrix[2]= 0.0; m_Matrix[6]= 0.0; m_Matrix[10]= 1.0; m_Matrix[14]= 0.0;
00503         m_Matrix[3]= 0.0; m_Matrix[7]= 0.0; m_Matrix[11]= 0.0; m_Matrix[15]= 1.0;
00504 
00505         return *this;
00506 }
00507 
00508 GLC_Matrix4x4& GLC_Matrix4x4::transpose(void)
00509 {
00510         GLC_Matrix4x4 MatT(m_Matrix);
00511         int IndexOrigine;
00512         int IndexTrans;
00513         for (int Colonne= 0; Colonne < DIMMAT4X4; Colonne++)
00514         {
00515                 for (int Ligne=0 ; Ligne < DIMMAT4X4; Ligne++)
00516                 {
00517                         IndexOrigine= (Colonne * DIMMAT4X4) + Ligne;
00518                         IndexTrans= (Ligne * DIMMAT4X4) + Colonne;
00519 
00520                         MatT.m_Matrix[IndexTrans]= m_Matrix[IndexOrigine];
00521                 }
00522         }
00523 
00524         // Load the transposed in matrix in this matrix
00525         memcpy(m_Matrix, MatT.m_Matrix, sizeof(double) * 16);
00526 
00527         return *this;
00528 }
00529 
00530 double GLC_Matrix4x4::determinant(void) const
00531 {
00532         double Determinant= 0.0;
00533         double SubMat3x3[9];
00534         int Signe= 1;
00535 
00536         for (int Colonne= 0; Colonne < DIMMAT4X4; Colonne++, Signe*= -1)
00537         {
00538                 getSubMat(0, Colonne, SubMat3x3);
00539                 Determinant+= Signe * m_Matrix[Colonne * DIMMAT4X4] * getDeterminant3x3(SubMat3x3);
00540         }
00541 
00542         return Determinant;
00543 
00544 }
00545 
00546 double GLC_Matrix4x4::getDeterminantLC(const int Ligne, const int Colonne) const
00547 {
00548         double Mat3x3[9];
00549         double Determinant;
00550 
00551         getSubMat(Ligne, Colonne, Mat3x3);
00552 
00553         if ( 0 == ((Ligne + Colonne) % 2)) // Even number
00554                 Determinant= m_Matrix[(Colonne + DIMMAT4X4) + Ligne] * getDeterminant3x3(Mat3x3);
00555         else
00556                 Determinant= - m_Matrix[(Colonne + DIMMAT4X4) + Ligne] * getDeterminant3x3(Mat3x3);
00557 
00558         return Determinant;
00559 }
00560 
00561 void GLC_Matrix4x4::getSubMat(const int Ligne, const int Colonne, double *ResultMat) const
00562 {
00563 
00564         int LigneResult;
00565         int ColonneResult;
00566         int IndexOrigine;
00567         int IndexResult;
00568 
00569         for (int ColonneOrigine= 0; ColonneOrigine < DIMMAT4X4; ColonneOrigine++)
00570         {
00571                 if (ColonneOrigine != Colonne)
00572                 {
00573                         if (ColonneOrigine < Colonne)
00574                                 ColonneResult= ColonneOrigine;
00575                         else
00576                                 ColonneResult= ColonneOrigine - 1;
00577 
00578                         for (int LigneOrigine= 0; LigneOrigine < DIMMAT4X4; LigneOrigine++)
00579                         {
00580                                 if (LigneOrigine != Ligne)
00581                                 {
00582                                         if (LigneOrigine < Ligne)
00583                                                 LigneResult= LigneOrigine;
00584                                         else
00585                                                 LigneResult= LigneOrigine - 1;
00586                                         IndexOrigine= (ColonneOrigine * DIMMAT4X4) + LigneOrigine;
00587                                         IndexResult= (ColonneResult * (DIMMAT4X4 - 1)) + LigneResult;
00588 
00589                                         ResultMat[IndexResult]= m_Matrix[IndexOrigine];
00590                                 }
00591                         }
00592                 }
00593         }
00594 }
00595 
00596 GLC_Matrix4x4 GLC_Matrix4x4::getTranspose(void) const
00597 {
00598         GLC_Matrix4x4 MatT(m_Matrix);
00599         int IndexOrigine;
00600         int IndexTrans;
00601         for (int Colonne= 0; Colonne < DIMMAT4X4; Colonne++)
00602         {
00603                 for (int Ligne=0 ; Ligne < DIMMAT4X4; Ligne++)
00604                 {
00605                         IndexOrigine= (Colonne * DIMMAT4X4) + Ligne;
00606                         IndexTrans= (Ligne * DIMMAT4X4) + Colonne;
00607 
00608                         MatT.m_Matrix[IndexTrans]= m_Matrix[IndexOrigine];
00609                 }
00610         }
00611 
00612         return MatT;
00613 }
00614 
00615 GLC_Matrix4x4 GLC_Matrix4x4::getCoMat4x4(void) const
00616 {
00617         GLC_Matrix4x4 CoMat(m_Matrix);
00618         double SubMat3x3[9];
00619         int Index;
00620 
00621         for (int Colonne= 0; Colonne < DIMMAT4X4; Colonne++)
00622         {
00623                 for (int Ligne=0 ; Ligne < DIMMAT4X4; Ligne++)
00624                 {
00625                         getSubMat(Ligne, Colonne, SubMat3x3);
00626                         Index= (Colonne * DIMMAT4X4) + Ligne;
00627                         if (((Colonne + Ligne + 2) % 2) == 0) // Even Number
00628                                 CoMat.m_Matrix[Index]= getDeterminant3x3(SubMat3x3);
00629                         else
00630                                 CoMat.m_Matrix[Index]= -getDeterminant3x3(SubMat3x3);
00631                 }
00632         }
00633 
00634         return CoMat;
00635 }
00636 
00637 
00638 #endif /*GLC_MATRIX4X4_H_*/

SourceForge.net Logo

©2005 Laurent Ribon