Added osg::PagedLOD and osgProducer::DatabasePager class, and linked up osgProducer::Viewer
to manage the pager.
This commit is contained in:
@@ -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
143
src/osg/PagedLOD.cpp
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -34,6 +34,7 @@ CXXFILES =\
|
||||
Node.cpp\
|
||||
Object.cpp\
|
||||
OccluderNode.cpp\
|
||||
PagedLOD.cpp\
|
||||
Point.cpp\
|
||||
PolygonMode.cpp\
|
||||
PolygonOffset.cpp\
|
||||
|
||||
125
src/osgPlugins/osg/PagedLOD.cpp
Normal file
125
src/osgPlugins/osg/PagedLOD.cpp
Normal 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;
|
||||
}
|
||||
198
src/osgProducer/DatabasePager.cpp
Normal file
198
src/osgProducer/DatabasePager.cpp
Normal 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);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
DatabasePager.cpp\
|
||||
EventAdapter.cpp\
|
||||
KeyboardMouseCallback.cpp\
|
||||
OsgCameraGroup.cpp\
|
||||
|
||||
@@ -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,7 +413,26 @@ 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();
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user