From 7fb89e4d45bbf1d5b24416d80afa058c166a26f0 Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Tue, 5 Jun 2018 21:56:36 +0100 Subject: [PATCH] Multiple LoD levels of MP Aircraft Support loading multiple models into PagedLOD. --- simgear/scene/model/modellib.cxx | 59 +++++++++++++++++++++++++------- simgear/scene/model/modellib.hxx | 51 ++++++++++++++++++++++++--- 2 files changed, 93 insertions(+), 17 deletions(-) diff --git a/simgear/scene/model/modellib.cxx b/simgear/scene/model/modellib.cxx index 3d931f2b..34707957 100644 --- a/simgear/scene/model/modellib.cxx +++ b/simgear/scene/model/modellib.cxx @@ -161,33 +161,68 @@ SGModelLib::loadDeferredModel(const string &path, SGPropertyNode *prop_root, return proxyNode; } + +/* + * Load a set of models at different LOD range_nearest + * + */ osg::PagedLOD* -SGModelLib::loadPagedModel(const string &path, SGPropertyNode *prop_root, - SGModelData *data) +SGModelLib::loadPagedModel(SGPropertyNode *prop_root, SGModelData *data, SGModelLOD model_lods) { 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); - plod->setMinimumExpiryTime( 0, prop_root->getDoubleValue("/sim/rendering/plod-minimum-expiry-time-secs", 180.0 ) ); osg::ref_ptr opt; opt = SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions()); opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get()); opt->setModelData(data); opt->setLoadPanel(static_panelFunc); - std::string lext = SGPath(path).lower_extension(); - - if ((lext == "ac") || (lext == "obj")) { - opt->setInstantiateEffects(true); - } - if (!prop_root || prop_root->getBoolValue("/sim/rendering/cache", true)) opt->setObjectCacheHint(osgDB::Options::CACHE_ALL); else opt->setObjectCacheHint(osgDB::Options::CACHE_NONE); + + for(unsigned int i = 0; i < model_lods.getNumLODs(); i++) { + SGModelLOD::ModelLOD lod = model_lods.getModelLOD(i); + plod->setName("Paged LOD for \"" + lod.path + "\""); + plod->setFileName(i, lod.path); + plod->setRange(i, lod.min_range, lod.max_range); + plod->setMinimumExpiryTime(i, prop_root->getDoubleValue("/sim/rendering/plod-minimum-expiry-time-secs", 180.0 ) ); + + std::string lext = SGPath(lod.path).lower_extension(); + + // We can only have one set of ReaderWriterOptions for the PagedLOD, so + // we will just have to assume that if one of the defined models can + // handle instantiated effects, then the other can as well. + if ((lext == "ac") || (lext == "obj")) { + opt->setInstantiateEffects(true); + } + } + plod->setDatabaseOptions(opt.get()); + return plod; } +osg::PagedLOD* +SGModelLib::loadPagedModel(const string &path, SGPropertyNode *prop_root, + SGModelData *data) +{ + SGModelLOD model_lods; + model_lods.insert(path, 0.0, 50.0*SG_NM_TO_METER); + return SGModelLib::loadPagedModel(prop_root, data, model_lods); +} + +osg::PagedLOD* +SGModelLib::loadPagedModel(std::vector paths, SGPropertyNode *prop_root, + SGModelData *data) +{ + SGModelLOD model_lods; + for(unsigned int i = 0; i < paths.size(); i++) { + // We don't have any range data, so simply set them all up to full range. + // Some other code will update the LoD ranges later. (AIBase::updateLOD) + model_lods.insert(paths[i], 0.0, 50.0*SG_NM_TO_METER); + } + return SGModelLib::loadPagedModel(prop_root, data, model_lods); +} + // end of modellib.cxx diff --git a/simgear/scene/model/modellib.hxx b/simgear/scene/model/modellib.hxx index cdd6d820..b9be0311 100644 --- a/simgear/scene/model/modellib.hxx +++ b/simgear/scene/model/modellib.hxx @@ -39,6 +39,7 @@ namespace osg { namespace simgear { class SGModelData; // defined below +class SGModelLOD; // defined below /** * Class for loading and managing models with XML wrappers. @@ -51,9 +52,9 @@ public: static void init(const std::string &root_dir, SGPropertyNode* root); static void resetPropertyRoot(); - + static void setPanelFunc(panel_func pf); - + // Load a 3D model (any format) // data->modelLoaded() will be called after the model is loaded static osg::Node* loadModel(const std::string &path, @@ -72,17 +73,24 @@ public: // 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::PagedLOD* loadPagedModel(SGPropertyNode *prop_root, + SGModelData *data, + SGModelLOD model_lods); static osg::PagedLOD* loadPagedModel(const std::string &path, SGPropertyNode *prop_root = NULL, SGModelData *data=0); - static std::string findDataFile(const std::string& file, + static osg::PagedLOD* loadPagedModel(std::vector paths, + SGPropertyNode *prop_root = NULL, + SGModelData *data=0); + + static std::string findDataFile(const std::string& file, const osgDB::Options* opts = NULL, - SGPath currentDir = SGPath()); + SGPath currentDir = SGPath()); protected: SGModelLib(); ~SGModelLib (); - + private: static SGPropertyNode_ptr static_propRoot; static panel_func static_panelFunc; @@ -102,6 +110,39 @@ public: virtual SGModelData* clone() const = 0; }; +/* + * Data for a model with multiple LoD versions + */ + +class SGModelLOD { +public: + struct ModelLOD { + ModelLOD(const string &p, float minrange, float maxrange) : + path(p), min_range(minrange), max_range(maxrange) + { } + const string &path; + float min_range; + float max_range; + }; +typedef std::vector ModelLODList; + +void insert(const ModelLOD& model) +{ + _models.push_back(model); +} + +void insert(const string &p, float minrange, float maxrange) +{ + insert(ModelLOD(p, minrange, maxrange)); +} + +unsigned getNumLODs() const { return _models.size(); } +const ModelLOD& getModelLOD(unsigned i) const { return _models[i]; } + +private: + ModelLODList _models; +}; + } #endif // _SG_MODEL_LIB_HXX