]> git.mxchange.org Git - simgear.git/commitdiff
scenery: Accumulate stg files until we find an OBJECT_BASE.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Sun, 11 Mar 2012 20:32:35 +0000 (21:32 +0100)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Thu, 15 Mar 2012 07:02:35 +0000 (08:02 +0100)
This should recover most of the old scenery loading behavior
before the last change. The z-fighting due to model duplication
does not happen over solid ground. Sea tiles are still broken.

simgear/scene/tgdb/TileEntry.cxx
simgear/scene/tgdb/TileEntry.hxx

index b9c726e9da54f55169f82b8b8e7d540c41cab98f..e292b55e1e001536edef1f95d0c9a3789bdf7862 100644 (file)
@@ -32,6 +32,7 @@
 #include <osg/MatrixTransform>
 #include <osg/Math>
 #include <osg/NodeCallback>
+#include <osg/ProxyNode>
 
 #include <osgDB/FileNameUtils>
 #include <osgDB/ReaderWriter>
@@ -59,7 +60,7 @@
 using std::string;
 using namespace simgear;
 
-ModelLoadHelper *TileEntry::_modelLoader=0;
+static ModelLoadHelper *_modelLoader=0;
 
 namespace {
 osgDB::RegisterReaderWriterProxy<ReaderWriterSTG> g_readerWriterSTGProxy;
@@ -80,6 +81,173 @@ static SGBucket getBucketFromFileName(const std::string& fileName)
     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<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);
+    
+    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<osg::Node> 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());
+                if(_modelLoader) {
+                    node = _modelLoader->loadTileModel(absName, false);
+                } else {
+                    osg::ref_ptr<SGReaderWriterOptions> 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" ) {
+                if(_modelLoader) {
+                    node = _modelLoader->loadTileModel(name, true);
+                } else {
+                    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;
+                }
+                
+                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;
+}
+    
+void
+TileEntry::setModelLoadHelper(ModelLoadHelper *m)
+{
+    _modelLoader=m;
+}
+
 // Constructor
 TileEntry::TileEntry ( const SGBucket& b )
     : tile_bucket( b ),
@@ -134,10 +302,6 @@ TileEntry::loadTileByFileName(const string& fileName,
 {
     SG_LOG(SG_TERRAIN, SG_INFO, "Loading tile " << fileName);
 
-    // Space for up to two stg file names.
-    // There is usually one in the Terrain and one in the Objects subdirectory.
-    std::string absoluteFileName[2];
-
     // 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.
@@ -145,200 +309,42 @@ TileEntry::loadTileByFileName(const string& fileName,
     // files spread across the scenery directories.
     std::string simpleFileName = osgDB::getSimpleFileName(fileName);
     SGBucket bucket = getBucketFromFileName(simpleFileName);
-    bool file_mode = false;
-    if (simpleFileName == fileName && options) {
-        // 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();
-        for (osgDB::FilePathList::const_iterator i = filePathList.begin();
-             i != filePathList.end(); ++i) {
-            SGPath terrain(*i);
-            terrain.append("Terrain");
-            terrain.append(basePath);
-            terrain.append(simpleFileName);
-
-            SGPath objects(*i);
-            objects.append("Objects");
-            objects.append(basePath);
-            objects.append(simpleFileName);
-
-            if (terrain.isFile() || objects.isFile()) {
-                absoluteFileName[0] = terrain.str();
-                absoluteFileName[1] = objects.str();
-                break;
-            }
-        }
-    } else {
+    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.
-        absoluteFileName[0] = osgDB::findDataFile(fileName, options);
-        // Do not generate an ocean tile if we have no btg
-        file_mode = true;
+        loadStgFile(osgDB::findDataFile(fileName, options), *group, options);
+        return group.release();
     }
 
-    std::string fg_root = options->getPluginStringData("SimGear::FG_ROOT");
-    osg::ref_ptr<SGReaderWriterOptions> opt;
-    opt = SGReaderWriterOptions::copyOrCreate(options);
-
-    bool found_tile_base = false;
-    osg::ref_ptr<osg::Group> group = new osg::Group;
-    for (unsigned i = 0; i < 2; ++i) {
-
-        if (absoluteFileName[i].empty())
-            continue;
-
-        sg_gzifstream in( absoluteFileName[i] );
-        if ( !in.is_open() )
-            continue;
-
-        SG_LOG(SG_TERRAIN, SG_INFO, "Loading stg file " << absoluteFileName[i]);
-
-        std::string filePath = osgDB::getFilePath(absoluteFileName[i]);
-
-        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());
-        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<osg::Node> node;
-            if ( token == "OBJECT_BASE" ) {
-                // Load only once (first found)
-                SG_LOG( SG_TERRAIN, SG_BULK, "    " << token << " " << name );
-
-                if (!found_tile_base) {
-                    found_tile_base = true;
-                    has_base = true;
-                    
-                    node = osgDB::readRefNodeFile(path.str(),
-                                                  staticOptions.get());
-
-                    if (!node.valid()) {
-                        SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName[i]
-                                << ": Failed to load OBJECT_BASE '"
-                                << name << "'" );
-                    }
-                } else
-                    SG_LOG(SG_TERRAIN, SG_BULK, "    (skipped)");
-
-            } else if ( token == "OBJECT" ) {
-                // Load only if base is not in another file
-                if (!found_tile_base || has_base) {
-                    node = osgDB::readRefNodeFile(path.str(),
-                                                  staticOptions.get());
-
-                    if (!node.valid()) {
-                        SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName[i]
-                                << ": Failed to load OBJECT '"
-                                << name << "'" );
-                    }
-                } else {
-                    SG_LOG(SG_TERRAIN, SG_BULK, "    " << token << "  "
-                           << name << "  (skipped)");
-                }
-
-            } 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());
-                    if(_modelLoader) {
-                        node = _modelLoader->loadTileModel(absName, false);
-                    } else {
-                        node = osgDB::readRefNodeFile(absName,
-                                               staticOptions.get());
-                    }
-
-                    if (!node.valid()) {
-                        SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName[i]
-                                << ": Failed to load OBJECT_STATIC '"
-                                << name << "'" );
-                    }
-                    
-                } else if ( token == "OBJECT_SHARED" ) {
-                    if(_modelLoader) {
-                        node = _modelLoader->loadTileModel(name, true);
-                    } else {
-                        /// Hmm, the findDataFile should happen in the downstream readers
-                        std::string absName = osgDB::findDataFile(name,
-                                                   sharedOptions.get());
-                        node = osgDB::readRefNodeFile(absName,
-                                                   sharedOptions.get());
-                    }
-
-                    if (!node.valid()) {
-                        SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName[i]
-                                << ": Failed to load OBJECT_SHARED '"
-                                << name << "'" );
-                    }
-                    
-                } else if ( token == "OBJECT_SIGN" ) {
-                    node = SGMakeSign(opt->getMaterialLib(), name);
-                    
-                } else if ( token == "OBJECT_RUNWAY_SIGN" ) {
-                    node = SGMakeRunwaySign(opt->getMaterialLib(), name);
-                    
-                } else {
-                    SG_LOG( SG_TERRAIN, SG_ALERT, absoluteFileName[i]
-                            << ": 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;
-        }
+    // 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;
     }
-
-    if (!found_tile_base && !file_mode) {
-        // ... or generate an ocean tile on the fly
+    
+    // ... 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);
@@ -347,7 +353,6 @@ TileEntry::loadTileByFileName(const string& fileName,
                     "Warning: failed to generate ocean tile!" );
         }
     }
-
     return group.release();
 }
 
index 551ccc67f4add9cc66d5e04a88a217508a597f5e..096caed9faaa458f5ef9a061b7c21551e8a5887a 100644 (file)
@@ -80,8 +80,6 @@ private:
     /** Time when tile expires. */ 
     double _time_expired;
 
-    static ModelLoadHelper *_modelLoader;
-
 public:
 
     // Constructor
@@ -91,7 +89,7 @@ public:
     // Destructor
     ~TileEntry();
 
-    static void setModelLoadHelper(ModelLoadHelper *m) { _modelLoader=m; }
+    static void setModelLoadHelper(ModelLoadHelper *m);
 
     // Update the ssg transform node for this tile so it can be
     // properly drawn relative to our (0,0,0) point