]> git.mxchange.org Git - simgear.git/commitdiff
Make LOD for buildings/trees/STG configurable.
authorStuart Buchanan <stuart_d_buchanan@yahoo.co.uk>
Fri, 8 Apr 2016 21:36:06 +0000 (22:36 +0100)
committerStuart Buchanan <stuart_d_buchanan@yahoo.co.uk>
Fri, 8 Apr 2016 21:36:06 +0000 (22:36 +0100)
Now based on /sim/rendering/static-lod/rough.

simgear/constants.h
simgear/scene/material/mat.cxx
simgear/scene/material/matmodel.cxx
simgear/scene/material/matmodel.hxx
simgear/scene/tgdb/ReaderWriterSTG.cxx
simgear/scene/tgdb/SGBuildingBin.hxx
simgear/scene/tgdb/SGTileDetailsCallback.hxx
simgear/scene/tgdb/obj.cxx

index 8a93990733de36e61a5632862e460c474bdaeba8..37bf7edaa69cfe63588d0beffd35377f3a77cbbe 100644 (file)
@@ -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
index d90a40ed4a06fdd1bfa455b7cab2b2b6cb156fd7..50e814a7b480b0c12921184fc818cdaed0063c68 100644 (file)
@@ -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<bool> dds;
     std::vector<SGPropertyNode_ptr> 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<SGPropertyNode_ptr> 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<SGPropertyNode_ptr> glyph_nodes = props->getChildren("glyph");
index f0f899c9cef60c5534bc965e0dd0d4d17120e39b..41d004daf5a6eecf575b858a269f49ac9a477191 100644 (file)
@@ -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<SGPropertyNode_ptr> object_nodes =
index 1687302e26bbe3c150c863ebf86855537f6abe94..4ac45db32d69b41af02aa1b49d0ede523843219b 100644 (file)
@@ -195,7 +195,7 @@ protected:
 
     friend class SGMaterial;
 
-    SGMatModelGroup (SGPropertyNode * node);
+    SGMatModelGroup (SGPropertyNode * node, float default_object_range);
 
 private:
 
index b0dfc10bba45f31332352c18b85f0db3dddcddc4..883c25c07a3d1acfcbe72be5ae48af3e044a3ca2 100644 (file)
@@ -38,6 +38,7 @@
 #include <osgDB/ReaderWriter>
 #include <osgDB/ReadFile>
 
+#include <simgear/math/sg_random.h>
 #include <simgear/math/SGGeometry.hxx>
 #include <simgear/bucket/newbucket.hxx>
 #include <simgear/debug/logstream.hxx>
@@ -92,7 +93,7 @@ struct ReaderWriterSTG::_ModelBin {
         osg::ref_ptr<SGReaderWriterOptions> _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<SGReaderWriterOptions> _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<SGReaderWriterOptions> options;
         options = SGReaderWriterOptions::copyOrCreate(opt);
 
+        // Determine object ranges
+        _object_range = atof(options->getPluginStringData("SimGear::ROUGH_LOD_RANGE").c_str());
+
         osg::ref_ptr<osg::Group> 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;
index f64599dbee8c8d9cd784ac9b117425216fa7af2c..7124673d5284b9f4eca245eab288fbbdae2474b6 100644 (file)
@@ -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++)
               {
index 2abd8ebceec199700c3c199902f21f21c7268d77..465be137004f9a0076c37c6ecf339c18fcb84134 100644 (file)
@@ -55,10 +55,7 @@ typedef std::list<SGDirectionalLightBin> 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<osg::Group> 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);
index 3ff0bed4a5c6c43462f8a4ca2df0e04fdae8d3b2..5efce0e2142cffb836a631bad4dd39c5460a7744 100644 (file)
@@ -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<SGReaderWriterOptions> 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);
     }