forcing users to use osgDB::readRef*File() methods. The later is preferable as it closes a potential threading bug when using paging databases in conjunction
with the osgDB::Registry Object Cache. This threading bug occurs when one thread gets an object from the Cache via an osgDB::read*File() call where only
a pointer to the object is passed back, so taking a reference to the object is delayed till it gets reassigned to a ref_ptr<>, but at the same time another
thread calls a flush of the Object Cache deleting this object as it's referenceCount is now zero. Using osgDB::readREf*File() makes sure the a ref_ptr<> is
passed back and the referenceCount never goes to zero.
To ensure the OSG builds when OSG_PROVIDE_READFILE is to OFF the many cases of osgDB::read*File() usage had to be replaced with a ref_ptr<> osgDB::readRef*File()
usage. The avoid this change causing lots of other client code to be rewritten to handle the use of ref_ptr<> in place of C pointer I introduced a serious of
templte methods in various class to adapt ref_ptr<> to the underly C pointer to be passed to old OSG API's, example of this is found in include/osg/Group:
bool addChild(Node* child); // old method which can only be used with a Node*
tempalte<class T> bool addChild(const osg::ref_ptr<T>& child) { return addChild(child.get()); } // adapter template method
These changes together cover 149 modified files, so it's a large submission. This extent of changes are warrent to make use of the Object Cache
and multi-threaded loaded more robust.
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/branches/OpenSceneGraph-3.4@15165 16af8721-9629-0410-8352-f15c8da7e697
I found that some of the items that had been paged in were being expired on the first frame that they were not visible (as the cache was full). This resulted in excessive paging every time the view was moved. With the following changes I could only allow children to be expired if they had not been used for e.g. 30 seconds or 60 frames."
Introduced a new callback osgDB::FindFileCallback that overrides the default behavior of findDataFile/findLibraryFile.
Introduced support for assigning ReaderWriter::Options directory to PagedLOD.
Introduced new osgDB::FileLocationCallback for assistancing the DatabasePager to know when a file is hosted on a local or remote file system.
New attribute DatabasePager::_expiryFrames sets number of frames a PagedLOD child is kept in memory. The attribute is set with DatabasePager::setExpiryFrames method or OSG_EXPIRY_FRAMES environmental variable.
New attribute PagedLOD::PerRangeData::_
frameNumber contains frame number of last cull traversal.
Children of PagedLOD are expired when time _AND_ number of frames since last cull traversal exceed OSG_EXPIRY_DELAY _AND_ OSG_EXPIRY_FRAMES respectively. By default OSG_EXPIRY_FRAMES = 1 which means that nodes from last cull/rendering
traversal will not be expired even if last cull time exceeds OSG_EXPIRY_DELAY. Setting OSG_EXPIRY_FRAMES = 0 revokes previous behaviour of PagedLOD.
Setting OSG_EXPIRY_FRAMES > 0 fixes problems of children reloading in lazy rendering applications. Required behaviour is achieved by manipulating OSG_EXPIRY_DELAY and OSG_EXPIRY_FRAMES together.
Two interface changes are made:
DatabasePager::updateSceneGraph(double currentFrameTime) is replaced by DatabasePager::updateSceneGraph(const osg::FrameStamp &frameStamp). The previous method is in #if 0 clause in the header file. Robert, decide if You want to include it.
PagedLOD::removeExpiredChildren(double expiryTime, NodeList &removedChildren) is deprecated (warning is printed), when subclassing use PagedLOD::removeExpiredChildren(double expiryTime, int expiryFrame, NodeList &removedChildren) instead. "
multi-threaded paging, where the Pager manages threads of reading local
and http files via seperate threads. This makes it possible to smoothly
browse large databases where parts of the data are locally cached while
others are on a remote server. Previously with this type of dataset
the pager would stall all paging while http requests were being served,
even when parts of the models are still loadable virtue of being in the
local cache.
Also as part of the refactoring the DatabaseRequest are now stored in the
ProxyNode/PagedLOD nodes to facilitate quite updating in the cull traversal,
with the new code avoiding mutex locks and searches. Previous on big
databases the overhead involved in make database requests could accumulate
to a point where it'd cause the cull traversal to break frame. The overhead
now is negligable.
Finally OSG_FILE_CACHE support has been moved from the curl plugin into
the DatabasePager. Eventually this functionality will be moved out into
osgDB for more general usage.
that removeChild(Node*), removeChild(uint) and equivilant Geode methods are
now inline methods, not designed to be overriden, and seperated out the
multiple remove method to be called removeChildren(uint, uint) which is
now the only virtual method. There removeChildren is now the method to
override in subclasses.
This reorganisation requires some call code to be rename removeChild usage
to removeChildren.
osg::PagedLOD::s/getDatabasePath() and support in PagedLOD::traverse().
osgDB::ReaderWriter::Options::s/getDatabasePath()
osgDB::Input::s/getOptions()
setting of osgDB::Input::setOptions() in ReaderWriterOSG.cpp
src/osgPlugins/ive/DataInputStream::s/getOptions()
setting of src/osgPlugins/ive/DataInputStream::setOptions() in ReaderWriterIVE.cpp
/** Set the object-space reference radius of the volume enclosed by the PagedLOD.
* Used to detmine the bounding sphere of the PagedLOD in the absense of any children.*/
inline void setRadius(float radius) { _radius = radius; }
/** Get the object-space radius of the volume enclosed by the PagedLOD.*/
inline float getRadius() const { return _radius; }
/** Set the number of children that the PagedLOD must keep around, even if thay are older than their expiry time.*/
inline void setNumChildrenThatCannotBeExpired(unsigned int num) { _numChildrenThatCannotBeExpired = num; }
/** Get the number of children that the PagedLOD must keep around, even if thay are older than their expiry time.*/
unsigned int getNumChildrenThatCannotBeExpired() const { return _numChildrenThatCannotBeExpired; }