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

Revision 5359, 13.0 kB (checked in by robert, 8 years ago)

From J.P. Delport, added units tests to pick up on erroneous Matrix::get(Quat&) computation.

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