From 74f8f18ad66c8fd2f373380f468c50a7d2e2b05a Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 19 Mar 2003 12:06:29 +0000 Subject: [PATCH] Added a realize callback to the OsgCameraGroup. Move osgtexture3D across to using the new realize callback for creating its textures. --- examples/osgtexture3D/osgtexture3D.cpp | 48 ++++++++++++++++++------- include/osgProducer/OsgCameraGroup | 31 ++++++++++++++++ src/osgProducer/OsgCameraGroup.cpp | 49 ++++++++++++++++++++------ 3 files changed, 105 insertions(+), 23 deletions(-) diff --git a/examples/osgtexture3D/osgtexture3D.cpp b/examples/osgtexture3D/osgtexture3D.cpp index 64966439c..7f76122fd 100644 --- a/examples/osgtexture3D/osgtexture3D.cpp +++ b/examples/osgtexture3D/osgtexture3D.cpp @@ -24,10 +24,10 @@ typedef std::vector< osg::ref_ptr > ImageList; -class ConstructStateCallback : public osg::NodeCallback +class ConstructStateCallback : public osgProducer::OsgCameraGroup::RealizeCallback { public: - ConstructStateCallback() {} + ConstructStateCallback(osg::Node* node):_node(node),_initialized(false) {} osg::StateSet* constructState() { @@ -82,6 +82,7 @@ class ConstructStateCallback : public osg::NodeCallback osg::Texture3D* texture3D = new osg::Texture3D; texture3D->setFilter(osg::Texture3D::MIN_FILTER,osg::Texture3D::LINEAR); texture3D->setFilter(osg::Texture3D::MAG_FILTER,osg::Texture3D::LINEAR); + texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::REPEAT); texture3D->setImage(image_3d); @@ -103,6 +104,32 @@ class ConstructStateCallback : public osg::NodeCallback return stateset; } + virtual void operator()(const Producer::RenderSurface&, osgProducer::OsgCameraGroup* , osgProducer::OsgSceneHandler* sh) + { + if (!_initialized) + { + // only initialize state once, only need for cases where multiple graphics contexts are + // if which case this callback can get called multiple times. + _initialized = true; + + if (_node) _node->setStateSet(constructState()); + } + // now safe to con + sh->init(); + + } + + + osg::Node* _node; + bool _initialized; + +}; + +class UpdateStateCallback : public osg::NodeCallback +{ + public: + UpdateStateCallback() {} + void animateState(osg::StateSet* stateset) { // here we simply get any existing texgen, and then increment its @@ -113,7 +140,7 @@ class ConstructStateCallback : public osg::NodeCallback { texgen->getPlane(osg::TexGen::R)[3] += 0.001f; } - + } virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) @@ -125,14 +152,6 @@ class ConstructStateCallback : public osg::NodeCallback // we have an exisitng stateset, so lets animate it. animateState(stateset); } - else - { - // no state exist yet, so we must be in the first - // pass, so lets create our stateset with all the - // textures in it. - stateset = constructState(); - if (stateset) node->setStateSet(stateset); - } // note, callback is repsonsible for scenegraph traversal so // should always include call the traverse(node,nv) to ensure @@ -189,7 +208,7 @@ osg::Node* createModel() // A bit hacky, and my plan is to reimplement the osg::scaleImage and // osg::Image::copySubImage() without using GLU which will get round // this current limitation. - geode->setUpdateCallback(new ConstructStateCallback()); + geode->setUpdateCallback(new UpdateStateCallback()); return geode; @@ -241,6 +260,11 @@ int main( int argc, char **argv ) // set the scene to render viewer.setSceneData(rootNode); + + // the construct state uses gl commands to resize images so we are forced + // to only call it once a valid graphics context has been established, + // for that we use a realize callback. + viewer.setRealizeCallback(new ConstructStateCallback(rootNode)); // create the windows and run the threads. viewer.realize(Producer::CameraGroup::ThreadPerCamera); diff --git a/include/osgProducer/OsgCameraGroup b/include/osgProducer/OsgCameraGroup index efb2a04e6..e9fff4d06 100644 --- a/include/osgProducer/OsgCameraGroup +++ b/include/osgProducer/OsgCameraGroup @@ -105,12 +105,40 @@ class OSGPRODUCER_EXPORT OsgCameraGroup : public Producer::CameraGroup void setFusionDistance( osgUtil::SceneView::FusionDistanceMode mode,float value=1.0f); + /** RealizeCallback class one should override to provide an the implemention of realize callbacks. + * Note, this callback overrides the normal call to OsgSceneHandler::init() so it become the your + * responisibility to call this within your callback if required, it is a safe assumption to + * always call OsgSceneHandler::init() within your callback..*/ + class OSGPRODUCER_EXPORT RealizeCallback : public osg::Referenced + { + public: + virtual void operator()( const Producer::RenderSurface & rs, OsgCameraGroup* cg, OsgSceneHandler* sh) = 0; + + protected: + virtual ~RealizeCallback() {} + }; + + /** Set the realize callback to use when once the render surfaces are realized.*/ + void setRealizeCallback( RealizeCallback* cb) { _realizeCallback = cb; } + + /** Get the realize callback.*/ + RealizeCallback* getRealizeCallback() { return _realizeCallback.get(); } + + /** Get the const realize callback.*/ + const RealizeCallback* getRealizeCallback() const { return _realizeCallback.get(); } + + + + + void advance(); + /** Realize the render surfaces (OpenGL graphics) and various threads, and call any realize callbacks.*/ virtual void realize( ThreadingModel thread_model= SingleThreaded ); + /** Dispatch the cull and draw for each of the Camera's for this frame.*/ virtual void frame(); @@ -130,6 +158,9 @@ class OSGPRODUCER_EXPORT OsgCameraGroup : public Producer::CameraGroup float _fusionDistanceValue; SceneHandlerList _shvec; + + osg::ref_ptr _realizeCallback; + osg::ref_ptr _ds; bool _initialized; osg::ref_ptr _frameStamp; diff --git a/src/osgProducer/OsgCameraGroup.cpp b/src/osgProducer/OsgCameraGroup.cpp index f9bd1923e..51de8fb7b 100644 --- a/src/osgProducer/OsgCameraGroup.cpp +++ b/src/osgProducer/OsgCameraGroup.cpp @@ -19,6 +19,37 @@ using namespace Producer; using namespace osgProducer; + + + +class RenderSurfaceRealizeCallback : public Producer::RenderSurface::Callback +{ +public: + + RenderSurfaceRealizeCallback(OsgCameraGroup* cameraGroup,OsgSceneHandler* sceneHandler): + _cameraGroup(cameraGroup), + _sceneHandler(sceneHandler) {} + + virtual void operator()( const RenderSurface & rs) + { + if (_cameraGroup) + { + if (_cameraGroup->getRealizeCallback()) + { + (*(_cameraGroup->getRealizeCallback()))(rs,_cameraGroup,_sceneHandler); + } + else if (_sceneHandler) _sceneHandler->init(); + } + else if (_sceneHandler) _sceneHandler->init(); + } + + OsgCameraGroup* _cameraGroup; + OsgSceneHandler* _sceneHandler; + +}; + + + std::string findCameraConfigFile(const std::string& configFile) { std::string foundFile = osgDB::findDataFile(configFile); @@ -191,29 +222,25 @@ void OsgCameraGroup::realize( ThreadingModel thread_model) if (!_ds) _ds = osg::DisplaySettings::instance(); _ds->setMaxNumberOfGraphicsContexts( _cfg->getNumberOfCameras() ); + + _shvec.clear(); for( unsigned int i = 0; i < _cfg->getNumberOfCameras(); i++ ) { Producer::Camera *cam = _cfg->getCamera(i); osgProducer::OsgSceneHandler *sh = new osgProducer::OsgSceneHandler(_ds.get()); sh->setDefaults(); - if( _global_stateset != NULL ) - sh->setGlobalStateSet( _global_stateset.get() ); - if( _scene_data != NULL ) - sh->setSceneData( _scene_data.get() ); - sh->setBackgroundColor( _background_color); - sh->getState()->setContextID(i); - sh->setFrameStamp( _frameStamp.get() ); _shvec.push_back( sh ); - cam->setSceneHandler( sh ); + RenderSurface* rs = cam->getRenderSurface(); + rs->setRealizeCallback( new RenderSurfaceRealizeCallback(this, sh)); } if( _global_stateset == NULL && _shvec.size() > 0 ) - { + { SceneHandlerList::iterator p = _shvec.begin(); - _global_stateset = (*p)->getGlobalStateSet(); - } + _global_stateset = (*p)->getGlobalStateSet(); + } setUpSceneViewsWithData();