Have removed the old lazy initialization of Matrix since it was causing bugs

and adding checks to many mothods which in the end slow it down more than
not intilizing the code!  The code is now simpler, more robust and faster:-)
This commit is contained in:
Robert Osfield 2002-02-05 21:51:06 +00:00
parent 92f68e2669
commit 7293af59ed
2 changed files with 73 additions and 80 deletions

View File

@ -15,6 +15,16 @@ namespace osg {
class Quat; class Quat;
/** The range of matrix modes that the scene graph might utilize.
* Similar in concept to different modes in OpenGL glMatrixMode().*/
enum MatrixMode
{
PROJECTION,
VIEW,
MODEL,
MODELVIEW
};
class SG_EXPORT Matrix : public Object class SG_EXPORT Matrix : public Object
{ {
@ -37,14 +47,22 @@ class SG_EXPORT Matrix : public Object
Matrix& operator = (const Matrix& ); Matrix& operator = (const Matrix& );
int compare(const Matrix& m) const { ensureRealized(); m.ensureRealized(); return memcmp(_mat,m._mat,sizeof(_mat)); } int compare(const Matrix& m) const { return memcmp(_mat,m._mat,sizeof(_mat)); }
bool operator < (const Matrix& m) const { return compare(m)<0; } bool operator < (const Matrix& m) const { return compare(m)<0; }
bool operator == (const Matrix& m) const { return compare(m)==0; } bool operator == (const Matrix& m) const { return compare(m)==0; }
bool operator != (const Matrix& m) const { return compare(m)!=0; } bool operator != (const Matrix& m) const { return compare(m)!=0; }
inline float& operator()(int row, int col) { ensureRealized(); return _mat[row][col]; } inline float& operator()(int row, int col) { return _mat[row][col]; }
inline float operator()(int row, int col) const { ensureRealized(); return _mat[row][col]; } inline float operator()(int row, int col) const { return _mat[row][col]; }
inline const bool valid() const { return !isNaN(); }
inline const bool isNaN() const { return osg::isNaN(_mat[0][0]) || osg::isNaN(_mat[0][1]) || osg::isNaN(_mat[0][2]) || osg::isNaN(_mat[0][3]) ||
osg::isNaN(_mat[1][0]) || osg::isNaN(_mat[1][1]) || osg::isNaN(_mat[1][2]) || osg::isNaN(_mat[1][3]) ||
osg::isNaN(_mat[2][0]) || osg::isNaN(_mat[2][1]) || osg::isNaN(_mat[2][2]) || osg::isNaN(_mat[2][3]) ||
osg::isNaN(_mat[3][0]) || osg::isNaN(_mat[3][1]) || osg::isNaN(_mat[3][2]) || osg::isNaN(_mat[3][3]); }
void set( float const * const ); void set( float const * const );
void set( float a00, float a01, float a02, float a03, void set( float a00, float a01, float a02, float a03,
@ -52,10 +70,8 @@ class SG_EXPORT Matrix : public Object
float a20, float a21, float a22, float a23, float a20, float a21, float a22, float a23,
float a30, float a31, float a32, float a33); float a30, float a31, float a32, float a33);
float * ptr() { ensureRealized(); return (float *)_mat; } float * ptr() { return (float *)_mat; }
const float * ptr() const { ensureRealized(); return (const float *)_mat; } const float * ptr() const { return (const float *)_mat; }
inline void ensureRealized() const { if (!fully_realized) const_cast<Matrix*>(this)->makeIdentity();}
void makeIdentity(); void makeIdentity();
@ -94,7 +110,7 @@ class SG_EXPORT Matrix : public Object
void setTrans( float tx, float ty, float tz ); void setTrans( float tx, float ty, float tz );
void setTrans( const Vec3& v ); void setTrans( const Vec3& v );
Vec3 getTrans() const { ensureRealized(); return Vec3(_mat[3][0],_mat[3][1],_mat[3][2]); } Vec3 getTrans() const { return Vec3(_mat[3][0],_mat[3][1],_mat[3][2]); }
/** apply apply an 3x3 transform of v*M[0..2,0..2] */ /** apply apply an 3x3 transform of v*M[0..2,0..2] */
inline static Vec3 transform3x3(const Vec3& v,const Matrix& m); inline static Vec3 transform3x3(const Vec3& v,const Matrix& m);
@ -149,7 +165,6 @@ class SG_EXPORT Matrix : public Object
private: private:
float _mat[4][4]; float _mat[4][4];
bool fully_realized;
}; };

View File

@ -21,7 +21,10 @@ using namespace osg;
+((a)._mat[r][3] * (b)._mat[3][c]) +((a)._mat[r][3] * (b)._mat[3][c])
Matrix::Matrix() : Object(), fully_realized(false) {} Matrix::Matrix() : Object()
{
makeIdentity();
}
Matrix::Matrix( const Matrix& other) : Object() Matrix::Matrix( const Matrix& other) : Object()
{ {
@ -42,20 +45,19 @@ Matrix::Matrix( float a00, float a01, float a02, float a03,
SET_ROW(1, a10, a11, a12, a13 ) SET_ROW(1, a10, a11, a12, a13 )
SET_ROW(2, a20, a21, a22, a23 ) SET_ROW(2, a20, a21, a22, a23 )
SET_ROW(3, a30, a31, a32, a33 ) SET_ROW(3, a30, a31, a32, a33 )
fully_realized = true;
} }
Matrix& Matrix::operator = (const Matrix& other ) { Matrix& Matrix::operator = (const Matrix& other )
{
if( &other == this ) return *this; if( &other == this ) return *this;
set((const float*)other._mat); set((const float*)other._mat);
return *this; return *this;
} }
void Matrix::set( float const * const def ) { void Matrix::set( float const * const def )
{
memcpy( _mat, def, sizeof(_mat) ); memcpy( _mat, def, sizeof(_mat) );
fully_realized = true;
} }
@ -68,14 +70,10 @@ void Matrix::set( float a00, float a01, float a02, float a03,
SET_ROW(1, a10, a11, a12, a13 ) SET_ROW(1, a10, a11, a12, a13 )
SET_ROW(2, a20, a21, a22, a23 ) SET_ROW(2, a20, a21, a22, a23 )
SET_ROW(3, a30, a31, a32, a33 ) SET_ROW(3, a30, a31, a32, a33 )
fully_realized = true;
} }
void Matrix::setTrans( float tx, float ty, float tz ) void Matrix::setTrans( float tx, float ty, float tz )
{ {
ensureRealized();
_mat[3][0] = tx; _mat[3][0] = tx;
_mat[3][1] = ty; _mat[3][1] = ty;
_mat[3][2] = tz; _mat[3][2] = tz;
@ -95,8 +93,6 @@ void Matrix::makeIdentity()
SET_ROW(1, 0, 1, 0, 0 ) SET_ROW(1, 0, 1, 0, 0 )
SET_ROW(2, 0, 0, 1, 0 ) SET_ROW(2, 0, 0, 1, 0 )
SET_ROW(3, 0, 0, 0, 1 ) SET_ROW(3, 0, 0, 0, 1 )
fully_realized = true;
} }
void Matrix::makeScale( const Vec3& v ) void Matrix::makeScale( const Vec3& v )
@ -110,8 +106,6 @@ void Matrix::makeScale( float x, float y, float z )
SET_ROW(1, 0, y, 0, 0 ) SET_ROW(1, 0, y, 0, 0 )
SET_ROW(2, 0, 0, z, 0 ) SET_ROW(2, 0, 0, z, 0 )
SET_ROW(3, 0, 0, 0, 1 ) SET_ROW(3, 0, 0, 0, 1 )
fully_realized = true;
} }
void Matrix::makeTranslate( const Vec3& v ) void Matrix::makeTranslate( const Vec3& v )
@ -125,8 +119,6 @@ void Matrix::makeTranslate( float x, float y, float z )
SET_ROW(1, 0, 1, 0, 0 ) SET_ROW(1, 0, 1, 0, 0 )
SET_ROW(2, 0, 0, 1, 0 ) SET_ROW(2, 0, 0, 1, 0 )
SET_ROW(3, x, y, z, 1 ) SET_ROW(3, x, y, z, 1 )
fully_realized = true;
} }
void Matrix::makeRotate( const Vec3& from, const Vec3& to ) void Matrix::makeRotate( const Vec3& from, const Vec3& to )
@ -153,7 +145,6 @@ void Matrix::makeRotate( float angle, float x, float y, float z )
void Matrix::makeRotate( const Quat& q ) void Matrix::makeRotate( const Quat& q )
{ {
q.get(*this); q.get(*this);
fully_realized = true;
} }
void Matrix::makeRotate( float yaw, float pitch, float roll) void Matrix::makeRotate( float yaw, float pitch, float roll)
@ -178,6 +169,7 @@ void Matrix::makeRotate( float yaw, float pitch, float roll)
void Matrix::mult( const Matrix& lhs, const Matrix& rhs ) void Matrix::mult( const Matrix& lhs, const Matrix& rhs )
{ {
// PRECONDITION: We assume neither &lhs nor &rhs == this // PRECONDITION: We assume neither &lhs nor &rhs == this
// if it did, use preMult or postMult instead // if it did, use preMult or postMult instead
_mat[0][0] = INNER_PRODUCT(lhs, rhs, 0, 0); _mat[0][0] = INNER_PRODUCT(lhs, rhs, 0, 0);
@ -196,17 +188,10 @@ void Matrix::mult( const Matrix& lhs, const Matrix& rhs )
_mat[3][1] = INNER_PRODUCT(lhs, rhs, 3, 1); _mat[3][1] = INNER_PRODUCT(lhs, rhs, 3, 1);
_mat[3][2] = INNER_PRODUCT(lhs, rhs, 3, 2); _mat[3][2] = INNER_PRODUCT(lhs, rhs, 3, 2);
_mat[3][3] = INNER_PRODUCT(lhs, rhs, 3, 3); _mat[3][3] = INNER_PRODUCT(lhs, rhs, 3, 3);
fully_realized = true;
} }
void Matrix::preMult( const Matrix& other ) void Matrix::preMult( const Matrix& other )
{ {
if( !fully_realized ) {
//act as if this were an identity Matrix
set((const float*)other._mat);
return;
}
// brute force method requiring a copy // brute force method requiring a copy
//Matrix tmp(other* *this); //Matrix tmp(other* *this);
// *this = tmp; // *this = tmp;
@ -228,11 +213,6 @@ void Matrix::preMult( const Matrix& other )
void Matrix::postMult( const Matrix& other ) void Matrix::postMult( const Matrix& other )
{ {
if( !fully_realized ) {
//act as if this were an identity Matrix
set((const float*)other._mat);
return;
}
// brute force method requiring a copy // brute force method requiring a copy
//Matrix tmp(*this * other); //Matrix tmp(*this * other);
// *this = tmp; // *this = tmp;
@ -252,31 +232,31 @@ void Matrix::postMult( const Matrix& other )
#undef SET_ROW #undef SET_ROW
#undef INNER_PRODUCT #undef INNER_PRODUCT
bool Matrix::invert( const Matrix& _m ) bool Matrix::invert( const Matrix& other )
{ {
if (&other==this)
if (&_m==this)
{ {
Matrix tm(_m); Matrix tm(other);
return invert(tm); return invert(tm);
} }
/*if ( _m._mat[0][3] == 0.0
&& _m._mat[1][3] == 0.0 // if ( other._mat[0][3] == 0.0
&& _m._mat[2][3] == 0.0 // && other._mat[1][3] == 0.0
&& _m._mat[3][3] == 1.0 ) // && other._mat[2][3] == 0.0
{ // && other._mat[3][3] == 1.0 )
return invertAffine( _m ); // {
}*/ // return invertAffine( other );
// }
// code lifted from VR Juggler. // code lifted from VR Juggler.
// not cleanly added, but seems to work. RO. // not cleanly added, but seems to work. RO.
const float* a = reinterpret_cast<const float*>(_m._mat); const float* a = reinterpret_cast<const float*>(other._mat);
float* b = reinterpret_cast<float*>(_mat); float* b = reinterpret_cast<float*>(_mat);
int n = 4; int n = 4;
int i, j, k; int i, j, k;
int r[ 4], c[ 4], row[ 4], col[ 4]; int r[ 4], c[ 4], row[ 4], col[ 4];
float m[ 4][ 4*2], pivot, max_m, tmp_m, fac; float m[ 4][ 4*2], pivot, maxother, tmpother, fac;
/* Initialization */ /* Initialization */
for ( i = 0; i < n; i ++ ) for ( i = 0; i < n; i ++ )
@ -299,16 +279,16 @@ bool Matrix::invert( const Matrix& _m )
for ( k = 0; k < n; k++ ) for ( k = 0; k < n; k++ )
{ {
/* Choosing the pivot */ /* Choosing the pivot */
for ( i = 0, max_m = 0; i < n; i++ ) for ( i = 0, maxother = 0; i < n; i++ )
{ {
if ( row[ i] ) continue; if ( row[ i] ) continue;
for ( j = 0; j < n; j++ ) for ( j = 0; j < n; j++ )
{ {
if ( col[ j] ) continue; if ( col[ j] ) continue;
tmp_m = fabs( m[ i][j]); tmpother = fabs( m[ i][j]);
if ( tmp_m > max_m) if ( tmpother > maxother)
{ {
max_m = tmp_m; maxother = tmpother;
r[ k] = i; r[ k] = i;
c[ k] = j; c[ k] = j;
} }
@ -319,8 +299,9 @@ bool Matrix::invert( const Matrix& _m )
if ( fabs( pivot) <= 1e-20) if ( fabs( pivot) <= 1e-20)
{ {
notify(WARN) << "*** pivot = %f in mat_inv. ***"<<std::endl; notify(WARN) << "Warning: pivot = "<< pivot <<" in Matrix::invert(), cannot compute inverse."<<std::endl;
//abort( 0); notify(WARN) << "input matrix to Matrix::invert() was = "<< other <<std::endl;
makeIdentity();
return false; return false;
} }
@ -358,14 +339,12 @@ bool Matrix::invert( const Matrix& _m )
for ( j = 0; j < n; j++ ) for ( j = 0; j < n; j++ )
b[ i * n + j] = m[ row[ i]][j + n]; b[ i * n + j] = m[ row[ i]][j + n];
fully_realized = true;
return true; // It worked return true; // It worked
} }
const double PRECISION_LIMIT = 1.0e-15; const double PRECISION_LIMIT = 1.0e-15;
bool Matrix::invertAffine( const Matrix& _m ) bool Matrix::invertAffine( const Matrix& other )
{ {
// adapted from Graphics Gems II. // adapted from Graphics Gems II.
// //
@ -391,13 +370,13 @@ bool Matrix::invertAffine( const Matrix& _m )
else neg += temp; \ else neg += temp; \
} }
temp = _m._mat[0][0] * _m._mat[1][1] * _m._mat[2][2]; ACCUMULATE; temp = other._mat[0][0] * other._mat[1][1] * other._mat[2][2]; ACCUMULATE;
temp = _m._mat[0][1] * _m._mat[1][2] * _m._mat[2][0]; ACCUMULATE; temp = other._mat[0][1] * other._mat[1][2] * other._mat[2][0]; ACCUMULATE;
temp = _m._mat[0][2] * _m._mat[1][0] * _m._mat[2][1]; ACCUMULATE; temp = other._mat[0][2] * other._mat[1][0] * other._mat[2][1]; ACCUMULATE;
temp = - _m._mat[0][2] * _m._mat[1][1] * _m._mat[2][0]; ACCUMULATE; temp = - other._mat[0][2] * other._mat[1][1] * other._mat[2][0]; ACCUMULATE;
temp = - _m._mat[0][1] * _m._mat[1][0] * _m._mat[2][2]; ACCUMULATE; temp = - other._mat[0][1] * other._mat[1][0] * other._mat[2][2]; ACCUMULATE;
temp = - _m._mat[0][0] * _m._mat[1][2] * _m._mat[2][1]; ACCUMULATE; temp = - other._mat[0][0] * other._mat[1][2] * other._mat[2][1]; ACCUMULATE;
det_1 = pos + neg; det_1 = pos + neg;
@ -410,27 +389,26 @@ bool Matrix::invertAffine( const Matrix& _m )
// inverse is adj(A)/det(A) // inverse is adj(A)/det(A)
det_1 = 1.0 / det_1; det_1 = 1.0 / det_1;
_mat[0][0] = (_m._mat[1][1] * _m._mat[2][2] - _m._mat[1][2] * _m._mat[2][1]) * det_1; _mat[0][0] = (other._mat[1][1] * other._mat[2][2] - other._mat[1][2] * other._mat[2][1]) * det_1;
_mat[1][0] = (_m._mat[1][0] * _m._mat[2][2] - _m._mat[1][2] * _m._mat[2][0]) * det_1; _mat[1][0] = (other._mat[1][0] * other._mat[2][2] - other._mat[1][2] * other._mat[2][0]) * det_1;
_mat[2][0] = (_m._mat[1][0] * _m._mat[2][1] - _m._mat[1][1] * _m._mat[2][0]) * det_1; _mat[2][0] = (other._mat[1][0] * other._mat[2][1] - other._mat[1][1] * other._mat[2][0]) * det_1;
_mat[0][1] = (_m._mat[0][1] * _m._mat[2][2] - _m._mat[0][2] * _m._mat[2][1]) * det_1; _mat[0][1] = (other._mat[0][1] * other._mat[2][2] - other._mat[0][2] * other._mat[2][1]) * det_1;
_mat[1][1] = (_m._mat[0][0] * _m._mat[2][2] - _m._mat[0][2] * _m._mat[2][0]) * det_1; _mat[1][1] = (other._mat[0][0] * other._mat[2][2] - other._mat[0][2] * other._mat[2][0]) * det_1;
_mat[2][1] = (_m._mat[0][0] * _m._mat[2][1] - _m._mat[0][1] * _m._mat[2][0]) * det_1; _mat[2][1] = (other._mat[0][0] * other._mat[2][1] - other._mat[0][1] * other._mat[2][0]) * det_1;
_mat[0][2] = (_m._mat[0][1] * _m._mat[1][2] - _m._mat[0][2] * _m._mat[1][1]) * det_1; _mat[0][2] = (other._mat[0][1] * other._mat[1][2] - other._mat[0][2] * other._mat[1][1]) * det_1;
_mat[1][2] = (_m._mat[0][0] * _m._mat[1][2] - _m._mat[0][2] * _m._mat[1][0]) * det_1; _mat[1][2] = (other._mat[0][0] * other._mat[1][2] - other._mat[0][2] * other._mat[1][0]) * det_1;
_mat[2][2] = (_m._mat[0][0] * _m._mat[1][1] - _m._mat[0][1] * _m._mat[1][0]) * det_1; _mat[2][2] = (other._mat[0][0] * other._mat[1][1] - other._mat[0][1] * other._mat[1][0]) * det_1;
// calculate -C * inv(A) // calculate -C * inv(A)
_mat[3][0] = -(_m._mat[3][0] * _mat[0][0] + _m._mat[3][1] * _mat[1][0] + _m._mat[3][2] * _mat[2][0] ); _mat[3][0] = -(other._mat[3][0] * _mat[0][0] + other._mat[3][1] * _mat[1][0] + other._mat[3][2] * _mat[2][0] );
_mat[3][1] = -(_m._mat[3][0] * _mat[0][1] + _m._mat[3][1] * _mat[1][1] + _m._mat[3][2] * _mat[2][1] ); _mat[3][1] = -(other._mat[3][0] * _mat[0][1] + other._mat[3][1] * _mat[1][1] + other._mat[3][2] * _mat[2][1] );
_mat[3][2] = -(_m._mat[3][0] * _mat[0][2] + _m._mat[3][1] * _mat[1][2] + _m._mat[3][2] * _mat[2][2] ); _mat[3][2] = -(other._mat[3][0] * _mat[0][2] + other._mat[3][1] * _mat[1][2] + other._mat[3][2] * _mat[2][2] );
_mat[0][3] = 0.0; _mat[0][3] = 0.0;
_mat[1][3] = 0.0; _mat[1][3] = 0.0;
_mat[2][3] = 0.0; _mat[2][3] = 0.0;
_mat[3][3] = 1.0; _mat[3][3] = 1.0;
fully_realized = true;
return true; return true;
} }