Add STG verbs for building mesh integration.
Add OBJECT_BUILDING_MESH_ROUGH and OBJECT_BUILDING_MESH_DETAILED Intended for use by OSM buildings.
This commit is contained in:
+4
-2
@@ -211,8 +211,10 @@ const float SG_RADIANS_TO_DEGREES = 180.0f / SG_PI;
|
|||||||
/** for backwards compatibility */
|
/** for backwards compatibility */
|
||||||
#define SG_SCENERY_FILE_FORMAT "0.4"
|
#define SG_SCENERY_FILE_FORMAT "0.4"
|
||||||
|
|
||||||
/** Default range in m at which all objects are displayed. Overridden by /sim/rendering/static-lod/rough **/
|
/** Default object ranges. Overridden by /sim/rendering/static-lod/[bare|rough|detailed] **/
|
||||||
#define SG_OBJECT_RANGE 9000.0
|
#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 **/
|
/** Radius of scenery tiles in m **/
|
||||||
#define SG_TILE_RADIUS 14000.0
|
#define SG_TILE_RADIUS 14000.0
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ SGMaterial::read_properties(const SGReaderWriterOptions* options,
|
|||||||
const SGPropertyNode *props,
|
const SGPropertyNode *props,
|
||||||
SGPropertyNode *prop_root)
|
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<bool> dds;
|
std::vector<bool> dds;
|
||||||
std::vector<SGPropertyNode_ptr> textures = props->getChildren("texture");
|
std::vector<SGPropertyNode_ptr> textures = props->getChildren("texture");
|
||||||
for (unsigned int i = 0; i < textures.size(); i++)
|
for (unsigned int i = 0; i < textures.size(); i++)
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
osg::ref_ptr<SGReaderWriterOptions> _options;
|
osg::ref_ptr<SGReaderWriterOptions> _options;
|
||||||
};
|
};
|
||||||
struct _ObjectStatic {
|
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 _errorLocation;
|
||||||
std::string _token;
|
std::string _token;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
@@ -209,7 +209,10 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_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)
|
_foundBase(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -283,6 +286,13 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
|
|
||||||
bool read(const std::string& absoluteFileName, const osgDB::Options* options)
|
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())
|
if (absoluteFileName.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -332,12 +342,6 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
SGPath path = filePath;
|
SGPath path = filePath;
|
||||||
path.append(name);
|
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") {
|
if (token == "OBJECT_BASE") {
|
||||||
// Load only once (first found)
|
// Load only once (first found)
|
||||||
SG_LOG( SG_TERRAIN, SG_BULK, " " << token << " " << name );
|
SG_LOG( SG_TERRAIN, SG_BULK, " " << token << " " << name );
|
||||||
@@ -361,62 +365,93 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
_objectList.push_back(obj);
|
_objectList.push_back(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else if (!onlyTerrain) {
|
||||||
// Always OK to load
|
// 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 (token == "OBJECT_STATIC" || token == "OBJECT_STATIC_AGL") {
|
||||||
if (!onlyTerrain) {
|
osg::ref_ptr<SGReaderWriterOptions> opt;
|
||||||
osg::ref_ptr<SGReaderWriterOptions> opt;
|
opt = staticOptions(filePath, options);
|
||||||
opt = staticOptions(filePath, options);
|
if (SGPath(name).lower_extension() == "ac")
|
||||||
if (SGPath(name).lower_extension() == "ac")
|
opt->setInstantiateEffects(true);
|
||||||
opt->setInstantiateEffects(true);
|
else
|
||||||
else
|
opt->setInstantiateEffects(false);
|
||||||
opt->setInstantiateEffects(false);
|
_ObjectStatic obj;
|
||||||
_ObjectStatic obj;
|
obj._errorLocation = absoluteFileName;
|
||||||
obj._errorLocation = absoluteFileName;
|
obj._token = token;
|
||||||
obj._token = token;
|
obj._name = name;
|
||||||
obj._name = name;
|
obj._agl = (token == "OBJECT_STATIC_AGL");
|
||||||
obj._agl = (token == "OBJECT_STATIC_AGL");
|
obj._proxy = true;
|
||||||
obj._proxy = true;
|
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
|
||||||
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
|
obj._range = range;
|
||||||
obj._range = range;
|
obj._options = opt;
|
||||||
obj._options = opt;
|
_objectStaticList.push_back(obj);
|
||||||
_objectStaticList.push_back(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") {
|
} else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") {
|
||||||
if (!onlyTerrain) {
|
osg::ref_ptr<SGReaderWriterOptions> opt;
|
||||||
osg::ref_ptr<SGReaderWriterOptions> opt;
|
opt = sharedOptions(filePath, options);
|
||||||
opt = sharedOptions(filePath, options);
|
if (SGPath(name).lower_extension() == "ac")
|
||||||
if (SGPath(name).lower_extension() == "ac")
|
opt->setInstantiateEffects(true);
|
||||||
opt->setInstantiateEffects(true);
|
else
|
||||||
else
|
opt->setInstantiateEffects(false);
|
||||||
opt->setInstantiateEffects(false);
|
_ObjectStatic obj;
|
||||||
_ObjectStatic obj;
|
obj._errorLocation = absoluteFileName;
|
||||||
obj._errorLocation = absoluteFileName;
|
obj._token = token;
|
||||||
obj._token = token;
|
obj._name = name;
|
||||||
obj._name = name;
|
obj._agl = (token == "OBJECT_SHARED_AGL");
|
||||||
obj._agl = (token == "OBJECT_SHARED_AGL");
|
obj._proxy = false;
|
||||||
obj._proxy = false;
|
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
|
||||||
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
|
obj._range = range;
|
||||||
obj._range = range;
|
obj._options = opt;
|
||||||
obj._options = opt;
|
_objectStaticList.push_back(obj);
|
||||||
_objectStaticList.push_back(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (token == "OBJECT_SIGN" || token == "OBJECT_SIGN_AGL") {
|
} else if (token == "OBJECT_SIGN" || token == "OBJECT_SIGN_AGL") {
|
||||||
if (!onlyTerrain) {
|
_Sign sign;
|
||||||
_Sign sign;
|
sign._token = token;
|
||||||
sign._token = token;
|
sign._name = name;
|
||||||
sign._name = name;
|
sign._agl = (token == "OBJECT_SIGN_AGL");
|
||||||
sign._agl = (token == "OBJECT_SIGN_AGL");
|
in >> sign._lon >> sign._lat >> sign._elev >> sign._hdg >> sign._size;
|
||||||
in >> sign._lon >> sign._lat >> sign._elev >> sign._hdg >> sign._size;
|
_signList.push_back(sign);
|
||||||
_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<SGReaderWriterOptions> 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 {
|
} else {
|
||||||
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
|
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
|
||||||
<< ": Unknown token '" << token << "'" );
|
<< ": Unknown token '" << token << "'" );
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
|
||||||
|
<< ": Unknown token '" << token << "'" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,9 +463,6 @@ struct ReaderWriterSTG::_ModelBin {
|
|||||||
osg::ref_ptr<SGReaderWriterOptions> options;
|
osg::ref_ptr<SGReaderWriterOptions> options;
|
||||||
options = SGReaderWriterOptions::copyOrCreate(opt);
|
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;
|
osg::ref_ptr<osg::Group> terrainGroup = new osg::Group;
|
||||||
terrainGroup->setDataVariance(osg::Object::STATIC);
|
terrainGroup->setDataVariance(osg::Object::STATIC);
|
||||||
terrainGroup->setName("terrain");
|
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");
|
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.
|
// 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;
|
return pagedLOD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double _object_range;
|
double _object_range_bare;
|
||||||
|
double _object_range_rough;
|
||||||
|
double _object_range_detailed;
|
||||||
|
bool _building_mesh_enabled;
|
||||||
bool _foundBase;
|
bool _foundBase;
|
||||||
std::list<_Object> _objectList;
|
std::list<_Object> _objectList;
|
||||||
std::list<_ObjectStatic> _objectStaticList;
|
std::list<_ObjectStatic> _objectStaticList;
|
||||||
|
|||||||
@@ -992,7 +992,7 @@ public:
|
|||||||
bool use_random_buildings = false;
|
bool use_random_buildings = false;
|
||||||
float vegetation_density = 1.0f;
|
float vegetation_density = 1.0f;
|
||||||
float building_density = 1.0f;
|
float building_density = 1.0f;
|
||||||
float object_range = SG_OBJECT_RANGE;
|
float object_range = SG_OBJECT_RANGE_ROUGH;
|
||||||
bool useVBOs = false;
|
bool useVBOs = false;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Group> randomObjects;
|
osg::ref_ptr<osg::Group> randomObjects;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ SGLoadBTG(const std::string& path, const simgear::SGReaderWriterOptions* options
|
|||||||
double ratio = SG_SIMPLIFIER_RATIO;
|
double ratio = SG_SIMPLIFIER_RATIO;
|
||||||
double maxLength = SG_SIMPLIFIER_MAX_LENGTH;
|
double maxLength = SG_SIMPLIFIER_MAX_LENGTH;
|
||||||
double maxError = SG_SIMPLIFIER_MAX_ERROR;
|
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;
|
double tile_min_expiry = SG_TILE_MIN_EXPIRY;
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
|
|||||||
Reference in New Issue
Block a user