Added osg::Matrix::getOtho,getFrustum and getLookAt() methods.

Added test for new matrix methods into unit tests example, but these really
should go in their own lib...
This commit is contained in:
Robert Osfield 2003-07-16 20:14:48 +00:00
parent 8e0e9d35d8
commit a4b29996fd
3 changed files with 159 additions and 29 deletions

View File

@ -2,6 +2,86 @@
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>
#include <osg/Matrix>
void testFrustum(double left,double right,double bottom,double top,double zNear,double zFar)
{
osg::Matrix f;
f.makeFrustum(left,right,bottom,top,zNear,zFar);
double c_zNear = f(3,2) / (f(2,2)-1.0f);
double c_zFar = f(3,2) / (1.0f+f(2,2));
double c_left = c_zNear * (f(2,0)-1.0f) / f(0,0);
double c_right = c_zNear * (1.0f+f(2,0)) / f(0,0);
double c_top = c_zNear * (1+f(2,1)) / f(1,1);
double c_bottom = c_zNear * (f(2,1)-1.0f) / f(1,1);
f.getFrustum(c_left,c_right,c_bottom,c_top,c_zNear,c_zFar);
std::cout << "testFrustum"<<std::endl;
std::cout << " left = "<<left<<" compute "<<c_left<<std::endl;
std::cout << " right = "<<right<<" compute "<<c_right<<std::endl;
std::cout << " bottom = "<<bottom<<" compute "<<c_bottom<<std::endl;
std::cout << " top = "<<top<<" compute "<<c_top<<std::endl;
std::cout << " zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
std::cout << " zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
std::cout << std::endl;
}
void testOrtho(double left,double right,double bottom,double top,double zNear,double zFar)
{
osg::Matrix f;
f.makeOrtho(left,right,bottom,top,zNear,zFar);
double c_zNear = (f(3,2)+1.0f) / f(2,2);
double c_zFar = (f(3,2)-1.0f) / f(2,2);
double c_left = -(1.0f+f(3,0)) / f(0,0);
double c_right = (1.0f-f(3,0)) / f(0,0);
double c_bottom = -(1.0f+f(3,1)) / f(1,1);
double c_top = (1.0f-f(3,1)) / f(1,1);
f.getOrtho(c_left,c_right,c_bottom,c_top,c_zNear,c_zFar);
std::cout << "testOrtho"<<std::endl;
std::cout << " left = "<<left<<" compute "<<c_left<<std::endl;
std::cout << " right = "<<right<<" compute "<<c_right<<std::endl;
std::cout << " bottom = "<<bottom<<" compute "<<c_bottom<<std::endl;
std::cout << " top = "<<top<<" compute "<<c_top<<std::endl;
std::cout << " zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
std::cout << " zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
std::cout << std::endl;
}
void testLookAt(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up)
{
osg::Matrix mv;
mv.makeLookAt(eye,center,up);
osg::Vec3 c_eye,c_center,c_up;
mv.getLookAt(c_eye,c_center,c_up);
std::cout << "testLookAt"<<std::endl;
std::cout << " eye "<<eye<< " compute "<<c_eye<<std::endl;
std::cout << " eye "<<center<< " compute "<<c_center<<std::endl;
std::cout << " eye "<<up<< " compute "<<c_up<<std::endl;
std::cout << std::endl;
}
int main( int argc, char** argv )
{
osg::ArgumentParser arguments(&argc,argv);
@ -11,11 +91,21 @@ int main( int argc, char** argv )
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options]");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
arguments.getApplicationUsage()->addCommandLineOption("qt","Display qualified tests.");
arguments.getApplicationUsage()->addCommandLineOption("matrix","Display qualified tests.");
if (arguments.argc()<=1)
{
arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
return 1;
}
bool printQualifiedTest = false;
while (arguments.read("qt")) printQualifiedTest = true;
bool displayMatrixTest = false;
while (arguments.read("matrix")) displayMatrixTest = true;
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{
@ -34,10 +124,20 @@ int main( int argc, char** argv )
return 1;
}
if (arguments.argc()<=1)
if (displayMatrixTest)
{
arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
return 1;
std::cout<<"****** Running matrix tests ******"<<std::endl;
testFrustum(-1,1,-1,1,1,1000);
testFrustum(0,1,1,2,2.5,100000);
testOrtho(0,1,1,2,2.1,1000);
testOrtho(-1,10,1,20,2.5,100000);
testLookAt(osg::Vec3(10.0,4.0,2.0),osg::Vec3(10.0,4.0,2.0)+osg::Vec3(0.0,1.0,0.0),osg::Vec3(0.0,0.0,1.0));
testLookAt(osg::Vec3(10.0,4.0,2.0),osg::Vec3(10.0,4.0,2.0)+osg::Vec3(1.0,1.0,0.0),osg::Vec3(0.0,0.0,1.0));
}

View File

@ -107,6 +107,12 @@ class SG_EXPORT Matrix
double bottom, double top,
double zNear, double zFar);
/** Get the othorgraphic settings of the orthographic projection matrix.
* Note, if matrix is not an orthographic matrix then invalid values will be returned.*/
void getOrtho(double& left, double& right,
double& bottom, double& top,
double& zNear, double& zFar);
/** Set to a 2D orthographic projection. See glOrtho2D for further details.*/
inline void makeOrtho2D(double left, double right,
double bottom, double top)
@ -114,19 +120,28 @@ class SG_EXPORT Matrix
makeOrtho(left,right,bottom,top,-1.0,1.0);
}
/** Set to a perspective projection. See glFrustum for further details.*/
void makeFrustum(double left, double right,
double bottom, double top,
double zNear, double zFar);
/** Get the frustum setting of a perspective projection matrix.
* Note, if matrix is not an orthographic matrix then invalid values will be returned.*/
void getFrustum(double& left, double& right,
double& bottom, double& top,
double& zNear, double& zFar);
/** Set to a symmetrical perspective projection, See gluPerspective for further details.
* Aspect ratio is defined as width/height.*/
void makePerspective(double fovy,double aspectRatio,
double zNear, double zFar);
/** Set to the position and orientation as per a camera, using the same convention as gluLookAt. */
/** Set to the position and orientation modelview matrix, using the same convention as gluLookAt. */
void makeLookAt(const Vec3& eye,const Vec3& center,const Vec3& up);
/** Get to the position and orientation of a modelview matrix, using the same convention as gluLookAt. */
void getLookAt(Vec3& eye,Vec3& center,Vec3& up,float lookDistance=1.0f);
bool invert( const Matrix& );
@ -209,31 +224,6 @@ class SG_EXPORT Matrix
return r;
}
// temporarily commented out while waiting for a more generic implementation
// of MatrixProduct proxy class.
// // Helper class to optimize product expressions somewhat
// class MatrixProduct {
// public:
// const Matrix& A;
// const Matrix& B;
//
// MatrixProduct( const Matrix& lhs, const Matrix& rhs ) : A(lhs), B(rhs) {}
// };
//
// inline MatrixProduct operator * ( const Matrix& other ) const
// { return MatrixProduct(*this, other); }
//
// inline void operator = ( const MatrixProduct& p )
// {
// if( this == &(p.A)) postMult(p.B);
// else if( this == &(p.B)) preMult(p.A);
// else mult( p.A, p.B );
// }
//
// Matrix( const MatrixProduct& p ) //allows implicit evaluation of the product
// { mult( p.A, p.B ); }
protected:
float _mat[4][4];

View File

@ -326,6 +326,21 @@ void Matrix::makeOrtho(double left, double right,
SET_ROW(3, tx, ty, tz, 1.0f )
}
void Matrix::getOrtho(double& left, double& right,
double& bottom, double& top,
double& zNear, double& zFar)
{
zNear = (_mat[3][2]+1.0f) / _mat[2][2];
zFar = (_mat[3][2]-1.0f) / _mat[2][2];
left = -(1.0f+_mat[3][0]) / _mat[0][0];
right = (1.0f-_mat[3][0]) / _mat[0][0];
bottom = -(1.0f+_mat[3][1]) / _mat[1][1];
top = (1.0f-_mat[3][1]) / _mat[1][1];
}
void Matrix::makeFrustum(double left, double right,
double bottom, double top,
double zNear, double zFar)
@ -341,6 +356,20 @@ void Matrix::makeFrustum(double left, double right,
SET_ROW(3, 0.0f, 0.0f, D, 0.0f )
}
void Matrix::getFrustum(double& left, double& right,
double& bottom, double& top,
double& zNear, double& zFar)
{
zNear = _mat[3][2] / (_mat[2][2]-1.0f);
zFar = _mat[3][2] / (1.0f+_mat[2][2]);
left = zNear * (_mat[2][0]-1.0f) / _mat[0][0];
right = zNear * (1.0f+_mat[2][0]) / _mat[0][0];
top = zNear * (1.0f+_mat[2][1]) / _mat[1][1];
bottom = zNear * (_mat[2][1]-1.0f) / _mat[1][1];
}
void Matrix::makePerspective(double fovy,double aspectRatio,
double zNear, double zFar)
@ -373,4 +402,15 @@ void Matrix::makeLookAt(const Vec3& eye,const Vec3& center,const Vec3& up)
preMult(Matrix::translate(-eye));
}
void Matrix::getLookAt(Vec3& eye,Vec3& center,Vec3& up,float lookDistance)
{
Matrix inv;
inv.invert(*this);
eye = osg::Vec3(0.0f,0.0f,0.0f)*inv;
up = transform3x3(*this,osg::Vec3(0.0f,1.0f,0.0f));
center = transform3x3(*this,osg::Vec3(0.0f,0.0f,-1));
center.normalize();
center = eye + center*lookDistance;
}
#undef SET_ROW