From 88720a031b4c646940530bbcf67a699225879929 Mon Sep 17 00:00:00 2001 From: Richard Harrison Date: Tue, 6 Nov 2018 18:42:07 +0100 Subject: [PATCH] Changes to the model interior LOD management. If a model is marked as interior there were a number of problems. 1 - the LOD setting AI/MP interior used the distance from the aircraft; this obviously doesn't quite work for when using the model view. 2 - with the way that models are now loaded as two LOD levels only the interior from the first model loaded (usually the lowest detail) would be considered or processed because the model loader had marked itself as already run (which it had, but not for the model that was actually just loaded. (2) above could also be the cause of other things not working because the nasal model loaded would not be called, nor would the sound path be setup. There could be other things that aren't working properly because the assumption is that there is just one model. The fix for (1) is to use the standard OSG PagedLOD and let it handle the details, so I've changed the interior to use this and removed the distane from ownship checks. The fix for (2) is to use a map to decide if the model that has just finished loading has already been processed, and if not then proceed as normal. --- src/AIModel/AIBase.cxx | 41 +++++++++++++++++++++++++++------------ src/AIModel/AIManager.cxx | 6 ++++-- src/AIModel/AIManager.hxx | 1 + 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/AIModel/AIBase.cxx b/src/AIModel/AIBase.cxx index e04093ba5..e214d016e 100644 --- a/src/AIModel/AIBase.cxx +++ b/src/AIModel/AIBase.cxx @@ -77,9 +77,12 @@ public: void modelLoaded(const std::string& path, SGPropertyNode *prop, osg::Node *n) { // WARNING: Called in a separate OSG thread! Only use thread-safe stuff here... - if (_ready) + if (_ready && _modelLoaded.count(path) > 0) return; + _modelLoaded[path] = true; + _ready = true; + if(prop->hasChild("interior-path")){ _interiorPath = prop->getStringValue("interior-path"); _hasInteriorPath = true; @@ -88,7 +91,6 @@ public: _fxpath = prop->getStringValue("sound/path"); _nasal->modelLoaded(path, prop, n); - _ready = true; } @@ -109,6 +111,7 @@ private: std::string _fxpath; std::string _interiorPath; + std::map _modelLoaded; bool _ready = false; bool _initialized = false; bool _hasInteriorPath = false; @@ -305,16 +308,21 @@ void FGAIBase::updateInterior() if(!_modeldata || !_modeldata->hasInteriorPath()) return; - if(!_modeldata->getInteriorLoaded()){ // interior is not yet load - double d2 = dist(SGVec3d::fromGeod(pos), globals->get_aircraft_position_cart()); - if(d2 <= _maxRangeInterior){ // if the AI is in-range we load the interior - _interior = SGModelLib::loadPagedModel(_modeldata->getInteriorPath(), props, _modeldata); - if(_interior.valid()){ - _interior->setRange(0, 0.0, _maxRangeInterior); - aip.add(_interior.get()); - _modeldata->setInteriorLoaded(true); - SG_LOG(SG_AI, SG_INFO, "AIBase: Loaded interior model " << _interior->getName()); + if (!_modeldata->getInteriorLoaded()) { // interior is not yet load + _interior = SGModelLib::loadPagedModel(_modeldata->getInteriorPath(), props, _modeldata); + if (_interior.valid()) { + bool pixel_mode = !fgGetBool("/sim/rendering/static-lod/aimp-range-mode-distance", false); + if (pixel_mode) { + _interior->setRangeMode(osg::LOD::PIXEL_SIZE_ON_SCREEN); + _interior->setRange(0, _maxRangeInterior, FLT_MAX); } + else { + _interior->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT); + _interior->setRange(0, 0.0, _maxRangeInterior); + } + aip.add(_interior.get()); + _modeldata->setInteriorLoaded(true); + SG_LOG(SG_AI, SG_INFO, "AIBase: Loaded interior model " << _interior->getName()); } } } @@ -324,7 +332,6 @@ void FGAIBase::updateLOD() { double maxRangeDetail = fgGetDouble("/sim/rendering/static-lod/aimp-detailed", 3000.0); double maxRangeBare = fgGetDouble("/sim/rendering/static-lod/aimp-bare", 10000.0); - _maxRangeInterior = fgGetDouble("/sim/rendering/static-lod/aimp-interior", 50.0); if (_model.valid()) @@ -431,6 +438,16 @@ void FGAIBase::updateLOD() } } } + if (_modeldata->getInteriorLoaded() && _interior.valid()) { + if (pixel_mode) { + _interior->setRangeMode(osg::LOD::PIXEL_SIZE_ON_SCREEN); + _interior->setRange(0, _maxRangeInterior, FLT_MAX); + } + else { + _interior->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT); + _interior->setRange(0, 0.0, _maxRangeInterior); + } + } } } diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx index 83b447b2c..ddd14e538 100644 --- a/src/AIModel/AIManager.cxx +++ b/src/AIModel/AIManager.cxx @@ -106,8 +106,10 @@ private: FGAIManager::FGAIManager() : cb_ai_bare(SGPropertyChangeCallback(this,&FGAIManager::updateLOD, fgGetNode("/sim/rendering/static-lod/aimp-bare", true))), - cb_ai_detailed(SGPropertyChangeCallback(this,&FGAIManager::updateLOD, - fgGetNode("/sim/rendering/static-lod/aimp-detailed", true))) + cb_ai_detailed(SGPropertyChangeCallback(this, &FGAIManager::updateLOD, + fgGetNode("/sim/rendering/static-lod/aimp-detailed", true))), + cb_interior(SGPropertyChangeCallback(this, &FGAIManager::updateLOD, + fgGetNode("/sim/rendering/static-lod/aimp-interior", true))) { } diff --git a/src/AIModel/AIManager.hxx b/src/AIModel/AIManager.hxx index add5faf7f..9b58ede9e 100644 --- a/src/AIModel/AIManager.hxx +++ b/src/AIModel/AIManager.hxx @@ -150,6 +150,7 @@ private: SGPropertyChangeCallback cb_ai_bare; SGPropertyChangeCallback cb_ai_detailed; + SGPropertyChangeCallback cb_interior; class Scenario; typedef std::map ScenarioDict;