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 VCG_USE_EIGEN
00025 #include "deprecated_matrix44.h"
00026 #else
00027
00028 #ifndef __VCGLIB_MATRIX44
00029 #define __VCGLIB_MATRIX44
00030
00031 #include "eigen.h"
00032 #include <vcg/space/point3.h>
00033 #include <vcg/space/point4.h>
00034 #include <memory.h>
00035 #include <vector>
00036
00037 namespace vcg{
00038 template<class Scalar> class Matrix44;
00039 }
00040
00041 namespace Eigen{
00042 template<typename Scalar>
00043 struct ei_traits<vcg::Matrix44<Scalar> > : ei_traits<Eigen::Matrix<Scalar,4,4,RowMajor> > {};
00044 template<typename XprType> struct ei_to_vcgtype<XprType,4,4,RowMajor,4,4>
00045 { typedef vcg::Matrix44<typename XprType::Scalar> type; };
00046 }
00047
00048 namespace vcg {
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 template< typename Other,
00088 int OtherRows=Eigen::ei_traits<Other>::RowsAtCompileTime,
00089 int OtherCols=Eigen::ei_traits<Other>::ColsAtCompileTime>
00090 struct ei_matrix44_product_impl;
00091
00096 template<typename _Scalar>
00097 class Matrix44 : public Eigen::Matrix<_Scalar,4,4,Eigen::RowMajor>
00098 {
00099
00100 typedef Eigen::Matrix<_Scalar,4,4,Eigen::RowMajor> _Base;
00101 public:
00102
00103 using _Base::coeff;
00104 using _Base::coeffRef;
00105 using _Base::ElementAt;
00106 using _Base::setZero;
00107
00108 _EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix44,_Base);
00109 typedef _Scalar ScalarType;
00110 VCG_EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Matrix44)
00111
00112 Matrix44() : Base() {}
00113 ~Matrix44() {}
00114 Matrix44(const Matrix44 &m) : Base(m) {}
00115 Matrix44(const Scalar * v ) : Base(Eigen::Map<Eigen::Matrix<Scalar,4,4,Eigen::RowMajor> >(v)) {}
00116 template<typename OtherDerived>
00117 Matrix44(const Eigen::MatrixBase<OtherDerived>& other) : Base(other) {}
00118
00119 const typename Base::RowXpr operator[](int i) const { return Base::row(i); }
00120 typename Base::RowXpr operator[](int i) { return Base::row(i); }
00121
00122 typename Base::ColXpr GetColumn4(const int& i) const { return Base::col(i); }
00123 const Eigen::Block<Base,3,1> GetColumn3(const int& i) const { return this->template block<3,1>(0,i); }
00124
00125 typename Base::RowXpr GetRow4(const int& i) const { return Base::row(i); }
00126 Eigen::Block<Base,1,3> GetRow3(const int& i) const { return this->template block<1,3>(i,0); }
00127
00128 template <class Matrix44Type>
00129 void ToMatrix(Matrix44Type & m) const { m = (*this).template cast<typename Matrix44Type::Scalar>(); }
00130
00131 void ToEulerAngles(Scalar &alpha, Scalar &beta, Scalar &gamma);
00132
00133 template <class Matrix44Type>
00134 void FromMatrix(const Matrix44Type & m) { for(int i = 0; i < 16; i++) Base::data()[i] = m.data()[i]; }
00135
00136 void FromEulerAngles(Scalar alpha, Scalar beta, Scalar gamma);
00137 void SetDiagonal(const Scalar k);
00138 Matrix44 &SetScale(const Scalar sx, const Scalar sy, const Scalar sz);
00139 Matrix44 &SetScale(const Point3<Scalar> &t);
00140 Matrix44 &SetTranslate(const Point3<Scalar> &t);
00141 Matrix44 &SetTranslate(const Scalar sx, const Scalar sy, const Scalar sz);
00142 Matrix44 &SetShearXY(const Scalar sz);
00143 Matrix44 &SetShearXZ(const Scalar sy);
00144 Matrix44 &SetShearYZ(const Scalar sx);
00145
00147 Matrix44 &SetRotateDeg(Scalar AngleDeg, const Point3<Scalar> & axis);
00148 Matrix44 &SetRotateRad(Scalar AngleRad, const Point3<Scalar> & axis);
00149
00157 template<typename OtherDerived>
00158 inline const typename ei_matrix44_product_impl<OtherDerived>::ResultType
00159 operator * (const Eigen::MatrixBase<OtherDerived> &other) const
00160 { return ei_matrix44_product_impl<OtherDerived>::run(*this,other.derived()); }
00161
00162 void print() {std::cout << *this << "\n\n";}
00163
00164 };
00165
00166
00167 template <class T> Matrix44<T> &Invert(Matrix44<T> &m);
00168 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m);
00169
00170 typedef Matrix44<short> Matrix44s;
00171 typedef Matrix44<int> Matrix44i;
00172 typedef Matrix44<float> Matrix44f;
00173 typedef Matrix44<double> Matrix44d;
00174
00175 template < class PointType , class T > void operator*=( std::vector<PointType> &vert, const Matrix44<T> & m ) {
00176 typename std::vector<PointType>::iterator ii;
00177 for(ii=vert.begin();ii!=vert.end();++ii)
00178 (*ii).P()=m * (*ii).P();
00179 }
00180
00181 template <class T>
00182 void Matrix44<T>::ToEulerAngles(Scalar &alpha, Scalar &beta, Scalar &gamma)
00183 {
00184 alpha = atan2(coeff(1,2), coeff(2,2));
00185 beta = asin(-coeff(0,2));
00186 gamma = atan2(coeff(0,1), coeff(1,1));
00187 }
00188
00189 template <class T>
00190 void Matrix44<T>::FromEulerAngles(Scalar alpha, Scalar beta, Scalar gamma)
00191 {
00192 this->SetZero();
00193
00194 T cosalpha = cos(alpha);
00195 T cosbeta = cos(beta);
00196 T cosgamma = cos(gamma);
00197 T sinalpha = sin(alpha);
00198 T sinbeta = sin(beta);
00199 T singamma = sin(gamma);
00200
00201 ElementAt(0,0) = cosbeta * cosgamma;
00202 ElementAt(1,0) = -cosalpha * singamma + sinalpha * sinbeta * cosgamma;
00203 ElementAt(2,0) = sinalpha * singamma + cosalpha * sinbeta * cosgamma;
00204
00205 ElementAt(0,1) = cosbeta * singamma;
00206 ElementAt(1,1) = cosalpha * cosgamma + sinalpha * sinbeta * singamma;
00207 ElementAt(2,1) = -sinalpha * cosgamma + cosalpha * sinbeta * singamma;
00208
00209 ElementAt(0,2) = -sinbeta;
00210 ElementAt(1,2) = sinalpha * cosbeta;
00211 ElementAt(2,2) = cosalpha * cosbeta;
00212
00213 ElementAt(3,3) = 1;
00214 }
00215
00216 template <class T> void Matrix44<T>::SetDiagonal(const Scalar k) {
00217 setZero();
00218 ElementAt(0, 0) = k;
00219 ElementAt(1, 1) = k;
00220 ElementAt(2, 2) = k;
00221 ElementAt(3, 3) = 1;
00222 }
00223
00224 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const Point3<Scalar> &t) {
00225 SetScale(t[0], t[1], t[2]);
00226 return *this;
00227 }
00228 template <class T> Matrix44<T> &Matrix44<T>::SetScale(const Scalar sx, const Scalar sy, const Scalar sz) {
00229 setZero();
00230 ElementAt(0, 0) = sx;
00231 ElementAt(1, 1) = sy;
00232 ElementAt(2, 2) = sz;
00233 ElementAt(3, 3) = 1;
00234 return *this;
00235 }
00236
00237 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const Point3<Scalar> &t) {
00238 SetTranslate(t[0], t[1], t[2]);
00239 return *this;
00240 }
00241 template <class T> Matrix44<T> &Matrix44<T>::SetTranslate(const Scalar tx, const Scalar ty, const Scalar tz) {
00242 Base::setIdentity();
00243 ElementAt(0, 3) = tx;
00244 ElementAt(1, 3) = ty;
00245 ElementAt(2, 3) = tz;
00246 return *this;
00247 }
00248
00249 template <class T> Matrix44<T> &Matrix44<T>::SetRotateDeg(Scalar AngleDeg, const Point3<Scalar> & axis) {
00250 return SetRotateRad(math::ToRad(AngleDeg),axis);
00251 }
00252
00253 template <class T> Matrix44<T> &Matrix44<T>::SetRotateRad(Scalar AngleRad, const Point3<Scalar> & axis) {
00254
00255 T c = math::Cos(AngleRad);
00256 T s = math::Sin(AngleRad);
00257 T q = 1-c;
00258 Point3<T> t = axis;
00259 t.Normalize();
00260 ElementAt(0,0) = t[0]*t[0]*q + c;
00261 ElementAt(0,1) = t[0]*t[1]*q - t[2]*s;
00262 ElementAt(0,2) = t[0]*t[2]*q + t[1]*s;
00263 ElementAt(0,3) = 0;
00264 ElementAt(1,0) = t[1]*t[0]*q + t[2]*s;
00265 ElementAt(1,1) = t[1]*t[1]*q + c;
00266 ElementAt(1,2) = t[1]*t[2]*q - t[0]*s;
00267 ElementAt(1,3) = 0;
00268 ElementAt(2,0) = t[2]*t[0]*q -t[1]*s;
00269 ElementAt(2,1) = t[2]*t[1]*q +t[0]*s;
00270 ElementAt(2,2) = t[2]*t[2]*q +c;
00271 ElementAt(2,3) = 0;
00272 ElementAt(3,0) = 0;
00273 ElementAt(3,1) = 0;
00274 ElementAt(3,2) = 0;
00275 ElementAt(3,3) = 1;
00276 return *this;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 template <class T> Matrix44<T> & Matrix44<T>::SetShearXY( const Scalar sh) {
00299 Base::setIdentity();
00300 ElementAt(0,1) = sh;
00301 return *this;
00302 }
00303
00304 template <class T> Matrix44<T> & Matrix44<T>::SetShearXZ( const Scalar sh) {
00305 Base::setIdentity();
00306 ElementAt(0,2) = sh;
00307 return *this;
00308 }
00309
00310 template <class T> Matrix44<T> &Matrix44<T>::SetShearYZ( const Scalar sh) {
00311 Base::setIdentity();
00312 ElementAt(1,2) = sh;
00313 return *this;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 template <class T>
00367 bool Decompose(Matrix44<T> &M, Point3<T> &ScaleV, Point3<T> &ShearV, Point3<T> &RotV,Point3<T> &TranV)
00368 {
00369 if(!(M(3,0)==0 && M(3,1)==0 && M(3,2)==0 && M(3,3)==1) )
00370 return false;
00371 if(math::Abs(M.Determinant())<1e-10) return false;
00372
00373
00374 TranV=M.GetColumn3(3);
00375
00376
00377 ScaleV[0]=Norm(M.GetColumn3(0));
00378 Point3<T> R[3];
00379 R[0]=M.GetColumn3(0);
00380 R[0].Normalize();
00381
00382 ShearV[0]=R[0].dot(M.GetColumn3(1));
00383 R[1]= M.GetColumn3(1)-R[0]*ShearV[0];
00384 assert(math::Abs(R[1].dot(R[0]))<1e-10);
00385 ScaleV[1]=Norm(R[1]);
00386 R[1]=R[1]/ScaleV[1];
00387 ShearV[0]=ShearV[0]/ScaleV[1];
00388
00389 ShearV[1]=R[0].dot(M.GetColumn3(2));
00390 R[2]= M.GetColumn3(2)-R[0]*ShearV[1];
00391 assert(math::Abs(R[2].dot(R[0]))<1e-10);
00392
00393 R[2] = R[2]-R[1]*(R[2].dot(R[1]));
00394 assert(math::Abs(R[2].dot(R[1]))<1e-10);
00395 assert(math::Abs(R[2].dot(R[0]))<1e-10);
00396
00397 ScaleV[2]=Norm(R[2]);
00398 ShearV[1]=ShearV[1]/ScaleV[2];
00399 R[2]=R[2]/ScaleV[2];
00400 assert(math::Abs(R[2].dot(R[1]))<1e-10);
00401 assert(math::Abs(R[2].dot(R[0]))<1e-10);
00402
00403 ShearV[2]=R[1].dot(M.GetColumn3(2));
00404 ShearV[2]=ShearV[2]/ScaleV[2];
00405 int i,j;
00406 for(i=0;i<3;++i)
00407 for(j=0;j<3;++j)
00408 M(i,j)=R[j][i];
00409
00410
00411
00412 double det=M.Determinant();
00413 if(math::Abs(det)<1e-10) return false;
00414 assert(math::Abs(math::Abs(det)-1.0)<1e-10);
00415 if(det<0) {
00416 ScaleV *= -1;
00417 M *= -1;
00418 }
00419
00420 double alpha,beta,gamma;
00421 beta=asin( M(0,2));
00422 double cosbeta=cos(beta);
00423 if(math::Abs(cosbeta) > 1e-5)
00424 {
00425 alpha=asin(-M(1,2)/cosbeta);
00426 if((M(2,2)/cosbeta) < 0 ) alpha=M_PI-alpha;
00427 gamma=asin(-M(0,1)/cosbeta);
00428 if((M(0,0)/cosbeta)<0) gamma = M_PI-gamma;
00429 }
00430 else
00431 {
00432 alpha=asin(-M(1,0));
00433 if(M(1,1)<0) alpha=M_PI-alpha;
00434 gamma=0;
00435 }
00436
00437 RotV[0]=math::ToDeg(alpha);
00438 RotV[1]=math::ToDeg(beta);
00439 RotV[2]=math::ToDeg(gamma);
00440
00441 return true;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 template <class T> Matrix44<T> & Invert(Matrix44<T> &m) {
00456 return m = m.lu().inverse();
00457 }
00458
00459 template <class T> Matrix44<T> Inverse(const Matrix44<T> &m) {
00460 return m.lu().inverse();
00461 }
00462
00463 template<typename Other,int OtherCols>
00464 struct ei_matrix44_product_impl<Other, 4,OtherCols>
00465 {
00466 typedef typename Other::Scalar Scalar;
00467 typedef typename Eigen::ProductReturnType<typename Matrix44<Scalar>::Base,Other>::Type ResultType;
00468 static ResultType run(const Matrix44<Scalar>& tr, const Other& other)
00469 { return (static_cast<const typename Matrix44<Scalar>::Base&>(tr)) * other; }
00470 };
00471
00472 template<typename Other>
00473 struct ei_matrix44_product_impl<Other, 3,1>
00474 {
00475 typedef typename Other::Scalar Scalar;
00476 typedef Eigen::Matrix<Scalar,3,1> ResultType;
00477 static ResultType run(const Matrix44<Scalar>& tr, const Other& p)
00478 {
00479 Scalar w;
00480 Eigen::Matrix<Scalar,3,1> s;
00481 s[0] = tr.ElementAt(0, 0)*p[0] + tr.ElementAt(0, 1)*p[1] + tr.ElementAt(0, 2)*p[2] + tr.ElementAt(0, 3);
00482 s[1] = tr.ElementAt(1, 0)*p[0] + tr.ElementAt(1, 1)*p[1] + tr.ElementAt(1, 2)*p[2] + tr.ElementAt(1, 3);
00483 s[2] = tr.ElementAt(2, 0)*p[0] + tr.ElementAt(2, 1)*p[1] + tr.ElementAt(2, 2)*p[2] + tr.ElementAt(2, 3);
00484 w = tr.ElementAt(3, 0)*p[0] + tr.ElementAt(3, 1)*p[1] + tr.ElementAt(3, 2)*p[2] + tr.ElementAt(3, 3);
00485 if(w!= 0) s /= w;
00486 return s;
00487 }
00488 };
00489
00490 }
00491 #endif
00492
00493 #endif