]> git.mxchange.org Git - simgear.git/commitdiff
scene: Reorganize stg loading.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Sat, 25 Aug 2012 06:43:12 +0000 (08:43 +0200)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Sun, 26 Aug 2012 13:08:20 +0000 (15:08 +0200)
This is in preparation loading the non btg objects
in a seperate page node. Reorganize this code again.

simgear/scene/model/SGReaderWriterXML.cxx
simgear/scene/tgdb/ReaderWriterSTG.cxx
simgear/scene/tgdb/ReaderWriterSTG.hxx

index fc7d67f394f06c3c5d1da3d882a800283becbc3c..8399a35dacc2a24a8f6742274f0600d539012ac7 100644 (file)
@@ -77,9 +77,11 @@ const char* SGReaderWriterXML::className() const
 }
 
 osgDB::ReaderWriter::ReadResult
-SGReaderWriterXML::readNode(const std::string& fileName,
+SGReaderWriterXML::readNode(const std::string& name,
                             const osgDB::Options* options) const
 {
+    std::string fileName = osgDB::findDataFile(name, options);
+
     osg::Node *result=0;
     try {
         SGPath p = SGModelLib::findDataFile(fileName);
index 0f800791ea3300addf327030923d067628fde965..24ac5c14d4647bf99f5d8b5d7b12831cf18ae9e7 100644 (file)
 #include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
 #include <simgear/scene/util/OsgMath.hxx>
-#include <simgear/scene/material/mat.hxx>
-#include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/tgdb/apt_signs.hxx>
 #include <simgear/scene/tgdb/obj.hxx>
 
 #include "SGOceanTile.hxx"
 
-using namespace simgear;
+namespace simgear {
 
 /// Ok, this is a hack - we do not exactly know if it's an airport or not.
 /// This feature might also vanish again later. This is currently to
@@ -79,18 +77,265 @@ static SGBucket bucketIndexFromFileName(const std::string& fileName)
   return SGBucket(index);
 }
 
-static bool hasOptionalValue(sg_gzifstream &in)
-{
-    while ( (in.peek() != '\n') && (in.peek() != '\r')
-            && isspace(in.peek()) ) {
-        in.get();
+struct ReaderWriterSTG::_ModelBin {
+    struct _Object {
+        std::string _errorLocation;
+        std::string _token;
+        std::string _name;
+        osg::ref_ptr<SGReaderWriterOptions> _options;
+    };
+    struct _ObjectStatic {
+        _ObjectStatic() : _proxy(false), _lon(0), _lat(0), _elev(0), _hdg(0), _pitch(0), _roll(0) { }
+        std::string _errorLocation;
+        std::string _token;
+        std::string _name;
+        bool _proxy;
+        double _lon, _lat, _elev;
+        double _hdg, _pitch, _roll;
+        osg::ref_ptr<SGReaderWriterOptions> _options;
+    };
+    struct _Sign {
+        _Sign() : _lon(0), _lat(0), _elev(0), _hdg(0), _size(-1) { }
+        std::string _errorLocation;
+        std::string _token;
+        std::string _name;
+        double _lon, _lat, _elev;
+        double _hdg;
+        int _size;
+    };
+
+    _ModelBin() :
+        _foundBase(false)
+    { }
+
+    SGReaderWriterOptions* sharedOptions(const std::string& filePath, const osgDB::Options* options)
+    {
+        osg::ref_ptr<SGReaderWriterOptions> 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);
+
+        return sharedOptions.release();
     }
-    if ( isdigit(in.peek()) || (in.peek() == '-') ){
+    SGReaderWriterOptions* staticOptions(const std::string& filePath, const osgDB::Options* options)
+    {
+        osg::ref_ptr<SGReaderWriterOptions> staticOptions;
+        staticOptions = SGReaderWriterOptions::copyOrCreate(options);
+        staticOptions->getDatabasePathList().clear();
+
+        staticOptions->getDatabasePathList().push_back(filePath);
+        staticOptions->setObjectCacheHint(osgDB::Options::CACHE_NONE);
+
+        return staticOptions.release();
+    }
+
+    bool read(const std::string& absoluteFileName, const osgDB::Options* options)
+    {
+        if (absoluteFileName.empty())
+            return false;
+
+        sg_gzifstream stream(absoluteFileName);
+        if (!stream.is_open())
+            return false;
+
+        SG_LOG(SG_TERRAIN, SG_INFO, "Loading stg file " << absoluteFileName);
+    
+        std::string filePath = osgDB::getFilePath(absoluteFileName);
+
+        // do only load airport btg files.
+        bool onlyAirports = options->getPluginStringData("SimGear::FG_ONLY_AIRPORTS") == "ON";
+        // do only load terrain btg files
+        bool onlyTerrain = options->getPluginStringData("SimGear::FG_ONLY_TERRAIN") == "ON";
+        
+        while (!stream.eof()) {
+            // read a line
+            std::string line;
+            std::getline(stream, line);
+            
+            // strip comments
+            std::string::size_type hash_pos = line.find('#');
+            if (hash_pos != std::string::npos)
+                line.resize(hash_pos);
+            
+            // and process further
+            std::stringstream in(line);
+            
+            std::string token;
+            in >> token;
+            
+            // No comment
+            if (token.empty())
+                continue;
+            
+            // Then there is always a name
+            std::string name;
+            in >> name;
+            
+            SGPath path = filePath;
+            path.append(name);
+            
+            if (token == "OBJECT_BASE") {
+                // Load only once (first found)
+                SG_LOG( SG_TERRAIN, SG_BULK, "    " << token << " " << name );
+                _foundBase = true;
+                if (!onlyAirports || isAirportBtg(name)) {
+                    _Object obj;
+                    obj._errorLocation = absoluteFileName;
+                    obj._token = token;
+                    obj._name = path.str();
+                    obj._options = staticOptions(filePath, options);
+                    _objectList.push_back(obj);
+                }
+                
+            } else if (token == "OBJECT") {
+                if (!onlyAirports || isAirportBtg(name)) {
+                    _Object obj;
+                    obj._errorLocation = absoluteFileName;
+                    obj._token = token;
+                    obj._name = path.str();
+                    obj._options = staticOptions(filePath, options);
+                    _objectList.push_back(obj);
+                }
+                
+            } else {
+                // Always OK to load
+                if (token == "OBJECT_STATIC") {
+                    if (!onlyTerrain) {
+                        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._proxy = true;
+                        in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
+                        obj._options = opt;
+                        _objectStaticList.push_back(obj);
+                    }
+                        
+                } else if (token == "OBJECT_SHARED") {
+                    if (!onlyTerrain) {
+                        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._proxy = false;
+                        in >> obj._lon >> obj._lat >> obj._elev >> obj._hdg >> obj._pitch >> obj._roll;
+                        obj._options = opt;
+                        _objectStaticList.push_back(obj);
+                    }
+
+                } else if (token == "OBJECT_SIGN") {
+                    if (!onlyTerrain) {
+                        _Sign sign;
+                        sign._token = token;
+                        sign._name = name;
+                        in >> sign._lon >> sign._lat >> sign._elev >> sign._hdg >> sign._size;
+                        _signList.push_back(sign);
+                    }
+
+                } else {
+                    SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
+                            << ": Unknown token '" << token << "'" );
+                }
+            }
+        }
+        
         return true;
-    } else {
-        return false;
     }
-}
+    
+    osg::Node* load(const SGBucket& bucket, const osgDB::Options* opt)
+    {
+        osg::ref_ptr<SGReaderWriterOptions> options;
+        options = SGReaderWriterOptions::copyOrCreate(opt);
+
+        osg::ref_ptr<osg::Group> group = new osg::Group;
+        group->setDataVariance(osg::Object::STATIC);
+
+        if (_foundBase) {
+            for (std::list<_Object>::iterator i = _objectList.begin(); i != _objectList.end(); ++i) {
+                osg::ref_ptr<osg::Node> node;
+                node = osgDB::readRefNodeFile(i->_name, i->_options.get());
+                if (!node.valid()) {
+                    SG_LOG(SG_TERRAIN, SG_ALERT, i->_errorLocation << ": Failed to load "
+                           << i->_token << " '" << i->_name << "'");
+                    continue;
+                }
+                group->addChild(node.get());
+            }
+        } else {
+            SG_LOG(SG_TERRAIN, SG_INFO, "  Generating ocean tile");
+            
+            osg::Node* node = SGOceanTile(bucket, options->getMaterialLib());
+            if (node) {
+                group->addChild(node);
+            } else {
+                SG_LOG( SG_TERRAIN, SG_ALERT,
+                        "Warning: failed to generate ocean tile!" );
+            }
+        }
+
+        for (std::list<_ObjectStatic>::iterator i = _objectStaticList.begin(); i != _objectStaticList.end(); ++i) {
+            osg::ref_ptr<osg::Node> node;
+            if (i->_proxy)  {
+                osg::ref_ptr<osg::ProxyNode> proxy = new osg::ProxyNode;
+                proxy->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
+                proxy->setFileName(0, i->_name);
+                proxy->setDatabaseOptions(i->_options.get());
+                node = proxy;
+            } else {
+                node = osgDB::readRefNodeFile(i->_name, i->_options.get());
+                if (!node.valid()) {
+                    SG_LOG(SG_TERRAIN, SG_ALERT, i->_errorLocation << ": Failed to load "
+                           << i->_token << " '" << i->_name << "'");
+                    continue;
+                }
+            }
+            if (SGPath(i->_name).lower_extension() == "ac")
+                node->setNodeMask(~simgear::MODELLIGHT_BIT);
+            
+            osg::Matrix matrix;
+            matrix = makeZUpFrame(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev));
+            matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_hdg), osg::Vec3(0, 0, 1)));
+            matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_pitch), osg::Vec3(0, 1, 0)));
+            matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(i->_roll), osg::Vec3(1, 0, 0)));
+            
+            osg::MatrixTransform* matrixTransform;
+            matrixTransform = new osg::MatrixTransform(matrix);
+            matrixTransform->setDataVariance(osg::Object::STATIC);
+            matrixTransform->addChild(node.get());
+            group->addChild(matrixTransform);
+        }
+        
+        simgear::AirportSignBuilder signBuilder(options->getMaterialLib(), bucket.get_center());
+        for (std::list<_Sign>::iterator i = _signList.begin(); i != _signList.end(); ++i)
+            signBuilder.addSign(SGGeod::fromDegM(i->_lon, i->_lat, i->_elev), i->_hdg, i->_name, i->_size);
+        if (signBuilder.getSignsGroup())
+            group->addChild(signBuilder.getSignsGroup());
+        
+        return group.release();
+    }
+        
+    bool _foundBase;
+    std::list<_Object> _objectList;
+    std::list<_ObjectStatic> _objectStaticList;
+    std::list<_Sign> _signList;
+};
 
 ReaderWriterSTG::ReaderWriterSTG()
 {
@@ -109,262 +354,46 @@ const char* ReaderWriterSTG::className() const
 osgDB::ReaderWriter::ReadResult
 ReaderWriterSTG::readNode(const std::string& fileName, const osgDB::Options* options) const
 {
+    _ModelBin modelBin;
+    SGBucket bucket(bucketIndexFromFileName(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.
-    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;
-
-
-
-    SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName);
-
-    SGBucket bucket(bucketIndexFromFileName(fileName));
-    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(), bucket, *group, options))
-            foundBase = true;
-        
-        SGPath terrain(*i);
-        terrain.append("Terrain");
-        terrain.append(basePath);
-        terrain.append(fileName);
-        if (readStgFile(terrain.str(), bucket, *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();
-}
-
-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;
-    std::string path = osgDB::findDataFile(fileName, options);
-    readStgFile(path, bucketIndexFromFileName(path), *group, options);
-
-    return group.get();
-}
-
-bool
-ReaderWriterSTG::readStgFile(const std::string& absoluteFileName,
-                             const SGBucket& bucket,
-                             osg::Group& group, const osgDB::Options* options) const
-{
-    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<SGReaderWriterOptions> staticOptions;
-    staticOptions = SGReaderWriterOptions::copyOrCreate(options);
-    staticOptions->getDatabasePathList().clear();
-    staticOptions->getDatabasePathList().push_back(filePath);
-    staticOptions->setObjectCacheHint(osgDB::Options::CACHE_NONE);
-    
-    osg::ref_ptr<SGReaderWriterOptions> 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);
-
-    // do only load airport btg files.
-    bool onlyAirports = options->getPluginStringData("SimGear::FG_ONLY_AIRPORTS") == "ON";
-    // do only load terrain btg files
-    bool onlyTerrain = options->getPluginStringData("SimGear::FG_ONLY_TERRAIN") == "ON";
-
-    simgear::AirportSignBuilder signBuilder(staticOptions->getMaterialLib(), bucket.get_center());
-  
-    bool has_base = false;
-    while ( ! in.eof() ) {
-        std::string token;
-        in >> token;
-        
-        // No comment
-        if ( token.empty() || token[0] == '#' ) {
-            in >> ::skipeol;
-            continue;
-        }
+    if (osgDB::getSimpleFileName(fileName) != fileName) {
+        if (!modelBin.read(fileName, options))
+            return ReadResult::FILE_NOT_FOUND;
+    } else {
+        // For stg meta files, we need options for the search path.
+        if (!options)
+            return ReadResult::FILE_NOT_FOUND;
         
-        // Then there is always a name
-        std::string name;
-        in >> name;
+        SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName);
         
-        SGPath path = filePath;
-        path.append(name);
+        std::string basePath = bucket.gen_base_path();
         
-        osg::ref_ptr<osg::Node> node;
-        if ( token == "OBJECT_BASE" ) {
-            // Load only once (first found)
-            SG_LOG( SG_TERRAIN, SG_BULK, "    " << token << " " << name );
-            
-            has_base = true;
-
-            if (!onlyAirports || isAirportBtg(name)) {
-                node = osgDB::readRefNodeFile(path.str(),
-                                              staticOptions.get());
-                
-                if (!node.valid()) {
-                    SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
-                            << ": Failed to load OBJECT_BASE '"
-                            << name << "'" );
-                }
-            }
+        // Stop scanning once an object base is found
+        // 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() && !modelBin._foundBase; ++i) {
+            SGPath objects(*i);
+            objects.append("Objects");
+            objects.append(basePath);
+            objects.append(fileName);
+            modelBin.read(objects.str(), options);
             
-        } else if ( token == "OBJECT" ) {
-            if (!onlyAirports || isAirportBtg(name)) {
-                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" ) {
-                if (!onlyTerrain) {
-                    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")
-                    {
-                        proxyNode->setNodeMask( ~simgear::MODELLIGHT_BIT );
-                        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_STATIC '"
-                                << name << "'" );
-                    }
-                }
-                
-            } else if ( token == "OBJECT_SHARED" ) {
-                if (!onlyTerrain) {
-                    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());
-                    if (SGPath(absName).lower_extension() == "ac")
-                        opt->setInstantiateEffects(true);
-                    else
-                        opt->setInstantiateEffects(false);
-                    node = osgDB::readRefNodeFile(absName, opt.get());
-                    if (SGPath(absName).lower_extension() == "ac")
-                        node->setNodeMask( ~simgear::MODELLIGHT_BIT );
-                    
-                    if (!node.valid()) {
-                        SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName
-                                << ": Failed to load OBJECT_SHARED '"
-                                << name << "'" );
-                    }
-                }
-                
-            } else if ( token == "OBJECT_SIGN" ) {
-                int size(-1);
-
-                if ( hasOptionalValue(in) ){
-                    in >> size;
-                }
-                if (!onlyTerrain)
-                    signBuilder.addSign(SGGeod::fromDegM(lon, lat, elev), hdg, name, size);
-            } 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)));
-
-                if ( hasOptionalValue(in) ){
-                    double pitch(0.0), roll(0.0);
-                    in >> pitch >> roll;
-
-                    matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(pitch),
-                                                   osg::Vec3(0, 1, 0)));
-                    matrix.preMultRotate(osg::Quat(SGMiscd::deg2rad(roll),
-                                                   osg::Vec3(1, 0, 0)));
-                }
-
-                osg::MatrixTransform* matrixTransform;
-                matrixTransform = new osg::MatrixTransform(matrix);
-                matrixTransform->setDataVariance(osg::Object::STATIC);
-                matrixTransform->addChild(node.get());
-                node = matrixTransform;
-            }
+            SGPath terrain(*i);
+            terrain.append("Terrain");
+            terrain.append(basePath);
+            terrain.append(fileName);
+            modelBin.read(terrain.str(), options);
         }
-        
-        if (node.valid())
-            group.addChild(node.get());
-        
-        in >> ::skipeol;
     }
-  
-    if (signBuilder.getSignsGroup())
-        group.addChild(signBuilder.getSignsGroup());
 
-    return has_base;
+    return modelBin.load(bucket, options);
+}
+
 }
index 63c3eb72943ad8dad25fefc4be233a0794010577..8e19578e872f14798c3a43be96084159c08ef3e5 100644 (file)
@@ -39,14 +39,7 @@ public:
     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&, const SGBucket& bucket,  osg::Group&, const osgDB::Options*) const;
+    struct _ModelBin;
 };
 
 }