Added osg::PagedLOD and osgProducer::DatabasePager class, and linked up osgProducer::Viewer

to manage the pager.
This commit is contained in:
Robert Osfield 2003-07-08 14:44:00 +00:00
parent 9239173019
commit c2eabe1d4b
21 changed files with 810 additions and 59 deletions

View File

@ -149,6 +149,7 @@ EXAMPLE_DIRS = \
osgprerendercubemap\
osgslideshow\
# osgpagedlod\
# osgsimulation\
# osgdemeter\
# osgjigsaw\

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -2,6 +2,8 @@ TOPDIR = ../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
GeoSet.cpp\
IO_GeoSet.cpp\
OrientationConverter.cpp\
osgconv.cpp\

View File

@ -14,41 +14,6 @@
#include <osgProducer/Viewer>
#if 0
enum Methods
{
SET_1,
SET_2,
END
};
typedef std::pair<Methods,std::string> MethodPair;
class Proxy
{
public:
Proxy(MethodPair* methods)
{
std::cout<<"methods "<<methods<<std::endl;
for(int i=0;methods[i].first!=END;++i)
{
std::cout<<"\t"<<methods[i].first<<"\t"<<methods[i].second<<std::endl;
}
}
};
static MethodPair methods[] =
{
MethodPair(SET_1,"SET_1"),
MethodPair(SET_2,"SET_2"),
MethodPair(END,"")
};
Proxy myproxy(methods);
#endif
int main( int argc, char **argv )
{

View File

@ -31,6 +31,7 @@ class MatrixTransform;
class PositionAttitudeTransform;
class Projection;
class LOD;
class PagedLOD;
class Switch;
class Impostor;
class ClearNode;
@ -238,11 +239,33 @@ class SG_EXPORT NodeVisitor : public virtual Referenced
virtual void apply(Switch& node) { apply((Group&)node); }
virtual void apply(Sequence& node) { apply((Group&)node); }
virtual void apply(LOD& node) { apply((Group&)node); }
virtual void apply(PagedLOD& node) { apply((LOD&)node); }
virtual void apply(Impostor& node) { apply((LOD&)node); }
virtual void apply(ClearNode& node) { apply((Group&)node); }
virtual void apply(OccluderNode& node) { apply((Group&)node); }
/** callback for managing database paging, such as generated by PagedLOD nodes.*/
class DatabaseRequestHandler : public osg::Referenced
{
public:
virtual void requestNodeFile(const std::string& fileName,osg::Group* group) = 0;
protected:
virtual ~DatabaseRequestHandler() {}
};
/** Set the handler for database requests.*/
void setDatabaseRequestHandler(DatabaseRequestHandler* handler) { _databaseRequestHandler = handler; }
/** Get the handler for database requests.*/
DatabaseRequestHandler* getDatabaseRequestHandler() { return _databaseRequestHandler.get(); }
/** Get the const handler for database requests.*/
const DatabaseRequestHandler* getDatabaseRequestHandler() const { return _databaseRequestHandler.get(); }
protected:
VisitorType _visitorType;
@ -258,6 +281,8 @@ class SG_EXPORT NodeVisitor : public virtual Referenced
ref_ptr<Referenced> _userData;
ref_ptr<DatabaseRequestHandler> _databaseRequestHandler;
};

89
include/osg/PagedLOD Normal file
View File

@ -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 <osg/LOD>
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<std::string> 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<double> 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

View File

@ -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 <osg/NodeVisitor>
#include <osg/Group>
#include <osg/PagedLOD>
#include <Producer/Thread>
#include <Producer/Mutex>
#include <osgProducer/Export>
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<osg::PagedLOD> > PagedLODList;
protected :
virtual ~DatabasePager() {}
struct DatabaseRequest : public osg::Referenced
{
DatabaseRequest():
_numOfRequests(0)
{}
std::string _fileName;
unsigned int _numOfRequests;
osg::ref_ptr<osg::Group> _groupForAddingLoadedSubgraph;
osg::ref_ptr<osg::Node> _loadedModel;
};
typedef std::vector< osg::ref_ptr<DatabaseRequest> > DatabaseRequestList;
DatabaseRequestList _fileRequestList;
Producer::Mutex _fileRequestListMutex;
DatabaseRequestList _fileLoadedList;
Producer::Mutex _fileLoadedListMutex;
PagedLODList _pagedLODList;
double _expiryDelay;
};
}
#endif

View File

@ -27,6 +27,7 @@
#include <osg/DisplaySettings>
#include <osgProducer/OsgSceneHandler>
#include <osgProducer/DatabasePager>
namespace osgProducer {
@ -189,6 +190,8 @@ class OSGPRODUCER_EXPORT OsgCameraGroup : public Producer::CameraGroup
osg::Timer_t _start_tick;
osg::ref_ptr<osg::FrameStamp> _frameStamp;
osg::ref_ptr<DatabasePager> _databasePager;
void _init();
};

View File

@ -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 <osg/NodeVisitor>
#include <osg/ArgumentParser>

View File

@ -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.*/

View File

@ -55,6 +55,7 @@ CXXFILES =\
Notify.cpp\
Object.cpp\
OccluderNode.cpp\
PagedLOD.cpp\
Point.cpp\
PolygonMode.cpp\
PolygonOffset.cpp\

143
src/osg/PagedLOD.cpp Normal file
View File

@ -0,0 +1,143 @@
#include <osg/PagedLOD>
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;i<numChildren;++i)
{
if (_rangeList[i].first<=distance && distance<_rangeList[i].second)
{
if (updateTimeStamp) _timeStampList[i]=timeStamp;
//std::cout<<"PagedLOD::traverse() - Selecting child "<<i<<std::endl;
_children[i]->accept(nv);
childTraversed = true;
}
}
if (!childTraversed)
{
//std::cout<<"PagedLOD::traverse() - falling back "<<std::endl;
// select the last valid child.
if (numChildren>0)
{
//std::cout<<" to child "<<numChildren-1<<std::endl;
if (updateTimeStamp) _timeStampList[numChildren-1]=timeStamp;
_children[numChildren-1]->accept(nv);
}
// now request the loading of the next unload child.
if (nv.getDatabaseRequestHandler() && numChildren<_fileNameList.size())
{
//std::cout<<" requesting child "<<_fileNameList[numChildren]<<std::endl;
nv.getDatabaseRequestHandler()->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]<expiryTime)
{
//std::cout<<"Removing child "<<_children[i].get()<<std::endl;
Group::removeChild(_children[i].get());
}
}
}

View File

@ -31,6 +31,44 @@
using namespace osg;
using namespace osgDB;
#if 0
// temporary test of autoregistering, not compiled by default.
enum Methods
{
SET_1,
SET_2,
END
};
typedef std::pair<Methods,std::string> MethodPair;
class Proxy
{
public:
Proxy(MethodPair* methods)
{
std::cout<<"methods "<<methods<<std::endl;
for(int i=0;methods[i].first!=END;++i)
{
std::cout<<"\t"<<methods[i].first<<"\t"<<methods[i].second<<std::endl;
}
}
};
static MethodPair methods[] =
{
MethodPair(SET_1,"SET_1"),
MethodPair(SET_2,"SET_2"),
MethodPair(END,"")
};
Proxy myproxy(methods);
#endif
void PrintFilePathList(std::ostream& stream,const FilePathList& filepath)
{
for(FilePathList::const_iterator itr=filepath.begin();

View File

@ -34,6 +34,7 @@ CXXFILES =\
Node.cpp\
Object.cpp\
OccluderNode.cpp\
PagedLOD.cpp\
Point.cpp\
PolygonMode.cpp\
PolygonOffset.cpp\

View File

@ -0,0 +1,125 @@
#include "osg/PagedLOD"
#include "osgDB/Registry"
#include "osgDB/Input"
#include "osgDB/Output"
using namespace osg;
using namespace osgDB;
// forward declare functions to use later.
bool PagedLOD_readLocalData(Object& obj, Input& fr);
bool PagedLOD_writeLocalData(const Object& obj, Output& fw);
// register the read and write functions with the osgDB::Registry.
RegisterDotOsgWrapperProxy g_PagedLODProxy
(
new osg::PagedLOD,
"PagedLOD",
"Object Node LOD PagedLOD",
&PagedLOD_readLocalData,
&PagedLOD_writeLocalData
);
bool PagedLOD_readLocalData(Object& obj, Input& fr)
{
bool iteratorAdvanced = false;
PagedLOD& lod = static_cast<PagedLOD&>(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<const PagedLOD&>(obj);
fw.indent() << "FileNameList "<<lod.getNumFileNames()<<" {"<< std::endl;
fw.moveIn();
unsigned int numChildrenToWriteOut = 0;
for(unsigned int i=0; i<lod.getNumFileNames();++i)
{
if (lod.getFileName(i).empty())
{
fw.indent() << "\"\"" << std::endl;
++numChildrenToWriteOut;
}
else
{
fw.indent() << lod.getFileName(i) << std::endl;
}
}
fw.moveOut();
fw.indent() << "}"<< std::endl;
fw.indent() << "num_children " << numChildrenToWriteOut << std::endl;
for(unsigned int i=0;i<lod.getNumChildren();++i)
{
if (lod.getFileName(i).empty())
{
fw.writeObject(*lod.getChild(i));
}
}
return true;
}

View File

@ -0,0 +1,198 @@
#include <osgProducer/DatabasePager>
#include <osgDB/ReadFile>
using namespace osgProducer;
DatabasePager::DatabasePager()
{
std::cout<<"Constructing DatabasePager()"<<std::endl;
_expiryDelay = 1.0;
}
void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* group)
{
// search to see if filename already exist in the file loaded list.
bool foundEntry = false;
_fileLoadedListMutex.lock();
for(DatabaseRequestList::iterator litr = _fileLoadedList.begin();
litr != _fileLoadedList.end() && !foundEntry;
++litr)
{
if ((*litr)->_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> databaseRequest = new DatabaseRequest;
databaseRequest->_fileName = fileName;
databaseRequest->_groupForAddingLoadedSubgraph = group;
_fileRequestList.push_back(databaseRequest);
}
_fileRequestListMutex.unlock();
}
if (!threadIsRunning())
{
std::cout<<"DatabasePager::startThread()"<<std::endl;
startThread();
}
}
void DatabasePager::run()
{
std::cout<<"DatabasePager::run()"<<std::endl;
while(true)
{
osg::ref_ptr<DatabaseRequest> 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"<<databaseRequest->_fileName<<" after "<<databaseRequest->_numOfRequests<<" requests."<<std::endl;
}
}
void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
{
double expiryTime = currentFrameTime - _expiryDelay;
//std::cout<<"DatabasePager::removeExpiredSubgraphs("<<expiryTime<<") "<<std::endl;
for(PagedLODList::iterator itr=_pagedLODList.begin();
itr!=_pagedLODList.end();
++itr)
{
osg::PagedLOD* plod = itr->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 "<<plod<<" orphaned"<<std::endl;
_pagedLODList.erase(_pagedLODList.begin()+i);
}
else
{
//std::cout<<" PagedLOD "<<plod<<" refcount "<<plod->referenceCount()<<std::endl;
}
}
}
class FindPagedLODsVisitor : public osg::NodeVisitor
{
public:
FindPagedLODsVisitor(DatabasePager::PagedLODList& pagedLODList):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_pagedLODList(pagedLODList)
{
}
virtual void apply(osg::PagedLOD& plod)
{
_pagedLODList.push_back(&plod);
traverse(plod);
}
DatabasePager::PagedLODList& _pagedLODList;
};
void DatabasePager::registerPagedLODs(osg::Node* subgraph)
{
FindPagedLODsVisitor fplv(_pagedLODList);
if (subgraph) subgraph->accept(fplv);
}

View File

@ -2,6 +2,7 @@ TOPDIR = ../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
DatabasePager.cpp\
EventAdapter.cpp\
KeyboardMouseCallback.cpp\
OsgCameraGroup.cpp\

View File

@ -19,6 +19,7 @@
#include <osgDB/FileUtils>
#include <osgProducer/OsgCameraGroup>
#include <osgProducer/DatabasePager>
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"<<std::endl;
osg::notify(osg::INFO)<<" to avoid threading problems in osgParticle."<<std::endl;
@ -403,8 +413,27 @@ bool OsgCameraGroup::realize()
}
if (sfsn._foundPagedLOD)
{
std::cout << "setting up paged LOD"<<std::endl;
_databasePager = new DatabasePager;
_databasePager->registerPagedLODs(getTopMostSceneData());
for(SceneHandlerList::iterator p=_shvec.begin();
p!=_shvec.end();
++p)
{
(*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
}
}
}
_initialized = CameraGroup::realize();
return _initialized;

View File

@ -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());