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.
This commit is contained in:
@@ -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<osg::State> _localState;
|
||||
/** external state is used to override the default state.*/
|
||||
osg::ref_ptr<osg::State> _externalState;
|
||||
/** active state is equal to _externalState when it is valid, otherwise defaults to _localState.*/
|
||||
osg::ref_ptr<osg::State> _activeState;
|
||||
osg::ref_ptr<osg::State> _state;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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<osg::Camera> _camera;
|
||||
osg::ref_ptr<osg::State> _state;
|
||||
|
||||
bool _initCalled;
|
||||
osg::ref_ptr<osg::NodeVisitor> _initVisitor;
|
||||
osg::ref_ptr<osg::NodeVisitor> _appVisitor;
|
||||
osg::ref_ptr<osgUtil::CullVisitor> _cullVisitor;
|
||||
osg::ref_ptr<osgUtil::RenderGraph> _rendergraph;
|
||||
|
||||
@@ -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;i<node.getNumDrawables();++i)
|
||||
{
|
||||
node.getDrawable(i)->setUseDisplayList(false);
|
||||
}
|
||||
node.getStateSet()->compile(*_state);
|
||||
}
|
||||
break;
|
||||
case(SWITCH_ON_DISPLAY_LISTS):
|
||||
|
||||
for(int i=0;i<node.getNumDrawables();++i)
|
||||
{
|
||||
for(int i=0;i<node.getNumDrawables();++i)
|
||||
Drawable* drawable = node.getDrawable(i);
|
||||
if (drawable->getUseDisplayList())
|
||||
{
|
||||
node.getDrawable(i)->setUseDisplayList(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case(COMPILE_ON_DISPLAY_LISTS):
|
||||
{
|
||||
for(int i=0;i<node.getNumDrawables();++i)
|
||||
{
|
||||
if (node.getDrawable(i)->getUseDisplayList())
|
||||
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;i<node.getNumDrawables();++i)
|
||||
{
|
||||
node.compileDrawables(*_activeState);
|
||||
node.getDrawable(i)->setUseDisplayList(false);
|
||||
}
|
||||
}
|
||||
if (_mode&SWITCH_ON_DISPLAY_LISTS)
|
||||
{
|
||||
for(int i=0;i<node.getNumDrawables();++i)
|
||||
{
|
||||
node.getDrawable(i)->setUseDisplayList(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (_mode&COMPILE_DISPLAY_LISTS && _state.valid())
|
||||
{
|
||||
for(int i=0;i<node.getNumDrawables();++i)
|
||||
{
|
||||
if (node.getDrawable(i)->getUseDisplayList())
|
||||
{
|
||||
node.getDrawable(i)->compile(*_state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <osgUtil/SceneView>
|
||||
#include <osgUtil/AppVisitor>
|
||||
#include <osgUtil/DisplayListVisitor>
|
||||
|
||||
#include <osg/Notify>
|
||||
#include <osg/Texture>
|
||||
@@ -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());
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user