Added osg::PagedLOD and osgProducer::DatabasePager class, and linked up osgProducer::Viewer
to manage the pager.
This commit is contained in:
parent
9239173019
commit
c2eabe1d4b
@ -149,6 +149,7 @@ EXAMPLE_DIRS = \
|
||||
osgprerendercubemap\
|
||||
osgslideshow\
|
||||
|
||||
# osgpagedlod\
|
||||
# osgsimulation\
|
||||
# osgdemeter\
|
||||
# osgjigsaw\
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -2,6 +2,8 @@ TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
GeoSet.cpp\
|
||||
IO_GeoSet.cpp\
|
||||
OrientationConverter.cpp\
|
||||
osgconv.cpp\
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ class MatrixTransform;
|
||||
class PositionAttitudeTransform;
|
||||
class Projection;
|
||||
class LOD;
|
||||
class PagedLOD;
|
||||
class Switch;
|
||||
class Impostor;
|
||||
class ClearNode;
|
||||
@ -238,25 +239,49 @@ 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;
|
||||
int _traversalNumber;
|
||||
VisitorType _visitorType;
|
||||
int _traversalNumber;
|
||||
|
||||
ref_ptr<FrameStamp> _frameStamp;
|
||||
ref_ptr<FrameStamp> _frameStamp;
|
||||
|
||||
TraversalMode _traversalMode;
|
||||
Node::NodeMask _traversalMask;
|
||||
Node::NodeMask _nodeMaskOverride;
|
||||
TraversalMode _traversalMode;
|
||||
Node::NodeMask _traversalMask;
|
||||
Node::NodeMask _nodeMaskOverride;
|
||||
|
||||
NodePath _nodePath;
|
||||
NodePath _nodePath;
|
||||
|
||||
ref_ptr<Referenced> _userData;
|
||||
ref_ptr<Referenced> _userData;
|
||||
|
||||
ref_ptr<DatabaseRequestHandler> _databaseRequestHandler;
|
||||
|
||||
};
|
||||
|
||||
|
89
include/osg/PagedLOD
Normal file
89
include/osg/PagedLOD
Normal 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
|
98
include/osgProducer/DatabasePager
Normal file
98
include/osgProducer/DatabasePager
Normal 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
|
@ -27,6 +27,7 @@
|
||||
#include <osg/DisplaySettings>
|
||||
|
||||
#include <osgProducer/OsgSceneHandler>
|
||||
#include <osgProducer/DatabasePager>
|
||||
|
||||
namespace osgProducer {
|
||||
|
||||
@ -188,6 +189,8 @@ class OSGPRODUCER_EXPORT OsgCameraGroup : public Producer::CameraGroup
|
||||
osg::Timer _timer;
|
||||
osg::Timer_t _start_tick;
|
||||
osg::ref_ptr<osg::FrameStamp> _frameStamp;
|
||||
|
||||
osg::ref_ptr<DatabasePager> _databasePager;
|
||||
|
||||
void _init();
|
||||
};
|
||||
|
@ -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>
|
||||
|
@ -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<const osg::ClearNode> _clearNode;
|
||||
|
||||
bool _impostorActive;
|
||||
bool _depthSortImpostorSprites;
|
||||
float _impostorPixelErrorThreshold;
|
||||
int _numFramesToKeepImpostorSprites;
|
||||
bool _impostorActive;
|
||||
bool _depthSortImpostorSprites;
|
||||
float _impostorPixelErrorThreshold;
|
||||
int _numFramesToKeepImpostorSprites;
|
||||
|
||||
|
||||
typedef std::vector< osg::ref_ptr<RenderLeaf> > 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<osg::ImpostorSpriteManager> _impostorSpriteManager;
|
||||
osg::ref_ptr<osg::ImpostorSpriteManager> _impostorSpriteManager;
|
||||
|
||||
osg::ref_ptr<osg::State> _state;
|
||||
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user