diff --git a/applications/osgviewer/osgviewer.cpp b/applications/osgviewer/osgviewer.cpp index 49bfd9c25..4a75d3918 100644 --- a/applications/osgviewer/osgviewer.cpp +++ b/applications/osgviewer/osgviewer.cpp @@ -29,7 +29,6 @@ int main_osgProducer(osg::ArgumentParser& arguments) arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters"); arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available"); arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available"); - arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings."); @@ -140,8 +139,101 @@ int main_osgProducer(osg::ArgumentParser& arguments) #include #include +class ThreadingHandler : public osgGA::GUIEventHandler +{ +public: + + ThreadingHandler() {} + + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) + { + osgViewer::Viewer* viewer = dynamic_cast(&aa); + if (!viewer) return false; + + switch(ea.getEventType()) + { + case(osgGA::GUIEventAdapter::KEYUP): + { + if (ea.getKey()=='m') + { + switch(viewer->getThreadingModel()) + { + case(osgViewer::Viewer::SingleThreaded): + viewer->setThreadingModel(osgViewer::Viewer::ThreadPerContext); + osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerContext' selected."<setThreadingModel(osgViewer::Viewer::ThreadPerCamera); + osg::notify(osg::NOTICE)<<"Threading model 'ThreadPerCamera' selected."<setThreadingModel(osgViewer::Viewer::SingleThreaded); + osg::notify(osg::NOTICE)<<"Threading model 'SingleTheaded' selected."<getEndBarrierPosition()) + { + case(osgViewer::Viewer::BeforeSwapBuffers): + viewer->setEndBarrierPosition(osgViewer::Viewer::AfterSwapBuffers); + osg::notify(osg::NOTICE)<<"Threading model 'AfterSwapBuffers' selected."<setEndBarrierPosition(osgViewer::Viewer::BeforeSwapBuffers); + osg::notify(osg::NOTICE)<<"Threading model 'BeforeSwapBuffers' selected."<setApplicationName(arguments.getApplicationName()); + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the standard OpenSceneGraph example which loads and visualises 3d models."); + arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); + arguments.getApplicationUsage()->addCommandLineOption("--image ","Load an image and render it on a quad"); + arguments.getApplicationUsage()->addCommandLineOption("--dem ","Load an image/DEM and render it on a HeightField"); + arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters"); + arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available"); + arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available"); + arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings."); + + // if user request help write it out to cout. + bool helpAll = arguments.read("--help-all"); + unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) | + ((helpAll || arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) | + ((helpAll || arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 ); + if (helpType) + { + arguments.getApplicationUsage()->write(std::cout, helpType); + return 1; + } + + // report any errors if they have occurred when parsing the program arguments. + if (arguments.errors()) + { + arguments.writeErrorMessages(std::cout); + return 1; + } + + if (arguments.argc()<=1) + { + arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); + return 1; + } + osgViewer::Viewer viewer; // set up the camera manipulators. @@ -176,7 +268,35 @@ int main_osgViewer(osg::ArgumentParser& arguments) viewer.addEventHandler( statesetManipulator.get() ); } - viewer.setSceneData( osgDB::readNodeFiles(arguments) ); + // add the thread model handler + { + viewer.addEventHandler(new ThreadingHandler); + } + + // load the data + osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); + if (!loadedModel) + { + std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl; + return 1; + } + + // any option left unread are converted into errors to write out later. + arguments.reportRemainingOptionsAsUnrecognized(); + + // report any errors if they have occurred when parsing the program arguments. + if (arguments.errors()) + { + arguments.writeErrorMessages(std::cout); + return 1; + } + + + // optimize the scene graph, remove redundant nodes and state etc. + osgUtil::Optimizer optimizer; + optimizer.optimize(loadedModel.get()); + + viewer.setSceneData( loadedModel.get() ); return viewer.run(); } diff --git a/examples/osgcamera/osgcamera.cpp b/examples/osgcamera/osgcamera.cpp index e3919955e..ddaa00cc1 100644 --- a/examples/osgcamera/osgcamera.cpp +++ b/examples/osgcamera/osgcamera.cpp @@ -123,7 +123,7 @@ int main( int argc, char **argv ) while (arguments.read("-p",pathfile)) { apm = new osgGA::AnimationPathManipulator(pathfile); - if(!apm.valid() || !(apm->valid()) ) + if (!apm.valid() || !(apm->valid()) ) { apm = 0; } diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index 39de2d1c6..fee7dd9e6 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -57,14 +57,30 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View /** Get the threading model the rendering traversals will use.*/ ThreadingModel getThreadingModel() const { return _threadingModel; } - /** Set the key value that the viewer checks on each frame to see if the viewer's done flag should be set to + enum BarrierPosition + { + BeforeSwapBuffers, + AfterSwapBuffers + }; + + /** Set the position of the end barrier. + * AfterSwapBuffers will may result is slightly higher framerates, by may + * lead to inconcistent swapping between different windows. + * BeforeSwapBuffers may lead to slightly lower framerate, but improve consistency in timing of swap buffers, + * especially important if you are likely to consistently break frame.*/ + void setEndBarrierPosition(BarrierPosition bp); + + /** Get the end barrier position.*/ + BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; } + + /** Set the key event that the viewer checks on each frame to see if the viewer's done flag should be set to * signal end of viewers main loop. * Default value is Escape (osgGA::GUIEVentAdapter::KEY_Escape). * Setting to 0 switches off the feature.*/ - void setKeySetsDone(int key) { _keySetsDone = key; } + void setKeyEventSetsDone(int key) { _keyEventSetsDone = key; } - /** get the key value that the viewer checks on each frame to see if the viewer's done flag.*/ - int getKeySetsDone() const { return _keySetsDone; } + /** get the key event that the viewer checks on each frame to see if the viewer's done flag.*/ + int getKeyEventSetsDone() const { return _keyEventSetsDone; } /** if the flag is true, the viewer set its done flag when a QUIT_APPLICATION is received, false disables this feature */ void setQuitEventSetsDone(bool flag) { _quitEventSetsDone = flag; } @@ -121,11 +137,12 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View bool _firstFrame; bool _done; - int _keySetsDone; + int _keyEventSetsDone; bool _quitEventSetsDone; ThreadingModel _threadingModel; - + BarrierPosition _endBarrierPosition; + osg::ref_ptr _startRenderingBarrier; osg::ref_ptr _endRenderingDispatchBarrier; diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 33695ac6a..c90ef52ae 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -26,9 +26,10 @@ using namespace osgViewer; Viewer::Viewer(): _firstFrame(true), _done(false), - _keySetsDone(osgGA::GUIEventAdapter::KEY_Escape), + _keyEventSetsDone(osgGA::GUIEventAdapter::KEY_Escape), _quitEventSetsDone(true), _threadingModel(ThreadPerContext), + _endBarrierPosition(AfterSwapBuffers), _numThreadsOnBarrier(0) { _eventVisitor = new osgGA::EventVisitor; @@ -129,6 +130,18 @@ void Viewer::setThreadingModel(ThreadingModel threadingModel) if (_threadingModel!=SingleThreaded) startThreading(); } + +void Viewer::setEndBarrierPosition(BarrierPosition bp) +{ + if (_endBarrierPosition == bp) return; + + if (_threadingModel!=SingleThreaded) stopThreading(); + + _endBarrierPosition = bp; + + if (_threadingModel!=SingleThreaded) startThreading(); +} + void Viewer::stopThreading() { if (_numThreadsOnBarrier==0) return; @@ -293,12 +306,21 @@ void Viewer::startThreading() // add the rendering operation itself. gc->getGraphicsThread()->add(new RunOperations(gc)); - // add the endRenderingDispatchBarrier - gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + if (_endBarrierPosition==BeforeSwapBuffers) + { + // add the endRenderingDispatchBarrier + gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + } // add the swap buffers gc->getGraphicsThread()->add(swapOp.get()); + if (_endBarrierPosition==AfterSwapBuffers) + { + // add the endRenderingDispatchBarrier + gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + } + } @@ -801,7 +823,7 @@ void Viewer::eventTraversal() // osg::notify(osg::NOTICE)<<"Events "<getEventType()) { case(osgGA::GUIEventAdapter::KEYUP): - if (event->getKey()==_keySetsDone) _done = true; - else if (event->getKey()=='s') { setThreadingModel(SingleThreaded); } - else if (event->getKey()=='c') { setThreadingModel(ThreadPerCamera); } - else if (event->getKey()=='w') { setThreadingModel(ThreadPerContext); } + if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true; break; case(osgGA::GUIEventAdapter::QUIT_APPLICATION): - _done = true; + if (_quitEventSetsDone) _done = true; break; default: diff --git a/src/osgWrappers/osgViewer/Viewer.cpp b/src/osgWrappers/osgViewer/Viewer.cpp index 9a1b8e26e..b2e349a84 100644 --- a/src/osgWrappers/osgViewer/Viewer.cpp +++ b/src/osgWrappers/osgViewer/Viewer.cpp @@ -32,6 +32,11 @@ BEGIN_ENUM_REFLECTOR(osgViewer::Viewer::ThreadingModel) I_EnumLabel(osgViewer::Viewer::ThreadPerCamera); END_REFLECTOR +BEGIN_ENUM_REFLECTOR(osgViewer::Viewer::BarrierPosition) + I_EnumLabel(osgViewer::Viewer::BeforeSwapBuffers); + I_EnumLabel(osgViewer::Viewer::AfterSwapBuffers); +END_REFLECTOR + BEGIN_OBJECT_REFLECTOR(osgViewer::Viewer) I_BaseType(osgViewer::View); I_Constructor0(____Viewer, @@ -69,13 +74,21 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::Viewer) __ThreadingModel__getThreadingModel, "Get the threading model the rendering traversals will use. ", ""); - I_Method1(void, setKeySetsDone, IN, int, key, - __void__setKeySetsDone__int, - "Set the key value that the viewer checks on each frame to see if the viewer's done flag should be set to signal end of viewers main loop. ", + I_Method1(void, setEndBarrierPosition, IN, osgViewer::Viewer::BarrierPosition, bp, + __void__setEndBarrierPosition__BarrierPosition, + "Set the position of the end barrier. ", + "AfterSwapBuffers will may result is slightly higher framerates, by may lead to inconcistent swapping between different windows. BeforeSwapBuffers may lead to slightly lower framerate, but improve consistency in timing of swap buffers, especially important if you are likely to consistently break frame. "); + I_Method0(osgViewer::Viewer::BarrierPosition, getEndBarrierPosition, + __BarrierPosition__getEndBarrierPosition, + "Get the end barrier position. ", + ""); + I_Method1(void, setKeyEventSetsDone, IN, int, key, + __void__setKeyEventSetsDone__int, + "Set the key event that the viewer checks on each frame to see if the viewer's done flag should be set to signal end of viewers main loop. ", "Default value is Escape (osgGA::GUIEVentAdapter::KEY_Escape). Setting to 0 switches off the feature. "); - I_Method0(int, getKeySetsDone, - __int__getKeySetsDone, - "get the key value that the viewer checks on each frame to see if the viewer's done flag. ", + I_Method0(int, getKeyEventSetsDone, + __int__getKeyEventSetsDone, + "get the key event that the viewer checks on each frame to see if the viewer's done flag. ", ""); I_Method1(void, setQuitEventSetsDone, IN, bool, flag, __void__setQuitEventSetsDone__bool, @@ -143,12 +156,15 @@ BEGIN_OBJECT_REFLECTOR(osgViewer::Viewer) I_SimpleProperty(bool, Done, 0, __void__setDone__bool); + I_SimpleProperty(osgViewer::Viewer::BarrierPosition, EndBarrierPosition, + __BarrierPosition__getEndBarrierPosition, + __void__setEndBarrierPosition__BarrierPosition); I_SimpleProperty(osg::FrameStamp *, FrameStamp, __osg_FrameStamp_P1__getFrameStamp, 0); - I_SimpleProperty(int, KeySetsDone, - __int__getKeySetsDone, - __void__setKeySetsDone__int); + I_SimpleProperty(int, KeyEventSetsDone, + __int__getKeyEventSetsDone, + __void__setKeyEventSetsDone__int); I_SimpleProperty(bool, QuitEventSetsDone, __bool__getQuitEventSetsDone, __void__setQuitEventSetsDone__bool);