00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCGLIB_MATRIX44
00025 #define __VCGLIB_MATRIX44
00026
00027 #include <memory.h>
00028 #include <vcg/math/base.h>
00029 #include <vcg/space/point3.h>
00030 #include <vcg/space/point4.h>
00031 #include <vector>
00032 #include <iostream>
00033 #include <eigenlib/Eigen/Core>
00034 #include <eigenlib/Eigen/LU>
00035
00036 namespace vcg {
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00074 template <class T> class Matrix44 {
00075 protected:
00076 T _a[16];
00077
00078 public:
00079 typedef T ScalarType;
00080
00082
00086 Matrix44() {}
00087 ~Matrix44() {}
00088 Matrix44(const Matrix44 &m);
00089 Matrix44(const T v[]);
00090
00091 T &ElementAt(const int row, const int col);
00092 T ElementAt(const int row, const int col) const;
00093
00094
00095 T *V();
00096 const T *V() const ;
00097
00098 T *operator[](const int i);
00099 const T *operator[](const int i) const;
00100
00101
00102 Point4<T> GetColumn4(const int& i)const{
00103 assert(i>=0 && i<4);
00104 return Point4<T>(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i),ElementAt(3,i));
00105
00106 }
00107
00108 Point3<T> GetColumn3(const int& i)const{
00109 assert(i>=0 && i<4);
00110 return Point3<T>(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i));
00111 }
00112
00113 Point4<T> GetRow4(const int& i)const{
00114 assert(i>=0 && i<4);
00115 return Point4<T>(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2),ElementAt(i,3));
00116
00117 }
00118
00119 Point3<T> GetRow3(const int& i)const{
00120 assert(i>=0 && i<4);
00121 return Point3<T>(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2));
00122
00123 }
00124
00125 Matrix44 operator+(const Matrix44 &m) const;
00126 Matrix44 operator-(const Matrix44 &m) const;
00127 Matrix44 operator*(const Matrix44 &m) const;
00128 Point4<T> operator*(const Point4<T> &v) const;
00129
00130 bool operator==(const Matrix44 &m) const;
00131 bool operator!= (const Matrix44 &m) const;
00132
00133 Matrix44 operator-() const;
00134 Matrix44 operator*(const T k) const;
00135 void operator+=(const Matrix44 &m);
00136 void operator-=(const Matrix44 &m);
00137 void operator*=( const Matrix44 & m );
00138 void operator*=( const T k );
00139
00140 template <class Matrix44Type>
00141 void ToMatrix(Matrix44Type & m) const {for(int i = 0; i < 16; i++) m.V()[i]=V()[i];}
00142
00143 void ToEulerAngles(T &alpha, T &beta, T &gamma);
00144
00145 template <class Matrix44Type>
00146 void FromMatrix(const Matrix44Type & m){for(int i = 0; i < 16; i++) V()[i]=m.V()[i];}
00147
00148 template <class EigenMatrix44Type>
00149 void ToEigenMatrix(EigenMatrix44Type & m) const {
00150 for(int i = 0; i < 4; i++)
00151 for(int j = 0; j < 4; j++)
00152 m(i,j)=(*this)[i][j];
00153 }
00154
00155 template <class EigenMatrix44Type>
00156 void FromEigenMatrix(const EigenMatrix44Type & m){
00157 for(int i = 0; i < 4; i++)
00158 for(int j = 0; j < 4; j++)
00159 ElementAt(i,j)=T(m(i,j));
00160 }
00161
00162 void FromEulerAngles(T alpha, T beta, T gamma);
00163 void SetZero();
00164 void SetIdentity();
00165 void SetDiagonal(const T k);
00166 Matrix44 &SetScale(const T sx, const T sy, const T sz);
00167 Matrix44 &SetScale(const Point3<T> &t);
00168 Matrix44<T>& SetColumn(const unsigned int ii,const Point4<T> &t);
00169 Matrix44<T>& SetColumn(const unsigned int ii,const Point3<T> &t);
00170 Matrix44 &SetTranslate(const Point3<T> &t);
00171 Matrix44 &SetTranslate(const T sx, const T sy, const T sz);
00172 Matrix44 &SetShearXY(const T sz);
00173 Matrix44 &SetShearXZ(const T sy);
00174 Matrix44 &SetShearYZ(const T sx);
00175
00177 Matrix44 &SetRotateDeg(T AngleDeg, const Point3<T> & axis);
00178 Matrix44 &SetRotateRad(T AngleRad, const Point3<T> & axis);
00179
00180 T Determinant() const;
00181
00182 template <class Q> void Import(const Matrix44<Q> &m) {
00183 for(int i = 0; i < 16; i++)
00184 _a[i] = (T)(m.V()[i]);
00185 }
00186 template <class Q>
00187 static inline Matrix44 Construct( const Matrix44<Q> & b )
00188 {
00189 Matrix44<T> tmp; tmp.FromMatrix(b);
00190 return tmp;
00191 }
00192
00193 static inline const Matrix44 &Identity( )
00194 {
00195 static Matrix44<T> tmp; tmp.SetIdentity();
00196 return tmp;
00197 }
00198
00199
00200 Matrix44 transpose() const
00201 {
00202 Matrix44 res = *this;
00203 Transpose(res);
00204 return res;
00205 }
00206 void transposeInPlace() { Transpose(*this); }
00207
00208 void print() {
00209 unsigned int i, j, p;
00210 for (i=0, p=0; i<4; i++, p+=4)
00211 {
00212 std::cout << "[\t";
00213 for (j=0; j<4; j++)
00214 std::cout << _a[p+j] << "\t";
00215
00216 std::cout << "]\n";
00217 }
00218 std::cout << "\n";
00219 }
00220
00221 };
00222
00223
00224
00225
00227 template <class T> Point3<T> operator*(const Matrix44<T> &m, const Point3<T> &p);
00228
00229 template <class T> Matrix44<T> &Transpose(Matrix44<T> &m);
00230
00231 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m);
00232
00233 typedef Matrix44<short> Matrix44s;
00234 typedef Matrix44<int> Matrix44i;
00235 typedef Matrix44<float> Matrix44f;
00236 typedef Matrix44<double> Matrix44d;
00237
00238
00239
00240 template <class T> Matrix44<T>::Matrix44(const Matrix44<T> &m) {
00241 memcpy((T *)_a, (const T *)m._a, 16 * sizeof(T));
00242 }
00243
00244 template <class T> Matrix44<T>::Matrix44(const T v[]) {
00245 memcpy((T *)_a, v, 16 * sizeof(T));
00246 }
00247
00248 template <class T> T &Matrix44<T>::ElementAt(const int row, const int col) {
00249 assert(row >= 0 && row < 4);
00250 assert(col >= 0 && col < 4);
00251 return _a[(row<<2) + col];
00252 }
00253
00254 template <class T> T Matrix44<T>::ElementAt(const int row, const int col) const {
00255 assert(row >= 0 && row < 4);
00256 assert(col >= 0 && col < 4);
00257 return _a[(row<<2) + col];
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 template <class T> T *Matrix44<T>::operator[](const int i) {
00270 assert(i >= 0 && i < 4);
00271 return _a+i*4;
00272 }
00273
00274 template <class T> const T *Matrix44<T>::operator[](const int i) const {
00275 assert(i >= 0 && i < 4);
00276 return _a+i*4;
00277 }
00278 template <class T> T *Matrix44<T>::V() { return _a;}
00279 template <class T> const T *Matrix44<T>::V() const { return _a;}
00280
00281
00282 template <class T> Matrix44<T> Matrix44<T>::operator+(const Matrix44 &m) const {
00283 Matrix44<T> ret;
00284 for(int i = 0; i < 16; i++)
00285 ret.V()[i] = V()[i] + m.V()[i];
00286 return ret;
00287 }
00288
00289 template <class T> Matrix44<T> Matrix44<T>::operator-(const Matrix44 &m) const {
00290 Matrix44<T> ret;
00291 for(int i = 0; i < 16; i++)
00292 ret.V()[i] = V()[i] - m.V()[i];
00293 return ret;
00294 }
00295
00296 template <class T> Matrix44<T> Matrix44<T>::operator*(const Matrix44 &m) const {
00297 Matrix44 ret;
00298 for(int i = 0; i < 4; i++)
00299 for(int j = 0; j < 4; j++) {
00300 T t = 0.0;
00301 for(int k = 0; k < 4; k++)
00302 t += ElementAt(i, k) * m.ElementAt(k, j);
00303 ret.ElementAt(i, j) = t;
00304 }
00305 return ret;
00306 }
00307
00308 template <class T> Point4<T> Matrix44<T>::operator*(const Point4<T> &v) const {
00309 Point4<T> ret;
00310 for(int i = 0; i < 4; i++){
00311 T t = 0.0;
00312 for(int k = 0; k < 4; k++)
00313 t += ElementAt(i,k) * v[k];
00314 ret[i] = t;
00315 }
00316 return ret;
00317 }
00318
00319
00320 template <class T> bool Matrix44<T>::operator==(const Matrix44 &m) const {
00321 for(int i = 0; i < 4; ++i)
00322 for(int j = 0; j < 4; ++j)
00323 if(ElementAt(i,j) != m.ElementAt(i,j))
00324 return false;
00325 return true;
00326 }
00327 template <class T> bool Matrix44<T>::operator!=(const Matrix44 &m) const {
00328 for(int i = 0; i < 4; ++i)
00329 for(int j = 0; j < 4; ++j)
00330 if(ElementAt(i,j) != m.ElementAt(i,j))
00331 return true;
00332 return false;
00333 }
00334
00335 template <class T> Matrix44<T> Matrix44<T>::operator-() const {
00336 Matrix44<T> res;
00337 for(int i = 0; i < 16; i++)
00338 res.V()[i] = -V()[i];
00339 return res;
00340 }
00341
00342 template <class T> Matrix44<T> Matrix44<T>::operator*(const T k) const {
00343 Matrix44<T> res;
00344 for(int i = 0; i < 16; i++)
00345 res.V()[i] =V()[i] * k;
00346 return res;
00347 }
00348
00349 template <class T> void Matrix44<T>::operator+=(const Matrix44 &m) {
00350 for(int i = 0; i < 16; i++)
00351 V()[i] += m.V()[i];
00352 }
00353 template <class T> void Matrix44<T>::operator-=(const Matrix44 &m) {
00354 for(int i = 0; i < 16; i++)
00355 V()[i] -= m.V()[i];
00356 }
00357 template <class T> void Matrix44<T>::operator*=( const Matrix44 & m ) {
00358 *this = *this *m;
00359 }
00360
00361 template < class PointType , class T > void operator*=( std::vector<PointType> &vert, const Matrix44<T> & m ) {
00362 typename std::vector<PointType>::iterator ii;
00363 for(ii=vert.begin();ii!=vert.end();++ii)
00364 (*ii).P()=m * (*ii).P();
00365 }
00366
00367 template <class T> void Matrix44<T>::operator*=( const T k ) {
00368 for(int i = 0; i < 16; i++)
00369 _a[i] *= k;
00370 }
00371
00372 template <class T>
00373 void Matrix44<T>::ToEulerAngles(T &alpha, T &beta, T &gamma)
00374 {
00375 alpha = atan2(ElementAt(1,2), ElementAt(2,2));
00376 beta = asin(-ElementAt(0,2));
00377 gamma = atan2(ElementAt(0,1), ElementAt(0,0));
00378 }
00379
00380 template <class T>
00381 void Matrix44<T>::FromEulerAngles(T alpha, T beta, T gamma)
00382 {
00383 this->SetZero();
00384
00385 T cosalpha = cos(alpha);
00386 T cosbeta = cos(beta);
00387 T cosgamma = cos(gamma);
00388 T sinalpha = sin(alpha);
00389 T sinbeta = sin(beta);
00390 T singamma = sin(gamma);
00391
00392 ElementAt(0,0) = cosbeta * cosgamma;
00393 ElementAt(1,0) = -cosalpha * singamma + sinalpha * sinbeta * cosgamma;
00394 ElementAt(2,0) = sinalpha * singamma + cosalpha * sinbeta * cosgamma;
00395
00396 ElementAt(0,1) = cosbeta * singamma;
00397 ElementAt(1,1) = cosalpha * cosgamma + sinalpha * sinbeta * singamma;
00398 ElementAt(2,1) = -sinalpha * cosgamma + cosalpha * sinbeta * singamma;
00399
00400 ElementAt(0,2) = -sinbeta;
00401 ElementAt(1,2) = sinalpha * cosbeta;
00402 ElementAt(2,2) = cosalpha * cosbeta;
00403
00404 ElementAt(3,3) = 1;
00405 }
00406
00407 template <class T> void Matrix44<T>::SetZero() {
00408 memset((T *)_a, 0, 16 * sizeof(T));
00409 }
00410
00411 template <class T> void Matrix44<T>::SetIdentity() {
00412 SetDiagonal(1);
00413 }
00414
00415 template <class T> void Matrix44<T>::SetDiagonal(const T k) {
00416 SetZero();
00417 ElementAt(0, 0) = k;
00418 ElementAt(1, 1) = k;
00419 ElementAt(2, 2) = k;
00420 ElementAt(3, 3) = 1;
00421 }
00422
00423 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const Point3<T> &t) {
00424 SetScale(t[0], t[1], t[2]);
00425 return *this;
00426 }
00427 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const T sx, const T sy, const T sz) {
00428 SetZero();
00429 ElementAt(0, 0) = sx;
00430 ElementAt(1, 1) = sy;
00431 ElementAt(2, 2) = sz;
00432 ElementAt(3, 3) = 1;
00433 return *this;
00434 }
00435
00436 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const Point3<T> &t) {
00437 SetTranslate(t[0], t[1], t[2]);
00438 return *this;
00439 }
00440 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const T tx, const T ty, const T tz) {
00441 SetIdentity();
00442 ElementAt(0, 3) = tx;
00443 ElementAt(1, 3) = ty;
00444 ElementAt(2, 3) = tz;
00445 return *this;
00446 }
00447
00448 template <class T> Matrix44<T> &Matrix44<T>::SetColumn(const unsigned int ii,const Point3<T> &t) {
00449 assert( ii < 4 );
00450 ElementAt(0, ii) = t.X();
00451 ElementAt(1, ii) = t.Y();
00452 ElementAt(2, ii) = t.Z();
00453 return *this;
00454 }
00455
00456 template <class T> Matrix44<T> &Matrix44<T>::SetColumn(const unsigned int ii,const Point4<T> &t) {
00457 assert( ii < 4 );
00458 ElementAt(0, ii) = t[0];
00459 ElementAt(1, ii) = t[1];
00460 ElementAt(2, ii) = t[2];
00461 ElementAt(3, ii) = t[3];
00462 return *this;
00463 }
00464
00465
00466 template <class T> Matrix44<T> &Matrix44<T>::SetRotateDeg(T AngleDeg, const Point3<T> & axis) {
00467 return SetRotateRad(math::ToRad(AngleDeg),axis);
00468 }
00469
00470 template <class T> Matrix44<T> &Matrix44<T>::SetRotateRad(T AngleRad, const Point3<T> & axis) {
00471
00472 T c = math::Cos(AngleRad);
00473 T s = math::Sin(AngleRad);
00474 T q = 1-c;
00475 Point3<T> t = axis;
00476 t.Normalize();
00477 ElementAt(0,0) = t[0]*t[0]*q + c;
00478 ElementAt(0,1) = t[0]*t[1]*q - t[2]*s;
00479 ElementAt(0,2) = t[0]*t[2]*q + t[1]*s;
00480 ElementAt(0,3) = 0;
00481 ElementAt(1,0) = t[1]*t[0]*q + t[2]*s;
00482 ElementAt(1,1) = t[1]*t[1]*q + c;
00483 ElementAt(1,2) = t[1]*t[2]*q - t[0]*s;
00484 ElementAt(1,3) = 0;
00485 ElementAt(2,0) = t[2]*t[0]*q -t[1]*s;
00486 ElementAt(2,1) = t[2]*t[1]*q +t[0]*s;
00487 ElementAt(2,2) = t[2]*t[2]*q +c;
00488 ElementAt(2,3) = 0;
00489 ElementAt(3,0) = 0;
00490 ElementAt(3,1) = 0;
00491 ElementAt(3,2) = 0;
00492 ElementAt(3,3) = 1;
00493 return *this;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 template <class T>
00547 bool Decompose(Matrix44<T> &M, Point3<T> &ScaleV, Point3<T> &ShearV, Point3<T> &RotV,Point3<T> &TranV)
00548 {
00549 if(!(M[3][0]==0 && M[3][1]==0 && M[3][2]==0 && M[3][3]==1) )
00550 return false;
00551 if(math::Abs(M.Determinant())<1e-10) return false;
00552
00553
00554 TranV=M.GetColumn3(3);
00555
00556
00557 ScaleV[0]=Norm(M.GetColumn3(0));
00558 Point3<T> R[3];
00559 R[0]=M.GetColumn3(0);
00560 R[0].Normalize();
00561
00562 ShearV[0]=R[0]*M.GetColumn3(1);
00563 R[1]= M.GetColumn3(1)-R[0]*ShearV[0];
00564 assert(math::Abs(R[1]*R[0])<1e-10);
00565 ScaleV[1]=Norm(R[1]);
00566 R[1]=R[1]/ScaleV[1];
00567 ShearV[0]=ShearV[0]/ScaleV[1];
00568
00569 ShearV[1]=R[0]*M.GetColumn3(2);
00570 R[2]= M.GetColumn3(2)-R[0]*ShearV[1];
00571 assert(math::Abs(R[2]*R[0])<1e-10);
00572
00573 R[2] = R[2]-R[1]*(R[2]*R[1]);
00574 assert(math::Abs(R[2]*R[1])<1e-10);
00575 assert(math::Abs(R[2]*R[0])<1e-10);
00576
00577 ScaleV[2]=Norm(R[2]);
00578 ShearV[1]=ShearV[1]/ScaleV[2];
00579 R[2]=R[2]/ScaleV[2];
00580 assert(math::Abs(R[2]*R[1])<1e-10);
00581 assert(math::Abs(R[2]*R[0])<1e-10);
00582
00583 ShearV[2]=R[1]*M.GetColumn3(2);
00584 ShearV[2]=ShearV[2]/ScaleV[2];
00585 int i,j;
00586 for(i=0;i<3;++i)
00587 for(j=0;j<3;++j)
00588 M[i][j]=R[j][i];
00589
00590
00591
00592 double det=M.Determinant();
00593 if(math::Abs(det)<1e-10) return false;
00594 assert(math::Abs(math::Abs(det)-1.0)<1e-10);
00595 if(det<0) {
00596 ScaleV *= -1;
00597 M *= -1;
00598 }
00599
00600 double alpha,beta,gamma;
00601 beta=asin( M[0][2]);
00602 double cosbeta=cos(beta);
00603 if(math::Abs(cosbeta) > 1e-5)
00604 {
00605 alpha=asin(-M[1][2]/cosbeta);
00606 if((M[2][2]/cosbeta) < 0 ) alpha=M_PI-alpha;
00607 gamma=asin(-M[0][1]/cosbeta);
00608 if((M[0][0]/cosbeta)<0) gamma = M_PI-gamma;
00609 }
00610 else
00611 {
00612 alpha=asin(-M[1][0]);
00613 if(M[1][1]<0) alpha=M_PI-alpha;
00614 gamma=0;
00615 }
00616
00617 RotV[0]=math::ToDeg(alpha);
00618 RotV[1]=math::ToDeg(beta);
00619 RotV[2]=math::ToDeg(gamma);
00620
00621 return true;
00622 }
00623
00624
00625
00626
00627 template <class T> T Matrix44<T>::Determinant() const {
00628 Eigen::Matrix4d mm;
00629 this->ToEigenMatrix(mm);
00630 return mm.determinant();
00631 }
00632
00633
00634 template <class T> Point3<T> operator*(const Matrix44<T> &m, const Point3<T> &p) {
00635 T w;
00636 Point3<T> s;
00637 s[0] = m.ElementAt(0, 0)*p[0] + m.ElementAt(0, 1)*p[1] + m.ElementAt(0, 2)*p[2] + m.ElementAt(0, 3);
00638 s[1] = m.ElementAt(1, 0)*p[0] + m.ElementAt(1, 1)*p[1] + m.ElementAt(1, 2)*p[2] + m.ElementAt(1, 3);
00639 s[2] = m.ElementAt(2, 0)*p[0] + m.ElementAt(2, 1)*p[1] + m.ElementAt(2, 2)*p[2] + m.ElementAt(2, 3);
00640 w = m.ElementAt(3, 0)*p[0] + m.ElementAt(3, 1)*p[1] + m.ElementAt(3, 2)*p[2] + m.ElementAt(3, 3);
00641 if(w!= 0) s /= w;
00642 return s;
00643 }
00644
00645 template <class T> Matrix44<T> &Transpose(Matrix44<T> &m) {
00646 for(int i = 1; i < 4; i++)
00647 for(int j = 0; j < i; j++) {
00648 std::swap(m.ElementAt(i, j), m.ElementAt(j, i));
00649 }
00650 return m;
00651 }
00652
00653 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m) {
00654 Eigen::Matrix4d mm,mmi;
00655 m.ToEigenMatrix(mm);
00656 mmi=mm.inverse();
00657 Matrix44<T> res;
00658 res.FromEigenMatrix(mmi);
00659 return res;
00660 }
00661
00662 }
00663 #endif
00664
00665