From 493aab8bab9df7d4ff13db3135703a899d0255c4 Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Fri, 8 Apr 2016 22:36:06 +0100 Subject: [PATCH] Make LOD for buildings/trees/STG configurable. Now based on /sim/rendering/static-lod/rough. --- simgear/constants.h | 5 +++ simgear/scene/material/mat.cxx | 7 +++-- simgear/scene/material/matmodel.cxx | 4 +-- simgear/scene/material/matmodel.hxx | 2 +- simgear/scene/tgdb/ReaderWriterSTG.cxx | 33 +++++++++++++++++--- simgear/scene/tgdb/SGBuildingBin.hxx | 2 +- simgear/scene/tgdb/SGTileDetailsCallback.hxx | 14 +++++---- simgear/scene/tgdb/obj.cxx | 7 +++-- 8 files changed, 55 insertions(+), 19 deletions(-) diff --git a/simgear/constants.h b/simgear/constants.h index 8a939907..37bf7eda 100644 --- a/simgear/constants.h +++ b/simgear/constants.h @@ -211,5 +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 + +/** Radius of scenery tiles in m **/ +#define SG_TILE_RADIUS 14000.0 #endif // _SG_CONSTANTS_H diff --git a/simgear/scene/material/mat.cxx b/simgear/scene/material/mat.cxx index d90a40ed..50e814a7 100644 --- a/simgear/scene/material/mat.cxx +++ b/simgear/scene/material/mat.cxx @@ -136,6 +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); std::vector dds; std::vector textures = props->getChildren("texture"); for (unsigned int i = 0; i < textures.size(); i++) @@ -316,7 +317,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, building_large_min_depth = props->getFloatValue("building-large-min-depth-m", 50.0); building_large_max_depth = props->getFloatValue("building-large-max-depth-m", 75.0); - building_range = props->getDoubleValue("building-range-m", 10000.0); + building_range = props->getDoubleValue("building-range-m", default_object_range); cos_object_max_density_slope_angle = cos(props->getFloatValue("object-max-density-angle-deg", 20.0) * osg::PI/180.0); cos_object_zero_density_slope_angle = cos(props->getFloatValue("object-zero-density-angle-deg", 30.0) * osg::PI/180.0); @@ -326,7 +327,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, tree_effect = props->getStringValue("tree-effect", "Effects/tree"); tree_height = props->getDoubleValue("tree-height-m", 0.0); tree_width = props->getDoubleValue("tree-width-m", 0.0); - tree_range = props->getDoubleValue("tree-range-m", 0.0); + tree_range = props->getDoubleValue("tree-range-m", default_object_range); tree_varieties = props->getIntValue("tree-varieties", 1); cos_tree_max_density_slope_angle = cos(props->getFloatValue("tree-max-density-angle-deg", 30.0) * osg::PI/180.0); cos_tree_zero_density_slope_angle = cos(props->getFloatValue("tree-zero-density-angle-deg", 45.0) * osg::PI/180.0); @@ -384,7 +385,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options, std::vector object_group_nodes = ((SGPropertyNode *)props)->getChildren("object-group"); for (unsigned int i = 0; i < object_group_nodes.size(); i++) - object_groups.push_back(new SGMatModelGroup(object_group_nodes[i])); + object_groups.push_back(new SGMatModelGroup(object_group_nodes[i], default_object_range)); // read glyph table for taxi-/runway-signs std::vector glyph_nodes = props->getChildren("glyph"); diff --git a/simgear/scene/material/matmodel.cxx b/simgear/scene/material/matmodel.cxx index f0f899c9..41d004da 100644 --- a/simgear/scene/material/matmodel.cxx +++ b/simgear/scene/material/matmodel.cxx @@ -185,8 +185,8 @@ SGMatModel::get_heading_type () const // Implementation of SGMatModelGroup. //////////////////////////////////////////////////////////////////////// -SGMatModelGroup::SGMatModelGroup (SGPropertyNode * node) - : _range_m(node->getDoubleValue("range-m", 2000)) +SGMatModelGroup::SGMatModelGroup (SGPropertyNode * node, float default_object_range) + : _range_m(node->getDoubleValue("range-m", default_object_range)) { // Load the object subnodes std::vector object_nodes = diff --git a/simgear/scene/material/matmodel.hxx b/simgear/scene/material/matmodel.hxx index 1687302e..4ac45db3 100644 --- a/simgear/scene/material/matmodel.hxx +++ b/simgear/scene/material/matmodel.hxx @@ -195,7 +195,7 @@ protected: friend class SGMaterial; - SGMatModelGroup (SGPropertyNode * node); + SGMatModelGroup (SGPropertyNode * node, float default_object_range); private: diff --git a/simgear/scene/tgdb/ReaderWriterSTG.cxx b/simgear/scene/tgdb/ReaderWriterSTG.cxx index b0dfc10b..883c25c0 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.cxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.cxx @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -92,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) { } + _ObjectStatic() : _agl(false), _proxy(false), _lon(0), _lat(0), _elev(0), _hdg(0), _pitch(0), _roll(0), _range(SG_OBJECT_RANGE) { } std::string _errorLocation; std::string _token; std::string _name; @@ -100,6 +101,7 @@ struct ReaderWriterSTG::_ModelBin { bool _proxy; double _lon, _lat, _elev; double _hdg, _pitch, _roll; + double _range; osg::ref_ptr _options; }; struct _Sign { @@ -159,7 +161,8 @@ struct ReaderWriterSTG::_ModelBin { matrixTransform->setName("rotateStaticObject"); matrixTransform->setDataVariance(osg::Object::STATIC); matrixTransform->addChild(node.get()); - leaf->addChild(matrixTransform, 0, 20000); //TODO: Make configurable? + + leaf->addChild(matrixTransform, 0, o._range); } }; struct GetModelLODCoord { @@ -196,6 +199,7 @@ struct ReaderWriterSTG::_ModelBin { return group.release(); } + mt _seed; std::list<_ObjectStatic> _objectStaticList; std::list<_Sign> _signList; @@ -205,6 +209,7 @@ struct ReaderWriterSTG::_ModelBin { }; _ModelBin() : + _object_range(SG_OBJECT_RANGE), _foundBase(false) { } @@ -289,6 +294,12 @@ struct ReaderWriterSTG::_ModelBin { std::string filePath = osgDB::getFilePath(absoluteFileName); + // Bucket provides a consistent seed + // so we have consistent set of pseudo-random numbers for each STG file + mt seed; + int bucket = atoi(SGPath(absoluteFileName).file_base().c_str()); + mt_init(&seed, bucket); + // do only load airport btg files. bool onlyAirports = options->getPluginStringData("SimGear::FG_ONLY_AIRPORTS") == "ON"; // do only load terrain btg files @@ -320,7 +331,13 @@ 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,6 +378,7 @@ struct ReaderWriterSTG::_ModelBin { 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); } @@ -380,6 +398,7 @@ struct ReaderWriterSTG::_ModelBin { 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); } @@ -409,6 +428,9 @@ 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"); @@ -472,12 +494,15 @@ struct ReaderWriterSTG::_ModelBin { pagedLOD->setDatabaseOptions(callbackOptions.get()); pagedLOD->setFileName(pagedLOD->getNumChildren(), "Dummy name - use the stored data in the read file callback"); - pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 30000); + + // Objects may end up displayed up to 2x the object range. + pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 2.0 * _object_range + SG_TILE_RADIUS); return pagedLOD; } } + double _object_range; bool _foundBase; std::list<_Object> _objectList; std::list<_ObjectStatic> _objectStaticList; diff --git a/simgear/scene/tgdb/SGBuildingBin.hxx b/simgear/scene/tgdb/SGBuildingBin.hxx index f64599db..7124673d 100644 --- a/simgear/scene/tgdb/SGBuildingBin.hxx +++ b/simgear/scene/tgdb/SGBuildingBin.hxx @@ -206,7 +206,7 @@ public: LOD* result = new LOD; if (_fade_out) { - // Create a series of LOD nodes so buidling cover decreases + // Create a series of LOD nodes so building cover decreases // gradually with distance from _range to 2*_range for (float i = 0.0; i < SG_BUILDING_FADE_OUT_LEVELS; i++) { diff --git a/simgear/scene/tgdb/SGTileDetailsCallback.hxx b/simgear/scene/tgdb/SGTileDetailsCallback.hxx index 2abd8ebc..465be137 100644 --- a/simgear/scene/tgdb/SGTileDetailsCallback.hxx +++ b/simgear/scene/tgdb/SGTileDetailsCallback.hxx @@ -55,10 +55,7 @@ typedef std::list SGDirectionalLightListBin; #define SG_SIMPLIFIER_RATIO (0.001) #define SG_SIMPLIFIER_MAX_LENGTH (1000.0) #define SG_SIMPLIFIER_MAX_ERROR (2000.0) -#define SG_OBJECT_RANGE (9000.0) -#define SG_TILE_RADIUS (14000.0) #define SG_TILE_MIN_EXPIRY (180.0) - using namespace simgear; // QuadTreeBuilder is used by Random Objects Generator @@ -995,6 +992,7 @@ public: bool use_random_buildings = false; float vegetation_density = 1.0f; float building_density = 1.0f; + float object_range = SG_OBJECT_RANGE; bool useVBOs = false; osg::ref_ptr randomObjects; @@ -1020,6 +1018,9 @@ public: building_density = propertyNode->getFloatValue("/sim/rendering/building-density", building_density); + object_range + = propertyNode->getFloatValue("/sim/rendering/static-lod/rough", + object_range); } useVBOs = (_options->getPluginStringData("SimGear::USE_VBOS") == "ON"); @@ -1106,9 +1107,10 @@ public: if (randomObjects.valid() || forestNode.valid() || buildingNode.valid()) { objectLOD = new osg::LOD; - if (randomObjects.valid()) objectLOD->addChild(randomObjects.get(), 0, 20000); - if (forestNode.valid()) objectLOD->addChild(forestNode.get(), 0, 20000); - if (buildingNode.valid()) objectLOD->addChild(buildingNode.get(), 0, 20000); + // random objects, trees and buildings can be displayed up to 2xrange out. + if (randomObjects.valid()) objectLOD->addChild(randomObjects.get(), 0, 2.0 * object_range + SG_TILE_RADIUS); + if (forestNode.valid()) objectLOD->addChild(forestNode.get(), 0, 2.0 * object_range + SG_TILE_RADIUS); + if (buildingNode.valid()) objectLOD->addChild(buildingNode.get(), 0, 2.0 * object_range + SG_TILE_RADIUS); unsigned nodeMask = SG_NODEMASK_CASTSHADOW_BIT | SG_NODEMASK_RECEIVESHADOW_BIT | SG_NODEMASK_TERRAIN_BIT; objectLOD->setNodeMask(nodeMask); diff --git a/simgear/scene/tgdb/obj.cxx b/simgear/scene/tgdb/obj.cxx index 3ff0bed4..5efce0e2 100644 --- a/simgear/scene/tgdb/obj.cxx +++ b/simgear/scene/tgdb/obj.cxx @@ -129,7 +129,7 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options } else if (simplifyDistant) { // Simplified terrain is only used in the distance, the // call-back below will re-generate the closer version - pagedLOD->addChild(node, object_range + SG_TILE_RADIUS, FLT_MAX); + pagedLOD->addChild(node, 2*object_range + SG_TILE_RADIUS, FLT_MAX); } osg::ref_ptr opt; @@ -152,7 +152,10 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options // Ensure that the random objects aren't expired too quickly pagedLOD->setMinimumExpiryTime(pagedLOD->getNumChildren(), tile_min_expiry); pagedLOD->setFileName(pagedLOD->getNumChildren(), "Dummy filename for random objects callback"); - pagedLOD->setRange(pagedLOD->getNumChildren(), 0, object_range + SG_TILE_RADIUS); + + // LOD Range is 2x the object range plus the tile radius because we display some objects up to 2x the + // range to reduce popping. + pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 2 *object_range + SG_TILE_RADIUS); transform->addChild(pagedLOD); } -- 2.39.5