Refactored the way the Scene is used in Viewer and CompositeViewer to ensure

that only on Scene exists per scene graph.
This commit is contained in:
Robert Osfield
2007-08-10 10:52:35 +00:00
parent 9b04594126
commit 7366daca91
11 changed files with 234 additions and 245 deletions

View File

@@ -133,3 +133,18 @@ void RunOperations::operator () (osg::GraphicsContext* context)
{
context->runOperations();
}
/////////////////////////////////////////////////////////////////////////////
//
// EndOfDynamicDrawBlock
//
EndOfDynamicDrawBlock::EndOfDynamicDrawBlock(unsigned int numberOfBlocks):
BlockCount(numberOfBlocks)
{
}
void EndOfDynamicDrawBlock::completed(osg::State* /*state*/)
{
BlockCount::completed();
}

View File

@@ -61,6 +61,11 @@ void CompositeViewer::constructorInit()
setEventQueue(new osgGA::EventQueue);
_eventVisitor = new osgGA::EventVisitor;
_eventVisitor->setFrameStamp(_frameStamp.get());
_updateVisitor = new osgUtil::UpdateVisitor;
_updateVisitor->setFrameStamp(_frameStamp.get());
}
CompositeViewer::~CompositeViewer()
@@ -106,6 +111,8 @@ void CompositeViewer::addView(osgViewer::View* view)
_views.push_back(view);
view->setFrameStamp(_frameStamp.get());
if (threadsWereRuinning) startThreading();
}
@@ -177,6 +184,13 @@ void CompositeViewer::setStartTick(osg::Timer_t tick)
{
_startTick = tick;
for(Views::iterator vitr = _views.begin();
vitr != _views.end();
++vitr)
{
(*vitr)->setStartTick(tick);
}
Contexts contexts;
getContexts(contexts,false);
@@ -970,16 +984,24 @@ void CompositeViewer::updateTraversal()
Scenes scenes;
getScenes(scenes);
for(Scenes::iterator sitr = scenes.begin();
sitr != scenes.end();
++sitr)
{
(*sitr)->setFrameStamp(_frameStamp.get());
(*sitr)->updateTraversal();
Scene* scene = *sitr;
if (scene->getSceneData())
{
scene->getSceneData()->accept(*_updateVisitor);
}
if (scene->getDatabasePager())
{
// syncronize changes required by the DatabasePager thread to the scene graph
scene->getDatabasePager()->updateSceneGraph(_frameStamp->getReferenceTime());
}
}
for(Views::iterator vitr = _views.begin();
vitr != _views.end();
++vitr)
@@ -987,23 +1009,22 @@ void CompositeViewer::updateTraversal()
View* view = vitr->get();
Scene* scene = view->getScene();
osgUtil::UpdateVisitor* uv = scene ? scene->getUpdateVisitor() : 0;
if (uv)
{
// call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
// leave that to the scene update traversal.
osg::NodeVisitor::TraversalMode tm = uv->getTraversalMode();
uv->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
_updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
if (view->getCamera() && view->getCamera()->getUpdateCallback()) view->getCamera()->accept(*uv);
if (view->getCamera() && view->getCamera()->getUpdateCallback()) view->getCamera()->accept(*_updateVisitor);
for(unsigned int i=0; i<view->getNumSlaves(); ++i)
{
osg::Camera* camera = view->getSlave(i)._camera.get();
if (camera && camera->getUpdateCallback()) camera->accept(*uv);
if (camera && camera->getUpdateCallback()) camera->accept(*_updateVisitor);
}
uv->setTraversalMode(tm);
_updateVisitor->setTraversalMode(tm);
}

View File

@@ -20,7 +20,6 @@
#include <osgViewer/Renderer>
#include <osgViewer/View>
#include <osgViewer/Viewer>
#include <osgDB/DatabasePager>
@@ -232,12 +231,10 @@ void Renderer::updateSceneView(osgUtil::SceneView* sceneView)
}
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(view);
Scene* scene = view ? view->getScene() : 0;
osgDB::DatabasePager* databasePager = scene ? scene->getDatabasePager() : 0;
osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
sceneView->getCullVisitor()->setDatabaseRequestHandler(databasePager);
sceneView->setFrameStamp(scene ? scene->getFrameStamp() : state->getFrameStamp());
sceneView->setFrameStamp(view ? view->getFrameStamp() : state->getFrameStamp());
if (databasePager) databasePager->setCompileGLObjectsForContextID(state->getContextID(), true);
@@ -246,7 +243,7 @@ void Renderer::updateSceneView(osgUtil::SceneView* sceneView)
sceneView->setDisplaySettings(ds);
if (viewer) _startTick = viewer->getStartTick();
if (view) _startTick = view->getStartTick();
}
@@ -330,8 +327,7 @@ void Renderer::draw()
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex[_currentDraw]);
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
Scene* scene = view ? view->getScene() : 0;
osgDB::DatabasePager* databasePager = scene ? scene->getDatabasePager() : 0;
osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
// osg::notify(osg::NOTICE)<<"Drawing buffer "<<_currentDraw<<std::endl;
@@ -433,8 +429,7 @@ void Renderer::cull_draw()
updateSceneView(sceneView);
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
Scene* scene = view ? view->getScene() : 0;
osgDB::DatabasePager* databasePager = scene ? scene->getDatabasePager() : 0;
osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
osg::GraphicsContext* compileContext = osg::GraphicsContext::getCompileContext(sceneView->getState()->getContextID());
osg::GraphicsThread* compileThread = compileContext ? compileContext->getGraphicsThread() : 0;

View File

@@ -16,35 +16,35 @@
using namespace osgViewer;
Scene::Scene():
_firstFrame(true)
{
_frameStamp = new osg::FrameStamp;
_frameStamp->setFrameNumber(0);
_frameStamp->setReferenceTime(0);
typedef std::vector< osg::observer_ptr<Scene> > SceneCache;
static OpenThreads::Mutex s_sceneCacheMutex;
static SceneCache s_sceneCache;
_updateVisitor = new osgUtil::UpdateVisitor;
_updateVisitor->setFrameStamp(_frameStamp.get());
Scene::Scene():
osg::Referenced(true)
{
setDatabasePager(osgDB::DatabasePager::create());
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_sceneCacheMutex);
s_sceneCache.push_back(this);
}
Scene::~Scene()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_sceneCacheMutex);
for(SceneCache::iterator itr = s_sceneCache.begin();
itr != s_sceneCache.end();
++itr)
{
Scene* scene = itr->get();
if (scene==this)
{
s_sceneCache.erase(itr);
break;
}
}
}
void Scene::setFrameStamp(osg::FrameStamp* frameStamp)
{
_frameStamp = frameStamp;
_updateVisitor->setFrameStamp(_frameStamp.get());
}
void Scene::init()
{
osg::notify(osg::NOTICE)<<"Scene::init() not implementated yet."<<std::endl;
}
void Scene::setSceneData(osg::Node* node)
{
_sceneData = node;
@@ -71,31 +71,17 @@ void Scene::setDatabasePager(osgDB::DatabasePager* dp)
_databasePager = dp;
}
void Scene::advance()
Scene* Scene::getScene(osg::Node* node)
{
// double previousTime = _frameStamp->getReferenceTime();
_frameStamp->setReferenceTime(osg::Timer::instance()->time_s());
_frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
// osg::notify(osg::NOTICE)<<"Frame rate = "<<1.0/(_frameStamp->getReferenceTime()-previousTime)<<std::endl;
}
void Scene::updateTraversal()
{
_updateVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
if (!getSceneData()) return;
getSceneData()->accept(*_updateVisitor);
if (_databasePager.valid())
{
// syncronize changes required by the DatabasePager thread to the scene graph
_databasePager->updateSceneGraph(_frameStamp->getReferenceTime());
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_sceneCacheMutex);
for(SceneCache::iterator itr = s_sceneCache.begin();
itr != s_sceneCache.end();
++itr)
{
Scene* scene = itr->get();
if (scene && scene->getSceneData()==node) return scene;
}
return 0;
}

View File

@@ -17,6 +17,7 @@
#include <osg/io_utils>
#include <osgUtil/Optimizer>
#include <osgUtil/IntersectionVisitor>
using namespace osgViewer;
@@ -125,6 +126,15 @@ View::View():
{
// osg::notify(osg::NOTICE)<<"Constructing osgViewer::View"<<std::endl;
_startTick = 0;
_frameStamp = new osg::FrameStamp;
_frameStamp->setFrameNumber(0);
_frameStamp->setReferenceTime(0);
_frameStamp->setSimulationTime(0);
_scene = new Scene;
// make sure View is safe to reference multi-threaded.
setThreadSafeRefUnref(true);
@@ -141,6 +151,12 @@ View::View(const osgViewer::View& view, const osg::CopyOp& copyop):
_fusionDistanceMode(view._fusionDistanceMode),
_fusionDistanceValue(view._fusionDistanceValue)
{
_scene = new Scene;
// need to attach a Renderer to the maaster camera which has been default constructed
getCamera()->setRenderer(createRenderer(getCamera()));
setEventQueue(new osgGA::EventQueue);
}
View::~View()
@@ -148,6 +164,7 @@ View::~View()
// osg::notify(osg::NOTICE)<<"Destructing osgViewer::View"<<std::endl;
}
osg::GraphicsOperation* View::createRenderer(osg::Camera* camera)
{
Renderer* render = new Renderer(camera);
@@ -169,16 +186,62 @@ void View::init()
}
}
void View::setStartTick(osg::Timer_t tick)
{
_startTick = tick;
}
void View::setSceneData(osg::Node* node)
{
_scene = new osgViewer::Scene;
_scene->setSceneData(node);
if (_scene->getSceneData()==node) return;
Scene* scene = Scene::getScene(node);
if (scene)
{
osg::notify(osg::INFO)<<"View::setSceneData() Sharing scene "<<scene<<std::endl;
_scene = scene;
}
else
{
if (_scene->referenceCount()!=1)
{
// we are not the only reference to the Scene so we cannot reuse it.
_scene = new Scene;
osg::notify(osg::INFO)<<"View::setSceneData() Allocating new scene"<<_scene.get()<<std::endl;
}
else
{
osg::notify(osg::INFO)<<"View::setSceneData() Reusing exisitng scene"<<_scene.get()<<std::endl;
}
_scene->setSceneData(node);
}
if (getSceneData())
{
// now make sure the scene graph is set up with the correct DataVariance to protect the dyamic elements of
// the scene graph from being run in parallel.
osgUtil::Optimizer::StaticObjectDetectionVisitor sodv;
getSceneData()->accept(sodv);
}
computeActiveCoordinateSystemNodePath();
assignSceneDataToCameras();
}
osgDB::DatabasePager* View::getDatabasePager()
{
return _scene.valid() ? _scene->getDatabasePager() : 0;
}
const osgDB::DatabasePager* View::getDatabasePager() const
{
return _scene.valid() ? _scene->getDatabasePager() : 0;
}
void View::setCameraManipulator(osgGA::MatrixManipulator* manipulator)
{
_cameraManipulator = manipulator;
@@ -829,67 +892,3 @@ bool View::computeIntersections(float x,float y, osg::NodePath& nodePath, osgUti
return false;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// EndOfDynamicDrawBlock
//
EndOfDynamicDrawBlock::EndOfDynamicDrawBlock(unsigned int numberOfBlocks):
_numberOfBlocks(numberOfBlocks),
_blockCount(0)
{
}
void EndOfDynamicDrawBlock::completed(osg::State* /*state*/)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_blockCount>0)
{
--_blockCount;
if (_blockCount==0)
{
// osg::notify(osg::NOTICE)<<"Released"<<std::endl;
_cond.broadcast();
}
}
}
void EndOfDynamicDrawBlock::block()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_blockCount)
_cond.wait(&_mut);
}
void EndOfDynamicDrawBlock::release()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_blockCount)
{
_blockCount = 0;
_cond.broadcast();
}
}
void EndOfDynamicDrawBlock::reset()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_numberOfBlocks!=_blockCount)
{
if (_numberOfBlocks==0) _cond.broadcast();
_blockCount = _numberOfBlocks;
}
}
void EndOfDynamicDrawBlock::setNumOfBlocks(unsigned int blockCount)
{
_numberOfBlocks = blockCount;
}
EndOfDynamicDrawBlock::~EndOfDynamicDrawBlock()
{
_blockCount = 0;
release();
}

View File

@@ -16,7 +16,6 @@
#include <osg/DeleteHandler>
#include <osg/io_utils>
#include <osgUtil/Optimizer>
#include <osgUtil/GLObjectsVisitor>
#include <osgDB/Registry>
#include <osgGA/TrackballManipulator>
@@ -86,16 +85,14 @@ void Viewer::constructorInit()
_useMainThreadForRenderingTraversal = true;
_endBarrierPosition = AfterSwapBuffers;
_numWindowsOpenAtLastSetUpThreading = 0;
_startTick = 0;
_frameStamp = new osg::FrameStamp;
_frameStamp->setFrameNumber(0);
_frameStamp->setReferenceTime(0);
_frameStamp->setSimulationTime(0);
_eventVisitor = new osgGA::EventVisitor;
_eventVisitor->setActionAdapter(this);
_eventVisitor->setFrameStamp(_frameStamp.get());
_updateVisitor = new osgUtil::UpdateVisitor;
_updateVisitor->setFrameStamp(_frameStamp.get());
setStats(new osg::Stats("Viewer"));
}
@@ -205,7 +202,7 @@ int Viewer::run()
void Viewer::setStartTick(osg::Timer_t tick)
{
_startTick = tick;
View::setStartTick(tick);
Contexts contexts;
getContexts(contexts,false);
@@ -239,23 +236,9 @@ void Viewer::setReferenceTime(double time)
void Viewer::setSceneData(osg::Node* node)
{
_scene = new osgViewer::Scene;
_scene->setSceneData(node);
_scene->setFrameStamp(_frameStamp.get());
if (getSceneData())
{
// now make sure the scene graph is set up with the correct DataVariance to protect the dyamic elements of
// the scene graph from being run in parallel.
osgUtil::Optimizer::StaticObjectDetectionVisitor sodv;
getSceneData()->accept(sodv);
}
computeActiveCoordinateSystemNodePath();
setReferenceTime(0.0);
assignSceneDataToCameras();
View::setSceneData(node);
}
GraphicsWindowEmbedded* Viewer::setUpViewerAsEmbeddedInWindow(int x, int y, int width, int height)
@@ -543,7 +526,7 @@ void Viewer::startThreading()
{
_startRenderingBarrier = 0;
_endRenderingDispatchBarrier = 0;
_endDynamicDrawBlock = new EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation);
_endDynamicDrawBlock = new osg::EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation);
if (!osg::Referenced::getDeleteHandler()) osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2));
else osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2);
@@ -1349,26 +1332,32 @@ void Viewer::updateTraversal()
double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
// do the update traversal of the scene.
if (_scene.valid()) _scene->updateTraversal();
if (getSceneData())
{
getSceneData()->accept(*_updateVisitor);
}
if (_scene->getDatabasePager())
{
// syncronize changes required by the DatabasePager thread to the scene graph
_scene->getDatabasePager()->updateSceneGraph(_frameStamp->getReferenceTime());
}
osgUtil::UpdateVisitor* uv = _scene.valid() ? _scene->getUpdateVisitor() : 0;
if (uv)
{
// call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
// leave that to the scene update traversal.
osg::NodeVisitor::TraversalMode tm = uv->getTraversalMode();
uv->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
_updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*uv);
if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*_updateVisitor);
for(unsigned int i=0; i<getNumSlaves(); ++i)
{
osg::Camera* camera = getSlave(i)._camera.get();
if (camera && camera->getUpdateCallback()) camera->accept(*uv);
if (camera && camera->getUpdateCallback()) camera->accept(*_updateVisitor);
}
uv->setTraversalMode(tm);
_updateVisitor->setTraversalMode(tm);
}
if (_cameraManipulator.valid())