From 7082abb8ad4cdbd16b35181f28c6964e20aeba5b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 20 Oct 2001 20:26:36 +0000 Subject: [PATCH] Added support for an osgUtil::SceneView::init() traversal which is called once per scene view. The user can attach a NodeVisitor to do init for them, or leave it to the default which is to use the osgUtil::DisplayListVisitor which compiles all display lists and texture objects. The init traversal is called automatically by the first call to either app() or cull(), so should not be called by user code during initialization. This ensures that a valid graphics context has been established before OpenGL is initialized. osgUtil::DisplayListVisitor has also been updated to use a bit mask for options, and the addition of compilation of texture objects (via StateAttribute::compile) has also been added. --- include/osgUtil/DisplayListVisitor | 61 ++++++++---------------- include/osgUtil/SceneView | 20 ++++++-- src/osgUtil/DisplayListVisitor.cpp | 74 +++++++++++++++++++----------- src/osgUtil/SceneView.cpp | 46 +++++++++++++++---- 4 files changed, 120 insertions(+), 81 deletions(-) diff --git a/include/osgUtil/DisplayListVisitor b/include/osgUtil/DisplayListVisitor index c1971ea1b..9581098c9 100644 --- a/include/osgUtil/DisplayListVisitor +++ b/include/osgUtil/DisplayListVisitor @@ -14,68 +14,52 @@ namespace osgUtil { /** Visitor for traversing scene graph and setting each osg::GeoSet's _useDisplayList flag, - * with option to immediately compile osg::GeoSet's OpenGL Display lists. - * The mode of operation - * of the visitor is controlled by setting the DisplayListMode either on visitor - * constructor or via the setDisplayListMode() method. DisplayListMode options are: - * _displayListMode == SWITCH_ON_AND_COMPILE_DISPLAY_LISTS cals gset->compile() on - * all Geode children. Note, the visitor must only be used within a valid - * OpenGL context as compile uses OpenGL calls. - * _displayListMode == SWITCH_ON_DISPLAY_LISTS sets the Geode's children with - * gset->setUseDisplayList(true), this method does not directly create display list, - * or uses OpenGL calls so if safe to use before a valid OpenGL context has been set up. - * On the next redraw of the scene, the gset's draw methods will be called - * which then will respond to their _useDisplayList being set by creating display lists - * automatically. - * _displayListMode == SWITCH_OFF_DISPLAY_LISTS sets the Geode's children with - * gset->setUseDisplayList(false), this method does not directly create display list, - * or uses OpenGL calls so if safe to use before a valid OpenGL context has been set up. + * with option to immediately compile osg::Drawable OpenGL Display lists and + * osg::StateAttribute's. */ class OSGUTIL_EXPORT DisplayListVisitor : public osg::NodeVisitor { public: - /** Operation modes of the DisplayListVisitor.*/ - enum DisplayListMode + /** Operation modes of the.*/ + enum ModeValues { - SWITCH_ON_AND_COMPILE_DISPLAY_LISTS, - COMPILE_ON_DISPLAY_LISTS, - SWITCH_ON_DISPLAY_LISTS, - SWITCH_OFF_DISPLAY_LISTS + SWITCH_ON_DISPLAY_LISTS = 0x1, + SWITCH_OFF_DISPLAY_LISTS = 0x2, + COMPILE_DISPLAY_LISTS = 0x4, + COMPILE_STATE_ATTRIBUTES = 0x8 }; + + typedef unsigned int Mode; /** Construct a CompileGeoSetsVisior to traverse all child, * with set specified display list mode. Default mode is to * gset->setUseDisplayList(true). */ - DisplayListVisitor(DisplayListMode mode=SWITCH_ON_DISPLAY_LISTS); + DisplayListVisitor(Mode mode=COMPILE_DISPLAY_LISTS|COMPILE_STATE_ATTRIBUTES); /** Set the operational mode of how the visitor should set up osg::GeoSet's.*/ - void setDisplayListMode(DisplayListMode mode) { _displayListMode = mode; } + void setMode(Mode mode) { _mode = mode; } /** Get the operational mode.*/ - DisplayListMode getDisplayListMode() const { return _displayListMode; } + Mode getMode() const { return _mode; } + /** Set the State to use during traversal. */ void setState(osg::State* state) { - _externalState = state; - if (_externalState.valid()) _activeState = _externalState; - else _activeState = _localState; + _state = state; } osg::State* getState() { - return _activeState.get(); + return _state.get(); } /** Simply traverse using standard NodeVisitor traverse method.*/ - virtual void apply(osg::Node& node) - { - traverse(node); - } - + virtual void apply(osg::Node& node); + /** For each Geode visited set the display list usage according to the * _displayListMode. */ @@ -83,14 +67,9 @@ class OSGUTIL_EXPORT DisplayListVisitor : public osg::NodeVisitor protected: - DisplayListMode _displayListMode; + Mode _mode; - /** local state is created in constructor and used as the default state during traversal.*/ - osg::ref_ptr _localState; - /** external state is used to override the default state.*/ - osg::ref_ptr _externalState; - /** active state is equal to _externalState when it is valid, otherwise defaults to _localState.*/ - osg::ref_ptr _activeState; + osg::ref_ptr _state; }; diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index 4ea05d61e..bf09a99fc 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -110,6 +110,10 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced const osg::State* getState() const { return _state.get(); } + void setInitVisitor(osg::NodeVisitor* av) { _initVisitor = av; } + osg::NodeVisitor* getInitVisitor() { return _initVisitor.get(); } + const osg::NodeVisitor* getInitVisitor() const { return _initVisitor.get(); } + void setAppVisitor(osg::NodeVisitor* av) { _appVisitor = av; } osg::NodeVisitor* getAppVisitor() { return _appVisitor.get(); } const osg::NodeVisitor* getAppVisitor() const { return _appVisitor.get(); } @@ -181,14 +185,22 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced inline const osg::FrameStamp* getFrameStamp() const { return _frameStamp.get(); } + /** Do init traversal of attached scene graph using Init NodeVisitor. + * The init traversal is called once for each SceneView, and should + * be used to compile display list, texture objects intialize data + * not otherwise intializaed during scene graph loading. Note, is + * called automatically by app&cull if it hasn't already been called + * elsewhere. Also init() should only ever be called within a valid + * graphics context.*/ + virtual void init(); - /** do app traversal of attached scene graph using App NodeVisitor.*/ + /** Do app traversal of attached scene graph using App NodeVisitor.*/ virtual void app(); - /** do cull traversal of attached scene graph using App CullVisitor.*/ + /** Do cull traversal of attached scene graph using Cull NodeVisitor.*/ virtual void cull(); - /** do draw traversal of draw bins generated by cull traversal.*/ + /** Do draw traversal of draw bins generated by cull traversal.*/ virtual void draw(); protected: @@ -201,6 +213,8 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced osg::ref_ptr _camera; osg::ref_ptr _state; + bool _initCalled; + osg::ref_ptr _initVisitor; osg::ref_ptr _appVisitor; osg::ref_ptr _cullVisitor; osg::ref_ptr _rendergraph; diff --git a/src/osgUtil/DisplayListVisitor.cpp b/src/osgUtil/DisplayListVisitor.cpp index b98909b15..69c51d3ce 100644 --- a/src/osgUtil/DisplayListVisitor.cpp +++ b/src/osgUtil/DisplayListVisitor.cpp @@ -4,53 +4,71 @@ using namespace osg; using namespace osgUtil; -DisplayListVisitor::DisplayListVisitor(DisplayListMode mode) +DisplayListVisitor::DisplayListVisitor(Mode mode) { setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN); - _displayListMode = mode; - _localState = new osg::State; - _externalState = NULL; + _mode = mode; - _activeState = _localState; + _state = NULL; } +void DisplayListVisitor::apply(osg::Node& node) +{ + if ((_mode&COMPILE_STATE_ATTRIBUTES) && node.getStateSet() && _state.valid()) + { + node.getStateSet()->compile(*_state); + } + + traverse(node); +} + void DisplayListVisitor::apply(osg::Geode& node) { - switch(_displayListMode) + if (_mode&COMPILE_STATE_ATTRIBUTES && _state.valid()) { - case(SWITCH_OFF_DISPLAY_LISTS): + if (node.getStateSet()) { - for(int i=0;isetUseDisplayList(false); - } + node.getStateSet()->compile(*_state); } - break; - case(SWITCH_ON_DISPLAY_LISTS): + + for(int i=0;igetUseDisplayList()) { - node.getDrawable(i)->setUseDisplayList(true); - } - } - break; - case(COMPILE_ON_DISPLAY_LISTS): - { - for(int i=0;igetUseDisplayList()) + if (drawable->getStateSet()) { - node.getDrawable(i)->compile(*_activeState); + drawable->getStateSet()->compile(*_state); } } } - break; - case(SWITCH_ON_AND_COMPILE_DISPLAY_LISTS): + } + + if (_mode&SWITCH_OFF_DISPLAY_LISTS) + { + for(int i=0;isetUseDisplayList(false); + } + } + if (_mode&SWITCH_ON_DISPLAY_LISTS) + { + for(int i=0;isetUseDisplayList(true); + } + } + + if (_mode&COMPILE_DISPLAY_LISTS && _state.valid()) + { + for(int i=0;igetUseDisplayList()) + { + node.getDrawable(i)->compile(*_state); + } } - break; } } diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index f5cb78fd5..8298bbb49 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -28,6 +29,8 @@ SceneView::SceneView() _viewport = new Viewport; + _initCalled = false; + } @@ -46,19 +49,21 @@ void SceneView::setDefaults() _light->setDiffuse(Vec4(0.8f,0.8f,0.8f,1.0f)); _light->setSpecular(Vec4(0.1f,0.1f,0.1f,1.0f)); - - - _camera = new osg::Camera; + _camera = new Camera; - _state = new osg::State; + _state = new State; - _rendergraph = new osgUtil::RenderGraph; - _renderStage = new osgUtil::RenderStage; + _rendergraph = new RenderGraph; + _renderStage = new RenderStage; - _appVisitor = new osgUtil::AppVisitor; - - _cullVisitor = new osgUtil::CullVisitor; + DisplayListVisitor* dlv = new DisplayListVisitor(); + dlv->setState(_state.get()); + _initVisitor = dlv; + + _appVisitor = new AppVisitor; + + _cullVisitor = new CullVisitor; _cullVisitor->setRenderGraph(_rendergraph.get()); _cullVisitor->setRenderStage(_renderStage.get()); @@ -85,9 +90,29 @@ void SceneView::setDefaults() } +void SceneView::init() +{ + _initCalled = true; + + if (_sceneData.valid() && _initVisitor.valid()) + { + _initVisitor->reset(); + _initVisitor->setFrameStamp(_frameStamp.get()); + + if (_frameStamp.valid()) + { + _initVisitor->setTraversalNumber(_frameStamp->getFrameNumber()); + } + + _sceneData->accept(*_initVisitor.get()); + + } +} void SceneView::app() { + if (!_initCalled) init(); + if (_sceneData.valid() && _appVisitor.valid()) { _appVisitor->reset(); @@ -108,8 +133,11 @@ void SceneView::app() void SceneView::cull() { + if (!_sceneData) return; + if (!_initCalled) init(); + _camera->adjustAspectRatio(_viewport->aspectRatio());