diff --git a/simgear/constants.h b/simgear/constants.h index 37bf7eda..173d664a 100644 --- a/simgear/constants.h +++ b/simgear/constants.h @@ -211,8 +211,10 @@ const float SG_RADIANS_TO_DEGREES = 180.0f / SG_PI; /** for backwards compatibility */ #define SG_SCENERY_FILE_FORMAT "0.4" -/** Default range in m at which all objects are displayed. Overridden by /sim/rendering/static-lod/rough **/ -#define SG_OBJECT_RANGE 9000.0 +/** Default object ranges. Overridden by /sim/rendering/static-lod/[bare|rough|detailed] **/ +#define SG_OBJECT_RANGE_BARE 30000.0 +#define SG_OBJECT_RANGE_ROUGH 9000.0 +#define SG_OBJECT_RANGE_DETAILED 1500.0 /** Radius of scenery tiles in m **/ #define SG_TILE_RADIUS 14000.0 diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index 7a362fd6..178b8227 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -136,7 +136,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, const SGPropertyNode *props, SGPropertyNode *prop_root) { - float default_object_range = prop_root->getFloatValue("/sim/rendering/static-lod/rough", SG_OBJECT_RANGE); + float default_object_range = prop_root->getFloatValue("/sim/rendering/static-lod/rough", SG_OBJECT_RANGE_ROUGH); std::vector dds; std::vector textures = props->getChildren("texture"); for (unsigned int i = 0; i < textures.size(); i++) diff --git a/simgear/scene/tgdb/ReaderWriterSTG.cxx b/simgear/scene/tgdb/ReaderWriterSTG.cxx index 081e45ba..5f7f28e0 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.cxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.cxx @@ -93,7 +93,7 @@ struct ReaderWriterSTG::_ModelBin { osg::ref_ptr _options; }; struct _ObjectStatic { - _ObjectStatic() : _agl(false), _proxy(false), _lon(0), _lat(0), _elev(0), _hdg(0), _pitch(0), _roll(0), _range(SG_OBJECT_RANGE) { } + _ObjectStatic() : _agl(false), _proxy(false), _lon(0), _lat(0), _elev(0), _hdg(0), _pitch(0), _roll(0), _range(SG_OBJECT_RANGE_ROUGH) { } std::string _errorLocation; std::string _token; std::string _name; @@ -209,7 +209,10 @@ struct ReaderWriterSTG::_ModelBin { }; _ModelBin() : - _object_range(SG_OBJECT_RANGE), + _object_range_bare(SG_OBJECT_RANGE_BARE), + _object_range_rough(SG_OBJECT_RANGE_ROUGH), + _object_range_detailed(SG_OBJECT_RANGE_DETAILED), + _building_mesh_enabled(false), _foundBase(false) { } @@ -283,6 +286,13 @@ struct ReaderWriterSTG::_ModelBin { bool read(const std::string& absoluteFileName, const osgDB::Options* options) { + + // Determine object ranges + _object_range_bare = atof(options->getPluginStringData("SimGear::BARE_LOD_RANGE").c_str()); + _object_range_rough = atof(options->getPluginStringData("SimGear::ROUGH_LOD_RANGE").c_str()); + _object_range_detailed = atof(options->getPluginStringData("SimGear::DETAILED_LOD_RANGE").c_str()); + _building_mesh_enabled = (options->getPluginStringData("SimGear::RENDER_BUILDING_MESH") == "true"); + if (absoluteFileName.empty()) return false; @@ -332,12 +342,6 @@ struct ReaderWriterSTG::_ModelBin { SGPath path = filePath; path.append(name); - // Determine an appropriate range for the object, which has some randomness - double range = _object_range; - double lrand = mt_rand(&seed); - if (lrand < 0.1) range = range * 2.0; - else if (lrand < 0.4) range = range * 1.5; - if (token == "OBJECT_BASE") { // Load only once (first found) SG_LOG( SG_TERRAIN, SG_BULK, " " << token << " " << name ); @@ -361,62 +365,93 @@ struct ReaderWriterSTG::_ModelBin { _objectList.push_back(obj); } - } else { - // Always OK to load + } else if (!onlyTerrain) { + // Load non-terrain objects + + // Determine an appropriate range for the object, which has some randomness + double range = _object_range_rough; + double lrand = mt_rand(&seed); + if (lrand < 0.1) range = range * 2.0; + else if (lrand < 0.4) range = range * 1.5; + if (token == "OBJECT_STATIC" || token == "OBJECT_STATIC_AGL") { - if (!onlyTerrain) { - osg::ref_ptr opt; - opt = staticOptions(filePath, options); - if (SGPath(name).lower_extension() == "ac") - opt->setInstantiateEffects(true); - else - opt->setInstantiateEffects(false); - _ObjectStatic obj; - obj._errorLocation = absoluteFileName; - obj._token = token; - obj._name = name; - obj._agl = (token == "OBJECT_STATIC_AGL"); - obj._proxy = true; - in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll; - obj._range = range; - obj._options = opt; - _objectStaticList.push_back(obj); - } - + osg::ref_ptr opt; + opt = staticOptions(filePath, options); + if (SGPath(name).lower_extension() == "ac") + opt->setInstantiateEffects(true); + else + opt->setInstantiateEffects(false); + _ObjectStatic obj; + obj._errorLocation = absoluteFileName; + obj._token = token; + obj._name = name; + obj._agl = (token == "OBJECT_STATIC_AGL"); + obj._proxy = true; + in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll; + obj._range = range; + obj._options = opt; + _objectStaticList.push_back(obj); } else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") { - if (!onlyTerrain) { - osg::ref_ptr opt; - opt = sharedOptions(filePath, options); - if (SGPath(name).lower_extension() == "ac") - opt->setInstantiateEffects(true); - else - opt->setInstantiateEffects(false); - _ObjectStatic obj; - obj._errorLocation = absoluteFileName; - obj._token = token; - obj._name = name; - obj._agl = (token == "OBJECT_SHARED_AGL"); - obj._proxy = false; - in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll; - obj._range = range; - obj._options = opt; - _objectStaticList.push_back(obj); - } - + osg::ref_ptr opt; + opt = sharedOptions(filePath, options); + if (SGPath(name).lower_extension() == "ac") + opt->setInstantiateEffects(true); + else + opt->setInstantiateEffects(false); + _ObjectStatic obj; + obj._errorLocation = absoluteFileName; + obj._token = token; + obj._name = name; + obj._agl = (token == "OBJECT_SHARED_AGL"); + obj._proxy = false; + in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll; + obj._range = range; + obj._options = opt; + _objectStaticList.push_back(obj); } else if (token == "OBJECT_SIGN" || token == "OBJECT_SIGN_AGL") { - if (!onlyTerrain) { - _Sign sign; - sign._token = token; - sign._name = name; - sign._agl = (token == "OBJECT_SIGN_AGL"); - in >> sign._lon >> sign._lat >> sign._elev >> sign._hdg >> sign._size; - _signList.push_back(sign); - } + _Sign sign; + sign._token = token; + sign._name = name; + sign._agl = (token == "OBJECT_SIGN_AGL"); + in >> sign._lon >> sign._lat >> sign._elev >> sign._hdg >> sign._size; + _signList.push_back(sign); + } else if (token == "OBJECT_BUILDING_MESH_ROUGH" || token == "OBJECT_BUILDING_MESH_DETAILED") { + // Only load if building mesh enabled to avoid impacting low-powered systems + if (_building_mesh_enabled) { + osg::ref_ptr opt; + opt = staticOptions(filePath, options); + if (SGPath(name).lower_extension() == "ac") + opt->setInstantiateEffects(true); + else + opt->setInstantiateEffects(false); + _ObjectStatic obj; + obj._errorLocation = absoluteFileName; + obj._token = token; + obj._name = name; + obj._agl = false; + obj._proxy = true; + in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll; + + if (token == "OBJECT_BUILDING_MESH_DETAILED") { + // Apply a lower LOD range if this is a detailed building + range = _object_range_detailed; + double lrand = mt_rand(&seed); + if (lrand < 0.1) range = range * 2.0; + else if (lrand < 0.4) range = range * 1.5; + } + + obj._range = range; + obj._options = opt; + _objectStaticList.push_back(obj); + } } else { SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName << ": Unknown token '" << token << "'" ); } + } else { + SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName + << ": Unknown token '" << token << "'" ); } } @@ -428,9 +463,6 @@ struct ReaderWriterSTG::_ModelBin { osg::ref_ptr options; options = SGReaderWriterOptions::copyOrCreate(opt); - // Determine object ranges - _object_range = atof(options->getPluginStringData("SimGear::ROUGH_LOD_RANGE").c_str()); - osg::ref_ptr terrainGroup = new osg::Group; terrainGroup->setDataVariance(osg::Object::STATIC); terrainGroup->setName("terrain"); @@ -496,13 +528,16 @@ struct ReaderWriterSTG::_ModelBin { pagedLOD->setFileName(pagedLOD->getNumChildren(), "Dummy name - use the stored data in the read file callback"); // Objects may end up displayed up to 2x the object range. - pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 2.0 * _object_range + SG_TILE_RADIUS); + pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 2.0 * _object_range_rough + SG_TILE_RADIUS); return pagedLOD; } } - double _object_range; + double _object_range_bare; + double _object_range_rough; + double _object_range_detailed; + bool _building_mesh_enabled; bool _foundBase; std::list<_Object> _objectList; std::list<_ObjectStatic> _objectStaticList; diff --git a/simgear/scene/tgdb/SGTileDetailsCallback.hxx b/simgear/scene/tgdb/SGTileDetailsCallback.hxx index 1cd9139b..e7612c68 100644 --- a/simgear/scene/tgdb/SGTileDetailsCallback.hxx +++ b/simgear/scene/tgdb/SGTileDetailsCallback.hxx @@ -992,7 +992,7 @@ public: bool use_random_buildings = false; float vegetation_density = 1.0f; float building_density = 1.0f; - float object_range = SG_OBJECT_RANGE; + float object_range = SG_OBJECT_RANGE_ROUGH; bool useVBOs = false; osg::ref_ptr randomObjects; diff --git a/simgear/scene/tgdb/obj.cxx b/simgear/scene/tgdb/obj.cxx index 5efce0e2..2efe814e 100644 --- a/simgear/scene/tgdb/obj.cxx +++ b/simgear/scene/tgdb/obj.cxx @@ -52,7 +52,7 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options double ratio = SG_SIMPLIFIER_RATIO; double maxLength = SG_SIMPLIFIER_MAX_LENGTH; double maxError = SG_SIMPLIFIER_MAX_ERROR; - double object_range = SG_OBJECT_RANGE; + double object_range = SG_OBJECT_RANGE_ROUGH; double tile_min_expiry = SG_TILE_MIN_EXPIRY; if (options) {