Make LOD for buildings/trees/STG configurable.

Now based on /sim/rendering/static-lod/rough.
This commit is contained in:
Stuart Buchanan
2016-04-08 22:36:06 +01:00
parent 92a51059b4
commit 493aab8bab
8 changed files with 55 additions and 19 deletions

View 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

View 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");

View 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 =

View File

@@ -195,7 +195,7 @@ protected:
friend class SGMaterial;
SGMatModelGroup (SGPropertyNode * node);
SGMatModelGroup (SGPropertyNode * node, float default_object_range);
private:

View 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;

View 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++)
{

View 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);

View 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);
}