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.
This commit is contained in:
parent
a543560f7d
commit
ad079b8ed4
@ -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)
|
||||
|
@ -1139,14 +1139,6 @@
|
||||
RelativePath="..\..\simgear\scene\model\SGOffsetTransform.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGPagedLOD.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGPagedLOD.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGReaderWriterXML.cxx"
|
||||
>
|
||||
|
@ -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
|
||||
|
@ -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 <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,20 +46,53 @@ void CheckSceneryVisitor::apply(osg::Node& node)
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
void CheckSceneryVisitor::apply(osg::ProxyNode& node)
|
||||
{
|
||||
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::PagedLOD& 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);
|
||||
@ -64,14 +100,8 @@ void CheckSceneryVisitor::apply(osg::PagedLOD& node)
|
||||
|
||||
void CheckSceneryVisitor::apply(osg::Transform &node)
|
||||
{
|
||||
osg::Matrix currMatrix = _viewMatrices.back();
|
||||
bool pushMatrix = node.computeLocalToWorldMatrix(currMatrix, this);
|
||||
|
||||
if (pushMatrix) {
|
||||
_viewMatrices.push_back(currMatrix);
|
||||
}
|
||||
osg::Matrix matrix = _matrix;
|
||||
node.computeLocalToWorldMatrix(_matrix, this);
|
||||
traverse(node);
|
||||
if (pushMatrix) {
|
||||
_viewMatrices.pop_back();
|
||||
}
|
||||
_matrix = matrix;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
@ -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
|
@ -42,7 +42,6 @@
|
||||
#include <simgear/scene/util/SGNodeMasks.hxx>
|
||||
|
||||
#include "modellib.hxx"
|
||||
#include "SGPagedLOD.hxx"
|
||||
#include "SGReaderWriterXML.hxx"
|
||||
#include "SGReaderWriterXMLOptions.hxx"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user