From 43fceaf3a422d60c9a413860af06b53de1547cff Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Thu, 15 Mar 2012 20:28:48 +0100 Subject: [PATCH] scenery: Move the stg read code. Move the code reading the stg files into ReaderWriterSTG.cxx. --- simgear/scene/tgdb/ReaderWriterSTG.cxx | 246 ++++++++++++++++++++++++- simgear/scene/tgdb/TileEntry.cxx | 243 ------------------------ 2 files changed, 241 insertions(+), 248 deletions(-) diff --git a/simgear/scene/tgdb/ReaderWriterSTG.cxx b/simgear/scene/tgdb/ReaderWriterSTG.cxx index 47d45e68..2fa3adef 100644 --- a/simgear/scene/tgdb/ReaderWriterSTG.cxx +++ b/simgear/scene/tgdb/ReaderWriterSTG.cxx @@ -23,16 +23,252 @@ # include #endif -#include +#include "ReaderWriterSTG.hxx" + +#include +#include -#include #include +#include +#include +#include +#include -#include "TileEntry.hxx" -#include "ReaderWriterSTG.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SGOceanTile.hxx" using namespace simgear; +static SGBucket getBucketFromFileName(const std::string& fileName) +{ + std::istringstream ss(osgDB::getNameLessExtension(fileName)); + long index; + ss >> index; + if (ss.fail()) + return SGBucket(); + return SGBucket(index); +} + +static bool +loadStgFile(const std::string& absoluteFileName, osg::Group& group, const osgDB::Options* options) +{ + if (absoluteFileName.empty()) + return false; + + sg_gzifstream in( absoluteFileName ); + if ( !in.is_open() ) + return false; + + SG_LOG(SG_TERRAIN, SG_INFO, "Loading stg file " << absoluteFileName); + + std::string filePath = osgDB::getFilePath(absoluteFileName); + + osg::ref_ptr staticOptions; + staticOptions = SGReaderWriterOptions::copyOrCreate(options); + staticOptions->getDatabasePathList().clear(); + staticOptions->getDatabasePathList().push_back(filePath); + staticOptions->setObjectCacheHint(osgDB::Options::CACHE_NONE); + + osg::ref_ptr sharedOptions; + sharedOptions = SGReaderWriterOptions::copyOrCreate(options); + sharedOptions->getDatabasePathList().clear(); + + SGPath path = filePath; + path.append(".."); path.append(".."); path.append(".."); + sharedOptions->getDatabasePathList().push_back(path.str()); + std::string fg_root = options->getPluginStringData("SimGear::FG_ROOT"); + sharedOptions->getDatabasePathList().push_back(fg_root); + + bool has_base = false; + while ( ! in.eof() ) { + std::string token; + in >> token; + + // No comment + if ( token.empty() || token[0] == '#' ) { + in >> ::skipeol; + continue; + } + + // Then there is always a name + std::string name; + in >> name; + + SGPath path = filePath; + path.append(name); + + osg::ref_ptr node; + if ( token == "OBJECT_BASE" ) { + // Load only once (first found) + SG_LOG( SG_TERRAIN, SG_BULK, " " << token << " " << name ); + + has_base = true; + node = osgDB::readRefNodeFile(path.str(), + staticOptions.get()); + + if (!node.valid()) { + SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName + << ": Failed to load OBJECT_BASE '" + << name << "'" ); + } + + } else if ( token == "OBJECT" ) { + node = osgDB::readRefNodeFile(path.str(), + staticOptions.get()); + + if (!node.valid()) { + SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName + << ": Failed to load OBJECT '" + << name << "'" ); + } + + } else { + double lon, lat, elev, hdg; + in >> lon >> lat >> elev >> hdg; + + // Always OK to load + if ( token == "OBJECT_STATIC" ) { + /// Hmm, the findDataFile should happen downstream + std::string absName = osgDB::findDataFile(name, + staticOptions.get()); + osg::ref_ptr opt; + opt = new SGReaderWriterOptions(*staticOptions); + if (SGPath(absName).lower_extension() == "ac") + opt->setInstantiateEffects(true); + else + opt->setInstantiateEffects(false); + node = osgDB::readRefNodeFile(absName, opt.get()); + + if (!node.valid()) { + SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName + << ": Failed to load OBJECT_STATIC '" + << name << "'" ); + } + + } else if ( token == "OBJECT_SHARED" ) { + osg::ref_ptr opt; + opt = new SGReaderWriterOptions(*sharedOptions); + + /// Hmm, the findDataFile should happen in the downstream readers + std::string absName = osgDB::findDataFile(name, opt.get()); + + osg::ProxyNode* proxyNode = new osg::ProxyNode; + proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); + proxyNode->setFileName(0, absName); + if (SGPath(absName).lower_extension() == "ac") + opt->setInstantiateEffects(true); + else + opt->setInstantiateEffects(false); + proxyNode->setDatabaseOptions(opt.get()); + node = proxyNode; + + if (!node.valid()) { + SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName + << ": Failed to load OBJECT_SHARED '" + << name << "'" ); + } + + } else if ( token == "OBJECT_SIGN" ) { + node = SGMakeSign(staticOptions->getMaterialLib(), name); + + } else if ( token == "OBJECT_RUNWAY_SIGN" ) { + node = SGMakeRunwaySign(staticOptions->getMaterialLib(), name); + + } else { + SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName + << ": Unknown token '" << token << "'" ); + } + + if (node.valid()) { + osg::Matrix matrix; + matrix = makeZUpFrame(SGGeod::fromDegM(lon, lat, elev)); + matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(hdg), + osg::Vec3(0, 0, 1))); + + osg::MatrixTransform* matrixTransform; + matrixTransform = new osg::MatrixTransform(matrix); + matrixTransform->setDataVariance(osg::Object::STATIC); + matrixTransform->addChild(node.get()); + node = matrixTransform; + } + } + + if (node.valid()) + group.addChild(node.get()); + + in >> ::skipeol; + } + + return has_base; +} + +static osg::Node* +loadTileByFileName(const string& fileName, const osgDB::Options* options) +{ + SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName); + + // We treat 123.stg different than ./123.stg. + // The difference is that ./123.stg as well as any absolute path + // really loads the given stg file and only this. + // In contrast 123.stg uses the search paths to load a set of stg + // files spread across the scenery directories. + std::string simpleFileName = osgDB::getSimpleFileName(fileName); + SGBucket bucket = getBucketFromFileName(simpleFileName); + osg::ref_ptr group = new osg::Group; + if (simpleFileName != fileName || !options) { + // This is considered a real existing file. + // We still apply the search path algorithms for relative files. + loadStgFile(osgDB::findDataFile(fileName, options), *group, options); + return group.release(); + } + + // This is considered a meta file, so apply the scenery path search + const osgDB::FilePathList& filePathList = options->getDatabasePathList(); + std::string basePath = bucket.gen_base_path(); + // Stop scanning once an object base is found + bool foundBase = false; + for (osgDB::FilePathList::const_iterator i = filePathList.begin(); + i != filePathList.end() && !foundBase; ++i) { + SGPath objects(*i); + objects.append("Objects"); + objects.append(basePath); + objects.append(simpleFileName); + if (loadStgFile(objects.str(), *group, options)) + foundBase = true; + + SGPath terrain(*i); + terrain.append("Terrain"); + terrain.append(basePath); + terrain.append(simpleFileName); + if (loadStgFile(terrain.str(), *group, options)) + foundBase = true; + } + + // ... or generate an ocean tile on the fly + if (!foundBase) { + SG_LOG(SG_TERRAIN, SG_INFO, " Generating ocean tile"); + + osg::ref_ptr opt; + opt = SGReaderWriterOptions::copyOrCreate(options); + osg::Node* node = SGOceanTile(bucket, opt->getMaterialLib()); + if ( node ) { + group->addChild(node); + } else { + SG_LOG( SG_TERRAIN, SG_ALERT, + "Warning: failed to generate ocean tile!" ); + } + } + return group.release(); +} + ReaderWriterSTG::ReaderWriterSTG() { supportsExtension("stg", "SimGear stg database format"); @@ -56,7 +292,7 @@ osgDB::ReaderWriter::ReadResult ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* options) const { - osg::Node* result = TileEntry::loadTileByFileName(fileName, options); + osg::Node* result = loadTileByFileName(fileName, options); // For debugging race conditions #ifdef SLOW_PAGER sleep(5); diff --git a/simgear/scene/tgdb/TileEntry.cxx b/simgear/scene/tgdb/TileEntry.cxx index 71a7f57d..84df9bf2 100644 --- a/simgear/scene/tgdb/TileEntry.cxx +++ b/simgear/scene/tgdb/TileEntry.cxx @@ -29,198 +29,15 @@ #include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "SGOceanTile.hxx" #include "TileEntry.hxx" using std::string; using namespace simgear; -static SGBucket getBucketFromFileName(const std::string& fileName) -{ - std::istringstream ss(osgDB::getNameLessExtension(fileName)); - long index; - ss >> index; - if (ss.fail()) - return SGBucket(); - return SGBucket(index); -} - -static bool -loadStgFile(const std::string& absoluteFileName, osg::Group& group, const osgDB::Options* options) -{ - if (absoluteFileName.empty()) - return false; - - sg_gzifstream in( absoluteFileName ); - if ( !in.is_open() ) - return false; - - SG_LOG(SG_TERRAIN, SG_INFO, "Loading stg file " << absoluteFileName); - - std::string filePath = osgDB::getFilePath(absoluteFileName); - - osg::ref_ptr staticOptions; - staticOptions = SGReaderWriterOptions::copyOrCreate(options); - staticOptions->getDatabasePathList().clear(); - staticOptions->getDatabasePathList().push_back(filePath); - staticOptions->setObjectCacheHint(osgDB::Options::CACHE_NONE); - - osg::ref_ptr sharedOptions; - sharedOptions = SGReaderWriterOptions::copyOrCreate(options); - sharedOptions->getDatabasePathList().clear(); - - SGPath path = filePath; - path.append(".."); path.append(".."); path.append(".."); - sharedOptions->getDatabasePathList().push_back(path.str()); - std::string fg_root = options->getPluginStringData("SimGear::FG_ROOT"); - sharedOptions->getDatabasePathList().push_back(fg_root); - - bool has_base = false; - while ( ! in.eof() ) { - std::string token; - in >> token; - - // No comment - if ( token.empty() || token[0] == '#' ) { - in >> ::skipeol; - continue; - } - - // Then there is always a name - std::string name; - in >> name; - - SGPath path = filePath; - path.append(name); - - osg::ref_ptr node; - if ( token == "OBJECT_BASE" ) { - // Load only once (first found) - SG_LOG( SG_TERRAIN, SG_BULK, " " << token << " " << name ); - - has_base = true; - node = osgDB::readRefNodeFile(path.str(), - staticOptions.get()); - - if (!node.valid()) { - SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName - << ": Failed to load OBJECT_BASE '" - << name << "'" ); - } - - } else if ( token == "OBJECT" ) { - node = osgDB::readRefNodeFile(path.str(), - staticOptions.get()); - - if (!node.valid()) { - SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName - << ": Failed to load OBJECT '" - << name << "'" ); - } - - } else { - double lon, lat, elev, hdg; - in >> lon >> lat >> elev >> hdg; - - // Always OK to load - if ( token == "OBJECT_STATIC" ) { - /// Hmm, the findDataFile should happen downstream - std::string absName = osgDB::findDataFile(name, - staticOptions.get()); - osg::ref_ptr opt; - opt = new SGReaderWriterOptions(*staticOptions); - if (SGPath(absName).lower_extension() == "ac") - opt->setInstantiateEffects(true); - else - opt->setInstantiateEffects(false); - node = osgDB::readRefNodeFile(absName, opt.get()); - - if (!node.valid()) { - SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName - << ": Failed to load OBJECT_STATIC '" - << name << "'" ); - } - - } else if ( token == "OBJECT_SHARED" ) { - osg::ref_ptr opt; - opt = new SGReaderWriterOptions(*sharedOptions); - - /// Hmm, the findDataFile should happen in the downstream readers - std::string absName = osgDB::findDataFile(name, opt.get()); - - osg::ProxyNode* proxyNode = new osg::ProxyNode; - proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER); - proxyNode->setFileName(0, absName); - if (SGPath(absName).lower_extension() == "ac") - opt->setInstantiateEffects(true); - else - opt->setInstantiateEffects(false); - proxyNode->setDatabaseOptions(opt.get()); - node = proxyNode; - - if (!node.valid()) { - SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName - << ": Failed to load OBJECT_SHARED '" - << name << "'" ); - } - - } else if ( token == "OBJECT_SIGN" ) { - node = SGMakeSign(staticOptions->getMaterialLib(), name); - - } else if ( token == "OBJECT_RUNWAY_SIGN" ) { - node = SGMakeRunwaySign(staticOptions->getMaterialLib(), name); - - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName - << ": Unknown token '" << token << "'" ); - } - - if (node.valid() && token != "OBJECT") { - osg::Matrix matrix; - matrix = makeZUpFrame(SGGeod::fromDegM(lon, lat, elev)); - matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(hdg), - osg::Vec3(0, 0, 1))); - - osg::MatrixTransform* matrixTransform; - matrixTransform = new osg::MatrixTransform(matrix); - matrixTransform->setDataVariance(osg::Object::STATIC); - matrixTransform->addChild(node.get()); - node = matrixTransform; - } - } - - if (node.valid()) - group.addChild(node.get()); - - in >> ::skipeol; - } - - return has_base; -} - // Constructor TileEntry::TileEntry ( const SGBucket& b ) : tile_bucket( b ), @@ -269,66 +86,6 @@ void TileEntry::prep_ssg_node(float vis) { _node->setRange( 0, 0, vis + bounding_radius ); } -osg::Node* -TileEntry::loadTileByFileName(const string& fileName, - const osgDB::Options* options) -{ - SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName); - - // We treat 123.stg different than ./123.stg. - // The difference is that ./123.stg as well as any absolute path - // really loads the given stg file and only this. - // In contrast 123.stg uses the search paths to load a set of stg - // files spread across the scenery directories. - std::string simpleFileName = osgDB::getSimpleFileName(fileName); - SGBucket bucket = getBucketFromFileName(simpleFileName); - osg::ref_ptr group = new osg::Group; - if (simpleFileName != fileName || !options) { - // This is considered a real existing file. - // We still apply the search path algorithms for relative files. - loadStgFile(osgDB::findDataFile(fileName, options), *group, options); - return group.release(); - } - - // This is considered a meta file, so apply the scenery path search - const osgDB::FilePathList& filePathList = options->getDatabasePathList(); - std::string basePath = bucket.gen_base_path(); - // Stop scanning once an object base is found - bool foundBase = false; - for (osgDB::FilePathList::const_iterator i = filePathList.begin(); - i != filePathList.end() && !foundBase; ++i) { - SGPath objects(*i); - objects.append("Objects"); - objects.append(basePath); - objects.append(simpleFileName); - if (loadStgFile(objects.str(), *group, options)) - foundBase = true; - - SGPath terrain(*i); - terrain.append("Terrain"); - terrain.append(basePath); - terrain.append(simpleFileName); - if (loadStgFile(terrain.str(), *group, options)) - foundBase = true; - } - - // ... or generate an ocean tile on the fly - if (!foundBase) { - SG_LOG(SG_TERRAIN, SG_INFO, " Generating ocean tile"); - - osg::ref_ptr opt; - opt = SGReaderWriterOptions::copyOrCreate(options); - osg::Node* node = SGOceanTile(bucket, opt->getMaterialLib()); - if ( node ) { - group->addChild(node); - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "Warning: failed to generate ocean tile!" ); - } - } - return group.release(); -} - void TileEntry::addToSceneGraph(osg::Group *terrain_branch) { -- 2.39.5