From c2eabe1d4b52e563d4da6868a95a4314840756f3 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 8 Jul 2003 14:44:00 +0000 Subject: [PATCH] Added osg::PagedLOD and osgProducer::DatabasePager class, and linked up osgProducer::Viewer to manage the pager. --- Make/makedirdefs | 1 + VisualStudio/osg/osg.dsp | 8 + VisualStudio/osgPlugins/osg/dot_osg.dsp | 4 + VisualStudio/osgProducer/osgProducer.dsp | 8 + examples/osgconv/GNUmakefile.inst | 2 + examples/osgviewer/osgviewer.cpp | 35 ---- include/osg/NodeVisitor | 41 ++++- include/osg/PagedLOD | 89 ++++++++++ include/osgProducer/DatabasePager | 98 +++++++++++ include/osgProducer/OsgCameraGroup | 3 + include/osgProducer/Viewer | 4 +- include/osgUtil/CullVisitor | 12 +- src/osg/GNUmakefile | 1 + src/osg/PagedLOD.cpp | 143 ++++++++++++++++ src/osgDB/Registry.cpp | 38 +++++ src/osgPlugins/osg/GNUmakefile | 1 + src/osgPlugins/osg/PagedLOD.cpp | 125 ++++++++++++++ src/osgProducer/DatabasePager.cpp | 198 +++++++++++++++++++++++ src/osgProducer/GNUmakefile | 1 + src/osgProducer/OsgCameraGroup.cpp | 47 ++++-- src/osgProducer/Viewer.cpp | 10 ++ 21 files changed, 810 insertions(+), 59 deletions(-) create mode 100644 include/osg/PagedLOD create mode 100644 include/osgProducer/DatabasePager create mode 100644 src/osg/PagedLOD.cpp create mode 100644 src/osgPlugins/osg/PagedLOD.cpp create mode 100644 src/osgProducer/DatabasePager.cpp diff --git a/Make/makedirdefs b/Make/makedirdefs index 759dc71fb..4a16830de 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -149,6 +149,7 @@ EXAMPLE_DIRS = \ osgprerendercubemap\ osgslideshow\ +# osgpagedlod\ # osgsimulation\ # osgdemeter\ # osgjigsaw\ diff --git a/VisualStudio/osg/osg.dsp b/VisualStudio/osg/osg.dsp index 7ffd27dd9..7b86a8d7e 100755 --- a/VisualStudio/osg/osg.dsp +++ b/VisualStudio/osg/osg.dsp @@ -301,6 +301,10 @@ SOURCE=..\..\src\osg\OccluderNode.cpp # End Source File # Begin Source File +SOURCE=..\..\src\osg\PagedLOD.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osg\Point.cpp # End Source File # Begin Source File @@ -693,6 +697,10 @@ SOURCE=..\..\Include\Osg\OccluderNode # End Source File # Begin Source File +SOURCE=..\..\Include\Osg\PagedLOD +# End Source File +# Begin Source File + SOURCE=..\..\Include\Osg\Plane # End Source File # Begin Source File diff --git a/VisualStudio/osgPlugins/osg/dot_osg.dsp b/VisualStudio/osgPlugins/osg/dot_osg.dsp index 5a11b468d..07c91b0f9 100755 --- a/VisualStudio/osgPlugins/osg/dot_osg.dsp +++ b/VisualStudio/osgPlugins/osg/dot_osg.dsp @@ -218,6 +218,10 @@ SOURCE=..\..\..\src\osgPlugins\osg\OccluderNode.cpp # End Source File # Begin Source File +SOURCE=..\..\..\src\osgPlugins\osg\PagedLOD.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\src\osgPlugins\osg\Point.cpp # End Source File # Begin Source File diff --git a/VisualStudio/osgProducer/osgProducer.dsp b/VisualStudio/osgProducer/osgProducer.dsp index ae1d858b6..107d1358b 100755 --- a/VisualStudio/osgProducer/osgProducer.dsp +++ b/VisualStudio/osgProducer/osgProducer.dsp @@ -93,6 +93,10 @@ LINK32=link.exe # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" Begin Source File +SOURCE=..\..\src\osgProducer\DatabasePager.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\osgProducer\Version.cpp # End Source File # Begin Source File @@ -125,6 +129,10 @@ SOURCE=..\..\src\osgProducer\KeyboardMouseCallback.cpp # PROP Default_Filter ";h;hpp;hxx;hm;inl" # Begin Source File +SOURCE=..\..\Include\osgProducer\DatabasePager +# End Source File +# Begin Source File + SOURCE=..\..\Include\osgProducer\Export # End Source File # Begin Source File diff --git a/examples/osgconv/GNUmakefile.inst b/examples/osgconv/GNUmakefile.inst index 1884ddf36..f6d58795d 100644 --- a/examples/osgconv/GNUmakefile.inst +++ b/examples/osgconv/GNUmakefile.inst @@ -2,6 +2,8 @@ TOPDIR = ../.. include $(TOPDIR)/Make/makedefs CXXFILES =\ + GeoSet.cpp\ + IO_GeoSet.cpp\ OrientationConverter.cpp\ osgconv.cpp\ diff --git a/examples/osgviewer/osgviewer.cpp b/examples/osgviewer/osgviewer.cpp index 50fa96f46..2f26883fa 100644 --- a/examples/osgviewer/osgviewer.cpp +++ b/examples/osgviewer/osgviewer.cpp @@ -14,41 +14,6 @@ #include -#if 0 -enum Methods -{ - SET_1, - SET_2, - END -}; - - -typedef std::pair MethodPair; - -class Proxy -{ -public: - Proxy(MethodPair* methods) - { - std::cout<<"methods "< _frameStamp; + ref_ptr _frameStamp; - TraversalMode _traversalMode; - Node::NodeMask _traversalMask; - Node::NodeMask _nodeMaskOverride; + TraversalMode _traversalMode; + Node::NodeMask _traversalMask; + Node::NodeMask _nodeMaskOverride; - NodePath _nodePath; + NodePath _nodePath; - ref_ptr _userData; + ref_ptr _userData; + + ref_ptr _databaseRequestHandler; }; diff --git a/include/osg/PagedLOD b/include/osg/PagedLOD new file mode 100644 index 000000000..6f5022265 --- /dev/null +++ b/include/osg/PagedLOD @@ -0,0 +1,89 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_PagedLOD +#define OSG_PagedLOD 1 + +#include + +namespace osg { + +/** PagedLOD. +*/ +class SG_EXPORT PagedLOD : public LOD +{ + public : + + PagedLOD() {} + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + PagedLOD(const PagedLOD&,const CopyOp& copyop=CopyOp::SHALLOW_COPY); + + META_Node(osg, PagedLOD); + + + + virtual void traverse(NodeVisitor& nv); + + virtual bool addChild(Node *child); + + virtual bool addChild(Node *child, float min, float max); + + virtual bool addChild(Node *child, float min, float max,const std::string& filename); + + virtual bool removeChild(Node *child); + + typedef std::vector FileNameList; + + void setFileName(unsigned int childNo, const std::string& filename); + + const std::string& getFileName(unsigned int childNo) const { return _fileNameList[childNo]; } + + /** returns the number of filenames currently set. */ + inline unsigned int getNumFileNames() const { return _fileNameList.size(); } + + /** return the list of filename.*/ + inline FileNameList& getFileNameList() { return _fileNameList; } + + /** return the list of filename.*/ + inline const FileNameList& getFileNameList() const { return _fileNameList; } + + + typedef std::vector TimeStampList; + + void setTimeStamp(unsigned int childNo, double timeStamp); + + double getTimeStamp(unsigned int childNo) const { return _timeStampList[childNo]; } + + /** returns the number of filenames currently set. */ + inline unsigned int getNumTimeStamps() const { return _fileNameList.size(); } + + /** return the list of time stamps.*/ + inline TimeStampList& getTimeStampList() { return _timeStampList; } + + /** return the list of time stamps.*/ + inline const TimeStampList& getTimeStampList() const { return _timeStampList; } + + void removeExpiredChildren(double expiryTime); + + protected : + + virtual ~PagedLOD() {} + + FileNameList _fileNameList; + TimeStampList _timeStampList; +}; + +} + +#endif diff --git a/include/osgProducer/DatabasePager b/include/osgProducer/DatabasePager new file mode 100644 index 000000000..03c35c1d6 --- /dev/null +++ b/include/osgProducer/DatabasePager @@ -0,0 +1,98 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGPRODUCER_DATABASEPAGER +#define OSGPRODUCER_DATABASEPAGER 1 + +#include +#include +#include + +#include +#include + +#include + +namespace osgProducer { + +/** Database paging class which manages the loading of files in a background thread, + * and syncronizing of loaded models with the main scene graph.*/ +class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandler, public Producer::Thread +{ + public : + + DatabasePager(); + + /** add a request to load a node file to end the the database request list.*/ + virtual void requestNodeFile(const std::string& fileName,osg::Group* group); + + /** run does the database paging.*/ + virtual void run(); + + /** add the loaded data to the scene graph.*/ + void addLoadedDataToSceneGraph(); + + /** find all PagedLOD nodes in a subgraph and register them with + * the DatabasePager so it can keep track of expired nodes.*/ + void registerPagedLODs(osg::Node* subgraph); + + /** Set the amount of time that a subgraph will be kept without being visited in the cull traversal + * before being removed.*/ + void setExpiryDelay(double expiryDelay) { _expiryDelay = expiryDelay; } + + /** Get the amount of time that a subgraph will be kept without being visited in the cull traversal + * before being removed.*/ + double getExpiryDelay() const { return _expiryDelay; } + + /** iterate through the active PagedLOD nodes children removing + * children which havn't been visited since specified expiryTime.*/ + void removeExpiredSubgraphs(double currentFrameTime); + + + public: + + typedef std::vector< osg::ref_ptr > PagedLODList; + + protected : + + virtual ~DatabasePager() {} + + struct DatabaseRequest : public osg::Referenced + { + DatabaseRequest(): + _numOfRequests(0) + {} + + std::string _fileName; + unsigned int _numOfRequests; + osg::ref_ptr _groupForAddingLoadedSubgraph; + osg::ref_ptr _loadedModel; + }; + + typedef std::vector< osg::ref_ptr > DatabaseRequestList; + + DatabaseRequestList _fileRequestList; + Producer::Mutex _fileRequestListMutex; + + DatabaseRequestList _fileLoadedList; + Producer::Mutex _fileLoadedListMutex; + + PagedLODList _pagedLODList; + + double _expiryDelay; + +}; + +} + +#endif diff --git a/include/osgProducer/OsgCameraGroup b/include/osgProducer/OsgCameraGroup index f67505be1..22b7ea858 100644 --- a/include/osgProducer/OsgCameraGroup +++ b/include/osgProducer/OsgCameraGroup @@ -27,6 +27,7 @@ #include #include +#include namespace osgProducer { @@ -188,6 +189,8 @@ class OSGPRODUCER_EXPORT OsgCameraGroup : public Producer::CameraGroup osg::Timer _timer; osg::Timer_t _start_tick; osg::ref_ptr _frameStamp; + + osg::ref_ptr _databasePager; void _init(); }; diff --git a/include/osgProducer/Viewer b/include/osgProducer/Viewer index 615c335ed..9db705c13 100644 --- a/include/osgProducer/Viewer +++ b/include/osgProducer/Viewer @@ -11,8 +11,8 @@ * OpenSceneGraph Public License for more details. */ -#ifndef OSG_VIEWER_H -#define OSG_VIEWER_H +#ifndef OSGPRODUCER_VIEWER +#define OSGPRODUCER_VIEWER 1 #include #include diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 7d823676d..1066aea7a 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -215,6 +215,8 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac osg::State* getState() { return _state.get(); } const osg::State* getState() const { return _state.get(); } + + protected: // /** prevent unwanted copy construction.*/ @@ -255,10 +257,10 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac osg::ref_ptr _clearNode; - bool _impostorActive; - bool _depthSortImpostorSprites; - float _impostorPixelErrorThreshold; - int _numFramesToKeepImpostorSprites; + bool _impostorActive; + bool _depthSortImpostorSprites; + float _impostorPixelErrorThreshold; + int _numFramesToKeepImpostorSprites; typedef std::vector< osg::ref_ptr > RenderLeafList; @@ -267,7 +269,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac inline RenderLeaf* createOrReuseRenderLeaf(osg::Drawable* drawable,osg::RefMatrix* projection,osg::RefMatrix* matrix, float depth=0.0f); - osg::ref_ptr _impostorSpriteManager; + osg::ref_ptr _impostorSpriteManager; osg::ref_ptr _state; diff --git a/src/osg/GNUmakefile b/src/osg/GNUmakefile index 9ffb70ff0..ea8bb9652 100644 --- a/src/osg/GNUmakefile +++ b/src/osg/GNUmakefile @@ -55,6 +55,7 @@ CXXFILES =\ Notify.cpp\ Object.cpp\ OccluderNode.cpp\ + PagedLOD.cpp\ Point.cpp\ PolygonMode.cpp\ PolygonOffset.cpp\ diff --git a/src/osg/PagedLOD.cpp b/src/osg/PagedLOD.cpp new file mode 100644 index 000000000..eb8beb24b --- /dev/null +++ b/src/osg/PagedLOD.cpp @@ -0,0 +1,143 @@ +#include + +using namespace osg; + +PagedLOD::PagedLOD(const PagedLOD& plod,const CopyOp& copyop): + LOD(plod,copyop) +{ +} + +void PagedLOD::traverse(NodeVisitor& nv) +{ + + double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0; + bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR; + + switch(nv.getTraversalMode()) + { + case(NodeVisitor::TRAVERSE_ALL_CHILDREN): + std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv)); + break; + case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN): + { + float distance = nv.getDistanceToEyePoint(getCenter(),true); + + // first check to see if any children can be directly traversed. + unsigned int numChildren = osg::minimum(_children.size(),numChildren=_rangeList.size()); + bool childTraversed = false; + for(unsigned int i=0;iaccept(nv); + childTraversed = true; + } + } + + if (!childTraversed) + { + //std::cout<<"PagedLOD::traverse() - falling back "<0) + { + //std::cout<<" to child "<accept(nv); + } + + // now request the loading of the next unload child. + if (nv.getDatabaseRequestHandler() && numChildren<_fileNameList.size()) + { + //std::cout<<" requesting child "<<_fileNameList[numChildren]<requestNodeFile(_fileNameList[numChildren],this); + } + + + } + + + break; + } + default: + break; + } +} + +bool PagedLOD::addChild( Node *child ) +{ + if (LOD::addChild(child)) + { + if (_children.size()>_fileNameList.size()) _fileNameList.resize(_children.size()); + if (_children.size()>_timeStampList.size()) _timeStampList.resize(_children.size(),0); + return true; + } + return false; +} + +bool PagedLOD::addChild(Node *child, float min, float max) +{ + if (LOD::addChild(child,min,max)) + { + if (_children.size()>_fileNameList.size()) _fileNameList.resize(_children.size()); + if (_children.size()>_timeStampList.size()) _timeStampList.resize(_children.size(),0.0); + + return true; + } + return false; +} + + +bool PagedLOD::addChild(Node *child, float min, float max,const std::string& filename) +{ + if (LOD::addChild(child,min,max)) + { + if (_children.size()>_fileNameList.size()) _fileNameList.resize(_children.size()); + if (_children.size()>_timeStampList.size()) _timeStampList.resize(_children.size(),0.0); + + _fileNameList[_children.size()-1] = filename; + + return true; + } + return false; +} + +bool PagedLOD::removeChild( Node *child ) +{ + // find the child's position. + unsigned int pos=getChildIndex(child); + if (pos==_children.size()) return false; + + _rangeList.erase(_rangeList.begin()+pos); + _fileNameList.erase(_fileNameList.begin()+pos); + _timeStampList.erase(_timeStampList.begin()+pos); + + return Group::removeChild(child); +} + +void PagedLOD::setFileName(unsigned int childNo, const std::string& filename) +{ + if (childNo>=_fileNameList.size()) _fileNameList.resize(childNo+1); + _fileNameList[childNo] = filename; +} + +void PagedLOD::setTimeStamp(unsigned int childNo, double timeStamp) +{ + if (childNo>=_timeStampList.size()) _timeStampList.resize(childNo+1,0.0); + _timeStampList[childNo] = timeStamp; +} + +void PagedLOD::removeExpiredChildren(double expiryTime) +{ + for(unsigned int i=_children.size();i>0;) + { + --i; + if (!_fileNameList[i].empty() && _timeStampList[i] MethodPair; + + class Proxy + { + public: + Proxy(MethodPair* methods) + { + std::cout<<"methods "<(obj); + + bool matchFirst; + if ((matchFirst=fr.matchSequence("FileNameList {")) || fr.matchSequence("FileNameList %i {")) + { + + // set up coordinates. + int entry = fr[0].getNoNestedBrackets(); + int capacity; + + if (matchFirst) + { + fr += 2; + } + else if (fr[1].getInt(capacity)) + { + lod.getFileNameList().reserve(capacity); + fr += 3; + } + + unsigned int i=0; + while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) + { + if (fr[0].isString() || fr[0].isQuotedString()) + { + if (fr[0].getStr()) lod.setFileName(i,fr[0].getStr()); + else lod.setFileName(i,""); + + ++fr; + ++i; + } + else + { + ++fr; + } + } + + iteratorAdvanced = true; + ++fr; + + } + + int num_children; + if (fr[0].matchWord("num_children") && + fr[1].getInt(num_children)) + { + // could allocate space for children here... + fr+=2; + iteratorAdvanced = true; + } + + Node* node = NULL; + while((node=fr.readNode())!=NULL) + { + lod.addChild(node); + iteratorAdvanced = true; + } + + return iteratorAdvanced; +} + + +bool PagedLOD_writeLocalData(const Object& obj, Output& fw) +{ + const PagedLOD& lod = static_cast(obj); + + fw.indent() << "FileNameList "< +#include + +using namespace osgProducer; + +DatabasePager::DatabasePager() +{ + std::cout<<"Constructing DatabasePager()"<_fileName==fileName) + { + foundEntry = true; + ++((*litr)->_numOfRequests); + } + } + + _fileLoadedListMutex.unlock(); + + if (!foundEntry) + { + + _fileRequestListMutex.lock(); + + // search to see if entry already in file request list. + bool foundEntry = false; + for(DatabaseRequestList::iterator ritr = _fileRequestList.begin(); + ritr != _fileRequestList.end() && !foundEntry; + ++ritr) + { + if ((*ritr)->_fileName==fileName) + { + foundEntry = true; + ++((*ritr)->_numOfRequests); + } + } + + if (!foundEntry) + { + osg::ref_ptr databaseRequest = new DatabaseRequest; + + databaseRequest->_fileName = fileName; + databaseRequest->_groupForAddingLoadedSubgraph = group; + + _fileRequestList.push_back(databaseRequest); + } + + _fileRequestListMutex.unlock(); + } + + if (!threadIsRunning()) + { + std::cout<<"DatabasePager::startThread()"< databaseRequest; + + // get the front of the file request list. + _fileRequestListMutex.lock(); + if (!_fileRequestList.empty()) databaseRequest = _fileRequestList.front(); + _fileRequestListMutex.unlock(); + + if (databaseRequest.valid()) + { + // load the data, note safe to write to the databaseRequest since once + // it is created this thread is the only one to write to the _loadedModel pointer. + databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName); + + _fileRequestListMutex.lock(); + _fileRequestList.erase(_fileRequestList.begin()); + _fileRequestListMutex.unlock(); + + if (databaseRequest->_loadedModel.valid()) + { + _fileLoadedListMutex.lock(); + + _fileLoadedList.push_back(databaseRequest); + + _fileLoadedListMutex.unlock(); + } + } + + // hack hack hack... sleep for 1ms so we give other threads a chance.. + #ifdef WIN32 + Sleep(1); + #else + usleep(1000); + #endif + } + + cancel(); + join(); +} + +void DatabasePager::addLoadedDataToSceneGraph() +{ + DatabaseRequestList localFileLoadedList; + + // get the dat for the _fileLoadedList, leaving it empty via a std::vector<>.swap. + _fileLoadedListMutex.lock(); + localFileLoadedList.swap(_fileLoadedList); + _fileLoadedListMutex.unlock(); + + // add the loaded data into the scene graph. + for(DatabaseRequestList::iterator itr=localFileLoadedList.begin(); + itr!=localFileLoadedList.end(); + ++itr) + { + DatabaseRequest* databaseRequest = itr->get(); + registerPagedLODs(databaseRequest->_loadedModel.get()); + databaseRequest->_groupForAddingLoadedSubgraph->addChild(databaseRequest->_loadedModel.get()); + //std::cout<<"merged subgraph"<_fileName<<" after "<_numOfRequests<<" requests."<get(); + plod->removeExpiredChildren(expiryTime); + } + + for(unsigned int i=_pagedLODList.size(); + i>0; + ) + { + --i; + + osg::PagedLOD* plod = _pagedLODList[i].get(); + if (plod->referenceCount()==1) + { + //std::cout<<" PagedLOD "<referenceCount()<accept(fplv); +} + diff --git a/src/osgProducer/GNUmakefile b/src/osgProducer/GNUmakefile index d658414ac..a1e61cf9d 100644 --- a/src/osgProducer/GNUmakefile +++ b/src/osgProducer/GNUmakefile @@ -2,6 +2,7 @@ TOPDIR = ../.. include $(TOPDIR)/Make/makedefs CXXFILES =\ + DatabasePager.cpp\ EventAdapter.cpp\ KeyboardMouseCallback.cpp\ OsgCameraGroup.cpp\ diff --git a/src/osgProducer/OsgCameraGroup.cpp b/src/osgProducer/OsgCameraGroup.cpp index fe697a4e7..c758c2602 100644 --- a/src/osgProducer/OsgCameraGroup.cpp +++ b/src/osgProducer/OsgCameraGroup.cpp @@ -19,6 +19,7 @@ #include #include +#include using namespace Producer; using namespace osgProducer; @@ -262,23 +263,32 @@ bool OsgCameraGroup::realize( ThreadingModel thread_model ) // small visitor to check for the existance of particle systems, // which currently arn't thread safe, so we would need to disable // multithreading of cull and draw. -class SearchForParticleNodes : public osg::NodeVisitor +class SearchForSpecialNodes : public osg::NodeVisitor { public: - SearchForParticleNodes(): + SearchForSpecialNodes(): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), - _foundParticles(false) + _foundParticles(false), + _foundPagedLOD(false) { } virtual void apply(osg::Node& node) { if (strcmp(node.libraryName(),"osgParticle")==0) _foundParticles = true; - if (!_foundParticles) traverse(node); + + if (!_foundParticles || + !_foundPagedLOD) traverse(node); } - + + virtual void apply(osg::PagedLOD& node) + { + _foundPagedLOD = true; + apply((osg::Node&)node); + } bool _foundParticles; + bool _foundPagedLOD; }; bool OsgCameraGroup::realize() @@ -373,11 +383,11 @@ bool OsgCameraGroup::realize() setUpSceneViewsWithData(); - if (getTopMostSceneData() && _thread_model!=Producer::CameraGroup::SingleThreaded) + if (getTopMostSceneData()) { - SearchForParticleNodes sfpn; - getTopMostSceneData()->accept(sfpn); - if (sfpn._foundParticles) + SearchForSpecialNodes sfsn; + getTopMostSceneData()->accept(sfsn); + if (sfsn._foundParticles) { osg::notify(osg::INFO)<<"Warning: disabling multi-threading of cull and draw"<registerPagedLODs(getTopMostSceneData()); + + for(SceneHandlerList::iterator p=_shvec.begin(); + p!=_shvec.end(); + ++p) + { + (*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); + } + + } + } + _initialized = CameraGroup::realize(); diff --git a/src/osgProducer/Viewer.cpp b/src/osgProducer/Viewer.cpp index 4aa9f6aeb..20bd68357 100644 --- a/src/osgProducer/Viewer.cpp +++ b/src/osgProducer/Viewer.cpp @@ -352,6 +352,16 @@ void Viewer::update() } } + if (_databasePager.valid()) + { + // removed any children PagedLOD children that havn't been visited in the cull traversal recently. + _databasePager->removeExpiredSubgraphs(_frameStamp->getReferenceTime()); + + // add the newly loaded data into the scene graph. + _databasePager->addLoadedDataToSceneGraph(); + } + + if (_updateVisitor.valid()) { _updateVisitor->setTraversalNumber(_frameStamp->getFrameNumber());