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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user