00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "stdmisc.h"
00025
00026 #include "nel/misc/matrix.h"
00027 #include "nel/misc/plane.h"
00028 #include "nel/misc/debug.h"
00029
00030 using namespace std;
00031
00032
00033
00034 namespace NLMISC
00035 {
00036
00037
00038
00039 const CMatrix CMatrix::Identity;
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define MAT_TRANS 1
00049 #define MAT_ROT 2
00050 #define MAT_SCALEUNI 4
00051 #define MAT_SCALEANY 8
00052 #define MAT_PROJ 16
00053
00054
00055 #define MAT_VALIDROT 64
00056 #define MAT_VALIDPROJ 128
00057 #define MAT_VALIDALL (MAT_VALIDROT | MAT_VALIDPROJ)
00058
00059 #define MAT_IDENTITY 0
00060
00061
00062
00063
00064 #define a11 M[0]
00065 #define a21 M[1]
00066 #define a31 M[2]
00067 #define a41 M[3]
00068 #define a12 M[4]
00069 #define a22 M[5]
00070 #define a32 M[6]
00071 #define a42 M[7]
00072 #define a13 M[8]
00073 #define a23 M[9]
00074 #define a33 M[10]
00075 #define a43 M[11]
00076 #define a14 M[12]
00077 #define a24 M[13]
00078 #define a34 M[14]
00079 #define a44 M[15]
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 bool CMatrix::hasScalePart() const
00091 {
00092 return (StateBit&(MAT_SCALEUNI|MAT_SCALEANY))!=0;
00093 }
00094 bool CMatrix::hasProjectionPart() const
00095 {
00096 return (StateBit&MAT_PROJ)!=0;
00097 }
00098
00099
00100 bool CMatrix::hasScaleUniform() const
00101 {
00102 return (StateBit & (MAT_SCALEUNI|MAT_SCALEANY))== MAT_SCALEUNI;
00103 }
00104 float CMatrix::getScaleUniform() const
00105 {
00106 if(hasScaleUniform())
00107 return Scale33;
00108 else
00109 return 1;
00110 }
00111
00112
00113
00114
00115 inline bool CMatrix::hasRot() const
00116 {
00117 return (StateBit&(MAT_ROT|MAT_SCALEUNI|MAT_SCALEANY))!=0;
00118 }
00119 inline bool CMatrix::hasTrans() const
00120 {
00121 return (StateBit&MAT_TRANS)!=0;
00122 }
00123 inline bool CMatrix::hasProj() const
00124 {
00125 return (StateBit&MAT_PROJ)!=0;
00126 }
00127 inline bool CMatrix::hasAll() const
00128 {
00129 return (hasRot() && hasTrans() && hasProj());
00130 }
00131
00132
00133 inline void CMatrix::testExpandRot() const
00134 {
00135 if(hasRot())
00136 return;
00137 if(!(StateBit&MAT_VALIDROT))
00138 {
00139 CMatrix *self= const_cast<CMatrix*>(this);
00140 self->StateBit|=MAT_VALIDROT;
00141 self->a11= 1; self->a12=0; self->a13=0;
00142 self->a21= 0; self->a22=1; self->a23=0;
00143 self->a31= 0; self->a32=0; self->a33=1;
00144 self->Scale33= 1;
00145 }
00146 }
00147 inline void CMatrix::testExpandProj() const
00148 {
00149 if(hasProj())
00150 return;
00151 if(!(StateBit&MAT_VALIDPROJ))
00152 {
00153 CMatrix *self= const_cast<CMatrix*>(this);
00154 self->StateBit|=MAT_VALIDPROJ;
00155 self->a41=0; self->a42=0; self->a43=0; self->a44=1;
00156 }
00157 }
00158
00159
00160
00161 CMatrix::CMatrix(const CMatrix &m)
00162 {
00163 (*this)= m;
00164 }
00165
00166 CMatrix &CMatrix::operator=(const CMatrix &m)
00167 {
00168 StateBit= m.StateBit & ~MAT_VALIDALL;
00169 if(hasAll())
00170 {
00171 memcpy(M, m.M, 16*sizeof(float));
00172 Scale33= m.Scale33;
00173 }
00174 else
00175 {
00176 if(hasRot())
00177 {
00178 memcpy(&a11, &m.a11, 3*sizeof(float));
00179 memcpy(&a12, &m.a12, 3*sizeof(float));
00180 memcpy(&a13, &m.a13, 3*sizeof(float));
00181 Scale33= m.Scale33;
00182 }
00183 if(hasProj())
00184 {
00185 a41= m.a41;
00186 a42= m.a42;
00187 a43= m.a43;
00188 a44= m.a44;
00189 }
00190
00191 memcpy(&a14, &m.a14, 3*sizeof(float));
00192 }
00193 return *this;
00194 }
00195
00196
00197
00198 void CMatrix::identity()
00199 {
00200 StateBit= MAT_IDENTITY;
00201
00202 a14= a24= a34= 0;
00203
00204
00205 }
00206
00207 void CMatrix::setRot(const CVector &i, const CVector &j, const CVector &k, bool hintNoScale)
00208 {
00209 StateBit|= MAT_ROT | MAT_SCALEANY;
00210 if(hintNoScale)
00211 StateBit&= ~(MAT_SCALEANY|MAT_SCALEUNI);
00212 a11= i.x; a12= j.x; a13= k.x;
00213 a21= i.y; a22= j.y; a23= k.y;
00214 a31= i.z; a32= j.z; a33= k.z;
00215 Scale33= 1.0f;
00216 }
00217
00218 void CMatrix::setRot(const float m33[9], bool hintNoScale)
00219 {
00220 StateBit|= MAT_ROT | MAT_SCALEANY;
00221 if(hintNoScale)
00222 StateBit&= ~(MAT_SCALEANY|MAT_SCALEUNI);
00223 a11= m33[0]; a12= m33[3]; a13= m33[6];
00224 a21= m33[1]; a22= m33[4]; a23= m33[7];
00225 a31= m33[2]; a32= m33[5]; a33= m33[8];
00226 Scale33= 1.0f;
00227 }
00228
00229 void CMatrix::setRot(const CVector &v, TRotOrder ro)
00230 {
00231 CMatrix rot;
00232 rot.identity();
00233 rot.rotate(v, ro);
00234 float m33[9];
00235 rot.getRot(m33);
00236 setRot(m33, true);
00237 }
00238
00239
00240
00241 void CMatrix::setRot(const CMatrix &matrix)
00242 {
00243
00244 StateBit&= ~(MAT_ROT | MAT_SCALEUNI | MAT_SCALEANY);
00245 StateBit|= matrix.StateBit & (MAT_ROT | MAT_SCALEUNI | MAT_SCALEANY);
00246
00247 if(hasRot())
00248 {
00249 a11= matrix.a11; a12= matrix.a12; a13= matrix.a13;
00250 a21= matrix.a21; a22= matrix.a22; a23= matrix.a23;
00251 a31= matrix.a31; a32= matrix.a32; a33= matrix.a33;
00252
00253 if(hasScaleUniform())
00254 Scale33= matrix.Scale33;
00255 }
00256 else
00257 {
00258
00259 StateBit&= ~MAT_VALIDROT;
00260 }
00261 }
00262
00263
00264
00265 void CMatrix::setPos(const CVector &v)
00266 {
00267 a14= v.x;
00268 a24= v.y;
00269 a34= v.z;
00270 if(a14!=0 || a24!=0 || a34!=0)
00271 StateBit|= MAT_TRANS;
00272 else
00273
00274 StateBit&= ~MAT_TRANS;
00275 }
00276
00277 void CMatrix::movePos(const CVector &v)
00278 {
00279 a14+= v.x;
00280 a24+= v.y;
00281 a34+= v.z;
00282 if(a14!=0 || a24!=0 || a34!=0)
00283 StateBit|= MAT_TRANS;
00284 else
00285
00286 StateBit&= ~MAT_TRANS;
00287 }
00288
00289 void CMatrix::setProj(const float proj[4])
00290 {
00291 a41= proj[0];
00292 a42= proj[1];
00293 a43= proj[2];
00294 a44= proj[3];
00295
00296
00297 if(a41!=0 || a42!=0 || a43!=0 || a44!=1)
00298 StateBit|= MAT_PROJ;
00299 else
00300 {
00301
00302 StateBit&= ~MAT_PROJ;
00303 StateBit|= MAT_VALIDPROJ;
00304 }
00305 }
00306
00307 void CMatrix::resetProj()
00308 {
00309 a41= 0;
00310 a42= 0;
00311 a43= 0;
00312 a44= 1;
00313
00314 StateBit&= ~MAT_PROJ;
00315 StateBit|= MAT_VALIDPROJ;
00316 }
00317
00318 void CMatrix::set(const float m44[16])
00319 {
00320 StateBit= MAT_IDENTITY;
00321
00322 StateBit|= MAT_ROT | MAT_SCALEANY;
00323 memcpy(M, m44, 16*sizeof(float));
00324 Scale33= 1.0f;
00325
00326
00327 if(a14!=0 || a24!=0 || a34!=0)
00328 StateBit|= MAT_TRANS;
00329 else
00330
00331 StateBit&= ~MAT_TRANS;
00332
00333
00334 if(a41!=0 || a42!=0 || a43!=0 || a44!=1)
00335 StateBit|= MAT_PROJ;
00336 else
00337 {
00338
00339 StateBit&= ~MAT_PROJ;
00340 StateBit|= MAT_VALIDPROJ;
00341 }
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351 void CMatrix::getRot(CVector &i, CVector &j, CVector &k) const
00352 {
00353 if(hasRot())
00354 {
00355 i.set(a11, a21, a31);
00356 j.set(a12, a22, a32);
00357 k.set(a13, a23, a33);
00358 }
00359 else
00360 {
00361 i.set(1, 0, 0);
00362 j.set(0, 1, 0);
00363 k.set(0, 0, 1);
00364 }
00365 }
00366
00367 void CMatrix::getRot(float m33[9]) const
00368 {
00369 if(hasRot())
00370 {
00371 m33[0]= a11;
00372 m33[1]= a21;
00373 m33[2]= a31;
00374
00375 m33[3]= a12;
00376 m33[4]= a22;
00377 m33[5]= a32;
00378
00379 m33[6]= a13;
00380 m33[7]= a23;
00381 m33[8]= a33;
00382 }
00383 else
00384 {
00385 m33[0]= 1;
00386 m33[1]= 0;
00387 m33[2]= 0;
00388
00389 m33[3]= 0;
00390 m33[4]= 1;
00391 m33[5]= 0;
00392
00393 m33[6]= 0;
00394 m33[7]= 0;
00395 m33[8]= 1;
00396 }
00397 }
00398
00399 void CMatrix::getProj(float proj[4]) const
00400 {
00401 if(hasProj())
00402 {
00403 proj[0]= a41;
00404 proj[1]= a42;
00405 proj[2]= a43;
00406 proj[3]= a44;
00407 }
00408 else
00409 {
00410 proj[0]= 0;
00411 proj[1]= 0;
00412 proj[2]= 0;
00413 proj[3]= 1;
00414 }
00415 }
00416
00417 CVector CMatrix::getI() const
00418 {
00419 if(hasRot())
00420 return CVector(a11, a21, a31);
00421 else
00422 return CVector(1, 0, 0);
00423 }
00424
00425 CVector CMatrix::getJ() const
00426 {
00427 if(hasRot())
00428 return CVector(a12, a22, a32);
00429 else
00430 return CVector(0, 1, 0);
00431 }
00432
00433 CVector CMatrix::getK() const
00434 {
00435 if(hasRot())
00436 return CVector(a13, a23, a33);
00437 else
00438 return CVector(0, 0, 1);
00439 }
00440
00441 void CMatrix::get(float m44[16]) const
00442 {
00443 testExpandRot();
00444 testExpandProj();
00445 memcpy(m44, M, 16*sizeof(float));
00446 }
00447
00448 const float *CMatrix::get() const
00449 {
00450 testExpandRot();
00451 testExpandProj();
00452 return M;
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 void CMatrix::translate(const CVector &v)
00468 {
00469
00470 if( hasRot() )
00471 {
00472 a14+= a11*v.x + a12*v.y + a13*v.z;
00473 a24+= a21*v.x + a22*v.y + a23*v.z;
00474 a34+= a31*v.x + a32*v.y + a33*v.z;
00475 }
00476 else
00477 {
00478 a14+= v.x;
00479 a24+= v.y;
00480 a34+= v.z;
00481 }
00482
00483
00484 if( hasProj() )
00485 a44+= a41*v.x + a42*v.y + a43*v.z;
00486
00487
00488 if(a14!=0 || a24!=0 || a34!=0)
00489 StateBit|= MAT_TRANS;
00490 else
00491
00492 StateBit&= ~MAT_TRANS;
00493 }
00494
00495 void CMatrix::rotateX(float a)
00496 {
00497
00498 if(a==0)
00499 return;
00500 double ca,sa;
00501 ca=cos(a);
00502 sa=sin(a);
00503
00504
00505 if( hasRot() )
00506 {
00507 float b12=a12, b22=a22, b32=a32;
00508 float b13=a13, b23=a23, b33=a33;
00509 a12= (float)(b12*ca + b13*sa);
00510 a22= (float)(b22*ca + b23*sa);
00511 a32= (float)(b32*ca + b33*sa);
00512 a13= (float)(b13*ca - b12*sa);
00513 a23= (float)(b23*ca - b22*sa);
00514 a33= (float)(b33*ca - b32*sa);
00515 }
00516 else
00517 {
00518 testExpandRot();
00519 a12= 0.0f; a22= (float)ca; a32= (float)sa;
00520 a13= 0.0f; a23= (float)-sa; a33= (float)ca;
00521 }
00522
00523
00524 if( hasProj() )
00525 {
00526 float b42=a42, b43=a43;
00527 a42= (float)(b42*ca + b43*sa);
00528 a43= (float)(b43*ca - b42*sa);
00529 }
00530
00531
00532 StateBit|= MAT_ROT;
00533 }
00534
00535 void CMatrix::rotateY(float a)
00536 {
00537
00538 if(a==0)
00539 return;
00540 double ca,sa;
00541 ca=cos(a);
00542 sa=sin(a);
00543
00544
00545 if( hasRot() )
00546 {
00547 float b11=a11, b21=a21, b31=a31;
00548 float b13=a13, b23=a23, b33=a33;
00549 a11= (float)(b11*ca - b13*sa);
00550 a21= (float)(b21*ca - b23*sa);
00551 a31= (float)(b31*ca - b33*sa);
00552 a13= (float)(b13*ca + b11*sa);
00553 a23= (float)(b23*ca + b21*sa);
00554 a33= (float)(b33*ca + b31*sa);
00555 }
00556 else
00557 {
00558 testExpandRot();
00559 a11= (float)ca; a21=0.0f; a31= (float)-sa;
00560 a13= (float)sa; a23=0.0f; a33= (float)ca;
00561 }
00562
00563
00564 if( hasProj() )
00565 {
00566 float b41=a41, b43=a43;
00567 a41= (float)(b41*ca - b43*sa);
00568 a43= (float)(b43*ca + b41*sa);
00569 }
00570
00571
00572 StateBit|= MAT_ROT;
00573 }
00574
00575 void CMatrix::rotateZ(float a)
00576 {
00577
00578 if(a==0)
00579 return;
00580 double ca,sa;
00581 ca=cos(a);
00582 sa=sin(a);
00583
00584
00585 if( StateBit & (MAT_ROT|MAT_SCALEUNI|MAT_SCALEANY) )
00586 {
00587 float b11=a11, b21=a21, b31=a31;
00588 float b12=a12, b22=a22, b32=a32;
00589 a11= (float)(b11*ca + b12*sa);
00590 a21= (float)(b21*ca + b22*sa);
00591 a31= (float)(b31*ca + b32*sa);
00592 a12= (float)(b12*ca - b11*sa);
00593 a22= (float)(b22*ca - b21*sa);
00594 a32= (float)(b32*ca - b31*sa);
00595 }
00596 else
00597 {
00598 testExpandRot();
00599 a11= (float)ca; a21= (float)sa; a31=0.0f;
00600 a12= (float)-sa; a22= (float)ca; a32=0.0f;
00601 }
00602
00603
00604 if( hasProj() )
00605 {
00606 float b41=a41, b42=a42;
00607 a41= (float)(b41*ca + b42*sa);
00608 a42= (float)(b42*ca - b41*sa);
00609 }
00610
00611
00612 StateBit|= MAT_ROT;
00613 }
00614
00615 void CMatrix::rotate(const CVector &v, TRotOrder ro)
00616 {
00617 CMatrix rot;
00618 rot.identity();
00619 switch(ro)
00620 {
00621 case XYZ: rot.rotateX(v.x); rot.rotateY(v.y); rot.rotateZ(v.z); break;
00622 case XZY: rot.rotateX(v.x); rot.rotateZ(v.z); rot.rotateY(v.y); break;
00623 case YXZ: rot.rotateY(v.y); rot.rotateX(v.x); rot.rotateZ(v.z); break;
00624 case YZX: rot.rotateY(v.y); rot.rotateZ(v.z); rot.rotateX(v.x); break;
00625 case ZXY: rot.rotateZ(v.z); rot.rotateX(v.x); rot.rotateY(v.y); break;
00626 case ZYX: rot.rotateZ(v.z); rot.rotateY(v.y); rot.rotateX(v.x); break;
00627 }
00628
00629 (*this)*= rot;
00630 }
00631
00632
00633 void CMatrix::rotate(const CQuat &quat)
00634 {
00635 CMatrix rot;
00636 rot.setRot(quat);
00637 (*this)*= rot;
00638 }
00639
00640
00641 void CMatrix::scale(float f)
00642 {
00643
00644 if(f==1.0f) return;
00645 if(StateBit & MAT_SCALEANY)
00646 {
00647 scale(CVector(f,f,f));
00648 }
00649 else
00650 {
00651 testExpandRot();
00652 StateBit|= MAT_SCALEUNI;
00653 Scale33*=f;
00654 a11*= f; a12*=f; a13*=f;
00655 a21*= f; a22*=f; a23*=f;
00656 a31*= f; a32*=f; a33*=f;
00657
00658
00659 if( hasProj() )
00660 {
00661 a41*=f; a42*=f; a43*=f;
00662 }
00663 }
00664 }
00665
00666 void CMatrix::scale(const CVector &v)
00667 {
00668
00669 if( v==CVector(1,1,1) ) return;
00670 if( !(StateBit & MAT_SCALEANY) && v.x==v.y && v.x==v.z)
00671 {
00672 scale(v.x);
00673 }
00674 else
00675 {
00676 testExpandRot();
00677 StateBit|=MAT_SCALEANY;
00678 a11*= v.x; a12*=v.y; a13*=v.z;
00679 a21*= v.x; a22*=v.y; a23*=v.z;
00680 a31*= v.x; a32*=v.y; a33*=v.z;
00681
00682
00683 if( hasProj() )
00684 {
00685 a41*=v.x;
00686 a42*=v.y;
00687 a43*=v.z;
00688 }
00689 }
00690 }
00691
00692
00693
00694
00695
00696
00697
00698
00699 void CMatrix::setMulMatrixNoProj(const CMatrix &m1, const CMatrix &m2)
00700 {
00701
00702
00703
00704
00705
00706
00707 m1.testExpandRot();
00708 m2.testExpandRot();
00709
00710
00711 a11= m1.a11*m2.a11 + m1.a12*m2.a21 + m1.a13*m2.a31;
00712 a12= m1.a11*m2.a12 + m1.a12*m2.a22 + m1.a13*m2.a32;
00713 a13= m1.a11*m2.a13 + m1.a12*m2.a23 + m1.a13*m2.a33;
00714
00715 a21= m1.a21*m2.a11 + m1.a22*m2.a21 + m1.a23*m2.a31;
00716 a22= m1.a21*m2.a12 + m1.a22*m2.a22 + m1.a23*m2.a32;
00717 a23= m1.a21*m2.a13 + m1.a22*m2.a23 + m1.a23*m2.a33;
00718
00719 a31= m1.a31*m2.a11 + m1.a32*m2.a21 + m1.a33*m2.a31;
00720 a32= m1.a31*m2.a12 + m1.a32*m2.a22 + m1.a33*m2.a32;
00721 a33= m1.a31*m2.a13 + m1.a32*m2.a23 + m1.a33*m2.a33;
00722
00723
00724 a14= m1.a11*m2.a14 + m1.a12*m2.a24 + m1.a13*m2.a34 + m1.a14;
00725 a24= m1.a21*m2.a14 + m1.a22*m2.a24 + m1.a23*m2.a34 + m1.a24;
00726 a34= m1.a31*m2.a14 + m1.a32*m2.a24 + m1.a33*m2.a34 + m1.a34;
00727
00728
00729 StateBit= (m1.StateBit | m2.StateBit | MAT_VALIDROT) & ~(MAT_PROJ|MAT_VALIDPROJ);
00730
00731
00732 if( hasScaleUniform() )
00733 Scale33= m1.Scale33*m2.Scale33;
00734 else
00735 Scale33=1;
00736
00737 }
00738
00739
00740
00741 void CMatrix::setMulMatrix(const CMatrix &m1, const CMatrix &m2)
00742 {
00743
00744 identity();
00745 StateBit= m1.StateBit | m2.StateBit;
00746 StateBit&= ~MAT_VALIDALL;
00747
00748
00749
00750 bool M1Identity= ! m1.hasRot();
00751 bool M2Identity= ! m2.hasRot();
00752 bool M1ScaleOnly= ! (m1.StateBit & MAT_ROT);
00753 bool M2ScaleOnly= ! (m2.StateBit & MAT_ROT);
00754 bool MGeneralCase= !M1Identity && !M2Identity && !M1ScaleOnly && !M2ScaleOnly;
00755
00756
00757
00758 if( MGeneralCase )
00759 {
00760 a11= m1.a11*m2.a11 + m1.a12*m2.a21 + m1.a13*m2.a31;
00761 a12= m1.a11*m2.a12 + m1.a12*m2.a22 + m1.a13*m2.a32;
00762 a13= m1.a11*m2.a13 + m1.a12*m2.a23 + m1.a13*m2.a33;
00763
00764 a21= m1.a21*m2.a11 + m1.a22*m2.a21 + m1.a23*m2.a31;
00765 a22= m1.a21*m2.a12 + m1.a22*m2.a22 + m1.a23*m2.a32;
00766 a23= m1.a21*m2.a13 + m1.a22*m2.a23 + m1.a23*m2.a33;
00767
00768 a31= m1.a31*m2.a11 + m1.a32*m2.a21 + m1.a33*m2.a31;
00769 a32= m1.a31*m2.a12 + m1.a32*m2.a22 + m1.a33*m2.a32;
00770 a33= m1.a31*m2.a13 + m1.a32*m2.a23 + m1.a33*m2.a33;
00771 }
00772
00773 else if( M1Identity || M2Identity )
00774 {
00775
00776 if( M1Identity && M2Identity )
00777 {
00778
00779 testExpandRot();
00780 }
00781 else
00782 {
00783
00784 const CMatrix *c= M2Identity? &m1 : &m2;
00785 a11= c->a11; a12= c->a12; a13= c->a13;
00786 a21= c->a21; a22= c->a22; a23= c->a23;
00787 a31= c->a31; a32= c->a32; a33= c->a33;
00788 }
00789 }
00790
00791 else if( M1ScaleOnly && M2ScaleOnly )
00792 {
00793
00794 a11= m1.a11*m2.a11; a12= 0; a13= 0;
00795 a21= 0; a22= m1.a22*m2.a22; a23= 0;
00796 a31= 0; a32= 0; a33= m1.a33*m2.a33;
00797 }
00798
00799 else if( M1ScaleOnly && !M2ScaleOnly )
00800 {
00801 a11= m1.a11*m2.a11; a12= m1.a11*m2.a12; a13= m1.a11*m2.a13;
00802 a21= m1.a22*m2.a21; a22= m1.a22*m2.a22; a23= m1.a22*m2.a23;
00803 a31= m1.a33*m2.a31; a32= m1.a33*m2.a32; a33= m1.a33*m2.a33;
00804 }
00805 else
00806 {
00807
00808 nlassert(!M1ScaleOnly && M2ScaleOnly);
00809 a11= m1.a11*m2.a11; a12= m1.a12*m2.a22; a13= m1.a13*m2.a33;
00810 a21= m1.a21*m2.a11; a22= m1.a22*m2.a22; a23= m1.a23*m2.a33;
00811 a31= m1.a31*m2.a11; a32= m1.a32*m2.a22; a33= m1.a33*m2.a33;
00812 }
00813
00814
00815 if( m1.hasTrans() && m2.hasProj())
00816 {
00817 StateBit|= MAT_ROT|MAT_SCALEANY;
00818
00819 a11+= m1.a14*m2.a41;
00820 a12+= m1.a14*m2.a42;
00821 a13+= m1.a14*m2.a43;
00822
00823 a21+= m1.a24*m2.a41;
00824 a22+= m1.a24*m2.a42;
00825 a23+= m1.a24*m2.a43;
00826
00827 a31+= m1.a34*m2.a41;
00828 a32+= m1.a34*m2.a42;
00829 a33+= m1.a34*m2.a43;
00830 }
00831
00832
00833 if( (StateBit & MAT_SCALEUNI) && !(StateBit & MAT_SCALEANY) )
00834 {
00835
00836 m1.testExpandRot();
00837 m2.testExpandRot();
00838 Scale33= m1.Scale33*m2.Scale33;
00839 }
00840 else
00841 Scale33=1;
00842
00843
00844 StateBit|=MAT_VALIDROT;
00845
00846
00847
00848
00849 if( StateBit & MAT_TRANS )
00850 {
00851
00852 if( M1Identity )
00853 {
00854 a14= m2.a14;
00855 a24= m2.a24;
00856 a34= m2.a34;
00857 }
00858 else if (M1ScaleOnly )
00859 {
00860 a14= m1.a11*m2.a14;
00861 a24= m1.a22*m2.a24;
00862 a34= m1.a33*m2.a34;
00863 }
00864 else
00865 {
00866 a14= m1.a11*m2.a14 + m1.a12*m2.a24 + m1.a13*m2.a34;
00867 a24= m1.a21*m2.a14 + m1.a22*m2.a24 + m1.a23*m2.a34;
00868 a34= m1.a31*m2.a14 + m1.a32*m2.a24 + m1.a33*m2.a34;
00869 }
00870
00871 if(m1.StateBit & MAT_TRANS)
00872 {
00873 if(m2.StateBit & MAT_PROJ)
00874 {
00875 a14+= m1.a14*m2.a44;
00876 a24+= m1.a24*m2.a44;
00877 a34+= m1.a34*m2.a44;
00878 }
00879 else
00880 {
00881 a14+= m1.a14;
00882 a24+= m1.a24;
00883 a34+= m1.a34;
00884 }
00885 }
00886 }
00887
00888
00889
00890
00891 if( StateBit & MAT_PROJ )
00892 {
00893
00894 m1.testExpandRot();
00895 m1.testExpandProj();
00896 m2.testExpandRot();
00897 m2.testExpandProj();
00898 a41= m1.a41*m2.a11 + m1.a42*m2.a21 + m1.a43*m2.a31 + m1.a44*m2.a41;
00899 a42= m1.a41*m2.a12 + m1.a42*m2.a22 + m1.a43*m2.a32 + m1.a44*m2.a42;
00900 a43= m1.a41*m2.a13 + m1.a42*m2.a23 + m1.a43*m2.a33 + m1.a44*m2.a43;
00901 a44= m1.a41*m2.a14 + m1.a42*m2.a24 + m1.a43*m2.a34 + m1.a44*m2.a44;
00902
00903 StateBit|= MAT_VALIDPROJ;
00904 }
00905 else
00906 {
00907
00908 }
00909 }
00910
00911 void CMatrix::invert()
00912 {
00913
00914 *this= inverted();
00915 }
00916
00917
00918
00919 void CMatrix::transpose3x3()
00920 {
00921 if(hasRot())
00922 {
00923
00924 swap(a12, a21);
00925 swap(a13, a31);
00926 swap(a32, a23);
00927
00928 }
00929 }
00930
00931
00932 void CMatrix::transpose()
00933 {
00934 transpose3x3();
00935 if(hasTrans() || hasProj())
00936 {
00937
00938 testExpandProj();
00939
00940 swap(a41, a14);
00941 swap(a42, a24);
00942 swap(a43, a34);
00943
00944 if(!hasTrans() || !hasProj())
00945 {
00946
00947 if(hasTrans())
00948 {
00949 StateBit&= ~MAT_TRANS;
00950 StateBit|= MAT_PROJ;
00951 }
00952 else
00953 {
00954 StateBit&= ~MAT_PROJ;
00955 StateBit|= MAT_TRANS;
00956 }
00957 }
00958
00959 StateBit&= ~(MAT_VALIDPROJ);
00960 }
00961
00962 }
00963
00964
00965
00966 bool CMatrix::fastInvert33(CMatrix &ret) const
00967 {
00968
00969
00970
00971 if(StateBit & MAT_SCALEUNI)
00972 {
00973 if (Scale33 == 0.f) return false;
00974 double s,S;
00975
00976 S=1.0/Scale33;
00977 ret.Scale33= (float)S;
00978 s=S*S;
00979
00980 ret.a11= (float)(a11*s); ret.a12= (float)(a21*s); ret.a13= (float)(a31*s);
00981 ret.a21= (float)(a12*s); ret.a22= (float)(a22*s); ret.a23= (float)(a32*s);
00982 ret.a31= (float)(a13*s); ret.a32= (float)(a23*s); ret.a33= (float)(a33*s);
00983 }
00984 else
00985 {
00986 ret.Scale33=1;
00987
00988 ret.a11= a11; ret.a12= a21; ret.a13=a31;
00989 ret.a21= a12; ret.a22= a22; ret.a23=a32;
00990 ret.a31= a13; ret.a32= a23; ret.a33=a33;
00991 }
00992 return true;
00993
00994
00995 }
00996
00997 bool CMatrix::slowInvert33(CMatrix &ret) const
00998 {
00999 CVector invi,invj,invk;
01000 CVector i,j,k;
01001 double s;
01002
01003 i= getI();
01004 j= getJ();
01005 k= getK();
01006
01007 invi.x= j.y*k.z - k.y*j.z;
01008 invi.y= j.z*k.x - k.z*j.x;
01009 invi.z= j.x*k.y - k.x*j.y;
01010 invj.x= k.y*i.z - i.y*k.z;
01011 invj.y= k.z*i.x - i.z*k.x;
01012 invj.z= k.x*i.y - i.x*k.y;
01013 invk.x= i.y*j.z - j.y*i.z;
01014 invk.y= i.z*j.x - j.z*i.x;
01015 invk.z= i.x*j.y - j.x*i.y;
01016
01017 s= invi.x*i.x + invj.x*j.x + invk.x*k.x;
01018 if(s==0)
01019 return false;
01020
01021 s=1.0/s;
01022 ret.a11= (float)(invi.x*s); ret.a12= (float)(invi.y*s); ret.a13= (float)(invi.z*s);
01023 ret.a21= (float)(invj.x*s); ret.a22= (float)(invj.y*s); ret.a23= (float)(invj.z*s);
01024 ret.a31= (float)(invk.x*s); ret.a32= (float)(invk.y*s); ret.a33= (float)(invk.z*s);
01025
01026 return true;
01027
01028 }
01029
01030 bool CMatrix::slowInvert44(CMatrix &ret) const
01031 {
01032 sint i,j;
01033 double s;
01034
01035
01036
01037 for(i=0;i<=3;i++)
01038 {
01039 for(j=0;j<=3;j++)
01040 {
01041 sint l1=0,l2=0,l3=0;
01042 sint c1,c2,c3;
01043 getCofactIndex(i,l1,l2,l3);
01044 getCofactIndex(j,c1,c2,c3);
01045
01046 ret.mat(i,j)= 0;
01047 ret.mat(i,j)+= mat(l1,c1) * mat(l2,c2) * mat(l3,c3);
01048 ret.mat(i,j)+= mat(l1,c2) * mat(l2,c3) * mat(l3,c1);
01049 ret.mat(i,j)+= mat(l1,c3) * mat(l2,c1) * mat(l3,c2);
01050
01051 ret.mat(i,j)-= mat(l1,c1) * mat(l2,c3) * mat(l3,c2);
01052 ret.mat(i,j)-= mat(l1,c2) * mat(l2,c1) * mat(l3,c3);
01053 ret.mat(i,j)-= mat(l1,c3) * mat(l2,c2) * mat(l3,c1);
01054
01055 if( (i+j)&1 )
01056 ret.mat(i,j)=-ret.mat(i,j);
01057 }
01058 }
01059
01060
01061
01062 s= ret.mat(0,0) * mat(0,0) + ret.mat(0,1) * mat(0,1) + ret.mat(0,2) * mat(0,2) + ret.mat(0,3) * mat(0,3);
01063 if(s==0)
01064 return false;
01065
01066
01067
01068 s=1.0/s;
01069 for(i=0;i<=3;i++)
01070 {
01071 for(j=0;j<=3;j++)
01072 ret.mat(i,j)= (float)(ret.mat(i,j)*s);
01073 }
01074
01075
01076
01077 for(i=0;i<=3;i++)
01078 {
01079 for(j=i+1;j<=3;j++)
01080 {
01081 swap(ret.mat(i,j), ret.mat(j,i));
01082 }
01083 }
01084
01085 return true;
01086 }
01087
01088 CMatrix CMatrix::inverted() const
01089 {
01090
01091 CMatrix ret;
01092
01093 testExpandRot();
01094 testExpandProj();
01095
01096
01097
01098 if(StateBit & MAT_PROJ)
01099 {
01100 if(!slowInvert44(ret))
01101 {
01102 ret.identity();
01103 return ret;
01104 }
01105
01106
01107 ret.StateBit= MAT_TRANS|MAT_ROT|MAT_SCALEANY|MAT_PROJ;
01108
01109
01110 if(ret.a14!=0 || ret.a24!=0 || ret.a34!=0)
01111 ret.StateBit|= MAT_TRANS;
01112 else
01113 ret.StateBit&= ~MAT_TRANS;
01114
01115
01116 if(ret.a41!=0 || ret.a42!=0 || ret.a43!=0 || ret.a44!=1)
01117 ret.StateBit|= MAT_PROJ;
01118 else
01119 ret.StateBit&= ~MAT_PROJ;
01120 }
01121
01122
01123
01124 else
01125 {
01126
01127 if(StateBit & MAT_SCALEANY)
01128 {
01129 if(!slowInvert33(ret))
01130 {
01131 ret.identity();
01132 return ret;
01133 }
01134 }
01135 else
01136 {
01137 if (!fastInvert33(ret))
01138 {
01139 ret.identity();
01140 return ret;
01141 }
01142 }
01143
01144
01145
01146 if(StateBit & MAT_TRANS)
01147 {
01148
01149
01150
01151 ret.a14= ret.a11*(-a14) + ret.a12*(-a24) + ret.a13*(-a34);
01152 ret.a24= ret.a21*(-a14) + ret.a22*(-a24) + ret.a23*(-a34);
01153 ret.a34= ret.a31*(-a14) + ret.a32*(-a24) + ret.a33*(-a34);
01154 }
01155 else
01156 {
01157 ret.a14= 0;
01158 ret.a24= 0;
01159 ret.a34= 0;
01160 }
01161
01162
01163 ret.a41= 0; ret.a42= 0; ret.a43= 0; ret.a44= 1;
01164
01165
01166 ret.StateBit= StateBit;
01167 }
01168
01169
01170 return ret;
01171 }
01172
01173 bool CMatrix::normalize(TRotOrder ro)
01174 {
01175
01176 CVector ti,tj,tk;
01177 ti= getI();
01178 tj= getJ();
01179 tk= getK();
01180
01181 testExpandRot();
01182
01183
01184 switch(ro)
01185 {
01186 case XYZ:
01187 ti.normalize();
01188 tk= ti^tj;
01189 tk.normalize();
01190 tj= tk^ti;
01191 break;
01192 case XZY:
01193 ti.normalize();
01194 tj= tk^ti;
01195 tj.normalize();
01196 tk= ti^tj;
01197 break;
01198 case YXZ:
01199 tj.normalize();
01200 tk= ti^tj;
01201 tk.normalize();
01202 ti= tj^tk;
01203 break;
01204 case YZX:
01205 tj.normalize();
01206 ti= tj^tk;
01207 ti.normalize();
01208 tk= ti^tj;
01209 break;
01210 case ZXY:
01211 tk.normalize();
01212 tj= tk^ti;
01213 tj.normalize();
01214 ti= tj^tk;
01215 break;
01216 case ZYX:
01217 tk.normalize();
01218 ti= tj^tk;
01219 ti.normalize();
01220 tj= tk^ti;
01221 break;
01222 }
01223
01224
01225 if( ti.isNull() || tj.isNull() || tk.isNull() )
01226 return false;
01227 a11= ti.x; a12= tj.x; a13= tk.x;
01228 a21= ti.y; a22= tj.y; a23= tk.y;
01229 a31= ti.z; a32= tj.z; a33= tk.z;
01230
01231 StateBit&= ~(MAT_SCALEUNI|MAT_SCALEANY);
01232
01233 StateBit|= MAT_ROT;
01234 Scale33=1;
01235
01236 return true;
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246 CVector CMatrix::mulVector(const CVector &v) const
01247 {
01248
01249 CVector ret;
01250
01251 if( hasRot() )
01252 {
01253 ret.x= a11*v.x + a12*v.y + a13*v.z;
01254 ret.y= a21*v.x + a22*v.y + a23*v.z;
01255 ret.z= a31*v.x + a32*v.y + a33*v.z;
01256 return ret;
01257 }
01258 else
01259 return v;
01260 }
01261
01262
01263 CVector CMatrix::mulPoint(const CVector &v) const
01264 {
01265
01266 CVector ret;
01267
01268 if( hasRot() )
01269 {
01270 ret.x= a11*v.x + a12*v.y + a13*v.z;
01271 ret.y= a21*v.x + a22*v.y + a23*v.z;
01272 ret.z= a31*v.x + a32*v.y + a33*v.z;
01273 }
01274 else
01275 {
01276 ret= v;
01277 }
01278 if( hasTrans() )
01279 {
01280 ret.x+= a14;
01281 ret.y+= a24;
01282 ret.z+= a34;
01283 }
01284
01285 return ret;
01286 }
01287
01288
01289
01290
01291
01292 CVectorH CMatrix::operator*(const CVectorH& v) const
01293 {
01294
01295 CVectorH ret;
01296
01297 testExpandRot();
01298 testExpandProj();
01299
01300 ret.x= a11*v.x + a12*v.y + a13*v.z + a14*v.w;
01301 ret.y= a21*v.x + a22*v.y + a23*v.z + a24*v.w;
01302 ret.z= a31*v.x + a32*v.y + a33*v.z + a34*v.w;
01303 ret.w= a41*v.x + a42*v.y + a43*v.z + a44*v.w;
01304 return ret;
01305 }
01306
01307
01308
01309 CPlane operator*(const CPlane &p, const CMatrix &m)
01310 {
01311 m.testExpandRot();
01312 m.testExpandProj();
01313
01314 CPlane ret;
01315
01316 if( m.StateBit & (MAT_ROT|MAT_SCALEUNI|MAT_SCALEANY|MAT_PROJ) )
01317 {
01318
01319 ret.a= p.a*m.a11 + p.b*m.a21 + p.c*m.a31 + p.d*m.a41;
01320 ret.b= p.a*m.a12 + p.b*m.a22 + p.c*m.a32 + p.d*m.a42;
01321 ret.c= p.a*m.a13 + p.b*m.a23 + p.c*m.a33 + p.d*m.a43;
01322 ret.d= p.a*m.a14 + p.b*m.a24 + p.c*m.a34 + p.d*m.a44;
01323 return ret;
01324 }
01325 else if( m.StateBit & MAT_TRANS )
01326 {
01327
01328
01329 ret.a= p.a;
01330 ret.b= p.b;
01331 ret.c= p.c;
01332 ret.d= p.a*m.a14 + p.b*m.a24 + p.c*m.a34 + p.d*m.a44;
01333 return ret;
01334 }
01335 else
01336 return p;
01337 }
01338
01339
01340
01341
01342
01343
01344
01345
01346 void CMatrix::setRot(const CQuat &quat)
01347 {
01348
01349 StateBit&= ~(MAT_ROT | MAT_SCALEANY|MAT_SCALEUNI);
01350 Scale33= 1.0f;
01351 if(quat.isIdentity())
01352 {
01353 a11= 1; a12= 0; a13= 0;
01354 a21= 0; a22= 1; a23= 0;
01355 a31= 0; a32= 0; a33= 1;
01356 }
01357 else
01358 {
01359 StateBit|= MAT_ROT;
01360 float wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
01361
01362
01363 x2 = quat.x + quat.x; y2 = quat.y + quat.y;
01364 z2 = quat.z + quat.z;
01365 xx = quat.x * x2; xy = quat.x * y2; xz = quat.x * z2;
01366 yy = quat.y * y2; yz = quat.y * z2; zz = quat.z * z2;
01367 wx = quat.w * x2; wy = quat.w * y2; wz = quat.w * z2;
01368
01369 a11 = 1.0f - (yy + zz);
01370 a12 = xy - wz;
01371 a13 = xz + wy;
01372
01373 a21 = xy + wz;
01374 a22 = 1.0f - (xx + zz);
01375 a23 = yz - wx;
01376
01377 a31 = xz - wy;
01378 a32 = yz + wx;
01379 a33 = 1.0f - (xx + yy);
01380 }
01381 }
01382
01383
01384
01385 void CMatrix::getRot(CQuat &quat) const
01386 {
01387 const CMatrix *pmat= this;
01388 CMatrix MatNormed;
01389
01390
01391
01392 if(! (StateBit & MAT_ROT))
01393 {
01394 quat= CQuat::Identity;
01395 return;
01396 }
01397
01398
01399 if(StateBit & (MAT_SCALEUNI | MAT_SCALEANY) )
01400 {
01401 MatNormed= *this;
01402 MatNormed.normalize(ZYX);
01403 pmat= &MatNormed;
01404 }
01405
01406
01407 float tr, s, q[4];
01408
01409 tr = pmat->a11 + pmat->a22 + pmat->a33;
01410
01411
01412 if (tr > 0.0)
01413 {
01414 s = (float)sqrt (tr + 1.0f);
01415 quat.w = s / 2.0f;
01416 s = 0.5f / s;
01417 quat.x = (pmat->a32 - pmat->a23) * s;
01418 quat.y = (pmat->a13 - pmat->a31) * s;
01419 quat.z = (pmat->a21 - pmat->a12) * s;
01420 }
01421 else
01422 {
01423 sint i, j, k;
01424 sint nxt[3] = {1, 2, 0};
01425
01426
01427 i = 0;
01428 if (pmat->a22 > pmat->a11) i = 1;
01429 if (pmat->a33 > pmat->mat(i,i) ) i = 2;
01430 j = nxt[i];
01431 k = nxt[j];
01432
01433 s = (float) sqrt ( (pmat->mat(i,i) - (pmat->mat(j,j) + pmat->mat(k,k)) ) + 1.0);
01434
01435 q[i] = s * 0.5f;
01436
01437 if (s != 0.0f) s = 0.5f / s;
01438
01439 q[j] = (pmat->mat(j,i) + pmat->mat(i,j)) * s;
01440 q[k] = (pmat->mat(k,i) + pmat->mat(i,k)) * s;
01441 q[3] = (pmat->mat(k,j) - pmat->mat(j,k)) * s;
01442
01443 quat.x = q[0];
01444 quat.y = q[1];
01445 quat.z = q[2];
01446 quat.w = q[3];
01447 }
01448
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458 inline void CMatrix::setScaleUni(float scale)
01459 {
01460
01461 StateBit&= ~(MAT_ROT | MAT_SCALEANY | MAT_SCALEUNI);
01462 StateBit|= MAT_SCALEUNI | MAT_VALIDROT;
01463 Scale33= scale;
01464 a11= scale; a12= 0; a13= 0;
01465 a21= 0; a22= scale; a23= 0;
01466 a31= 0; a32= 0; a33= scale;
01467 }
01468
01469
01470 void CMatrix::setScale(float scale)
01471 {
01472 setScaleUni(scale);
01473 }
01474
01475
01476
01477 void CMatrix::setScale(const CVector &v)
01478 {
01479
01480 if(v.x==v.y && v.x==v.z)
01481 setScaleUni(v.x);
01482
01483
01484 StateBit&= ~(MAT_ROT | MAT_SCALEANY | MAT_SCALEUNI);
01485 StateBit|= MAT_SCALEANY | MAT_VALIDROT;
01486 a11= v.x; a12= 0; a13= 0;
01487 a21= 0; a22= v.y; a23= 0;
01488 a31= 0; a32= 0; a33= v.z;
01489
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499 void CMatrix::serial(IStream &f)
01500 {
01501
01502 (void)f.serialVersion(0);
01503
01504 if(f.isReading())
01505 identity();
01506 f.serial(StateBit);
01507
01508 if(!f.isReading() && !hasScaleUniform())
01509 {
01510 float fs= 1.f;
01511 f.serial(fs);
01512 }
01513 else
01514 f.serial(Scale33);
01515 if( hasRot() )
01516 {
01517 f.serial(a11, a12, a13);
01518 f.serial(a21, a22, a23);
01519 f.serial(a31, a32, a33);
01520 }
01521 if( hasTrans() )
01522 {
01523 f.serial(a14, a24, a34);
01524 }
01525 else if(f.isReading())
01526 {
01527
01528 a14= a24= a34= 0;
01529 }
01530 if( hasProj() )
01531 {
01532 f.serial(a41, a42, a43, a44);
01533 }
01534 }
01535
01536
01537
01538 void CMatrix::setArbitraryRotI(const CVector &idir)
01539 {
01540
01541 if( fabs(idir.z)<0.9f )
01542 setRot(idir, CVector::J, CVector::K);
01543 else
01544 setRot(idir, CVector::J, CVector::I);
01545 normalize(CMatrix::XZY);
01546 }
01547
01548 void CMatrix::setArbitraryRotJ(const CVector &jdir)
01549 {
01550
01551 if(fabs(jdir.z)<0.9f)
01552 setRot(CVector::I, jdir, CVector::K);
01553 else
01554 setRot(CVector::I, jdir, CVector::J);
01555 normalize(CMatrix::YZX);
01556 }
01557
01558 void CMatrix::setArbitraryRotK(const CVector &kdir)
01559 {
01560
01561 if( fabs(kdir.y)<0.9f )
01562 setRot(CVector::I, CVector::J, kdir);
01563 else
01564 setRot(CVector::I, CVector::K, kdir);
01565 normalize(CMatrix::ZYX);
01566 }
01567
01568
01569
01570
01571 }
01572