fixed: auto_ptr -> unique_ptr
[opensg.git] / Tools / osgBench / Test.cpp
blob134d64d59106294643743665ebfc063d21a9a108
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000,2001 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <OpenSG/OSGGLUT.h>
44 #include <OpenSG/OSGMatrixUtility.h>
45 #include <OpenSG/OSGGeoIgnorePumpGroup.h>
47 #include "Test.h"
49 Test::Test(void) :
50 _win(NULL), _scene(OSG::NullFC), _near(0), _far(0),
51 _froms(), _oris(), _fovs(),
52 _minTime(-1), _nFrames(0), _headlight(true),
53 _statsLevel(0), _time(0), _nRenderedFrames(0), _stats(),
54 _verbose(false), _useRenderTraversal(false)
58 Test::~Test()
62 // Set up scene characteristics
64 void Test::setScene(NodeBase &scene)
66 _scene = scene.getNode();
69 void Test::setScene(OSG::NodePtr scene)
71 _scene = scene;
74 void Test::setWindow(TestWindow &win)
76 _win = &win;
79 void Test::setHeadlight(bool on)
81 _headlight = on;
84 void Test::setNearFar(OSG::Real32 n, OSG::Real32 f)
86 _near = n;
87 _far = f;
90 // Setup Test Frames
92 // clear all the data
93 void Test::clear(void)
95 _froms.clear();
96 _oris.clear();
97 _fovs.clear();
100 // MinTime takes precedence, the path is repeated fully until the time is
101 // reached
103 void Test::setNFrames(OSG::UInt32 nframes)
105 _nFrames = nframes;
108 void Test::setMinTime(OSG::Real32 minTime)
110 _minTime = minTime;
113 void Test::addFromAtUp(OSG::Pnt3f from, OSG::Pnt3f at, OSG::Vec3f up)
115 OSG::Matrix m;
117 OSG::MatrixLookAt(m, from, at, up);
119 _froms.push_back(from);
120 _oris.push_back(OSG::Quaternion(m));
123 void Test::addFromAtUp(OSG::Real32 fromx, OSG::Real32 fromy, OSG::Real32 fromz,
124 OSG::Real32 atx, OSG::Real32 aty, OSG::Real32 atz,
125 OSG::Real32 upx, OSG::Real32 upy, OSG::Real32 upz)
127 addFromAtUp(OSG::Pnt3f(fromx, fromy, fromz),
128 OSG::Pnt3f(atx, aty, atz),
129 OSG::Vec3f(upx, upy, upz));
132 // Define Path from VRML-Style Positon/Quaternion Strings
133 void Test::addFromOri(OSG::Char8 *from, OSG::Char8 *ori)
135 OSG::Char8 *f = from, *o = ori;
136 OSG::UInt32 frames = 0;
138 while(f && *f && o && *o)
140 OSG::Pnt3f v;
141 OSG::Quaternion q;
143 const OSG::Char8 *grmbl=f;
144 #if defined(OSG_VERSION) && OSG_VERSION >= 020000
145 if (!OSG::FieldTraits<OSG::Pnt3f>::getFromCString(v, grmbl))
146 #elif defined(OSG_VERSION) && OSG_VERSION >= 010300
147 if (!OSG::FieldDataTraits<OSG::Pnt3f>::getFromString(v, grmbl))
148 #else
149 if (OSG::FieldDataTraits<OSG::Pnt3f>::getFromString(v, grmbl))
150 #endif
152 FWARNING(("Test::addFromOri: error reading from: '%s'!\n",
153 f));
154 return;
157 grmbl=o;
158 #if defined(OSG_VERSION) && OSG_VERSION >= 020000
159 if (!OSG::FieldTraits<OSG::Quaternion>::getFromCString(q, grmbl))
160 #elif defined(OSG_VERSION) && OSG_VERSION >= 010300
161 if (!OSG::FieldDataTraits<OSG::Quaternion>::getFromString(q, grmbl))
162 #else
163 if (OSG::FieldDataTraits<OSG::Quaternion>::getFromString(q, grmbl))
164 #endif
166 FWARNING(("Test::addFromOri: error reading ori: '%s'!\n",
167 o));
168 return;
171 _froms.push_back(v);
172 _oris.push_back(q);
174 f = strchr(f, ',');
175 if(f)
176 ++f;
178 o = strchr(o, ',');
179 if(o)
180 ++o;
184 // Make a rotational path around the whole model
185 void Test::makeOrbit(OSG::Real32 upx, OSG::Real32 upy, OSG::Real32 upz)
187 if(_scene == OSG::NullFC)
189 FWARNING(("Test::makeOrbit: need scene!\n"));
190 return;
193 OSG::commitChanges();
194 _scene->updateVolume();
196 OSG::DynamicVolume volume;
197 _scene->getWorldVolume(volume);
199 OSG::Pnt3f center;
200 volume.getCenter(center);
202 OSG::Real32 dia = (volume.getMax() - volume.getMin()).length();
204 OSG::Vec3f up(upx,upy,upz);
205 OSG::Vec3f dir, right;
207 up.normalize();
209 dir = up.cross(OSG::Vec3f(1,0,0));
210 if(dir.squareLength() < OSG::Eps)
212 dir = up.cross(OSG::Vec3f(0,1,0));
214 if(dir.squareLength() < OSG::Eps)
216 dir = up.cross(OSG::Vec3f(0,0,1));
217 if(dir.squareLength() < OSG::Eps)
219 up.setValues(0,1,0);
220 dir.setValues(0,0,1);
225 dir.normalize();
226 right = dir.cross(up);
227 up = right.cross(dir);
229 dir *= dia;
230 right *= dia;
232 _froms.clear();
233 _oris.clear();
235 // Add a few sensible camera locations
236 // Using 4 gives bad results, a few more are necessary
238 const OSG::Real32 nPoints = 100.f;
240 for(int i = 0; i <= nPoints; ++i)
242 OSG::Real32 c = OSG::osgcos( M_PI * 2.f / nPoints * i);
243 OSG::Real32 s = OSG::osgsin( M_PI * 2.f / nPoints * i);
245 addFromAtUp(center + dir * c + right * s, center, up);
249 // Make a pirouette inside the model
250 void Test::makePirouette(OSG::Real32 upx, OSG::Real32 upy, OSG::Real32 upz)
252 if(_scene == OSG::NullFC)
254 FWARNING(("Test::makePirouette: need scene!\n"));
255 return;
258 _scene->updateVolume();
260 OSG::DynamicVolume volume;
261 _scene->getWorldVolume(volume);
263 OSG::Pnt3f center;
264 volume.getCenter(center);
266 OSG::Real32 dia = (volume.getMax() - volume.getMin()).length() * .5;
268 OSG::Vec3f up(upx,upy,upz);
269 OSG::Vec3f dir, right;
271 up.normalize();
273 dir = up.cross(OSG::Vec3f(1,0,0));
274 if(dir.squareLength() < OSG::Eps)
276 dir = up.cross(OSG::Vec3f(0,1,0));
278 if(dir.squareLength() < OSG::Eps)
280 dir = up.cross(OSG::Vec3f(0,0,1));
281 if(dir.squareLength() < OSG::Eps)
283 up.setValues(0,1,0);
284 dir.setValues(0,0,1);
289 dir.normalize();
290 right = dir.cross(up);
291 up = right.cross(dir);
293 dir *= dia;
294 right *= dia;
296 _froms.clear();
297 _oris.clear();
299 addFromAtUp(center, center + dir * OSG::Sqrt2 , up);
300 addFromAtUp(center, center + dir + right , up);
302 addFromAtUp(center, center + right * OSG::Sqrt2, up);
303 addFromAtUp(center, center - dir + right , up);
305 addFromAtUp(center, center - dir * OSG::Sqrt2 , up);
306 addFromAtUp(center, center - dir - right , up);
308 addFromAtUp(center, center - right * OSG::Sqrt2, up);
309 addFromAtUp(center, center + dir - right , up);
311 addFromAtUp(center, center + dir * OSG::Sqrt2 , up);
315 // add a FOV to animate
316 void Test::addFov(OSG::Real32 fov)
318 _fovs.push_back(fov);
321 // Run Test
322 void Test::setStatistics(OSG::UInt16 level)
324 _statsLevel = level;
327 OSG::UInt16 Test::getStatistics(void)
329 return _statsLevel;
332 void Test::setVerbose(bool verbose)
334 _verbose = verbose;
337 void Test::useRenderTraversal(bool val)
339 _useRenderTraversal = val;
342 void Test::setIgnoreGeometry(bool ignore)
344 static bool isIgnored = false;
345 static OSG::GeoPumpGroup* igp = new OSG::GeoIgnorePumpGroup;
347 std::vector<OSG::GeoPumpGroup*> &p = OSG::GeoPumpGroup::getActiveGroups();
349 if(ignore && !isIgnored)
351 p.insert(p.begin(), igp);
352 isIgnored = true;
354 else if(!ignore && isIgnored)
356 p.erase(p.begin());
357 isIgnored = false;
361 // little helper function that runs the test loop. The main reason for this
362 // function is being able to profile it, without the initialisation.
364 void Test::runLoop( std::vector<OSG::Matrix> &views,
365 std::vector<OSG::Real32> &fovs)
367 OSG::Time start, stop;
368 OSG::SimpleSceneManager *ssm = _win->getSSM();
370 start = OSG::getSystemTime();
374 if(_statsLevel)
376 OSG::UInt32 ss = _stats.size();
378 _stats.resize(_stats.size() + views.size());
380 if(_statsLevel > 1)
382 for(OSG::UInt32 i = ss; i < _stats.size(); ++i)
384 _stats[i].getElem(OSG::Geometry::statNTriangles);
389 for(OSG::UInt32 i = 0; i < views.size(); ++i, ++_nRenderedFrames)
391 if(_verbose)
392 SWARNING << "Test::run: Frame " << i << " ("
393 << _nRenderedFrames << ") fov "
394 << fovs[i] << ", view" << std::endl << views[i]
395 << std::endl;
396 _win->setCamera(views[i]);
397 _win->setFov(fovs[i]);
399 if(_statsLevel)
401 if(_useRenderTraversal)
402 ssm->getRenderTraversalAction()->setStatistics(&_stats[_nRenderedFrames]);
403 else
404 ssm->getAction()->setStatistics(&_stats[_nRenderedFrames]);
407 OSG::Thread::getCurrentChangeList()->commitChanges();
409 _win->redraw();
412 while(_minTime > 0 && OSG::getSystemTime() - start < _minTime);
414 _win->finish();
416 stop = OSG::getSystemTime();
418 _time = stop - start;
420 if(_statsLevel)
422 if(_useRenderTraversal)
423 ssm->getRenderTraversalAction()->setStatistics(NULL);
424 else
425 ssm->getAction()->setStatistics(NULL);
429 void Test::run(void)
431 if(!_win || !_win->isOpen())
433 FWARNING(("Test::run: window not ready!\n"));
434 return;
436 if(!_scene)
438 FWARNING(("Test::run: no scene!\n"));
439 return;
441 if(_froms.empty())
443 FWARNING(("Test::run: no views!\n"));
444 return;
446 if(_oris.empty())
448 FWARNING(("Test::run: no views!\n"));
449 return;
451 if(_froms.size() != _oris.size())
453 FWARNING(("Test::run: _froms.size() != _oris.size()!\n"));
454 return;
457 if(_fovs.empty())
459 FWARNING(("Test::run: no fovs!\n"));
460 return;
463 std::vector<OSG::Matrix> views;
464 std::vector<OSG::Real32> fovs;
466 expandData(views, fovs);
468 OSG::Time start, stop;
469 OSG::SimpleSceneManager *ssm = _win->getSSM();
471 _win->setScene(_scene);
472 ssm->setHeadlight(_headlight);
473 ssm->setUseTraversalAction(_useRenderTraversal);
475 _stats.clear();
477 OSG::Thread::getCurrentChangeList()->commitChanges();
478 _win->showAll();
479 _win->redraw();
481 if(_near > 0 && _far > 0)
483 _win->setNearFar(_near, _far);
484 if(_verbose)
485 FWARNING(("Test::run: near=%f, far=%f\n", _near, _far));
488 _nRenderedFrames = 0;
490 _win->finish();
492 runLoop(views, fovs);
496 Image Test::snapshot(OSG::UInt32 frame)
498 if(!_win || !_win->isOpen())
500 FWARNING(("Test::snapshot: window not ready!\n"));
501 return Image();
503 if(!_scene)
505 FWARNING(("Test::snapshot: no scene!\n"));
506 return Image();
508 if(_froms.empty())
510 FWARNING(("Test::snapshot: no views!\n"));
511 return Image();
513 if(_oris.empty())
515 FWARNING(("Test::snapshot: no views!\n"));
516 return Image();
518 if(_froms.size() != _oris.size())
520 FWARNING(("Test::snapshot: _froms.size() != _oris.size()!\n"));
521 return Image();
524 if(_fovs.empty())
526 FWARNING(("Test::snapshot: no fovs!\n"));
527 return Image();
530 std::vector<OSG::Matrix> views;
531 std::vector<OSG::Real32> fovs;
533 expandData(views, fovs);
535 if(frame >= views.size())
537 FWARNING(("Test::snapshot: frame >= views.size()!\n"));
538 return Image();
541 OSG::SimpleSceneManager *ssm = _win->getSSM();
543 _win->setScene(_scene);
544 ssm->setHeadlight(_headlight);
546 _win->setCamera(views[frame]);
547 _win->setFov(fovs[frame]);
549 if(_useRenderTraversal)
550 ssm->getRenderTraversalAction()->setStatistics(NULL);
551 else
552 ssm->getAction()->setStatistics(NULL);
554 OSG::ImagePtr img;
556 img = _win->snapshot();
558 return Image(img);
561 // Get Results
563 OSG::Real32 Test::getFPS(void)
565 return _nRenderedFrames / _time;
568 OSG::Real32 Test::getTime(void)
570 return _time;
573 OSG::UInt32 Test::getNRenderedFrames(void)
575 return _nRenderedFrames;
578 OSG::Real64 Test::getStatValue(OSG::Char8 *name, OSG::UInt32 frame)
580 if(_stats.size() <= frame)
582 FWARNING(("Test::getStatValue: no statistics for frame %d!\n", frame));
583 return -1;
586 OSG::Real64 val;
587 std::string n(name);
589 #if defined(OSG_VERSION) && OSG_VERSION >= 13
590 if(!_stats[frame].getValue(n, val))
592 FWARNING(("Test::getStatValue: no statistics value '%s'!\n", name));
593 return -1;
595 #else
596 OSG::StatElemDescBase *desc = OSG::StatElemDescBase::findDescByName(name);
597 if(!desc)
599 FWARNING(("Test::getStatValue: name not known '%s'!\n", name));
600 return -1;
602 OSG::StatElem *el = _stats[frame].getElem(*desc, false);
603 if(!el)
605 FWARNING(("Test::getStatValue: no statistics value '%s'!\n", name));
606 return -1;
608 val = el->getValue();
609 #endif
611 return val;
615 // expand the animation data to have nFrames elements
617 void Test::expandData(std::vector<OSG::Matrix>& views, std::vector<OSG::Real32> &fovs)
619 views.resize(_nFrames);
620 fovs.resize(_nFrames);
622 // interpolate the values to get _nFrames values
624 OSG::Real32 vscale = (_froms.size() - 1) / (_nFrames - 1.f);
625 OSG::Real32 fscale = (_fovs.size() - 1) / (_nFrames - 1.f);
627 for(OSG::UInt32 i = 0; i < _nFrames; ++i)
629 OSG::UInt32 vi = static_cast<OSG::UInt32>(OSG::osgfloor(i * vscale));
630 OSG::Real32 v = i * vscale - vi;
632 if(v < OSG::Eps)
634 views[i].setTransform(_froms[vi].subZero(), _oris[vi]);
636 else
638 OSG::Quaternion q;
639 q.slerpThis(_oris[vi], _oris[vi+1], v);
641 OSG::Pnt3f p = _froms[vi] + v * (_froms[vi+1] - _froms[vi]);
643 views[i].setTransform(p.subZero(), q);
646 OSG::UInt32 fi = static_cast<OSG::UInt32>(OSG::osgfloor(i * fscale));
647 OSG::Real32 f = i * fscale - fi;
649 if(f < OSG::Eps)
651 fovs[i] = _fovs[fi];
653 else
655 fovs[i] = _fovs[fi] * (1.f - f) + _fovs[fi + 1] * f;;