From 49162a7a64d48ce983635bb993277b77a9640076 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Sun, 24 Feb 2013 13:03:06 +0100 Subject: [PATCH] stg: Defer loading models into a paged lod node. This defers loading the models into a paged lod node that is evaluated at a later point in time. That should help for memory problems with higher visibilities. --- simgear/scene/tgdb/ReaderWriterSTG.cxx | 135 ++++++++++++++++--------- 1 file changed, 86 insertions(+), 49 deletions(-) diff --git a/simgear/scene/tgdb/ReaderWriterSTG.cxx b/simgear/scene/tgdb/ReaderWriterSTG.cxx index 4892fac5..fe4f302a 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.cxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.cxx @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -37,12 +38,14 @@ #include #include +#include #include #include #include -#include -#include +#include #include +#include +#include #include #include @@ -109,6 +112,63 @@ struct ReaderWriterSTG::_ModelBin { int _size; }; + class DelayLoadReadFileCallback : public OptionsReadFileCallback { + public: + virtual osgDB::ReaderWriter::ReadResult + readNode(const std::string&, const osgDB::Options*) + { + osg::ref_ptr group = new osg::Group; + group->setDataVariance(osg::Object::STATIC); + + for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) { + osg::ref_ptr node; + if (i->_proxy) { + osg::ref_ptr proxy = new osg::ProxyNode; + proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); + proxy->setFileName(0, i->_name); + proxy->setDatabaseOptions(i->_options.get()); + node = proxy; + } else { + node = osgDB::readRefNodeFile(i->_name, i->_options.get()); + if (!node.valid()) { + SG_LOG(SG_TERRAIN, SG_ALERT, i->_errorLocation << ": Failed to load " + << i->_token << " '" << i->_name << "'"); + continue; + } + } + if (SGPath(i->_name).lower_extension() == "ac") + node->setNodeMask(~simgear::MODELLIGHT_BIT); + + osg::Matrix matrix; + matrix = makeZUpFrame(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev)); + matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_hdg), osg::Vec3(0, 0, 1))); + matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_pitch), osg::Vec3(0, 1, 0))); + matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_roll), osg::Vec3(1, 0, 0))); + + osg::MatrixTransform* matrixTransform; + matrixTransform = new osg::MatrixTransform(matrix); + matrixTransform->setDataVariance(osg::Object::STATIC); + matrixTransform->addChild(node.get()); + group->addChild(matrixTransform); + } + + simgear::AirportSignBuilder signBuilder(_options->getMaterialLib(), _bucket.get_center()); + for (std::list<_Sign>::iterator i = _signList.begin(); i != _signList.end(); ++i) + signBuilder.addSign(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev), i->_hdg, i->_name, i->_size); + if (signBuilder.getSignsGroup()) + group->addChild(signBuilder.getSignsGroup()); + + return group.release(); + } + + std::list<_ObjectStatic> _objectStaticList; + std::list<_Sign> _signList; + + /// The original options to use for this bunch of models + osg::ref_ptr _options; + SGBucket _bucket; + }; + _ModelBin() : _foundBase(false) { } @@ -326,58 +386,35 @@ struct ReaderWriterSTG::_ModelBin { continue; i->_elev += elevation(*terrainGroup, SGGeod::fromDeg(i->_lon, i->_lat)); } - - osg::ref_ptr modelGroup = new osg::Group; - modelGroup->setDataVariance(osg::Object::STATIC); - for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) { - osg::ref_ptr node; - if (i->_proxy) { - osg::ref_ptr proxy = new osg::ProxyNode; - proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); - proxy->setFileName(0, i->_name); - proxy->setDatabaseOptions(i->_options.get()); - node = proxy; - } else { - node = osgDB::readRefNodeFile(i->_name, i->_options.get()); - if (!node.valid()) { - SG_LOG(SG_TERRAIN, SG_ALERT, i->_errorLocation << ": Failed to load " - << i->_token << " '" << i->_name << "'"); - continue; - } - } - if (SGPath(i->_name).lower_extension() == "ac") - node->setNodeMask(~simgear::MODELLIGHT_BIT); + if (_objectStaticList.empty() && _signList.empty()) { + // The simple case, just return the terrain group + return terrainGroup.release(); + } else { + osg::PagedLOD* pagedLOD = new osg::PagedLOD; + pagedLOD->setCenterMode(osg::PagedLOD::USE_BOUNDING_SPHERE_CENTER); + + // This should be visible in any case. + // If this is replaced by some lower level of detail, the parent LOD node handles this. + pagedLOD->addChild(terrainGroup, 0, std::numeric_limits::max()); + + // we just need to know about the read file callback that itself holds the data + osg::ref_ptr readFileCallback = new DelayLoadReadFileCallback; + readFileCallback->_objectStaticList = _objectStaticList; + readFileCallback->_signList = _signList; + readFileCallback->_options = options; + readFileCallback->_bucket = bucket; + osg::ref_ptr callbackOptions = new osgDB::Options; + callbackOptions->setReadFileCallback(readFileCallback.get()); + pagedLOD->setDatabaseOptions(callbackOptions.get()); - osg::Matrix matrix; - matrix = makeZUpFrame(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev)); - matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_hdg), osg::Vec3(0, 0, 1))); - matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_pitch), osg::Vec3(0, 1, 0))); - matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_roll), osg::Vec3(1, 0, 0))); + pagedLOD->setFileName(pagedLOD->getNumChildren(), "Dummy name - use the stored data in the read file callback"); + pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 30000); - osg::MatrixTransform* matrixTransform; - matrixTransform = new osg::MatrixTransform(matrix); - matrixTransform->setDataVariance(osg::Object::STATIC); - matrixTransform->addChild(node.get()); - modelGroup->addChild(matrixTransform); + return pagedLOD; } - - simgear::AirportSignBuilder signBuilder(options->getMaterialLib(), bucket.get_center()); - for (std::list<_Sign>::iterator i = _signList.begin(); i != _signList.end(); ++i) - signBuilder.addSign(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev), i->_hdg, i->_name, i->_size); - if (signBuilder.getSignsGroup()) - modelGroup->addChild(signBuilder.getSignsGroup()); - - osg::LOD* lod = new osg::LOD; - lod->setDataVariance(osg::Object::STATIC); - if (terrainGroup->getNumChildren()) - lod->addChild(terrainGroup.get(), 0, std::numeric_limits::max()); - if (modelGroup->getNumChildren()) - lod->addChild(modelGroup.get(), 0, 30000); - - return lod; } - + bool _foundBase; std::list<_Object> _objectList; std::list<_ObjectStatic> _objectStaticList; -- 2.39.5