Add scenery-path-suffix support to terrasync

Remove /sim/rendering/building-mesh as it is
redundant.

Add check that objects are in the correct bounding
box of the containing STG file.
This commit is contained in:
Stuart Buchanan
2017-01-21 22:19:38 +00:00
parent bcecee0f76
commit 6c64e9b36c
3 changed files with 93 additions and 56 deletions

View File

@@ -212,7 +212,6 @@ struct ReaderWriterSTG::_ModelBin {
_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)
{ }
@@ -284,6 +283,21 @@ struct ReaderWriterSTG::_ModelBin {
return SGGeod::fromCart(cart).getElevationM();
}
void checkInsideBucket(const SGPath& absoluteFileName, float lon, float lat) {
SGBucket bucket = bucketIndexFromFileName(absoluteFileName.file_base().c_str());
if ((lon > bucket.get_center_lon() + bucket.get_width()/2.0) ||
(lon < bucket.get_center_lon() - bucket.get_width()/2.0) ||
(lat > bucket.get_center_lat() + bucket.get_height()/2.0) ||
(lat < bucket.get_center_lat() - bucket.get_height()/2.0) )
{
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
<< ": Object outside tile bounds " << lon << ", " << lat <<
"Center of tile: " << bucket.get_center_lon() << ", " <<
bucket.get_center_lat());
}
}
bool read(const SGPath& absoluteFileName, const osgDB::Options* options)
{
if (!absoluteFileName.exists()) {
@@ -299,8 +313,6 @@ struct ReaderWriterSTG::_ModelBin {
_object_range_bare = 1414.0f + atof(options->getPluginStringData("SimGear::LOD_RANGE_BARE").c_str());
_object_range_rough = 1414.0f + atof(options->getPluginStringData("SimGear::LOD_RANGE_ROUGH").c_str());
_object_range_detailed = 1414.0f + atof(options->getPluginStringData("SimGear::LOD_RANGE_DETAILED").c_str());
_building_mesh_enabled = (options->getPluginStringData("SimGear::RENDER_BUILDING_MESH") == "true");
SG_LOG(SG_TERRAIN, SG_INFO, "Loading stg file " << absoluteFileName);
@@ -392,7 +404,8 @@ struct ReaderWriterSTG::_ModelBin {
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
obj._range = range;
obj._options = opt;
_objectStaticList.push_back(obj);
checkInsideBucket(absoluteFileName, obj._lon, obj._lat);
_objectStaticList.push_back(obj);
} else if (token == "OBJECT_SHARED" || token == "OBJECT_SHARED_AGL") {
osg::ref_ptr<SGReaderWriterOptions> opt;
opt = sharedOptions(filePath, options);
@@ -409,7 +422,8 @@ struct ReaderWriterSTG::_ModelBin {
in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
obj._range = range;
obj._options = opt;
_objectStaticList.push_back(obj);
checkInsideBucket(absoluteFileName, obj._lon, obj._lat);
_objectStaticList.push_back(obj);
} else if (token == "OBJECT_SIGN" || token == "OBJECT_SIGN_AGL") {
_Sign sign;
sign._token = token;
@@ -418,35 +432,32 @@ struct ReaderWriterSTG::_ModelBin {
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") {
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;
// 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;
}
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);
}
obj._range = range;
obj._options = opt;
checkInsideBucket(absoluteFileName, obj._lon, obj._lat);
_objectStaticList.push_back(obj);
} else {
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
<< ": Unknown token '" << token << "'" );
@@ -531,7 +542,8 @@ struct ReaderWriterSTG::_ModelBin {
// Objects may end up displayed up to 2x the object range.
pagedLOD->setRange(pagedLOD->getNumChildren(), 0, 2.0 * _object_range_rough + SG_TILE_RADIUS);
SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile PagedLOD Center: " << pagedLOD->getCenter().x() << "," << pagedLOD->getCenter().y() << "," << pagedLOD->getCenter().z() );
SG_LOG( SG_TERRAIN, SG_DEBUG, "Tile PagedLOD Range: " << (2.0 * _object_range_rough + SG_TILE_RADIUS));
return pagedLOD;
}
}
@@ -539,7 +551,6 @@ struct ReaderWriterSTG::_ModelBin {
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;

View File

@@ -815,6 +815,7 @@ SGTerraSync::~SGTerraSync()
void SGTerraSync::setRoot(SGPropertyNode_ptr root)
{
_terraRoot = root->getNode("/sim/terrasync",true);
_renderingRoot = root->getNode("/sim/rendering", true);
}
void SGTerraSync::init()
@@ -953,12 +954,33 @@ void SGTerraSync::syncAirportsModels()
_workerThread->request( w );
}
string_list SGTerraSync::getSceneryPathSuffixes() const
{
string_list scenerySuffixes;
for (auto node : _renderingRoot->getChildren("scenery-path-suffix")) {
if (node->getBoolValue("enabled", true)) {
scenerySuffixes.push_back(node->getStringValue("name"));
}
}
if (scenerySuffixes.empty()) {
// if preferences didn't load, use some default
scenerySuffixes = {"Objects", "Terrain"}; // defaut values
}
return scenerySuffixes;
}
void SGTerraSync::syncAreaByPath(const std::string& aPath)
{
const char* terrainobjects[3] = { "Terrain/", "Objects/", 0 };
for (const char** tree = &terrainobjects[0]; *tree; tree++)
string_list scenerySuffixes = getSceneryPathSuffixes();
string_list::const_iterator it = scenerySuffixes.begin();
for (; it != scenerySuffixes.end(); ++it)
{
std::string dir = string(*tree) + aPath;
std::string dir = *it + "/" + aPath;
if (_activeTileDirs.find(dir) != _activeTileDirs.end()) {
continue;
}
@@ -982,9 +1004,12 @@ bool SGTerraSync::isTileDirPending(const std::string& sceneryDir) const
return false;
}
const char* terrainobjects[3] = { "Terrain/", "Objects/", 0 };
for (const char** tree = &terrainobjects[0]; *tree; tree++) {
string s = *tree + sceneryDir;
string_list scenerySuffixes = getSceneryPathSuffixes();
string_list::const_iterator it = scenerySuffixes.begin();
for (; it != scenerySuffixes.end(); ++it)
{
string s = *it + "/" + sceneryDir;
if (_activeTileDirs.find(s) != _activeTileDirs.end()) {
return true;
}

View File

@@ -42,8 +42,8 @@ public:
SGTerraSync();
virtual ~SGTerraSync();
virtual void init();
virtual void init();
virtual void shutdown();
virtual void reinit();
virtual void bind();
@@ -54,53 +54,54 @@ public:
/// us travelling in a direction. Avoid last_lat / last_lon blocking
/// certain tiles when we reposition.
void reposition();
bool isIdle();
bool scheduleTile(const SGBucket& bucket);
void syncAreaByPath(const std::string& aPath);
void setRoot(SGPropertyNode_ptr root);
/// retrive the associated log object, for displaying log
/// output somewhere (a UI, presumably)
BufferedLogCallback* log() const
{ return _log; }
/**
* Test if a scenery directory is queued or actively syncing.
* File path is the tile name, eg 'e001n52' or 'w003n56'. Will return true
* if either the Terrain or Objects variant is being synced.
*
*
*/
bool isTileDirPending(const std::string& sceneryDir) const;
void scheduleDataDir(const std::string& dataDir);
bool isDataDirPending(const std::string& dataDir) const;
protected:
void syncAirportsModels();
string_list getSceneryPathSuffixes() const;
class WorkerThread;
private:
WorkerThread* _workerThread;
SGPropertyNode_ptr _terraRoot;
SGPropertyNode_ptr _renderingRoot;
SGPropertyNode_ptr _stalledNode;
SGPropertyNode_ptr _cacheHits;
// we manually bind+init TerraSync during early startup
// to get better overlap of slow operations (Shared Models sync
// and nav-cache rebuild). As a result we need to track the bind/init
// state explicitly to avoid duplicate calls.
bool _bound, _inited;
simgear::TiedPropertyList _tiedProperties;
BufferedLogCallback* _log;
typedef std::set<std::string> string_set;
string_set _activeTileDirs;
};