00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
00216 private:
00217
00219 enum {TAILLEMAT4X4 = 16};
00221 enum {DIMMAT4X4 = 4};
00223 double m_Matrix[TAILLEMAT4X4];
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
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
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
00395 GLC_Vector3d VectRot(Vect);
00396 VectRot.normalize();
00397
00398
00399 const double SinAngleSur2= sin(dAngleRad / 2.0);
00400
00401
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
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;
00427 m_Matrix[13]= 0.0;
00428 m_Matrix[14]= 0.0;
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
00438 const GLC_Vector3d VectAxeRot(Vect1 ^ Vect2);
00439
00440 if (!VectAxeRot.isNull())
00441 {
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
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
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))
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)
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