2004-02-19 15:42:05 +01:00
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
2016-06-13 07:29:25 +02:00
* Copyright ( C ) 2004 - 2016 \ / ) \ / *
2004-02-19 15:42:05 +01:00
* Visual Computing Lab / \ / | *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved . *
* *
2008-10-27 20:35:17 +01:00
* This program is free software ; you can redistribute it and / or modify *
2004-02-19 15:42:05 +01:00
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License ( http : //www.gnu.org/licenses/gpl.txt) *
* for more details . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-05-07 12:05:50 +02:00
2008-10-27 20:35:17 +01:00
# ifndef VCG_USE_EIGEN
2008-10-27 15:48:14 +01:00
# include "deprecated_matrix44.h"
2008-10-27 20:35:17 +01:00
# else
2004-02-19 15:42:05 +01:00
# ifndef __VCGLIB_MATRIX44
# define __VCGLIB_MATRIX44
2008-10-27 15:48:14 +01:00
# include "eigen.h"
2004-02-19 16:28:01 +01:00
# include <vcg/space/point3.h>
# include <vcg/space/point4.h>
2008-10-27 15:48:14 +01:00
# include <memory.h>
2005-03-15 12:40:56 +01:00
# include <vector>
2004-02-19 15:58:23 +01:00
2008-10-27 15:48:14 +01:00
namespace vcg {
template < class Scalar > class Matrix44 ;
}
namespace Eigen {
template < typename Scalar >
struct ei_traits < vcg : : Matrix44 < Scalar > > : ei_traits < Eigen : : Matrix < Scalar , 4 , 4 , RowMajor > > { } ;
2008-10-29 01:05:44 +01:00
template < typename XprType > struct ei_to_vcgtype < XprType , 4 , 4 , RowMajor , 4 , 4 >
{ typedef vcg : : Matrix44 < typename XprType : : Scalar > type ; } ;
2008-10-27 15:48:14 +01:00
}
2004-02-19 15:58:23 +01:00
namespace vcg {
2008-10-28 21:06:17 +01:00
/*
2004-02-19 15:42:05 +01:00
Annotations :
Opengl stores matrix in column - major order . That is , the matrix is stored as :
a0 a4 a8 a12
a1 a5 a9 a13
a2 a6 a10 a14
a3 a7 a11 a15
2008-10-28 21:06:17 +01:00
Usually in opengl ( see opengl specs ) vectors are ' column ' vectors
so usually matrix are PRE - multiplied for a vector .
So the command glTranslate generate a matrix that
is ready to be premultipled for a vector :
2004-02-19 15:42:05 +01:00
1 0 0 tx
2008-10-28 11:16:43 +01:00
0 1 0 ty
2004-02-19 15:42:05 +01:00
0 0 1 tz
0 0 0 1
Matrix44 stores matrix in row - major order i . e .
a0 a1 a2 a3
a4 a5 a6 a7
a8 a9 a10 a11
a12 a13 a14 a15
2004-05-05 01:19:41 +02:00
So for the use of that matrix in opengl with their supposed meaning you have to transpose them before feeding to glMultMatrix .
2008-10-28 11:16:43 +01:00
This mechanism is hidden by the templated function defined in wrap / gl / math . h ;
2004-05-05 01:19:41 +02:00
If your machine has the ARB_transpose_matrix extension it will use the appropriate ;
The various gl - like command SetRotate , SetTranslate assume that you are making matrix
for ' column ' vectors .
2004-02-19 15:42:05 +01:00
*/
2008-10-29 15:01:44 +01:00
// Note that we have to pass Dim and HDim because it is not allowed to use a template
// parameter to define a template specialization. To be more precise, in the following
// specializations, it is not allowed to use Dim+1 instead of HDim.
template < typename Other ,
int OtherRows = Eigen : : ei_traits < Other > : : RowsAtCompileTime ,
int OtherCols = Eigen : : ei_traits < Other > : : ColsAtCompileTime >
struct ei_matrix44_product_impl ;
2005-06-28 19:42:47 +02:00
2008-10-28 21:06:17 +01:00
/** \deprecated use Eigen::Matrix<Scalar,4,4> (or the typedef) you want a real 4x4 matrix, or use Eigen::Transform<Scalar,3> if you want a transformation matrix for a 3D space (a Eigen::Transform<Scalar,3> is internally a 4x4 col-major matrix)
*
* This class represents a 4 x4 matrix . T is the kind of element in the matrix .
*/
2008-10-27 15:48:14 +01:00
template < typename _Scalar >
2008-10-27 20:35:17 +01:00
class Matrix44 : public Eigen : : Matrix < _Scalar , 4 , 4 , Eigen : : RowMajor > // FIXME col or row major !
2008-10-27 15:48:14 +01:00
{
2005-06-28 19:42:47 +02:00
2008-10-27 20:35:17 +01:00
typedef Eigen : : Matrix < _Scalar , 4 , 4 , Eigen : : RowMajor > _Base ;
2008-10-29 12:29:57 +01:00
public :
2008-10-27 20:35:17 +01:00
using _Base : : coeff ;
using _Base : : coeffRef ;
using _Base : : ElementAt ;
using _Base : : setZero ;
2008-10-27 15:48:14 +01:00
2008-10-27 20:35:17 +01:00
_EIGEN_GENERIC_PUBLIC_INTERFACE ( Matrix44 , _Base ) ;
2008-10-27 15:48:14 +01:00
typedef _Scalar ScalarType ;
2008-10-27 20:35:17 +01:00
VCG_EIGEN_INHERIT_ASSIGNMENT_OPERATORS ( Matrix44 )
2004-02-19 15:58:23 +01:00
2008-10-27 15:48:14 +01:00
Matrix44 ( ) : Base ( ) { }
~ Matrix44 ( ) { }
Matrix44 ( const Matrix44 & m ) : Base ( m ) { }
2008-10-27 20:35:17 +01:00
Matrix44 ( const Scalar * v ) : Base ( Eigen : : Map < Eigen : : Matrix < Scalar , 4 , 4 , Eigen : : RowMajor > > ( v ) ) { }
template < typename OtherDerived >
Matrix44 ( const Eigen : : MatrixBase < OtherDerived > & other ) : Base ( other ) { }
const typename Base : : RowXpr operator [ ] ( int i ) const { return Base : : row ( i ) ; }
typename Base : : RowXpr operator [ ] ( int i ) { return Base : : row ( i ) ; }
2004-02-19 15:42:05 +01:00
2008-10-27 20:35:17 +01:00
typename Base : : ColXpr GetColumn4 ( const int & i ) const { return Base : : col ( i ) ; }
const Eigen : : Block < Base , 3 , 1 > GetColumn3 ( const int & i ) const { return this - > template block < 3 , 1 > ( 0 , i ) ; }
2008-10-27 15:48:14 +01:00
2008-10-27 20:35:17 +01:00
typename Base : : RowXpr GetRow4 ( const int & i ) const { return Base : : row ( i ) ; }
Eigen : : Block < Base , 1 , 3 > GetRow3 ( const int & i ) const { return this - > template block < 1 , 3 > ( i , 0 ) ; }
2008-10-28 11:16:43 +01:00
2008-10-28 21:06:17 +01:00
template < class Matrix44Type >
2008-10-27 20:35:17 +01:00
void ToMatrix ( Matrix44Type & m ) const { m = ( * this ) . template cast < typename Matrix44Type : : Scalar > ( ) ; }
2007-07-03 18:06:48 +02:00
2008-10-27 15:48:14 +01:00
void ToEulerAngles ( Scalar & alpha , Scalar & beta , Scalar & gamma ) ;
2007-07-03 18:06:48 +02:00
2004-12-15 19:45:50 +01:00
template < class Matrix44Type >
2008-10-27 20:35:17 +01:00
void FromMatrix ( const Matrix44Type & m ) { for ( int i = 0 ; i < 16 ; i + + ) Base : : data ( ) [ i ] = m . data ( ) [ i ] ; }
2008-10-28 11:16:43 +01:00
2008-10-27 20:35:17 +01:00
void FromEulerAngles ( Scalar alpha , Scalar beta , Scalar gamma ) ;
2008-10-28 21:06:17 +01:00
void SetDiagonal ( const Scalar k ) ;
2008-10-27 20:35:17 +01:00
Matrix44 & SetScale ( const Scalar sx , const Scalar sy , const Scalar sz ) ;
Matrix44 & SetScale ( const Point3 < Scalar > & t ) ;
2008-10-28 21:06:17 +01:00
Matrix44 & SetTranslate ( const Point3 < Scalar > & t ) ;
2008-10-27 20:35:17 +01:00
Matrix44 & SetTranslate ( const Scalar sx , const Scalar sy , const Scalar sz ) ;
2008-10-28 21:06:17 +01:00
Matrix44 & SetShearXY ( const Scalar sz ) ;
Matrix44 & SetShearXZ ( const Scalar sy ) ;
Matrix44 & SetShearYZ ( const Scalar sx ) ;
///use radiants for angle.
Matrix44 & SetRotateDeg ( Scalar AngleDeg , const Point3 < Scalar > & axis ) ;
Matrix44 & SetRotateRad ( Scalar AngleRad , const Point3 < Scalar > & axis ) ;
2008-10-29 15:01:44 +01:00
/** taken from Eigen::Transform
* \ returns the product between the transform \ c * this and a matrix expression \ a other
2008-10-29 16:52:07 +01:00
*
* The right hand side \ a other might be either :
* \ li a matrix expression with 4 rows
* \ li a 3 D vector / point
*/
template < typename OtherDerived >
inline const typename ei_matrix44_product_impl < OtherDerived > : : ResultType
operator * ( const Eigen : : MatrixBase < OtherDerived > & other ) const
{ return ei_matrix44_product_impl < OtherDerived > : : run ( * this , other . derived ( ) ) ; }
2007-07-12 08:42:01 +02:00
2008-10-29 01:05:44 +01:00
void print ( ) { std : : cout < < * this < < " \n \n " ; }
2004-02-19 15:42:05 +01:00
} ;
2004-03-08 16:33:58 +01:00
//return NULL matrix if not invertible
2008-10-28 11:16:43 +01:00
template < class T > Matrix44 < T > & Invert ( Matrix44 < T > & m ) ;
template < class T > Matrix44 < T > Inverse ( const Matrix44 < T > & m ) ;
2004-02-19 15:42:05 +01:00
typedef Matrix44 < short > Matrix44s ;
2004-03-09 14:57:29 +01:00
typedef Matrix44 < int > Matrix44i ;
2004-02-19 15:42:05 +01:00
typedef Matrix44 < float > Matrix44f ;
typedef Matrix44 < double > Matrix44d ;
2005-03-15 12:40:56 +01:00
template < class PointType , class T > void operator * = ( std : : vector < PointType > & vert , const Matrix44 < T > & m ) {
2008-10-28 21:06:17 +01:00
typename std : : vector < PointType > : : iterator ii ;
for ( ii = vert . begin ( ) ; ii ! = vert . end ( ) ; + + ii )
( * ii ) . P ( ) = m * ( * ii ) . P ( ) ;
2005-03-15 12:40:56 +01:00
}
2007-07-03 18:06:48 +02:00
template < class T >
2008-10-27 20:35:17 +01:00
void Matrix44 < T > : : ToEulerAngles ( Scalar & alpha , Scalar & beta , Scalar & gamma )
2007-07-03 18:06:48 +02:00
{
2008-10-27 20:35:17 +01:00
alpha = atan2 ( coeff ( 1 , 2 ) , coeff ( 2 , 2 ) ) ;
beta = asin ( - coeff ( 0 , 2 ) ) ;
gamma = atan2 ( coeff ( 0 , 1 ) , coeff ( 1 , 1 ) ) ;
2007-07-03 18:06:48 +02:00
}
2008-10-28 11:16:43 +01:00
template < class T >
2008-10-27 20:35:17 +01:00
void Matrix44 < T > : : FromEulerAngles ( Scalar alpha , Scalar beta , Scalar gamma )
2007-02-05 15:16:33 +01:00
{
this - > SetZero ( ) ;
T cosalpha = cos ( alpha ) ;
T cosbeta = cos ( beta ) ;
T cosgamma = cos ( gamma ) ;
T sinalpha = sin ( alpha ) ;
T sinbeta = sin ( beta ) ;
T singamma = sin ( gamma ) ;
2008-10-28 11:16:43 +01:00
ElementAt ( 0 , 0 ) = cosbeta * cosgamma ;
ElementAt ( 1 , 0 ) = - cosalpha * singamma + sinalpha * sinbeta * cosgamma ;
2007-03-08 15:39:27 +01:00
ElementAt ( 2 , 0 ) = sinalpha * singamma + cosalpha * sinbeta * cosgamma ;
2008-10-28 11:16:43 +01:00
2007-03-08 15:39:27 +01:00
ElementAt ( 0 , 1 ) = cosbeta * singamma ;
2008-10-28 11:16:43 +01:00
ElementAt ( 1 , 1 ) = cosalpha * cosgamma + sinalpha * sinbeta * singamma ;
2007-03-08 15:39:27 +01:00
ElementAt ( 2 , 1 ) = - sinalpha * cosgamma + cosalpha * sinbeta * singamma ;
2008-10-28 11:16:43 +01:00
ElementAt ( 0 , 2 ) = - sinbeta ;
ElementAt ( 1 , 2 ) = sinalpha * cosbeta ;
2007-02-05 15:16:33 +01:00
ElementAt ( 2 , 2 ) = cosalpha * cosbeta ;
2008-10-28 11:16:43 +01:00
2007-02-05 15:16:33 +01:00
ElementAt ( 3 , 3 ) = 1 ;
}
2004-02-19 15:42:05 +01:00
2008-10-27 20:35:17 +01:00
template < class T > void Matrix44 < T > : : SetDiagonal ( const Scalar k ) {
2008-10-28 21:06:17 +01:00
setZero ( ) ;
ElementAt ( 0 , 0 ) = k ;
ElementAt ( 1 , 1 ) = k ;
ElementAt ( 2 , 2 ) = k ;
ElementAt ( 3 , 3 ) = 1 ;
2004-02-19 15:42:05 +01:00
}
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetScale ( const Point3 < Scalar > & t ) {
2008-10-28 21:06:17 +01:00
SetScale ( t [ 0 ] , t [ 1 ] , t [ 2 ] ) ;
return * this ;
2005-06-10 17:04:12 +02:00
}
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetScale ( const Scalar sx , const Scalar sy , const Scalar sz ) {
2008-10-28 21:06:17 +01:00
setZero ( ) ;
ElementAt ( 0 , 0 ) = sx ;
ElementAt ( 1 , 1 ) = sy ;
ElementAt ( 2 , 2 ) = sz ;
ElementAt ( 3 , 3 ) = 1 ;
return * this ;
2004-02-19 15:42:05 +01:00
}
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetTranslate ( const Point3 < Scalar > & t ) {
2008-10-28 21:06:17 +01:00
SetTranslate ( t [ 0 ] , t [ 1 ] , t [ 2 ] ) ;
return * this ;
2004-02-19 15:42:05 +01:00
}
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetTranslate ( const Scalar tx , const Scalar ty , const Scalar tz ) {
2008-10-28 21:06:17 +01:00
Base : : setIdentity ( ) ;
2007-02-05 15:16:33 +01:00
ElementAt ( 0 , 3 ) = tx ;
2008-10-28 21:06:17 +01:00
ElementAt ( 1 , 3 ) = ty ;
ElementAt ( 2 , 3 ) = tz ;
return * this ;
2004-02-19 15:42:05 +01:00
}
2008-07-13 07:37:00 +02:00
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetRotateDeg ( Scalar AngleDeg , const Point3 < Scalar > & axis ) {
2008-07-13 07:37:00 +02:00
return SetRotateRad ( math : : ToRad ( AngleDeg ) , axis ) ;
}
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetRotateRad ( Scalar AngleRad , const Point3 < Scalar > & axis ) {
2008-10-28 21:06:17 +01:00
//angle = angle*(T)3.14159265358979323846/180; e' in radianti!
T c = math : : Cos ( AngleRad ) ;
T s = math : : Sin ( AngleRad ) ;
2008-10-28 11:16:43 +01:00
T q = 1 - c ;
2004-02-19 15:42:05 +01:00
Point3 < T > t = axis ;
t . Normalize ( ) ;
2004-10-18 17:03:14 +02:00
ElementAt ( 0 , 0 ) = t [ 0 ] * t [ 0 ] * q + c ;
ElementAt ( 0 , 1 ) = t [ 0 ] * t [ 1 ] * q - t [ 2 ] * s ;
ElementAt ( 0 , 2 ) = t [ 0 ] * t [ 2 ] * q + t [ 1 ] * s ;
ElementAt ( 0 , 3 ) = 0 ;
ElementAt ( 1 , 0 ) = t [ 1 ] * t [ 0 ] * q + t [ 2 ] * s ;
ElementAt ( 1 , 1 ) = t [ 1 ] * t [ 1 ] * q + c ;
ElementAt ( 1 , 2 ) = t [ 1 ] * t [ 2 ] * q - t [ 0 ] * s ;
ElementAt ( 1 , 3 ) = 0 ;
ElementAt ( 2 , 0 ) = t [ 2 ] * t [ 0 ] * q - t [ 1 ] * s ;
ElementAt ( 2 , 1 ) = t [ 2 ] * t [ 1 ] * q + t [ 0 ] * s ;
ElementAt ( 2 , 2 ) = t [ 2 ] * t [ 2 ] * q + c ;
ElementAt ( 2 , 3 ) = 0 ;
ElementAt ( 3 , 0 ) = 0 ;
2008-10-27 20:35:17 +01:00
ElementAt ( 3 , 1 ) = 0 ;
2004-10-18 17:03:14 +02:00
ElementAt ( 3 , 2 ) = 0 ;
2008-10-27 20:35:17 +01:00
ElementAt ( 3 , 3 ) = 1 ;
2008-10-28 21:06:17 +01:00
return * this ;
2004-02-19 15:42:05 +01:00
}
2008-10-28 21:06:17 +01:00
/* Shear Matrixes
XY
1 k 0 0 x x + ky
0 1 0 0 y y
0 0 1 0 z z
0 0 0 1 1 1
2005-06-17 07:28:47 +02:00
2008-10-28 21:06:17 +01:00
1 0 k 0 x x + kz
0 1 0 0 y y
0 0 1 0 z z
0 0 0 1 1 1
2005-06-17 07:28:47 +02:00
2008-10-28 21:06:17 +01:00
1 1 0 0 x x
0 1 k 0 y y + kz
0 0 1 0 z z
0 0 0 1 1 1
2005-06-17 07:28:47 +02:00
2008-10-28 21:06:17 +01:00
*/
2005-06-17 07:28:47 +02:00
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetShearXY ( const Scalar sh ) { // shear the X coordinate as the Y coordinate change
Base : : setIdentity ( ) ;
2005-06-17 07:28:47 +02:00
ElementAt ( 0 , 1 ) = sh ;
2008-10-28 21:06:17 +01:00
return * this ;
2005-06-10 17:04:12 +02:00
}
2008-10-28 11:16:43 +01:00
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetShearXZ ( const Scalar sh ) { // shear the X coordinate as the Z coordinate change
Base : : setIdentity ( ) ;
2005-06-17 07:28:47 +02:00
ElementAt ( 0 , 2 ) = sh ;
2008-10-28 21:06:17 +01:00
return * this ;
2005-06-10 17:04:12 +02:00
}
2008-10-28 11:16:43 +01:00
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Matrix44 < T > : : SetShearYZ ( const Scalar sh ) { // shear the Y coordinate as the Z coordinate change
Base : : setIdentity ( ) ;
2005-06-17 07:28:47 +02:00
ElementAt ( 1 , 2 ) = sh ;
2008-10-28 21:06:17 +01:00
return * this ;
2005-06-10 17:04:12 +02:00
}
/*
2005-06-17 07:28:47 +02:00
Given a non singular , non projective matrix ( e . g . with the last row equal to [ 0 , 0 , 0 , 1 ] )
2008-10-28 11:16:43 +01:00
This procedure decompose it in a sequence of
2008-10-28 21:06:17 +01:00
Scale , Shear , Rotation e Translation
2005-06-10 17:04:12 +02:00
2005-06-17 07:28:47 +02:00
- ScaleV and Tranv are obiviously scaling and translation .
- ShearV contains three scalars with , respectively
2008-10-28 21:06:17 +01:00
ShearXY , ShearXZ e ShearYZ
2005-06-17 07:28:47 +02:00
- RotateV contains the rotations ( in degree ! ) around the x , y , z axis
2008-10-28 21:06:17 +01:00
The input matrix is modified leaving inside it a simple roto translation .
2005-06-10 17:04:12 +02:00
2008-10-28 21:06:17 +01:00
To obtain the original matrix the above transformation have to be applied in the strict following way :
2008-10-28 11:16:43 +01:00
2008-10-28 21:06:17 +01:00
OriginalMatrix = Trn * Rtx * Rty * Rtz * ShearYZ * ShearXZ * ShearXY * Scl
2005-06-17 07:28:47 +02:00
Example Code :
double srv ( ) { return ( double ( rand ( ) % 40 ) - 20 ) / 2.0 ; } // small random value
2008-10-28 21:06:17 +01:00
srand ( time ( 0 ) ) ;
Point3d ScV ( 10 + srv ( ) , 10 + srv ( ) , 10 + srv ( ) ) , ScVOut ( - 1 , - 1 , - 1 ) ;
Point3d ShV ( srv ( ) , srv ( ) , srv ( ) ) , ShVOut ( - 1 , - 1 , - 1 ) ;
Point3d RtV ( 10 + srv ( ) , srv ( ) , srv ( ) ) , RtVOut ( - 1 , - 1 , - 1 ) ;
Point3d TrV ( srv ( ) , srv ( ) , srv ( ) ) , TrVOut ( - 1 , - 1 , - 1 ) ;
2005-06-17 07:28:47 +02:00
2008-10-28 21:06:17 +01:00
Matrix44d Scl ; Scl . SetScale ( ScV ) ;
Matrix44d Sxy ; Sxy . SetShearXY ( ShV [ 0 ] ) ;
2005-06-17 07:28:47 +02:00
Matrix44d Sxz ; Sxz . SetShearXZ ( ShV [ 1 ] ) ;
Matrix44d Syz ; Syz . SetShearYZ ( ShV [ 2 ] ) ;
2008-10-28 21:06:17 +01:00
Matrix44d Rtx ; Rtx . SetRotate ( math : : ToRad ( RtV [ 0 ] ) , Point3d ( 1 , 0 , 0 ) ) ;
2005-06-17 07:28:47 +02:00
Matrix44d Rty ; Rty . SetRotate ( math : : ToRad ( RtV [ 1 ] ) , Point3d ( 0 , 1 , 0 ) ) ;
Matrix44d Rtz ; Rtz . SetRotate ( math : : ToRad ( RtV [ 2 ] ) , Point3d ( 0 , 0 , 1 ) ) ;
Matrix44d Trn ; Trn . SetTranslate ( TrV ) ;
2008-10-28 11:16:43 +01:00
2005-06-17 07:28:47 +02:00
Matrix44d StartM = Trn * Rtx * Rty * Rtz * Syz * Sxz * Sxy * Scl ;
2008-10-28 21:06:17 +01:00
Matrix44d ResultM = StartM ;
Decompose ( ResultM , ScVOut , ShVOut , RtVOut , TrVOut ) ;
Scl . SetScale ( ScVOut ) ;
Sxy . SetShearXY ( ShVOut [ 0 ] ) ;
Sxz . SetShearXZ ( ShVOut [ 1 ] ) ;
Syz . SetShearYZ ( ShVOut [ 2 ] ) ;
Rtx . SetRotate ( math : : ToRad ( RtVOut [ 0 ] ) , Point3d ( 1 , 0 , 0 ) ) ;
Rty . SetRotate ( math : : ToRad ( RtVOut [ 1 ] ) , Point3d ( 0 , 1 , 0 ) ) ;
Rtz . SetRotate ( math : : ToRad ( RtVOut [ 2 ] ) , Point3d ( 0 , 0 , 1 ) ) ;
Trn . SetTranslate ( TrVOut ) ;
// Now Rebuild is equal to StartM
2008-10-28 11:16:43 +01:00
Matrix44d RebuildM = Trn * Rtx * Rty * Rtz * Syz * Sxz * Sxy * Scl ;
2005-06-10 17:04:12 +02:00
*/
template < class T >
2008-10-28 11:16:43 +01:00
bool Decompose ( Matrix44 < T > & M , Point3 < T > & ScaleV , Point3 < T > & ShearV , Point3 < T > & RotV , Point3 < T > & TranV )
2005-06-10 17:04:12 +02:00
{
2008-10-28 11:16:43 +01:00
if ( ! ( M ( 3 , 0 ) = = 0 & & M ( 3 , 1 ) = = 0 & & M ( 3 , 2 ) = = 0 & & M ( 3 , 3 ) = = 1 ) ) // the matrix is projective
2005-06-10 17:04:12 +02:00
return false ;
if ( math : : Abs ( M . Determinant ( ) ) < 1e-10 ) return false ; // matrix should be at least invertible...
2008-10-28 21:06:17 +01:00
// First Step recover the traslation
2005-06-10 17:04:12 +02:00
TranV = M . GetColumn3 ( 3 ) ;
2008-10-28 11:16:43 +01:00
// Second Step Recover Scale and Shearing interleaved
2005-06-10 17:04:12 +02:00
ScaleV [ 0 ] = Norm ( M . GetColumn3 ( 0 ) ) ;
2008-09-22 15:49:15 +02:00
Point3 < T > R [ 3 ] ;
2005-06-10 17:04:12 +02:00
R [ 0 ] = M . GetColumn3 ( 0 ) ;
R [ 0 ] . Normalize ( ) ;
2008-10-28 11:16:43 +01:00
2008-10-27 20:35:17 +01:00
ShearV [ 0 ] = R [ 0 ] . dot ( M . GetColumn3 ( 1 ) ) ; // xy shearing
2005-06-10 17:04:12 +02:00
R [ 1 ] = M . GetColumn3 ( 1 ) - R [ 0 ] * ShearV [ 0 ] ;
2008-10-28 21:06:17 +01:00
assert ( math : : Abs ( R [ 1 ] . dot ( R [ 0 ] ) ) < 1e-10 ) ;
2008-10-28 11:16:43 +01:00
ScaleV [ 1 ] = Norm ( R [ 1 ] ) ; // y scaling
2005-06-10 17:04:12 +02:00
R [ 1 ] = R [ 1 ] / ScaleV [ 1 ] ;
2008-10-28 11:16:43 +01:00
ShearV [ 0 ] = ShearV [ 0 ] / ScaleV [ 1 ] ;
2005-06-10 17:04:12 +02:00
2008-10-27 20:35:17 +01:00
ShearV [ 1 ] = R [ 0 ] . dot ( M . GetColumn3 ( 2 ) ) ; // xz shearing
2005-06-10 17:04:12 +02:00
R [ 2 ] = M . GetColumn3 ( 2 ) - R [ 0 ] * ShearV [ 1 ] ;
2008-10-27 20:35:17 +01:00
assert ( math : : Abs ( R [ 2 ] . dot ( R [ 0 ] ) ) < 1e-10 ) ;
2008-10-28 11:16:43 +01:00
2008-10-27 20:35:17 +01:00
R [ 2 ] = R [ 2 ] - R [ 1 ] * ( R [ 2 ] . dot ( R [ 1 ] ) ) ;
assert ( math : : Abs ( R [ 2 ] . dot ( R [ 1 ] ) ) < 1e-10 ) ;
assert ( math : : Abs ( R [ 2 ] . dot ( R [ 0 ] ) ) < 1e-10 ) ;
2008-10-28 11:16:43 +01:00
2005-06-10 17:04:12 +02:00
ScaleV [ 2 ] = Norm ( R [ 2 ] ) ;
2008-10-28 11:16:43 +01:00
ShearV [ 1 ] = ShearV [ 1 ] / ScaleV [ 2 ] ;
2005-06-10 17:04:12 +02:00
R [ 2 ] = R [ 2 ] / ScaleV [ 2 ] ;
2008-10-27 20:35:17 +01:00
assert ( math : : Abs ( R [ 2 ] . dot ( R [ 1 ] ) ) < 1e-10 ) ;
assert ( math : : Abs ( R [ 2 ] . dot ( R [ 0 ] ) ) < 1e-10 ) ;
2008-10-28 11:16:43 +01:00
2008-10-27 20:35:17 +01:00
ShearV [ 2 ] = R [ 1 ] . dot ( M . GetColumn3 ( 2 ) ) ; // yz shearing
2005-06-10 17:04:12 +02:00
ShearV [ 2 ] = ShearV [ 2 ] / ScaleV [ 2 ] ;
2008-10-28 21:06:17 +01:00
int i , j ;
2005-06-10 17:04:12 +02:00
for ( i = 0 ; i < 3 ; + + i )
for ( j = 0 ; j < 3 ; + + j )
2008-10-28 11:16:43 +01:00
M ( i , j ) = R [ j ] [ i ] ;
2005-06-10 17:04:12 +02:00
// Third and last step: Recover the rotation
2008-10-28 11:16:43 +01:00
//now the matrix should be a pure rotation matrix so its determinant is +-1
2008-10-28 21:06:17 +01:00
double det = M . Determinant ( ) ;
if ( math : : Abs ( det ) < 1e-10 ) return false ; // matrix should be at least invertible...
assert ( math : : Abs ( math : : Abs ( det ) - 1.0 ) < 1e-10 ) ; // it should be +-1...
2008-10-28 11:16:43 +01:00
if ( det < 0 ) {
2005-06-10 17:04:12 +02:00
ScaleV * = - 1 ;
M * = - 1 ;
2008-10-28 11:16:43 +01:00
}
2005-06-10 17:04:12 +02:00
double alpha , beta , gamma ; // rotations around the x,y and z axis
2008-10-28 11:16:43 +01:00
beta = asin ( M ( 0 , 2 ) ) ;
2005-06-10 17:04:12 +02:00
double cosbeta = cos ( beta ) ;
2008-10-28 21:06:17 +01:00
if ( math : : Abs ( cosbeta ) > 1e-5 )
2008-10-28 11:16:43 +01:00
{
alpha = asin ( - M ( 1 , 2 ) / cosbeta ) ;
if ( ( M ( 2 , 2 ) / cosbeta ) < 0 ) alpha = M_PI - alpha ;
gamma = asin ( - M ( 0 , 1 ) / cosbeta ) ;
if ( ( M ( 0 , 0 ) / cosbeta ) < 0 ) gamma = M_PI - gamma ;
2005-06-10 17:04:12 +02:00
}
2008-10-28 21:06:17 +01:00
else
2008-10-28 11:16:43 +01:00
{
alpha = asin ( - M ( 1 , 0 ) ) ;
if ( M ( 1 , 1 ) < 0 ) alpha = M_PI - alpha ;
2005-06-10 17:04:12 +02:00
gamma = 0 ;
}
2008-10-28 21:06:17 +01:00
RotV [ 0 ] = math : : ToDeg ( alpha ) ;
2005-06-10 17:04:12 +02:00
RotV [ 1 ] = math : : ToDeg ( beta ) ;
RotV [ 2 ] = math : : ToDeg ( gamma ) ;
return true ;
}
2008-08-11 10:04:19 +02:00
/*
2008-10-28 21:06:17 +01:00
To invert a matrix you can
either invert the matrix inplace calling
2008-10-28 11:16:43 +01:00
2008-10-28 21:06:17 +01:00
vcg : : Invert ( yourMatrix ) ;
2008-10-28 11:16:43 +01:00
2008-10-28 21:06:17 +01:00
or get the inverse matrix of a given matrix without touching it :
2008-08-11 10:04:19 +02:00
2008-10-28 21:06:17 +01:00
invertedMatrix = vcg : : Inverse ( untouchedMatrix ) ;
2008-10-28 11:16:43 +01:00
2008-08-11 10:04:19 +02:00
*/
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > & Invert ( Matrix44 < T > & m ) {
return m = m . lu ( ) . inverse ( ) ;
2004-03-09 14:57:29 +01:00
}
2008-10-27 20:35:17 +01:00
template < class T > Matrix44 < T > Inverse ( const Matrix44 < T > & m ) {
return m . lu ( ) . inverse ( ) ;
2004-02-19 15:42:05 +01:00
}
2008-10-29 15:01:44 +01:00
template < typename Other , int OtherCols >
struct ei_matrix44_product_impl < Other , 4 , OtherCols >
{
2008-10-29 16:52:07 +01:00
typedef typename Other : : Scalar Scalar ;
2008-10-30 11:47:08 +01:00
typedef typename Eigen : : ProductReturnType < typename Matrix44 < Scalar > : : Base , Other > : : Type ResultType ;
2008-10-29 16:52:07 +01:00
static ResultType run ( const Matrix44 < Scalar > & tr , const Other & other )
2008-10-30 11:47:08 +01:00
{ return ( static_cast < const typename Matrix44 < Scalar > : : Base & > ( tr ) ) * other ; }
2008-10-29 15:01:44 +01:00
} ;
template < typename Other >
struct ei_matrix44_product_impl < Other , 3 , 1 >
{
2008-10-29 16:52:07 +01:00
typedef typename Other : : Scalar Scalar ;
typedef Eigen : : Matrix < Scalar , 3 , 1 > ResultType ;
static ResultType run ( const Matrix44 < Scalar > & tr , const Other & p )
{
Scalar w ;
2008-10-29 15:01:44 +01:00
Eigen : : Matrix < Scalar , 3 , 1 > s ;
s [ 0 ] = tr . ElementAt ( 0 , 0 ) * p [ 0 ] + tr . ElementAt ( 0 , 1 ) * p [ 1 ] + tr . ElementAt ( 0 , 2 ) * p [ 2 ] + tr . ElementAt ( 0 , 3 ) ;
s [ 1 ] = tr . ElementAt ( 1 , 0 ) * p [ 0 ] + tr . ElementAt ( 1 , 1 ) * p [ 1 ] + tr . ElementAt ( 1 , 2 ) * p [ 2 ] + tr . ElementAt ( 1 , 3 ) ;
s [ 2 ] = tr . ElementAt ( 2 , 0 ) * p [ 0 ] + tr . ElementAt ( 2 , 1 ) * p [ 1 ] + tr . ElementAt ( 2 , 2 ) * p [ 2 ] + tr . ElementAt ( 2 , 3 ) ;
2008-10-29 16:52:07 +01:00
w = tr . ElementAt ( 3 , 0 ) * p [ 0 ] + tr . ElementAt ( 3 , 1 ) * p [ 1 ] + tr . ElementAt ( 3 , 2 ) * p [ 2 ] + tr . ElementAt ( 3 , 3 ) ;
2008-10-29 15:01:44 +01:00
if ( w ! = 0 ) s / = w ;
return s ;
2008-10-29 16:52:07 +01:00
}
2008-10-29 15:01:44 +01:00
} ;
2004-02-19 15:42:05 +01:00
} //namespace
# endif
2008-10-27 20:35:17 +01:00
# endif