1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000,2001 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
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. *
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. *
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. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
43 #include <OpenSG/OSGGLUT.h>
44 #include <OpenSG/OSGMatrixUtility.h>
45 #include <OpenSG/OSGGeoIgnorePumpGroup.h>
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)
62 // Set up scene characteristics
64 void Test::setScene(NodeBase
&scene
)
66 _scene
= scene
.getNode();
69 void Test::setScene(OSG::NodePtr scene
)
74 void Test::setWindow(TestWindow
&win
)
79 void Test::setHeadlight(bool on
)
84 void Test::setNearFar(OSG::Real32 n
, OSG::Real32 f
)
93 void Test::clear(void)
100 // MinTime takes precedence, the path is repeated fully until the time is
103 void Test::setNFrames(OSG::UInt32 nframes
)
108 void Test::setMinTime(OSG::Real32 minTime
)
113 void Test::addFromAtUp(OSG::Pnt3f from
, OSG::Pnt3f at
, OSG::Vec3f up
)
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
)
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
))
149 if (OSG::FieldDataTraits
<OSG::Pnt3f
>::getFromString(v
, grmbl
))
152 FWARNING(("Test::addFromOri: error reading from: '%s'!\n",
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
))
163 if (OSG::FieldDataTraits
<OSG::Quaternion
>::getFromString(q
, grmbl
))
166 FWARNING(("Test::addFromOri: error reading ori: '%s'!\n",
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"));
193 OSG::commitChanges();
194 _scene
->updateVolume();
196 OSG::DynamicVolume volume
;
197 _scene
->getWorldVolume(volume
);
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
;
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
)
220 dir
.setValues(0,0,1);
226 right
= dir
.cross(up
);
227 up
= right
.cross(dir
);
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"));
258 _scene
->updateVolume();
260 OSG::DynamicVolume volume
;
261 _scene
->getWorldVolume(volume
);
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
;
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
)
284 dir
.setValues(0,0,1);
290 right
= dir
.cross(up
);
291 up
= right
.cross(dir
);
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
);
322 void Test::setStatistics(OSG::UInt16 level
)
327 OSG::UInt16
Test::getStatistics(void)
332 void Test::setVerbose(bool 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
);
354 else if(!ignore
&& isIgnored
)
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();
376 OSG::UInt32 ss
= _stats
.size();
378 _stats
.resize(_stats
.size() + views
.size());
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
)
392 SWARNING
<< "Test::run: Frame " << i
<< " ("
393 << _nRenderedFrames
<< ") fov "
394 << fovs
[i
] << ", view" << std::endl
<< views
[i
]
396 _win
->setCamera(views
[i
]);
397 _win
->setFov(fovs
[i
]);
401 if(_useRenderTraversal
)
402 ssm
->getRenderTraversalAction()->setStatistics(&_stats
[_nRenderedFrames
]);
404 ssm
->getAction()->setStatistics(&_stats
[_nRenderedFrames
]);
407 OSG::Thread::getCurrentChangeList()->commitChanges();
412 while(_minTime
> 0 && OSG::getSystemTime() - start
< _minTime
);
416 stop
= OSG::getSystemTime();
418 _time
= stop
- start
;
422 if(_useRenderTraversal
)
423 ssm
->getRenderTraversalAction()->setStatistics(NULL
);
425 ssm
->getAction()->setStatistics(NULL
);
431 if(!_win
|| !_win
->isOpen())
433 FWARNING(("Test::run: window not ready!\n"));
438 FWARNING(("Test::run: no scene!\n"));
443 FWARNING(("Test::run: no views!\n"));
448 FWARNING(("Test::run: no views!\n"));
451 if(_froms
.size() != _oris
.size())
453 FWARNING(("Test::run: _froms.size() != _oris.size()!\n"));
459 FWARNING(("Test::run: no fovs!\n"));
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
);
477 OSG::Thread::getCurrentChangeList()->commitChanges();
481 if(_near
> 0 && _far
> 0)
483 _win
->setNearFar(_near
, _far
);
485 FWARNING(("Test::run: near=%f, far=%f\n", _near
, _far
));
488 _nRenderedFrames
= 0;
492 runLoop(views
, fovs
);
496 Image
Test::snapshot(OSG::UInt32 frame
)
498 if(!_win
|| !_win
->isOpen())
500 FWARNING(("Test::snapshot: window not ready!\n"));
505 FWARNING(("Test::snapshot: no scene!\n"));
510 FWARNING(("Test::snapshot: no views!\n"));
515 FWARNING(("Test::snapshot: no views!\n"));
518 if(_froms
.size() != _oris
.size())
520 FWARNING(("Test::snapshot: _froms.size() != _oris.size()!\n"));
526 FWARNING(("Test::snapshot: no fovs!\n"));
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"));
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
);
552 ssm
->getAction()->setStatistics(NULL
);
556 img
= _win
->snapshot();
563 OSG::Real32
Test::getFPS(void)
565 return _nRenderedFrames
/ _time
;
568 OSG::Real32
Test::getTime(void)
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
));
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
));
596 OSG::StatElemDescBase
*desc
= OSG::StatElemDescBase::findDescByName(name
);
599 FWARNING(("Test::getStatValue: name not known '%s'!\n", name
));
602 OSG::StatElem
*el
= _stats
[frame
].getElem(*desc
, false);
605 FWARNING(("Test::getStatValue: no statistics value '%s'!\n", name
));
608 val
= el
->getValue();
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
;
634 views
[i
].setTransform(_froms
[vi
].subZero(), _oris
[vi
]);
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
;
655 fovs
[i
] = _fovs
[fi
] * (1.f
- f
) + _fovs
[fi
+ 1] * f
;;