]> git.mxchange.org Git - simgear.git/commitdiff
modellib: Add method for deferred model loading.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Tue, 8 Nov 2011 20:11:28 +0000 (21:11 +0100)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Tue, 8 Nov 2011 20:31:18 +0000 (21:31 +0100)
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
projects/VC90/SimGear.vcproj
simgear/scene/model/CMakeLists.txt
simgear/scene/model/CheckSceneryVisitor.cxx
simgear/scene/model/CheckSceneryVisitor.hxx
simgear/scene/model/SGPagedLOD.cxx [deleted file]
simgear/scene/model/SGPagedLOD.hxx [deleted file]
simgear/scene/model/SGReaderWriterXML.cxx
simgear/scene/model/modellib.cxx
simgear/scene/model/modellib.hxx

index fc2d2630a99d1fb8d00346eda3df52a3f5df66b0..d356c3579a9afb001a8da630455d35a14c084bd5 100644 (file)
@@ -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)
index f3d5089453fb5c3d24821c07e7383df672d09c95..7517d1cbf3c09fffaba4541ee8b4945425bcc0ea 100644 (file)
                                RelativePath="..\..\simgear\scene\model\SGOffsetTransform.hxx"\r
                                >\r
                        </File>\r
-                       <File\r
-                               RelativePath="..\..\simgear\scene\model\SGPagedLOD.cxx"\r
-                               >\r
-                       </File>\r
-                       <File\r
-                               RelativePath="..\..\simgear\scene\model\SGPagedLOD.hxx"\r
-                               >\r
-                       </File>\r
                        <File\r
                                RelativePath="..\..\simgear\scene\model\SGReaderWriterXML.cxx"\r
                                >\r
index 6890fbe4985588589cbfae1a273862575a788060..37ca27ffbc9d0d15bceccd828689fb81e4c054aa 100644 (file)
@@ -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
index 4a0625bc2ea325e11e6a64ddaabab6bd0bafaec5..e0149c069a5a8f6bb00298a05ffba65b1d9ae7bf 100644 (file)
@@ -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
 #endif
 
 #include <osg/Transform>
+#include <osg/ProxyNode>
+#include <osgDB/DatabasePager>
 
 #include <simgear/debug/logstream.hxx>
 
 #include "CheckSceneryVisitor.hxx"
-#include "SGPagedLOD.hxx"
 
 #include <simgear/math/SGMath.hxx>
 
@@ -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<SGPagedLOD*>(&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;
 }
index 4b9a357da6d5b3c75e41e808e0c79ddfe10d24f8..2d57ec8486de72cfea70995038624977b7d4f611 100644 (file)
@@ -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 <osg/NodeVisitor>
-#include <osg/fast_back_stack>
 
 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<osg::Matrix> _viewMatrices;
+    osg::Matrix _matrix;
 };
 
 }
diff --git a/simgear/scene/model/SGPagedLOD.cxx b/simgear/scene/model/SGPagedLOD.cxx
deleted file mode 100644 (file)
index b44019b..0000000
+++ /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 <simgear_config.h>
-#endif
-
-#include <osgDB/ReadFile>
-#include <osgDB/Input>
-#include <osgDB/ParameterOutput>
-#include <osgDB/DatabasePager>
-
-#include <simgear/debug/logstream.hxx>
-#include <simgear/structure/OSGVersion.hxx>
-
-#include "modellib.hxx"
-#include "SGReaderWriterXMLOptions.hxx"
-#include "SGPagedLOD.hxx"
-
-#include <simgear/math/SGMath.hxx>
-
-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<Group*>(_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 (file)
index 69f8dc2..0000000
+++ /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 <simgear/structure/OSGVersion.hxx>
-
-#define SG_PAGEDLOD_HAS_OPTIONS \
-    (SG_OSG_VERSION >= 29005)
-
-#include <osg/PagedLOD>
-#include <osgDB/Registry>
-#include <osgDB/ReaderWriter>
-#include <simgear/props/props.hxx>
-
-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<osgDB::ReaderWriter::Options*>(getDatabaseOptions());
-#else
-        return _readerWriterOptions.get();
-#endif
-    }
-
-    static void setRenderingCache(bool cache) {_cache = cache;}
-protected:
-    virtual ~SGPagedLOD();
-#if !SG_PAGEDLOD_HAS_OPTIONS
-    osg::ref_ptr<osgDB::ReaderWriter::Options> _readerWriterOptions;
-#endif
-private:
-    static bool _cache;
-};
-}
-#endif
index b17c776ad79ca07aeb050098c3abb74f03297e60..ab128df9adbec548ae999d267f5bbd23bb19fe81 100644 (file)
@@ -42,7 +42,6 @@
 #include <simgear/scene/util/SGNodeMasks.hxx>
 
 #include "modellib.hxx"
-#include "SGPagedLOD.hxx"
 #include "SGReaderWriterXML.hxx"
 #include "SGReaderWriterXMLOptions.hxx"
 
index 886825f89325b60d4fd677cddeccb4d53c53a6bb..413d1734f120a06b900dfd42035156de12dd9f22 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <boost/algorithm/string.hpp>
 
+#include <osg/PagedLOD>
+#include <osg/ProxyNode>
 #include <osgDB/ReadFile>
 #include <osgDB/WriteFile>
 #include <osgDB/Registry>
@@ -32,7 +34,6 @@
 #include <simgear/scene/model/ModelRegistry.hxx>
 #include <simgear/misc/ResourceManager.hxx>
 
-#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<SGReaderWriterXMLOptions> 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;
 }
 
index 61091085f057900063b796ea3af929ed1153583e..cdcbd7dd8fade0c9bce8ede869273b28d70326ff 100644 (file)
@@ -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);