From J.P Delport, "attached find an updated osgunittests.cpp that allows for the testing of

the matrix.getRotate() function when a matrix contains a scale as well
as a rotation.

The scale can optionally be switched off, see the top of
testQuatFromMatrix().

As expected, all the current methods for mat to quat conversion fail
these new tests. When the scale is omitted, mk2 of getRotate with sign
instead of signOrZero passes, as well as mk1.
"
This commit is contained in:
Robert Osfield 2007-06-01 21:38:53 +00:00
parent b92ebca928
commit 9a0b39c34b

View File

@ -3,6 +3,7 @@
#include <osg/Vec3> #include <osg/Vec3>
#include <osg/Matrix> #include <osg/Matrix>
#include <osg/Timer>
#include <osg/io_utils> #include <osg/io_utils>
#include "UnitTestFramework.h" #include "UnitTestFramework.h"
@ -143,36 +144,51 @@ void sizeOfTest()
} }
/// Exercises the Matrix.get(Quat&) function, printout is generated on problems only /// Exercise the Matrix.getRotate function.
/// Compare the output of:
/// q1 * q2
/// versus
/// (mat(q1)*mat(q2)*scale).getRotate()
/// for a range of rotations
void testGetQuatFromMatrix() { void testGetQuatFromMatrix() {
// acceptable error range
double eps=1e-3;
// Options
// acceptable error range
double eps=1e-6;
// scale matrix
// To not test with scale, use 1,1,1
// Not sure if 0's or negative values are acceptable
osg::Matrixd scalemat;
scalemat.makeScale(osg::Vec3d(0.9,0.5,0.1));
// range of rotations
#if 1 #if 1
// wide range // wide range
double rol1start = 0.0; double rol1start = 0.0;
double rol1stop = 360.0; double rol1stop = 360.0;
double rol1step = 30.0; double rol1step = 20.0;
double pit1start = 0.0; double pit1start = 0.0;
double pit1stop = 90.0; double pit1stop = 90.0;
double pit1step = 30.0; double pit1step = 20.0;
double yaw1start = 0.0; double yaw1start = 0.0;
double yaw1stop = 360.0; double yaw1stop = 360.0;
double yaw1step = 30.0; double yaw1step = 20.0;
double rol2start = 0.0; double rol2start = 0.0;
double rol2stop = 360.0; double rol2stop = 360.0;
double rol2step = 30.0; double rol2step = 20.0;
double pit2start = 0.0; double pit2start = 0.0;
double pit2stop = 90.0; double pit2stop = 90.0;
double pit2step = 30.0; double pit2step = 20.0;
double yaw2start = 0.0; double yaw2start = 0.0;
double yaw2stop = 360.0; double yaw2stop = 360.0;
double yaw2step = 30.0; double yaw2step = 20.0;
#else #else
// focussed range // focussed range
double rol1start = 0.0; double rol1start = 0.0;
@ -200,12 +216,18 @@ void testGetQuatFromMatrix() {
double yaw2step = 0.1; double yaw2step = 0.1;
#endif #endif
std::cout << std::endl << "Starting " << __FUNCTION__ << ", it can take a while ..." << std::endl;
osg::Timer_t tstart, tstop;
tstart = osg::Timer::instance()->tick();
int count=0;
for (double rol1 = rol1start; rol1 <= rol1stop; rol1 += rol1step) { for (double rol1 = rol1start; rol1 <= rol1stop; rol1 += rol1step) {
for (double pit1 = pit1start; pit1 <= pit1stop; pit1 += pit1step) { for (double pit1 = pit1start; pit1 <= pit1stop; pit1 += pit1step) {
for (double yaw1 = yaw1start; yaw1 <= yaw1stop; yaw1 += yaw1step) { for (double yaw1 = yaw1start; yaw1 <= yaw1stop; yaw1 += yaw1step) {
for (double rol2 = rol2start; rol2 <= rol2stop; rol2 += rol2step) { for (double rol2 = rol2start; rol2 <= rol2stop; rol2 += rol2step) {
for (double pit2 = pit2start; pit2 <= pit2stop; pit2 += pit2step) { for (double pit2 = pit2start; pit2 <= pit2stop; pit2 += pit2step) {
for (double yaw2 = yaw2start; yaw2 <= yaw2stop; yaw2 += yaw2step) { for (double yaw2 = yaw2start; yaw2 <= yaw2stop; yaw2 += yaw2step) {
count++;
// create two quats based on the roll, pitch and yaw values // create two quats based on the roll, pitch and yaw values
osg::Quat rot_quat1 = osg::Quat rot_quat1 =
osg::Quat(osg::DegreesToRadians(rol1),osg::Vec3d(1,0,0), osg::Quat(osg::DegreesToRadians(rol1),osg::Vec3d(1,0,0),
@ -226,9 +248,11 @@ void testGetQuatFromMatrix() {
mat1.makeRotate(rot_quat1); mat1.makeRotate(rot_quat1);
mat2.makeRotate(rot_quat2); mat2.makeRotate(rot_quat2);
// create an output quat by matrix multiplication and get // create an output quat by matrix multiplication and getRotate
osg::Matrixd out_mat; osg::Matrixd out_mat;
out_mat = mat2 * mat1; out_mat = mat2 * mat1;
// add matrix scale for even more nastiness
out_mat = out_mat * scalemat;
osg::Quat out_quat2; osg::Quat out_quat2;
out_quat2 = out_mat.getRotate(); out_quat2 = out_mat.getRotate();
@ -240,7 +264,8 @@ void testGetQuatFromMatrix() {
(fabs(out_quat1.y())-fabs(out_quat2.y())) > eps || (fabs(out_quat1.y())-fabs(out_quat2.y())) > eps ||
(fabs(out_quat1.z())-fabs(out_quat2.z())) > eps || (fabs(out_quat1.z())-fabs(out_quat2.z())) > eps ||
(fabs(out_quat1.w())-fabs(out_quat2.w())) > eps) { (fabs(out_quat1.w())-fabs(out_quat2.w())) > eps) {
std::cout << "problem at: r1=" << rol1 std::cout << __FUNCTION__ << " problem at: \n"
<< " r1=" << rol1
<< " p1=" << pit1 << " p1=" << pit1
<< " y1=" << yaw1 << " y1=" << yaw1
<< " r2=" << rol2 << " r2=" << rol2
@ -255,6 +280,9 @@ void testGetQuatFromMatrix() {
} }
} }
} }
tstop = osg::Timer::instance()->tick();
double duration = osg::Timer::instance()->delta_s(tstart,tstop);
std::cout << "Time for " << __FUNCTION__ << " with " << count << " iterations: " << duration << std::endl << std::endl;
} }
void testQuatRotate(const osg::Vec3d& from, const osg::Vec3d& to) void testQuatRotate(const osg::Vec3d& from, const osg::Vec3d& to)
@ -313,9 +341,10 @@ void testQuat()
testQuatRotate(osg::Vec3d(0.0,0.0,1.0),osg::Vec3d(0.0,0.0,-1.0)); testQuatRotate(osg::Vec3d(0.0,0.0,1.0),osg::Vec3d(0.0,0.0,-1.0));
testQuatRotate(osg::Vec3d(0.0,0.0,-1.0),osg::Vec3d(0.0,0.0,1.0)); testQuatRotate(osg::Vec3d(0.0,0.0,-1.0),osg::Vec3d(0.0,0.0,1.0));
// Test a range of rotations
testGetQuatFromMatrix(); testGetQuatFromMatrix();
// This is a specific test case for a matrix containing scale and rotation
osg::Matrix matrix(0.5, 0.0, 0.0, 0.0, osg::Matrix matrix(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0,
@ -324,8 +353,7 @@ void testQuat()
osg::Quat quat; osg::Quat quat;
matrix.get(quat); matrix.get(quat);
osg::notify(osg::NOTICE)<<"Matrix = "<<matrix<<" rotation="<<quat<<std::endl; osg::notify(osg::NOTICE)<<"Matrix = "<<matrix<<"rotation = "<<quat<<", expected quat = (0,0,0,1)"<<std::endl;
} }