root/OpenSceneGraph/trunk/examples/osgunittests/osgunittests.cpp @ 6810

Revision 6810, 16.2 kB (checked in by robert, 7 years ago)

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.
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/ArgumentParser>
2#include <osg/ApplicationUsage>
3
4#include <osg/Vec3>
5#include <osg/Matrix>
6#include <osg/Timer>
7#include <osg/io_utils>
8
9#include "UnitTestFramework.h"
10#include "performance.h"
11
12#include <iostream>
13
14void testFrustum(double left,double right,double bottom,double top,double zNear,double zFar)
15{
16    osg::Matrix f;
17    f.makeFrustum(left,right,bottom,top,zNear,zFar);
18
19    double c_left=0;
20    double c_right=0;
21    double c_top=0;
22    double c_bottom=0;
23    double c_zNear=0;
24    double c_zFar=0;
25   
26   
27    std::cout << "testFrustum"<<f.getFrustum(c_left,c_right,c_bottom,c_top,c_zNear,c_zFar)<<std::endl;
28    std::cout << "  left = "<<left<<" compute "<<c_left<<std::endl;
29    std::cout << "  right = "<<right<<" compute "<<c_right<<std::endl;
30
31    std::cout << "  bottom = "<<bottom<<" compute "<<c_bottom<<std::endl;
32    std::cout << "  top = "<<top<<" compute "<<c_top<<std::endl;
33
34    std::cout << "  zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
35    std::cout << "  zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
36   
37    std::cout << std::endl;
38}
39
40void testOrtho(double left,double right,double bottom,double top,double zNear,double zFar)
41{
42    osg::Matrix f;
43    f.makeOrtho(left,right,bottom,top,zNear,zFar);
44
45    double c_left=0;
46    double c_right=0;
47    double c_top=0;
48    double c_bottom=0;
49    double c_zNear=0;
50    double c_zFar=0;
51
52    std::cout << "testOrtho "<< f.getOrtho(c_left,c_right,c_bottom,c_top,c_zNear,c_zFar) << std::endl;
53    std::cout << "  left = "<<left<<" compute "<<c_left<<std::endl;
54    std::cout << "  right = "<<right<<" compute "<<c_right<<std::endl;
55
56    std::cout << "  bottom = "<<bottom<<" compute "<<c_bottom<<std::endl;
57    std::cout << "  top = "<<top<<" compute "<<c_top<<std::endl;
58
59    std::cout << "  zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
60    std::cout << "  zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
61   
62    std::cout << std::endl;
63}
64
65void testPerspective(double fovy,double aspect,double zNear,double zFar)
66{
67    osg::Matrix f;
68    f.makePerspective(fovy,aspect,zNear,zFar);
69
70    double c_fovy=0;
71    double c_aspect=0;
72    double c_zNear=0;
73    double c_zFar=0;
74
75    std::cout << "testPerspective "<< f.getPerspective(c_fovy,c_aspect,c_zNear,c_zFar) << std::endl;
76    std::cout << "  fovy = "<<fovy<<" compute "<<c_fovy<<std::endl;
77    std::cout << "  aspect = "<<aspect<<" compute "<<c_aspect<<std::endl;
78
79    std::cout << "  zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
80    std::cout << "  zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
81   
82    std::cout << std::endl;
83}
84
85void testLookAt(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up)
86{
87    osg::Matrix mv;
88    mv.makeLookAt(eye,center,up);
89   
90    osg::Vec3 c_eye,c_center,c_up;
91    mv.getLookAt(c_eye,c_center,c_up);
92   
93    std::cout << "testLookAt"<<std::endl;
94    std::cout << "  eye "<<eye<< " compute "<<c_eye<<std::endl;
95    std::cout << "  center "<<center<< " compute "<<c_center<<std::endl;
96    std::cout << "  up "<<up<< " compute "<<c_up<<std::endl;
97   
98    std::cout << std::endl;
99   
100}
101
102
103void testMatrixInvert(const osg::Matrix& matrix)
104{
105    //Invert it twice using the two inversion functions and view the results
106    osg::notify(osg::NOTICE)<<"testMatrixInvert("<<std::endl;
107    osg::notify(osg::NOTICE)<<matrix<<std::endl;
108    osg::notify(osg::NOTICE)<<")"<<std::endl;
109
110    osg::Matrix invM1_0;
111    invM1_0.invert(matrix);
112    osg::notify(osg::NOTICE)<<"Matrix::invert"<<std::endl;
113    osg::notify(osg::NOTICE)<<invM1_0<<std::endl;
114    osg::Matrix default_result = matrix*invM1_0;
115    osg::notify(osg::NOTICE)<<"matrix * invert="<<std::endl;
116    osg::notify(osg::NOTICE)<<default_result<<std::endl;;
117
118}
119
120void sizeOfTest()
121{
122  std::cout<<"sizeof(bool)=="<<sizeof(bool)<<std::endl;
123  std::cout<<"sizeof(char)=="<<sizeof(char)<<std::endl;
124  std::cout<<"sizeof(short)=="<<sizeof(short)<<std::endl;
125  std::cout<<"sizeof(short int)=="<<sizeof(short int)<<std::endl;
126  std::cout<<"sizeof(int)=="<<sizeof(int)<<std::endl;
127  std::cout<<"sizeof(long)=="<<sizeof(long)<<std::endl;
128  std::cout<<"sizeof(long int)=="<<sizeof(long int)<<std::endl;
129
130#if defined(_MSC_VER)
131  // long long isn't supported on VS6.0...
132  std::cout<<"sizeof(__int64)=="<<sizeof(__int64)<<std::endl;
133#else
134  std::cout<<"sizeof(long long)=="<<sizeof(long long)<<std::endl;
135#endif
136  std::cout<<"sizeof(float)=="<<sizeof(float)<<std::endl;
137  std::cout<<"sizeof(double)=="<<sizeof(double)<<std::endl;
138
139  std::cout<<"sizeof(std::istream::pos_type)=="<<sizeof(std::istream::pos_type)<<std::endl;
140  std::cout<<"sizeof(std::istream::off_type)=="<<sizeof(std::istream::off_type)<<std::endl;
141  std::cout<<"sizeof(OpenThreads::Mutex)=="<<sizeof(OpenThreads::Mutex)<<std::endl;
142
143  std::cout<<"sizeof(std::string)=="<<sizeof(std::string)<<std::endl;
144
145}
146
147/// Exercise the Matrix.getRotate function.
148/// Compare the output of:
149///  q1 * q2
150/// versus
151///  (mat(q1)*mat(q2)*scale).getRotate()
152/// for a range of rotations
153void testGetQuatFromMatrix() {
154   
155    // Options
156   
157    // acceptable error range
158    double eps=1e-6;
159
160    // scale matrix
161    // To not test with scale, use 1,1,1
162    // Not sure if 0's or negative values are acceptable
163    osg::Matrixd scalemat;
164    scalemat.makeScale(osg::Vec3d(0.9,0.5,0.1));
165   
166    // range of rotations
167#if 1
168    // wide range
169    double rol1start = 0.0;
170    double rol1stop = 360.0;
171    double rol1step = 20.0;
172
173    double pit1start = 0.0;
174    double pit1stop = 90.0;
175    double pit1step = 20.0;
176
177    double yaw1start = 0.0;
178    double yaw1stop = 360.0;
179    double yaw1step = 20.0;
180
181    double rol2start = 0.0;
182    double rol2stop = 360.0;
183    double rol2step = 20.0;
184
185    double pit2start = 0.0;
186    double pit2stop = 90.0;
187    double pit2step = 20.0;
188
189    double yaw2start = 0.0;
190    double yaw2stop = 360.0;
191    double yaw2step = 20.0;
192#else
193    // focussed range
194    double rol1start = 0.0;
195    double rol1stop = 0.0;
196    double rol1step = 0.1;
197
198    double pit1start = 0.0;
199    double pit1stop = 5.0;
200    double pit1step = 5.0;
201
202    double yaw1start = 89.0;
203    double yaw1stop = 91.0;
204    double yaw1step = 0.1;
205
206    double rol2start = 0.0;
207    double rol2stop = 0.0;
208    double rol2step = 0.1;
209
210    double pit2start = 0.0;
211    double pit2stop = 0.0;
212    double pit2step = 0.1;
213
214    double yaw2start = 89.0;
215    double yaw2stop = 91.0;
216    double yaw2step = 0.1;
217#endif
218   
219    std::cout << std::endl << "Starting " << __FUNCTION__ << ", it can take a while ..." << std::endl;
220
221    osg::Timer_t tstart, tstop;
222    tstart = osg::Timer::instance()->tick();
223    int count=0;
224    for (double rol1 = rol1start; rol1 <= rol1stop; rol1 += rol1step) {
225    for (double pit1 = pit1start; pit1 <= pit1stop; pit1 += pit1step) {
226        for (double yaw1 = yaw1start; yaw1 <= yaw1stop; yaw1 += yaw1step) {
227        for (double rol2 = rol2start; rol2 <= rol2stop; rol2 += rol2step) {
228            for (double pit2 = pit2start; pit2 <= pit2stop; pit2 += pit2step) {
229            for (double yaw2 = yaw2start; yaw2 <= yaw2stop; yaw2 += yaw2step) {
230                count++;
231                // create two quats based on the roll, pitch and yaw values
232                osg::Quat rot_quat1 =
233                osg::Quat(osg::DegreesToRadians(rol1),osg::Vec3d(1,0,0),
234                      osg::DegreesToRadians(pit1),osg::Vec3d(0,1,0),
235                      osg::DegreesToRadians(yaw1),osg::Vec3d(0,0,1));
236               
237                osg::Quat rot_quat2 =
238                osg::Quat(osg::DegreesToRadians(rol2),osg::Vec3d(1,0,0),
239                      osg::DegreesToRadians(pit2),osg::Vec3d(0,1,0),
240                      osg::DegreesToRadians(yaw2),osg::Vec3d(0,0,1));
241               
242                // create an output quat using quaternion math
243                osg::Quat out_quat1;
244                out_quat1 = rot_quat2 * rot_quat1;
245               
246                // create two matrices based on the input quats
247                osg::Matrixd mat1,mat2;
248                mat1.makeRotate(rot_quat1);
249                mat2.makeRotate(rot_quat2);
250       
251                // create an output quat by matrix multiplication and getRotate
252                osg::Matrixd out_mat;
253                out_mat = mat2 * mat1;
254                // add matrix scale for even more nastiness
255                out_mat = out_mat * scalemat;
256                osg::Quat out_quat2;
257                out_quat2 = out_mat.getRotate();
258               
259                // if the output quat length is not one
260                // or if the component magnitudes do not match,
261                // something is amiss
262                if (fabs(1.0-out_quat2.length()) > eps ||
263                (fabs(out_quat1.x())-fabs(out_quat2.x())) > eps ||
264                (fabs(out_quat1.y())-fabs(out_quat2.y())) > eps ||
265                (fabs(out_quat1.z())-fabs(out_quat2.z())) > eps ||
266                (fabs(out_quat1.w())-fabs(out_quat2.w())) > eps) {
267                std::cout << __FUNCTION__ << " problem at: \n"
268                      << " r1=" << rol1
269                      << " p1=" << pit1
270                      << " y1=" << yaw1
271                      << " r2=" << rol2
272                      << " p2=" << pit2
273                      << " y2=" << yaw2 << "\n";
274                std::cout << "quats:        " << out_quat1 << " length: " << out_quat1.length() << "\n";
275                std::cout << "mats and get: " << out_quat2 << " length: " << out_quat2.length() << "\n\n";
276                }
277            }
278            }
279        }
280        }
281    }
282    }
283    tstop = osg::Timer::instance()->tick();
284    double duration = osg::Timer::instance()->delta_s(tstart,tstop);
285    std::cout << "Time for " << __FUNCTION__ << " with " << count << " iterations: " << duration << std::endl << std::endl;
286}
287
288void testQuatRotate(const osg::Vec3d& from, const osg::Vec3d& to)
289{
290    osg::Quat q_nicolas;
291    q_nicolas.makeRotate(from,to);
292   
293    osg::Quat q_original;
294    q_original.makeRotate_original(from,to);
295   
296    std::cout<<"osg::Quat::makeRotate("<<from<<", "<<to<<")"<<std::endl;
297    std::cout<<"  q_nicolas = "<<q_nicolas<<std::endl;
298    std::cout<<"  q_original = "<<q_original<<std::endl;
299    std::cout<<"  from * M4x4(q_nicolas) = "<<from * osg::Matrixd::rotate(q_nicolas)<<std::endl;
300    std::cout<<"  from * M4x4(q_original) = "<<from * osg::Matrixd::rotate(q_original)<<std::endl;
301}
302
303void testQuat()
304{
305    osg::Quat q1;
306    q1.makeRotate(osg::DegreesToRadians(30.0),0.0f,0.0f,1.0f);
307
308    osg::Quat q2;
309    q2.makeRotate(osg::DegreesToRadians(133.0),0.0f,1.0f,1.0f);
310
311    osg::Quat q1_2 = q1*q2;
312    osg::Quat q2_1 = q2*q1;
313
314    osg::Matrix m1 = osg::Matrix::rotate(q1);
315    osg::Matrix m2 = osg::Matrix::rotate(q2);
316   
317    osg::Matrix m1_2 = m1*m2;
318    osg::Matrix m2_1 = m2*m1;
319   
320    osg::Quat qm1_2;
321    qm1_2.set(m1_2);
322   
323    osg::Quat qm2_1;
324    qm2_1.set(m2_1);
325   
326    std::cout<<"q1*q2 = "<<q1_2<<std::endl;
327    std::cout<<"q2*q1 = "<<q2_1<<std::endl;
328    std::cout<<"m1*m2 = "<<qm1_2<<std::endl;
329    std::cout<<"m2*m1 = "<<qm2_1<<std::endl;
330
331
332    testQuatRotate(osg::Vec3d(1.0,0.0,0.0),osg::Vec3d(0.0,1.0,0.0));
333    testQuatRotate(osg::Vec3d(0.0,1.0,0.0),osg::Vec3d(1.0,0.0,0.0));
334    testQuatRotate(osg::Vec3d(0.0,0.0,1.0),osg::Vec3d(0.0,1.0,0.0));
335    testQuatRotate(osg::Vec3d(1.0,1.0,1.0),osg::Vec3d(1.0,0.0,0.0));
336    testQuatRotate(osg::Vec3d(1.0,0.0,0.0),osg::Vec3d(1.0,0.0,0.0));
337    testQuatRotate(osg::Vec3d(1.0,0.0,0.0),osg::Vec3d(-1.0,0.0,0.0));
338    testQuatRotate(osg::Vec3d(-1.0,0.0,0.0),osg::Vec3d(1.0,0.0,0.0));
339    testQuatRotate(osg::Vec3d(0.0,1.0,0.0),osg::Vec3d(0.0,-1.0,0.0));
340    testQuatRotate(osg::Vec3d(0.0,-1.0,0.0),osg::Vec3d(0.0,1.0,0.0));
341    testQuatRotate(osg::Vec3d(0.0,0.0,1.0),osg::Vec3d(0.0,0.0,-1.0));
342    testQuatRotate(osg::Vec3d(0.0,0.0,-1.0),osg::Vec3d(0.0,0.0,1.0));
343
344    // Test a range of rotations
345    testGetQuatFromMatrix();
346
347    // This is a specific test case for a matrix containing scale and rotation
348    osg::Matrix matrix(0.5, 0.0, 0.0, 0.0,
349                       0.0, 0.5, 0.0, 0.0,
350                       0.0, 0.0, 0.5, 0.0,
351                       1.0, 1.0, 1.0, 1.0);
352                       
353    osg::Quat quat;
354    matrix.get(quat);
355   
356    osg::notify(osg::NOTICE)<<"Matrix = "<<matrix<<"rotation = "<<quat<<", expected quat = (0,0,0,1)"<<std::endl;
357}
358
359
360int main( int argc, char** argv )
361{
362    osg::ArgumentParser arguments(&argc,argv);
363
364    // set up the usage document, in case we need to print out how to use this program.
365    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which runs units tests.");
366    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options]");
367    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
368    arguments.getApplicationUsage()->addCommandLineOption("qt","Display qualified tests.");
369    arguments.getApplicationUsage()->addCommandLineOption("sizeof","Display sizeof tests.");
370    arguments.getApplicationUsage()->addCommandLineOption("matrix","Display qualified tests.");
371    arguments.getApplicationUsage()->addCommandLineOption("performance","Display qualified tests.");
372 
373
374    if (arguments.argc()<=1)
375    {
376        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
377        return 1;
378    }
379
380    bool printQualifiedTest = false;
381    while (arguments.read("qt")) printQualifiedTest = true;
382
383    bool printMatrixTest = false;
384    while (arguments.read("matrix")) printMatrixTest = true;
385
386    bool printSizeOfTest = false;
387    while (arguments.read("sizeof")) printSizeOfTest = true;
388
389    bool printQuatTest = false;
390    while (arguments.read("quat")) printQuatTest = true;
391
392    bool performanceTest = false;
393    while (arguments.read("p") || arguments.read("performance")) performanceTest = true;
394
395    // if user request help write it out to cout.
396    if (arguments.read("-h") || arguments.read("--help"))
397    {
398        std::cout<<arguments.getApplicationUsage()->getCommandLineUsage()<<std::endl;
399        arguments.getApplicationUsage()->write(std::cout,arguments.getApplicationUsage()->getCommandLineOptions());
400        return 1;
401    }
402
403    // any option left unread are converted into errors to write out later.
404    arguments.reportRemainingOptionsAsUnrecognized();
405
406    // report any errors if they have occured when parsing the program aguments.
407    if (arguments.errors())
408    {
409        arguments.writeErrorMessages(std::cout);
410        return 1;
411    }
412   
413    if (printQuatTest)
414    {
415        testQuat();
416    }
417
418
419    if (printMatrixTest)
420    {
421        std::cout<<"******   Running matrix tests   ******"<<std::endl;
422
423        testFrustum(-1,1,-1,1,1,1000);
424        testFrustum(0,1,1,2,2.5,100000);
425
426        testOrtho(0,1,1,2,2.1,1000);
427        testOrtho(-1,10,1,20,2.5,100000);
428
429        testPerspective(20,1,1,1000);
430        testPerspective(90,2,1,1000);
431
432        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));
433        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));
434       
435        testMatrixInvert(osg::Matrix(0.999848,  -0.002700,  0.017242, -0.1715,
436                                     0,         0.987960,   0.154710,  0.207295,
437                                     -0.017452, -0.154687,  0.987809, -0.98239,
438                                     0,         0,          0,         1));
439
440        testMatrixInvert(osg::Matrix(0.999848,  -0.002700,  0.017242,   0.0,
441                                     0.0,        0.987960,   0.154710,   0.0,
442                                     -0.017452, -0.154687,  0.987809,   0.0,
443                                     -0.1715,    0.207295,  -0.98239,   1.0));
444
445    }
446   
447    if (printSizeOfTest)
448    {
449        std::cout<<"**** sizeof() tests  ******"<<std::endl;
450       
451        sizeOfTest();
452
453        std::cout<<std::endl;
454    }
455
456
457    if (performanceTest)
458    {
459        std::cout<<"**** performance tests  ******"<<std::endl;
460       
461        runPerformanceTests();
462    }
463
464
465    if (printQualifiedTest)
466    {
467         std::cout<<"*****   Qualified Tests  ******"<<std::endl;
468
469         osgUtx::QualifiedTestPrinter printer;
470         osgUtx::TestGraph::instance().root()->accept( printer );   
471         std::cout<<std::endl;
472    }
473
474    std::cout<<"******   Running tests   ******"<<std::endl;
475
476    // Global Data or Context
477    osgUtx::TestContext ctx;
478    osgUtx::TestRunner runner( ctx );
479    runner.specify("root");
480
481    osgUtx::TestGraph::instance().root()->accept( runner );
482
483    return 0;
484}
Note: See TracBrowser for help on using the browser.