diff --git a/examples/osgposter/PosterPrinter.cpp b/examples/osgposter/PosterPrinter.cpp index 74d2f5d5f..ba5928fb8 100644 --- a/examples/osgposter/PosterPrinter.cpp +++ b/examples/osgposter/PosterPrinter.cpp @@ -59,14 +59,14 @@ public: if ( pagedLOD->getDatabasePath().empty() ) { nv->getDatabaseRequestHandler()->requestNodeFile( - pagedLOD->getFileName(numChildren), pagedLOD, + pagedLOD->getFileName(numChildren), nv->getNodePath(), 1.0, nv->getFrameStamp(), pagedLOD->getDatabaseRequest(numChildren), pagedLOD->getDatabaseOptions() ); } else { nv->getDatabaseRequestHandler()->requestNodeFile( - pagedLOD->getDatabasePath()+pagedLOD->getFileName(numChildren), pagedLOD, + pagedLOD->getDatabasePath()+pagedLOD->getFileName(numChildren), nv->getNodePath(), 1.0, nv->getFrameStamp(), pagedLOD->getDatabaseRequest(numChildren), pagedLOD->getDatabaseOptions() ); } diff --git a/include/osg/Node b/include/osg/Node index 0ceef34f3..04ddb13a6 100644 --- a/include/osg/Node +++ b/include/osg/Node @@ -23,8 +23,15 @@ #include #include + +// forward declare osgTerrrain::Terrain to enable declaration of asTerrain() method. +namespace osgTerrain { +class Terrain; +} + namespace osg { +// forcing declare classes to enable declaration of as*() methods. class NodeVisitor; class Group; class Transform; @@ -114,6 +121,15 @@ class OSG_EXPORT Node : public Object * Equivalent to dynamic_cast(this).*/ virtual const Geode* asGeode() const { return 0; } + /** Convert 'this' into a Transform pointer if Node is a Terrain, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual osgTerrain::Terrain* asTerrain() { return 0; } + + /** convert 'const this' into a const Terrain pointer if Node is a Terrain, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual const osgTerrain::Terrain* asTerrain() const { return 0; } + + /** Visitor Pattern : calls the apply method of a NodeVisitor with this node's type.*/ virtual void accept(NodeVisitor& nv); /** Traverse upwards : calls parents' accept method with NodeVisitor.*/ diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index 9b502c377..fe85bbe7e 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -280,7 +280,7 @@ class OSG_EXPORT NodeVisitor : public virtual Referenced DatabaseRequestHandler(): Referenced(true) {} - virtual void requestNodeFile(const std::string& fileName,osg::Group* group, float priority, const FrameStamp* framestamp, osg::ref_ptr& databaseRequest, const osg::Referenced* options=0) = 0; + virtual void requestNodeFile(const std::string& fileName, osg::NodePath& nodePath, float priority, const FrameStamp* framestamp, osg::ref_ptr& databaseRequest, const osg::Referenced* options=0) = 0; protected: virtual ~DatabaseRequestHandler() {} diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 02a9e4519..8f309bde8 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -70,7 +70,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** 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, + virtual void requestNodeFile(const std::string& fileName, osg::NodePath& nodePath, float priority, const osg::FrameStamp* framestamp, osg::ref_ptr& databaseRequest, const osg::Referenced* options); @@ -316,9 +316,12 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl double _timestampLastRequest; float _priorityLastRequest; unsigned int _numOfRequests; - osg::ObserverNodePath _observerNodePath; - osg::ref_ptr _loadedModel; - osg::ref_ptr _loadOptions; + + osg::observer_ptr _terrain; + osg::observer_ptr _group; + + osg::ref_ptr _loadedModel; + osg::ref_ptr _loadOptions; osg::observer_ptr _compileSet; diff --git a/include/osgDB/InputStream b/include/osgDB/InputStream index df7cfc327..3037f2620 100644 --- a/include/osgDB/InputStream +++ b/include/osgDB/InputStream @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/include/osgDB/Options b/include/osgDB/Options index fc6d91a01..c68c976d4 100644 --- a/include/osgDB/Options +++ b/include/osgDB/Options @@ -15,6 +15,7 @@ #define OSGDB_OPTIONS 1 #include +#include #include #include @@ -227,7 +228,6 @@ class OSGDB_EXPORT Options : public osg::Object /** Get the callback to use inform the DatabasePager whether a file is located on local or remote file system.*/ FileLocationCallback* getFileLocationCallback() const { return _fileLocationCallback.get(); } - /** Set the FileCache that is used to manage local storage of files downloaded from the internet.*/ void setFileCache(FileCache* fileCache) { _fileCache = fileCache; } @@ -235,6 +235,13 @@ class OSGDB_EXPORT Options : public osg::Object FileCache* getFileCache() const { return _fileCache.get(); } + /** Set the terrain observer_ptr, use to decorate any osgTerrain subgraphs.*/ + void setTerrain(osg::observer_ptr& terrain) { _terrain = terrain; } + + /** Get the terrain observer_ptr, use to decorate any osgTerrain subgraphs.*/ + const osg::observer_ptr& getTerrain() const { return _terrain; } + + protected: virtual ~Options() {} @@ -257,6 +264,8 @@ class OSGDB_EXPORT Options : public osg::Object osg::ref_ptr _fileLocationCallback; osg::ref_ptr _fileCache; + + osg::observer_ptr _terrain; }; } diff --git a/include/osgTerrain/Terrain b/include/osgTerrain/Terrain index fea4f240b..062bcf829 100644 --- a/include/osgTerrain/Terrain +++ b/include/osgTerrain/Terrain @@ -34,7 +34,11 @@ class OSGTERRAIN_EXPORT Terrain : public osg::CoordinateSystemNode META_Node(osgTerrain, Terrain); virtual void traverse(osg::NodeVisitor& nv); - + + virtual osgTerrain::Terrain* asTerrain() { return this; } + virtual const osgTerrain::Terrain* asTerrain() const { return this; } + + /** Set the sample ratio hint that TerrainTile should use when building geometry. * Defaults to 1.0, which means use all original sample points.*/ void setSampleRatio(float ratio); diff --git a/src/osg/PagedLOD.cpp b/src/osg/PagedLOD.cpp index 9a1cf4774..0c7f4ada1 100644 --- a/src/osg/PagedLOD.cpp +++ b/src/osg/PagedLOD.cpp @@ -218,12 +218,12 @@ void PagedLOD::traverse(NodeVisitor& nv) if (_databasePath.empty()) { - nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get()); + nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get()); } else { // prepend the databasePath to the child's filename. - nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get()); + nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,nv.getNodePath(),priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest, _databaseOptions.get()); } } diff --git a/src/osg/ProxyNode.cpp b/src/osg/ProxyNode.cpp index 377bc07a0..d6432022b 100644 --- a/src/osg/ProxyNode.cpp +++ b/src/osg/ProxyNode.cpp @@ -63,7 +63,7 @@ void ProxyNode::traverse(NodeVisitor& nv) { for(unsigned int i=_children.size(); i<_filenameList.size(); ++i) { - nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_filenameList[i].first, this, 1.0f, nv.getFrameStamp(), _filenameList[i].second, _databaseOptions.get()); + nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_filenameList[i].first, nv.getNodePath(), 1.0f, nv.getFrameStamp(), _filenameList[i].second, _databaseOptions.get()); } } else diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 9636540c7..55659cdde 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -799,7 +799,15 @@ void DatabasePager::DatabaseThread::run() { if (dr_loadOptions->getFileCache()) fileCache = dr_loadOptions->getFileCache(); if (dr_loadOptions->getFileLocationCallback()) fileLocationCallback = dr_loadOptions->getFileLocationCallback(); + + dr_loadOptions = dr_loadOptions->cloneOptions(); } + else + { + dr_loadOptions = new osgDB::Options; + } + + dr_loadOptions->setTerrain(databaseRequest->_terrain); // disable the FileCache if the fileLocationCallback tells us that it isn't required for this request. if (fileLocationCallback.valid() && !fileLocationCallback->useFileCache()) fileCache = 0; @@ -893,7 +901,7 @@ void DatabasePager::DatabaseThread::run() { fileCache->writeNode(*(loadedModel), fileName, dr_loadOptions.get()); } - osg::RefNodePath refNodePath; + { OpenThreads::ScopedLock drLock(_pager->_dr_mutex); if ((_pager->_frameNumber-databaseRequest->_frameNumberLastRequest)>1) @@ -901,16 +909,6 @@ void DatabasePager::DatabaseThread::run() OSG_INFO<<_name<<": Warning DatabaseRquest no longer required."<_observerNodePath.getRefNodePath(refNodePath)) - { - OSG_INFO<<_name<<": Warning node in parental chain has been deleted, discarding load."<delta_m(before,osg::Timer::instance()->tick())<<" ms"<_drawablePolicy, _pager); - // push the soon to be parent on the nodepath of the NodeVisitor so that - // during traversal one can test for where it'll be in the overall scene graph - // This is the benefit for osgTerrain::TerrainTile, so - // that it will find its Terrain node on its first traversal. - for(osg::RefNodePath::iterator rnp_itr = refNodePath.begin(); - rnp_itr != refNodePath.end(); - ++rnp_itr) - { - frov.pushOntoNodePath(rnp_itr->get()); - } - loadedModel->accept(frov); bool loadedObjectsNeedToBeCompiled = (_pager->_doPreCompile && frov.requiresCompilation() && _pager->_incrementalCompileOperation.valid()); @@ -1362,7 +1349,7 @@ bool DatabasePager::getRequestsInProgress() const } -void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* group, +void DatabasePager::requestNodeFile(const std::string& fileName, osg::NodePath& nodePath, float priority, const osg::FrameStamp* framestamp, osg::ref_ptr& databaseRequestRef, const osg::Referenced* options) @@ -1381,7 +1368,28 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou if (!_acceptNewRequests) return; - + + + if (nodePath.empty()) + { + OSG_NOTICE<<"Warning: DatabasePager::requestNodeFile(..) passed empty NodePath, so nowhere to attach new subgraph to."<asGroup(); + if (!group) + { + OSG_NOTICE<<"Warning: DatabasePager::requestNodeFile(..) passed NodePath without group as last node in path, so nowhere to attach new subgraph to."<asTerrain()) terrain = *itr; + } double timestamp = framestamp?framestamp->getReferenceTime():0.0; unsigned int frameNumber = framestamp?framestamp->getFrameNumber():static_cast(_frameNumber); @@ -1410,7 +1418,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou bool requeue = false; if (databaseRequest) { - OpenThreads::ScopedLock drLock(_dr_mutex); + OpenThreads::ScopedLock drLock(_dr_mutex); if (!(databaseRequest->valid())) { OSG_INFO<<"DatabaseRequest has been previously invalidated whilst still attached to scene graph."<_frameNumberLastRequest = frameNumber; databaseRequest->_timestampLastRequest = timestamp; databaseRequest->_priorityLastRequest = priority; - databaseRequest->_observerNodePath.setNodePathTo(group); + databaseRequest->_group = group; + databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; requeue = true; } @@ -1467,7 +1476,8 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou databaseRequest->_frameNumberLastRequest = frameNumber; databaseRequest->_timestampLastRequest = timestamp; databaseRequest->_priorityLastRequest = priority; - databaseRequest->_observerNodePath.setNodePathTo(group); + databaseRequest->_group = group; + databaseRequest->_terrain = terrain; databaseRequest->_loadOptions = loadOptions; _fileRequestQueue->addNoLock(databaseRequest.get()); @@ -1608,19 +1618,17 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) ++itr) { DatabaseRequest* databaseRequest = itr->get(); + // No need to take _dr_mutex. The pager threads are done with // the request; the cull traversal -- which might redispatch // the request -- can't run at the sametime as this update traversal. - osg::RefNodePath refNodePath; - if (databaseRequest->_observerNodePath.getRefNodePath(refNodePath)) + osg::ref_ptr group; + if (databaseRequest->_group.lock(group)) { - // OSG_NOTICE<<"Merging "<<_frameNumber-(*itr)->_frameNumberLastRequest<(refNodePath.back().get()); - if (osgDB::Registry::instance()->getSharedStateManager()) osgDB::Registry::instance()->getSharedStateManager()->share(databaseRequest->_loadedModel.get()); - osg::PagedLOD* plod = dynamic_cast(group); + osg::PagedLOD* plod = dynamic_cast(group.get()); if (plod) { plod->setTimeStamp(plod->getNumChildren(), timeStamp); @@ -1629,7 +1637,7 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp) } else { - osg::ProxyNode* proxyNode = dynamic_cast(group); + osg::ProxyNode* proxyNode = dynamic_cast(group.get()); if (proxyNode) { proxyNode->getDatabaseRequest(proxyNode->getNumChildren()) = 0; diff --git a/src/osgDB/Options.cpp b/src/osgDB/Options.cpp index 430271cfb..359b1df78 100644 --- a/src/osgDB/Options.cpp +++ b/src/osgDB/Options.cpp @@ -29,7 +29,8 @@ Options::Options(const Options& options,const osg::CopyOp& copyop): _readFileCallback(options._readFileCallback), _writeFileCallback(options._writeFileCallback), _fileLocationCallback(options._fileLocationCallback), - _fileCache(options._fileCache) {} + _fileCache(options._fileCache), + _terrain(options._terrain) {} void Options::parsePluginStringData(const std::string& str, char separator1, char separator2) { diff --git a/src/osgPlugins/ive/TerrainTile.cpp b/src/osgPlugins/ive/TerrainTile.cpp index 943a7a93e..072a6f9e3 100644 --- a/src/osgPlugins/ive/TerrainTile.cpp +++ b/src/osgPlugins/ive/TerrainTile.cpp @@ -16,7 +16,9 @@ #include "Group.h" #include "Layer.h" +#include #include +#include using namespace ive; @@ -132,6 +134,15 @@ void TerrainTile::read(DataInputStream* in) setTerrainTechnique(readTerrainTechnique(in)); + if (in->getOptions()) + { + osg::ref_ptr node; + if (in->getOptions()->getTerrain().lock(node)) + { + setTerrain(node->asTerrain()); + } + } + if (osgTerrain::TerrainTile::getTileLoadedCallback().valid()) osgTerrain::TerrainTile::getTileLoadedCallback()->loaded(this, in->getOptions()); } diff --git a/src/osgPlugins/txp/TXPPagedLOD.cpp b/src/osgPlugins/txp/TXPPagedLOD.cpp index a6e29165f..ed9b205b5 100644 --- a/src/osgPlugins/txp/TXPPagedLOD.cpp +++ b/src/osgPlugins/txp/TXPPagedLOD.cpp @@ -105,7 +105,7 @@ void TXPPagedLOD::traverse(osg::NodeVisitor& nv) //std::cout<<" requesting child "<<_fileNameList[numChildren]<<" priotity = "<requestNodeFile(_perRangeDataList[numChildren]._filename, - this, + nv.getNodePath(), priority, nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest); diff --git a/src/osgWrappers/deprecated-dotosg/osgTerrain/TerrainTile.cpp b/src/osgWrappers/deprecated-dotosg/osgTerrain/TerrainTile.cpp index 847a489ce..a0ef39bbe 100644 --- a/src/osgWrappers/deprecated-dotosg/osgTerrain/TerrainTile.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgTerrain/TerrainTile.cpp @@ -188,6 +188,14 @@ bool TerrainTile_readLocalData(osg::Object& obj, osgDB::Input &fr) itrAdvanced = true; } + if (fr.getOptions()) + { + osg::ref_ptr node; + if (fr.getOptions()->getTerrain().lock(node)) + { + terrainTile.setTerrain(node->asTerrain()); + } + } if (osgTerrain::TerrainTile::getTileLoadedCallback().valid()) osgTerrain::TerrainTile::getTileLoadedCallback()->loaded(&terrainTile, fr.getOptions()); diff --git a/src/osgWrappers/serializers/osgTerrain/TerrainTile.cpp b/src/osgWrappers/serializers/osgTerrain/TerrainTile.cpp index af5c76f46..d8c62e061 100644 --- a/src/osgWrappers/serializers/osgTerrain/TerrainTile.cpp +++ b/src/osgWrappers/serializers/osgTerrain/TerrainTile.cpp @@ -65,6 +65,16 @@ struct TerrainTileFinishedObjectReadCallback : public osgDB::FinishedObjectReadC virtual void objectRead(osgDB::InputStream& is, osg::Object& obj) { osgTerrain::TerrainTile& tile = static_cast(obj); + + if (is.getOptions()) + { + osg::ref_ptr node; + if (is.getOptions()->getTerrain().lock(node)) + { + tile.setTerrain(node->asTerrain()); + } + } + if ( osgTerrain::TerrainTile::getTileLoadedCallback().valid() ) osgTerrain::TerrainTile::getTileLoadedCallback()->loaded( &tile, is.getOptions() ); }