Added Various missing functions: SetShearXY, SetShearXZ, SetShearYZ, SetScale for point3 and Decompose

Completed *=(scalar); made uniform GetRow and GetColumn
This commit is contained in:
Paolo Cignoni 2005-06-10 15:04:12 +00:00
parent c379550e2e
commit fe5d343fd0
1 changed files with 163 additions and 36 deletions

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
Revision 1.25 2005/04/14 11:35:09 ponchio
*** empty log message ***
Revision 1.24 2005/03/18 00:14:39 cignoni
removed small gcc compiling issues
@ -123,7 +126,7 @@ public:
///@{
/** $name Contrutors
/** $name Constructors
* No automatic casting and default constructor is empty
*/
Matrix44() {};
@ -154,43 +157,29 @@ public:
const T *operator[](const int i) const;
// return a copy of the i-th column
Point4<T> GetColumn(const int& i)const{
assert(i >=0);
assert(i<4);
int first = i<<2;
return Point4<T>(_a[first],_a[first+1],_a[first+2],_a[first+3]);
Point4<T> GetColumn4(const int& i)const{
assert(i>=0 && i<4);
return Point4<T>(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i),ElementAt(3,i));
//return Point4<T>(_a[i],_a[i+4],_a[i+8],_a[i+12]);
}
// return the i-th row
Point4<T> & GetColumn4(const int& i)const{
assert(i >=0);
assert(i<4);
int first = i<<2;
return Point4<T>(_a[first],_a[first+4],_a[first+8],_a[first+12]);
Point3<T> GetColumn3(const int& i)const{
assert(i>=0 && i<4);
return Point3<T>(ElementAt(0,i),ElementAt(1,i),ElementAt(2,i));
}
// return a copy of the i-th row
Point4<T> Row4(const int& i)const{
assert(i >=0);
assert(i<4);
return *((Point4<T>*)(&_a[i<<2]));
Point4<T> GetRow4(const int& i)const{
assert(i>=0 && i<4);
return Point4<T>(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2),ElementAt(i,3));
// return *((Point4<T>*)(&_a[i<<2])); alternativa forse + efficiente
}
Point3<T> GetColumn3(const int& i)const{
assert(i >=0);
assert(i<4);
int first = i <<2;
return Point3<T>(_a[first],_a[first+4],_a[first+8]);
}
// return a copy of the i-th row
Point3<T> Row3(const int& i)const{
assert(i >=0);
assert(i<4);
return *((Point3<T>*)(&_a[i<<2]));
Point3<T> GetRow3(const int& i)const{
assert(i>=0 && i<4);
return Point3<T>(ElementAt(i,0),ElementAt(i,1),ElementAt(i,2));
// return *((Point4<T>*)(&_a[i<<2])); alternativa forse + efficiente
}
Matrix44 operator+(const Matrix44 &m) const;
Matrix44 operator-(const Matrix44 &m) const;
Matrix44 operator*(const Matrix44 &m) const;
@ -213,9 +202,14 @@ public:
void SetZero();
void SetIdentity();
void SetDiagonal(const T k);
Matrix44 &SetScale(const T sx, const T sy, const T sz);
Matrix44 &SetTranslate(const Point3<T> &t);
Matrix44 &SetScale(const T sx, const T sy, const T sz);
Matrix44 &SetScale(const Point3<T> &t);
Matrix44 &SetTranslate(const Point3<T> &t);
Matrix44 &SetTranslate(const T sx, const T sy, const T sz);
Matrix44 &SetShearXY(const T sz);
Matrix44 &SetShearXZ(const T sy);
Matrix44 &SetShearYZ(const T sx);
///use radiants for angle.
Matrix44 &SetRotate(T AngleRad, const Point3<T> & axis);
@ -289,7 +283,7 @@ template <class T> T Matrix44<T>::ElementAt(const int row, const int col) const
//template <class T> const T &Matrix44<T>::operator[](const int i) const {
// assert(i >= 0 && i < 16);
// return ((T *)_a)[i];
//}
//}
template <class T> T *Matrix44<T>::operator[](const int i) {
assert(i >= 0 && i < 16);
return _a+i*4;
@ -398,8 +392,8 @@ template < class PointType , class T > void operator*=( std::vector<PointType> &
}
template <class T> void Matrix44<T>::operator*=( const T k ) {
for(int i = 0; i < 4; i++)
operator[](i) *= k;
for(int i = 0; i < 16; i++)
_a[i] *= k;
}
@ -419,6 +413,10 @@ template <class T> void Matrix44<T>::SetDiagonal(const T k) {
ElementAt(3, 3) = 1;
}
template <class T> Matrix44<T> &Matrix44<T>::SetScale(const Point3<T> &t) {
SetScale(t[0], t[1], t[2]);
return *this;
}
template <class T> Matrix44<T> &Matrix44<T>::SetScale(const T sx, const T sy, const T sz) {
SetZero();
ElementAt(0, 0) = sx;
@ -465,6 +463,135 @@ template <class T> Matrix44<T> &Matrix44<T>::SetRotate(T AngleRad, const Point3<
return *this;
}
template <class T> Matrix44<T> & Matrix44<T>:: SetShearXY( const T sh) {// shear the X coordinate as the Y coordinate change
SetIdentity();
ElementAt(1,0) = sh;
return *this;
}
template <class T> Matrix44<T> & Matrix44<T>:: SetShearXZ( const T sh) {// shear the X coordinate as the Z coordinate change
SetIdentity();
ElementAt(2,0) = sh;
return *this;
}
template <class T> Matrix44<T> &Matrix44<T>:: SetShearYZ( const T sh) {// shear the Y coordinate as the Z coordinate change
SetIdentity();
ElementAt(2,1) = sh;
return *this;
}
/*
Data una matrice non proiettiva (in cui l'ultima riga e' (0,0,0,1)
la decompone in una sequenza (nell'ordine) di
Scale,Shear,Rotation e Translation
- ShearV e' un vettore di tre scalari che indicano
ShearXY, ShearXZ e ShearYZ
- RotateV e' un vettore di tre scalari che indicano la sequenza di rotazioni
in assi x,y,z
Genera una una matrice lasciandoci dentro solo la rototraslazione.
Example:
m=Decompose(ScV,ShV,RtV,TrV);
Matrix44d Scl; Scl.Scale(ScV[0],ScV[1],ScV[2]);
Matrix44d Sxy; Sxy.ShearXY(ShV[0]);
Matrix44d Sxz; Sxz.ShearXZ(ShV[1]);
Matrix44d Syz; Syz.ShearYZ(ShV[2]);
Matrix44d Rtx; Rtx.Rotate(RtV[0],Point3d(1,0,0));
Matrix44d Rty; Rty.Rotate(RtV[1],Point3d(0,1,0));
Matrix44d Rtz; Rtz.Rotate(RtV[2],Point3d(0,0,1));
Matrix44d Trn; Trn.Translate(TrV[0],TrV[1],TrV[2]);
// Rebuild e' uguale a Orig, prima della decompose
Matrix44d Rebuild = Scl * Sxy*Sxz*Syz * Rtx*Rty*Rtz * Trn;
*/
template <class T>
bool Decompose(Matrix44<T> &M, Point3<T> &ScaleV, Point3<T> &ShearV, Point3<T> &RotV,Point3<T> &TranV)
{
if(!(M[3][0]==0 && M[3][1]==0 && M[3][2]==0 && M[3][3]==1) ) // the matrix is projective
return false;
if(math::Abs(M.Determinant())<1e-10) return false; // matrix should be at least invertible...
// First Step recover the traslation
TranV=M.GetColumn3(3);
// Second Step Recover Scale and Shearing interleaved
ScaleV[0]=Norm(M.GetColumn3(0));
Point3d R[3];
R[0]=M.GetColumn3(0);
R[0].Normalize();
ShearV[0]=R[0]*M.GetColumn3(1); // xy shearing
R[1]= M.GetColumn3(1)-R[0]*ShearV[0];
assert(math::Abs(R[1]*R[0])<1e-10);
ScaleV[1]=Norm(R[1]); // y scaling
R[1]=R[1]/ScaleV[1];
ShearV[0]=ShearV[0]/ScaleV[1];
ShearV[1]=R[0]*M.GetColumn3(2); // xz shearing
R[2]= M.GetColumn3(2)-R[0]*ShearV[1];
assert(math::Abs(R[2]*R[0])<1e-10);
R[2] = R[2]-R[1]*(R[2]*R[1]);
assert(math::Abs(R[2]*R[1])<1e-10);
assert(math::Abs(R[2]*R[0])<1e-10);
ScaleV[2]=Norm(R[2]);
ShearV[1]=ShearV[1]/ScaleV[2];
R[2]=R[2]/ScaleV[2];
assert(math::Abs(R[2]*R[1])<1e-10);
assert(math::Abs(R[2]*R[0])<1e-10);
ShearV[2]=R[1]*M.GetColumn3(2); // yz shearing
ShearV[2]=ShearV[2]/ScaleV[2];
int i,j;
for(i=0;i<3;++i)
for(j=0;j<3;++j)
M[i][j]=R[j][i];
// Third and last step: Recover the rotation
//now the matrix should be a pure rotation matrix so its determinant is +-1
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...
if(det<0) {
ScaleV *= -1;
M *= -1;
}
double alpha,beta,gamma; // rotations around the x,y and z axis
beta=asin( M[0][2]);
double cosbeta=cos(beta);
if(math::Abs(cosbeta) > 1e-5)
{
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;
}
else
{
alpha=asin(-M[1][0]);
if(M[1][1]<0) alpha=M_PI-alpha;
gamma=0;
}
RotV[0]=math::ToDeg(alpha);
RotV[1]=math::ToDeg(beta);
RotV[2]=math::ToDeg(gamma);
return true;
}
template <class T> T Matrix44<T>::Determinant() const {
LinearSolve<T> solve(*this);