From ad079b8ed49f6356c4ae2019b232ddacd9fa62c2 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 8 Nov 2011 21:11:28 +0100 Subject: [PATCH] modellib: Add method for deferred model loading. Add method that schedules a ProxyNode to do just deferred model loading instead of full scenery paging. Add support for ProxyNodes to CheckSceneryVisitor. Use PagedLOD instead of our own derived method. --- CMakeLists.txt | 2 +- projects/VC90/SimGear.vcproj | 8 -- simgear/scene/model/CMakeLists.txt | 2 - simgear/scene/model/CheckSceneryVisitor.cxx | 78 +++++++++---- simgear/scene/model/CheckSceneryVisitor.hxx | 12 +- simgear/scene/model/SGPagedLOD.cxx | 123 -------------------- simgear/scene/model/SGPagedLOD.hxx | 75 ------------ simgear/scene/model/SGReaderWriterXML.cxx | 1 - simgear/scene/model/modellib.cxx | 39 ++++++- simgear/scene/model/modellib.hxx | 16 ++- 10 files changed, 104 insertions(+), 252 deletions(-) delete mode 100644 simgear/scene/model/SGPagedLOD.cxx delete mode 100644 simgear/scene/model/SGPagedLOD.hxx diff --git a/CMakeLists.txt b/CMakeLists.txt index fc2d2630..d356c357 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,7 @@ else() find_package(OpenGL REQUIRED) find_package(OpenAL REQUIRED) find_package(ALUT REQUIRED) - find_package(OpenSceneGraph 2.8.1 REQUIRED osgText osgSim osgDB osgParticle osgUtil) + find_package(OpenSceneGraph 3.0.0 REQUIRED osgText osgSim osgDB osgParticle osgUtil) endif(SIMGEAR_HEADLESS) if(JPEG_FACTORY) diff --git a/projects/VC90/SimGear.vcproj b/projects/VC90/SimGear.vcproj index f3d50894..7517d1cb 100644 --- a/projects/VC90/SimGear.vcproj +++ b/projects/VC90/SimGear.vcproj @@ -1139,14 +1139,6 @@ RelativePath="..\..\simgear\scene\model\SGOffsetTransform.hxx" > - - - - diff --git a/simgear/scene/model/CMakeLists.txt b/simgear/scene/model/CMakeLists.txt index 6890fbe4..37ca27ff 100644 --- a/simgear/scene/model/CMakeLists.txt +++ b/simgear/scene/model/CMakeLists.txt @@ -9,7 +9,6 @@ set(HEADERS SGInteractionAnimation.hxx SGMaterialAnimation.hxx SGOffsetTransform.hxx - SGPagedLOD.hxx SGReaderWriterXML.hxx SGReaderWriterXMLOptions.hxx SGRotateTransform.hxx @@ -32,7 +31,6 @@ set(SOURCES SGInteractionAnimation.cxx SGMaterialAnimation.cxx SGOffsetTransform.cxx - SGPagedLOD.cxx SGReaderWriterXML.cxx SGRotateTransform.cxx SGScaleTransform.cxx diff --git a/simgear/scene/model/CheckSceneryVisitor.cxx b/simgear/scene/model/CheckSceneryVisitor.cxx index 4a0625bc..e0149c06 100644 --- a/simgear/scene/model/CheckSceneryVisitor.cxx +++ b/simgear/scene/model/CheckSceneryVisitor.cxx @@ -1,4 +1,5 @@ // Copyright (C) 2008 Till Busch buti@bux.at +// Copyright (C) 2011 Mathias Froehlich // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -19,11 +20,12 @@ #endif #include +#include +#include #include #include "CheckSceneryVisitor.hxx" -#include "SGPagedLOD.hxx" #include @@ -33,9 +35,10 @@ CheckSceneryVisitor::CheckSceneryVisitor(osgDB::DatabasePager* dbp, const osg::V osg::FrameStamp* framestamp) :osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR, osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), -_position(position), _range(range), _loaded(true), _dbp(dbp), _framestamp(framestamp) + _position(position), _range(range), _loaded(true), _matrix(osg::Matrix::identity()) { - _viewMatrices.push_back(osg::Matrix::identity()); + setDatabaseRequestHandler(dbp); + setFrameStamp(framestamp); } void CheckSceneryVisitor::apply(osg::Node& node) @@ -43,35 +46,62 @@ void CheckSceneryVisitor::apply(osg::Node& node) traverse(node); } -void CheckSceneryVisitor::apply(osg::PagedLOD& node) +void CheckSceneryVisitor::apply(osg::ProxyNode& node) { - SGPagedLOD *sgplod = dynamic_cast(&node); - if (sgplod) { - osg::Vec3 pos = sgplod->getCenter() * _viewMatrices.back(); - double dist = (pos-_position).length(); - if (dist < _range) { - if (sgplod->getNumChildren() < 1) { - // if the DatabasePager would load LODs while the splashscreen - // is there, we could just wait for the models to be loaded - // by only setting setLoaded(false) here - sgplod->forceLoad(_dbp,_framestamp, getNodePath()); - setLoaded(false); - } + osg::Vec3 pos = node.getCenter() * _matrix; + double dist = (pos - _position).length(); + if (dist < _range) { + for (unsigned i = 0; i < node.getNumFileNames(); ++i) { + if (node.getFileName(i).empty()) + continue; + // Check if this is already loaded. + if (i < node.getNumChildren() && node.getChild(i)) + continue; + + // if the DatabasePager would load LODs while the splashscreen + // is there, we could just wait for the models to be loaded + // by only setting setLoaded(false) here + osg::NodePath nodePath = getNodePath(); + DatabaseRequestHandler* db = getDatabaseRequestHandler(); + const osg::FrameStamp* fs = getFrameStamp(); + db->requestNodeFile(node.getFileName(i), nodePath, 1.0 /*priority*/, fs, + node.getDatabaseRequest(i), node.getDatabaseOptions()); + setLoaded(false); } } traverse(node); } -void CheckSceneryVisitor::apply(osg::Transform &node) +void CheckSceneryVisitor::apply(osg::PagedLOD& node) { - osg::Matrix currMatrix = _viewMatrices.back(); - bool pushMatrix = node.computeLocalToWorldMatrix(currMatrix, this); + osg::Vec3 pos = node.getCenter() * _matrix; + double dist = (pos - _position).length(); + if (dist < _range) { + for (unsigned i = 0; i < node.getNumFileNames(); ++i) { + if (node.getFileName(i).empty()) + continue; + // Check if this is already loaded. + if (i < node.getNumChildren() && node.getChild(i)) + continue; - if (pushMatrix) { - _viewMatrices.push_back(currMatrix); + // if the DatabasePager would load LODs while the splashscreen + // is there, we could just wait for the models to be loaded + // by only setting setLoaded(false) here + osg::NodePath nodePath = getNodePath(); + DatabaseRequestHandler* db = getDatabaseRequestHandler(); + const osg::FrameStamp* fs = getFrameStamp(); + db->requestNodeFile(node.getFileName(i), nodePath, 1.0 /*priority*/, fs, + node.getDatabaseRequest(i), node.getDatabaseOptions()); + setLoaded(false); + } } traverse(node); - if (pushMatrix) { - _viewMatrices.pop_back(); - } +} + +void CheckSceneryVisitor::apply(osg::Transform &node) +{ + osg::Matrix matrix = _matrix; + node.computeLocalToWorldMatrix(_matrix, this); + traverse(node); + _matrix = matrix; } diff --git a/simgear/scene/model/CheckSceneryVisitor.hxx b/simgear/scene/model/CheckSceneryVisitor.hxx index 4b9a357d..2d57ec84 100644 --- a/simgear/scene/model/CheckSceneryVisitor.hxx +++ b/simgear/scene/model/CheckSceneryVisitor.hxx @@ -1,4 +1,5 @@ // Copyright (C) 2008 Till Busch buti@bux.at +// Copyright (C) 2011 Mathias Froehlich // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -18,7 +19,6 @@ #define CHECKSCENERYVISITOR_HXX #include -#include namespace osgDB { class DatabasePager; @@ -28,9 +28,7 @@ class DatabasePager; namespace simgear { -class SGPagedLOD; - -// Checks the scene graph for SGPagedLODs that are within range +// Checks the scene graph for PagedLOD or ProxyNodes that are within range // (compared to postion) and injects them into the DatabasePager. // After visiting, isLoaded() returns true if all models in range // are available. @@ -41,6 +39,7 @@ public: CheckSceneryVisitor(osgDB::DatabasePager* dbp, const osg::Vec3 &position, double range, osg::FrameStamp* framestamp); virtual void apply(osg::Node& node); + virtual void apply(osg::ProxyNode& node); virtual void apply(osg::PagedLOD& node); virtual void apply(osg::Transform& node); @@ -58,10 +57,7 @@ private: osg::Vec3 _position; double _range; bool _loaded; - osgDB::DatabasePager* _dbp; - osg::FrameStamp* _framestamp; - - osg::fast_back_stack _viewMatrices; + osg::Matrix _matrix; }; } diff --git a/simgear/scene/model/SGPagedLOD.cxx b/simgear/scene/model/SGPagedLOD.cxx deleted file mode 100644 index b44019b7..00000000 --- a/simgear/scene/model/SGPagedLOD.cxx +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2008 Till Busch buti@bux.at -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program 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 GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include - -#include -#include - -#include "modellib.hxx" -#include "SGReaderWriterXMLOptions.hxx" -#include "SGPagedLOD.hxx" - -#include - -using namespace osg; -using namespace simgear; - -bool SGPagedLOD::_cache = true; - -SGPagedLOD::SGPagedLOD() - : PagedLOD() -{ -} - -SGPagedLOD::~SGPagedLOD() -{ - //SG_LOG(SG_GENERAL, SG_ALERT, "SGPagedLOD::~SGPagedLOD(" << getFileName(0) << ")"); -} - -SGPagedLOD::SGPagedLOD(const SGPagedLOD& plod,const CopyOp& copyop) - : osg::PagedLOD(plod, copyop) -#if !SG_PAGEDLOD_HAS_OPTIONS - , _readerWriterOptions(plod._readerWriterOptions) -#endif -{ -} - -void -SGPagedLOD::setReaderWriterOptions(osgDB::ReaderWriter::Options *options) -{ - if (_cache) - options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL); - else - options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_NONE); -#if SG_PAGEDLOD_HAS_OPTIONS - setDatabaseOptions(options); -#else - _readerWriterOptions = options; -#endif -} - -bool SGPagedLOD::addChild(osg::Node *child) -{ - if (!PagedLOD::addChild(child)) - return false; - - setRadius(getBound().radius()); - setCenter(getBound().center()); - return true; -} - -// Work around interface change in osgDB::DatabasePager::requestNodeFile -struct NodePathProxy -{ - NodePathProxy(NodePath& nodePath) - : _nodePath(nodePath) - { - } - operator Group* () { return static_cast(_nodePath.back()); } - operator NodePath& () { return _nodePath; } - NodePath& _nodePath; -}; - -void SGPagedLOD::forceLoad(osgDB::DatabasePager *dbp, FrameStamp* framestamp, - NodePath& path) -{ - //SG_LOG(SG_GENERAL, SG_ALERT, "SGPagedLOD::forceLoad(" << - //getFileName(getNumChildren()) << ")"); - unsigned childNum = getNumChildren(); - setTimeStamp(childNum, 0); - double priority=1.0; - dbp->requestNodeFile(getFileName(childNum), NodePathProxy(path), - priority, framestamp, - getDatabaseRequest(childNum), - getReaderWriterOptions()); -} - -bool SGPagedLOD_writeLocalData(const Object& obj, osgDB::Output& fw) -{ - return true; -} - -namespace -{ -osgDB::RegisterDotOsgWrapperProxy sgPagedLODProxy -( - new SGPagedLOD, - "simgear::SGPagedLOD", - "Object Node LOD PagedLOD SGPagedLOD Group", - 0, - &SGPagedLOD_writeLocalData - ); -} diff --git a/simgear/scene/model/SGPagedLOD.hxx b/simgear/scene/model/SGPagedLOD.hxx deleted file mode 100644 index 69f8dc21..00000000 --- a/simgear/scene/model/SGPagedLOD.hxx +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2008 Till Busch buti@bux.at -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program 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 GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -#ifndef SGPAGEDLOD_HXX -#define SGPAGEDLOD_HXX 1 - -#include - -#define SG_PAGEDLOD_HAS_OPTIONS \ - (SG_OSG_VERSION >= 29005) - -#include -#include -#include -#include - -namespace osgDB { -class DatabasePager; -} - - -namespace simgear -{ - -class SGPagedLOD : public osg::PagedLOD -{ -public: - SGPagedLOD(); - - SGPagedLOD(const SGPagedLOD&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); - - META_Node(simgear, SGPagedLOD); - - // virtual void traverse(osg::NodeVisitor& nv); - virtual void forceLoad(osgDB::DatabasePager* dbp, - osg::FrameStamp* framestamp, - osg::NodePath& path); - - // reimplemented to notify the loading through ModelData - bool addChild(osg::Node *child); - - void setReaderWriterOptions(osgDB::ReaderWriter::Options *options); - - osgDB::ReaderWriter::Options* getReaderWriterOptions() { -#if SG_PAGEDLOD_HAS_OPTIONS - return static_cast(getDatabaseOptions()); -#else - return _readerWriterOptions.get(); -#endif - } - - static void setRenderingCache(bool cache) {_cache = cache;} -protected: - virtual ~SGPagedLOD(); -#if !SG_PAGEDLOD_HAS_OPTIONS - osg::ref_ptr _readerWriterOptions; -#endif -private: - static bool _cache; -}; -} -#endif diff --git a/simgear/scene/model/SGReaderWriterXML.cxx b/simgear/scene/model/SGReaderWriterXML.cxx index b17c776a..ab128df9 100644 --- a/simgear/scene/model/SGReaderWriterXML.cxx +++ b/simgear/scene/model/SGReaderWriterXML.cxx @@ -42,7 +42,6 @@ #include #include "modellib.hxx" -#include "SGPagedLOD.hxx" #include "SGReaderWriterXML.hxx" #include "SGReaderWriterXMLOptions.hxx" diff --git a/simgear/scene/model/modellib.cxx b/simgear/scene/model/modellib.cxx index 886825f8..413d1734 100644 --- a/simgear/scene/model/modellib.cxx +++ b/simgear/scene/model/modellib.cxx @@ -21,6 +21,8 @@ #include +#include +#include #include #include #include @@ -32,7 +34,6 @@ #include #include -#include "SGPagedLOD.hxx" #include "SGReaderWriterXML.hxx" #include "SGReaderWriterXMLOptions.hxx" @@ -56,7 +57,6 @@ void SGModelLib::init(const string &root_dir, SGPropertyNode* root) { osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir); static_propRoot = root; - SGPagedLOD::setRenderingCache(root->getBoolValue("/sim/rendering/cache",true)); } void SGModelLib::setPanelFunc(panel_func pf) @@ -122,11 +122,36 @@ SGModelLib::loadModel(const string &path, } +osg::Node* +SGModelLib::loadDeferedModel(const string &path, SGPropertyNode *prop_root, + SGModelData *data) +{ + osg::ProxyNode* proxyNode = new osg::ProxyNode; + proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); + proxyNode->setFileName(0, path); + + osg::ref_ptr opt + = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance() + ->getOptions())); + opt->setPropRoot(prop_root ? prop_root: static_propRoot.get()); + opt->setModelData(data); + opt->setLoadPanel(static_panelFunc); + if (SGPath(path).lower_extension() == "ac") + opt->setInstantiateEffects(true); + if (!prop_root || prop_root->getBoolValue("/sim/rendering/cache", true)) + opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL); + else + opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_NONE); + proxyNode->setDatabaseOptions(opt.get()); + + return proxyNode; +} + osg::Node* SGModelLib::loadPagedModel(const string &path, SGPropertyNode *prop_root, SGModelData *data) { - SGPagedLOD *plod = new SGPagedLOD; + osg::PagedLOD *plod = new osg::PagedLOD; plod->setName("Paged LOD for \"" + path + "\""); plod->setFileName(0, path); plod->setRange(0, 0.0, 50.0*SG_NM_TO_METER); @@ -137,9 +162,13 @@ SGModelLib::loadPagedModel(const string &path, SGPropertyNode *prop_root, opt->setPropRoot(prop_root ? prop_root: static_propRoot.get()); opt->setModelData(data); opt->setLoadPanel(static_panelFunc); - if (boost::iends_with(path, ".ac")) + if (SGPath(path).lower_extension() == "ac") opt->setInstantiateEffects(true); - plod->setReaderWriterOptions(opt.get()); + if (!prop_root || prop_root->getBoolValue("/sim/rendering/cache", true)) + opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL); + else + opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_NONE); + plod->setDatabaseOptions(opt.get()); return plod; } diff --git a/simgear/scene/model/modellib.hxx b/simgear/scene/model/modellib.hxx index 61091085..cdcbd7dd 100644 --- a/simgear/scene/model/modellib.hxx +++ b/simgear/scene/model/modellib.hxx @@ -55,11 +55,17 @@ public: SGModelData *data=0, bool load2DPanels=false); // Load a 3D model (any format) through the DatabasePager. - // Most models should be loaded using this function! - // This function will initially return an SGPagedLOD node. - // data->modelLoaded() will be called after the model is loaded and - // connected to the scene graph. See AIModelData on how to use this. - // NOTE: AIModelData uses observer_ptr to avoid circular references. + // This function initially just returns a proxy node that refers to + // the model file. Once the viewer steps onto that node the + // model will be loaded. + static osg::Node* loadDeferedModel(const std::string &path, + SGPropertyNode *prop_root = NULL, + SGModelData *data=0); + // Load a 3D model (any format) through the DatabasePager. + // This function initially just returns a PagedLOD node that refers to + // the model file. Once the viewer steps onto that node the + // model will be loaded. When the viewer does no longer reference this + // node for a long time the node is unloaded again. static osg::Node* loadPagedModel(const std::string &path, SGPropertyNode *prop_root = NULL, SGModelData *data=0); -- 2.39.5