scenery: Make stg loader files members of the loader.

This commit is contained in:
Mathias Froehlich 2012-03-16 07:22:16 +01:00
parent b5fb829468
commit a5435b7d8c
2 changed files with 110 additions and 113 deletions

View File

@ -47,18 +47,103 @@
using namespace simgear;
static SGBucket getBucketFromFileName(const std::string& fileName)
ReaderWriterSTG::ReaderWriterSTG()
{
supportsExtension("stg", "SimGear stg database format");
}
ReaderWriterSTG::~ReaderWriterSTG()
{
}
const char* ReaderWriterSTG::className() const
{
return "STG Database reader";
}
osgDB::ReaderWriter::ReadResult
ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* options) const
{
// 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.
if (osgDB::getSimpleFileName(fileName) != fileName)
return readStgFile(fileName, options);
// For stg meta files, we need options for the search path.
if (!options)
return ReadResult::FILE_NOT_FOUND;
// Extract the bucket from the filename
std::istringstream ss(osgDB::getNameLessExtension(fileName));
long index;
ss >> index;
if (ss.fail())
return SGBucket();
return SGBucket(index);
return ReadResult::FILE_NOT_FOUND;
SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName);
SGBucket bucket(index);
std::string basePath = bucket.gen_base_path();
osg::ref_ptr<osg::Group> group = new osg::Group;
// Stop scanning once an object base is found
bool foundBase = false;
// This is considered a meta file, so apply the scenery path search
const osgDB::FilePathList& filePathList = options->getDatabasePathList();
for (osgDB::FilePathList::const_iterator i = filePathList.begin();
i != filePathList.end() && !foundBase; ++i) {
SGPath objects(*i);
objects.append("Objects");
objects.append(basePath);
objects.append(fileName);
if (readStgFile(objects.str(), *group, options))
foundBase = true;
SGPath terrain(*i);
terrain.append("Terrain");
terrain.append(basePath);
terrain.append(fileName);
if (readStgFile(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<SGReaderWriterOptions> 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.get();
}
static bool
loadStgFile(const std::string& absoluteFileName, osg::Group& group, const osgDB::Options* options)
osgDB::ReaderWriter::ReadResult
ReaderWriterSTG::readStgFile(const std::string& fileName, const osgDB::Options* options) const
{
// This is considered a real existing file.
// We still apply the search path algorithms for relative files.
osg::ref_ptr<osg::Group> group = new osg::Group;
readStgFile(osgDB::findDataFile(fileName, options), *group, options);
return group.get();
}
bool
ReaderWriterSTG::readStgFile(const std::string& absoluteFileName,
osg::Group& group, const osgDB::Options* options) const
{
if (absoluteFileName.empty())
return false;
@ -136,16 +221,19 @@ loadStgFile(const std::string& absoluteFileName, osg::Group& group, const osgDB:
// 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<SGReaderWriterOptions> opt;
opt = new SGReaderWriterOptions(*staticOptions);
osg::ProxyNode* proxyNode = new osg::ProxyNode;
proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
/// Hmm, the findDataFile should happen downstream
std::string absName = osgDB::findDataFile(name, opt.get());
proxyNode->setFileName(0, absName);
if (SGPath(absName).lower_extension() == "ac")
opt->setInstantiateEffects(true);
else
opt->setInstantiateEffects(false);
node = osgDB::readRefNodeFile(absName, opt.get());
proxyNode->setDatabaseOptions(opt.get());
node = proxyNode;
if (!node.valid()) {
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
@ -156,19 +244,13 @@ loadStgFile(const std::string& absoluteFileName, osg::Group& group, const osgDB:
} else if ( token == "OBJECT_SHARED" ) {
osg::ref_ptr<SGReaderWriterOptions> 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;
node = osgDB::readRefNodeFile(absName, opt.get());
if (!node.valid()) {
SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
@ -209,97 +291,3 @@ loadStgFile(const std::string& absoluteFileName, osg::Group& group, const osgDB:
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<osg::Group> 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<SGReaderWriterOptions> 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");
}
ReaderWriterSTG::~ReaderWriterSTG()
{
}
const char* ReaderWriterSTG::className() const
{
return "STG Database reader";
}
//#define SLOW_PAGER 1
#ifdef SLOW_PAGER
#include <unistd.h>
#endif
osgDB::ReaderWriter::ReadResult
ReaderWriterSTG::readNode(const std::string& fileName,
const osgDB::Options* options) const
{
osg::Node* result = loadTileByFileName(fileName, options);
// For debugging race conditions
#ifdef SLOW_PAGER
sleep(5);
#endif
if (result)
return result;
else
return ReadResult::FILE_NOT_HANDLED;
}

View File

@ -33,9 +33,18 @@ public:
virtual const char* className() const;
virtual ReadResult readNode(const std::string& fileName,
const osgDB::Options* options)
const;
virtual ReadResult
readNode(const std::string&, const osgDB::Options*) const;
private:
/// Read an real existing stg file that exists on disk.
ReadResult
readStgFile(const std::string& fileName, const osgDB::Options* options) const;
/// Read an real existing stg file that exists on disk and return true
/// if a BASE_OBJECT is found.
bool
readStgFile(const std::string&, osg::Group&, const osgDB::Options*) const;
};
}