c++ - Multiple Qt widgets depicting different OpenSceneGraph nodes without performance loss -
we facing following problem: have application needs display multitude of separate openscenegraph scenes in different qt widgets. example, might have 1 qt widget depicting sphere, while widget depicts icosahedron. since using openscenegraph 3.0.1, followed osgviewerqt example official documentation implementing this.
the example code uses qtimer in order force updates viewer widget:
connect( &_timer, signal(timeout()), this, slot(update()) ); _timer.start( 10 ); the problems begin when want create , show multiple widgets. since each widget comes own timer, performance rapidly decreases number of open widgets. not interaction osg widgets slow, interaction other qt widgets noticeably lags. halfway recent quad-core system overwhelmed when approximately 5 windows open. issue definitely not related our graphics hardware. other applications may render larger scenes (blender, meshlab etc.) without negative performance impact.
so, summarize: best way of creating multiple qt widgets showing different openscenegraph scenes without performance impact?
what tried:
- we considered using single
osgviewer::compositeviewerrendering all scene objects. however, discarded idea because make interactions single widget complicated. - we tried putting rendering portion of each
osgviewer::compositeviewerin separate thread detailed osgqtwidgets example.
our second try (using threads) looked this:
class viewerframethread : public openthreads::thread { public: viewerframethread(osgviewer::viewerbase* viewerbase): _viewerbase(viewerbase) {} ~viewerframethread() { cancel(); while(isrunning()) { openthreads::thread::yieldcurrentthread(); } } int cancel() { _viewerbase->setdone(true); return 0; } void run() { int result = _viewerbase->run(); } osg::ref_ptr<osgviewer::viewerbase> _viewerbase; }; however, also resulted in remarkable performance decrease. each thread still requires cpu time (which not surprising basic interaction still handled timer). advantage of approach @ least interaction other qt widgets remain possible.
the ideal solution widget fires redraw requests whenever user interacts it, example clicking, double-clicking, scrolling etc. more precisely, widget should remain idle until there need update. akin possible at all? welcome suggestions.
having tried out several models problem, happy report found 1 working perfectly. using qthread (similar thread described above) wraps osgviewer::viewerbase object , calls viewer->run().
the trick keep cpu usage low force openscenegraph render on demand only. having tried out various options, found following 2 settings work best:
viewer->setrunframescheme( osgviewer::viewerbase::on_demand ); viewer->setthreadingmodel( osgviewer::viewerbase::culldrawthreadpercontext ); a viewer modified not use spurious cpu cycles continuous updates while still using multiple threads culling , drawing. other threading models might of course perform better in cases, me, sufficient.
if 1 else attempts similar solution, warned operations require explicit redraw requests. example, when handling interactions osg objects or when writing own cameramanipulator class, doesn't hurt call viewer->requestredraw() after changing viewer settings. else, viewer refresh when widget requires repaint.
in short, here's learned:
- don't use timers rendering
- don't give on multiple threads yet
- nothing beats reading source code (the official osg examples scarce on details, source never lies...)
Comments
Post a Comment