]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/model.cxx
OSG Reader and Writer for BTG files
[simgear.git] / simgear / scene / model / model.cxx
index 7a35768a38000480bc42b3fa7658db7235ccf396..4a2349be603cac35bf1aa7153c83d789577647fa 100644 (file)
@@ -22,6 +22,7 @@
 #include <osgDB/SharedStateManager>
 #include <osgUtil/Optimizer>
 
+#include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/SGStateAttributeVisitor.hxx>
 #include <simgear/scene/util/SGTextureStateAttributeVisitor.hxx>
 
@@ -128,10 +129,6 @@ private:
 
 class SGTexCompressionVisitor : public SGTextureStateAttributeVisitor {
 public:
-  SGTexCompressionVisitor(osg::Texture::InternalFormatMode formatMode) :
-    mFormatMode(formatMode)
-  { }
-
   virtual void apply(int, osg::StateSet::RefAttributePair& refAttr)
   {
     osg::Texture2D* texture;
@@ -145,15 +142,26 @@ public:
 
     int s = image->s();
     int t = image->t();
+
     if (s <= t && 32 <= s) {
-      texture->setInternalFormatMode(mFormatMode);
+      SGSceneFeatures::instance()->setTextureCompression(texture);
     } else if (t < s && 32 <= t) {
-      texture->setInternalFormatMode(mFormatMode);
+      SGSceneFeatures::instance()->setTextureCompression(texture);
     }
   }
+};
 
-private:
-  osg::Texture::InternalFormatMode mFormatMode;
+class SGTexDataVarianceVisitor : public SGTextureStateAttributeVisitor {
+public:
+  virtual void apply(int, osg::StateSet::RefAttributePair& refAttr)
+  {
+    osg::Texture* texture;
+    texture = dynamic_cast<osg::Texture*>(refAttr.first.get());
+    if (!texture)
+      return;
+    
+    texture->setDataVariance(osg::Object::STATIC);
+  }
 };
 
 class SGAcMaterialCrippleVisitor : public SGStateAttributeVisitor {
@@ -199,6 +207,15 @@ public:
   readNode(const std::string& fileName,
            const osgDB::ReaderWriter::Options* opt)
   {
+    osgDB::Registry* registry = osgDB::Registry::instance();
+    osgDB::ReaderWriter::ReadResult res;
+    // The BTG loader automatically looks for ".btg.gz" if a file with
+    // the .btg extension doesn't exist. Also, we don't want to add
+    // nodes, run the optimizer, etc. on the btg model.So, let it do
+    // its thing.
+    if (osgDB::equalCaseInsensitive(osgDB::getFileExtension(fileName), "btg")) {
+      return registry->readNodeImplementation(fileName, opt);
+    }
     std::string absFileName = osgDB::findDataFile(fileName);
     if (!osgDB::fileExists(absFileName)) {
       SG_LOG(SG_IO, SG_ALERT, "Cannot find model file \""
@@ -206,8 +223,6 @@ public:
       return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
     }
 
-    osgDB::Registry* registry = osgDB::Registry::instance();
-    osgDB::ReaderWriter::ReadResult res;
     res = registry->readNodeImplementation(absFileName, opt);
     if (!res.validNode())
       return res;
@@ -276,23 +291,17 @@ public:
       if (needTristrip)
         opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY;
       // opts |= osgUtil::Optimizer::TESSELATE_GEOMETRY;
-      opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
+      // opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
       optimizer.optimize(res.getNode(), opts);
 
-      // OSGFIXME
+      // Make sure the data variance of sharable objects is set to STATIC ...
+      SGTexDataVarianceVisitor dataVarianceVisitor;
+      res.getNode()->accept(dataVarianceVisitor);
+      // ... so that textures are now globally shared
       registry->getSharedStateManager()->share(res.getNode());
       
-      // OSGFIXME: guard that with a flag
-      // OSGFIXME: in the long term it is unclear if we have an OpenGL
-      // context here...
-      osg::Texture::Extensions* e = osg::Texture::getExtensions(0, true);
-      if (e->isTextureCompressionARBSupported()) {
-        SGTexCompressionVisitor texComp(osg::Texture::USE_ARB_COMPRESSION);
-        res.getNode()->accept(texComp);
-      } else if (e->isTextureCompressionS3TCSupported()) {
-        SGTexCompressionVisitor texComp(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
-        res.getNode()->accept(texComp);
-      }
+      SGTexCompressionVisitor texComp;
+      res.getNode()->accept(texComp);
     }
 
     // Add an extra reference to the model stored in the database.
@@ -313,10 +322,14 @@ public:
     res = osgDB::ReaderWriter::ReadResult(osg::CopyOp(flags)(res.getNode()));
     res.getNode()->addObserver(databaseReference);
 
+    // Update liveries
     SGTextureUpdateVisitor liveryUpdate(osgDB::getDataFilePathList());
     res.getNode()->accept(liveryUpdate);
 
-    // OSGFIXME: don't forget that mutex here
+    // Make sure the data variance of sharable objects is set to STATIC ...
+    SGTexDataVarianceVisitor dataVarianceVisitor;
+    res.getNode()->accept(dataVarianceVisitor);
+    // ... so that textures are now globally shared
     registry->getOrCreateSharedStateManager()->share(res.getNode(), 0);
 
     return res;
@@ -359,19 +372,10 @@ SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, int)
     int s = image->s();
     int t = image->t();
 
-    // OSGFIXME: guard with a flag
-    if (osg::Texture::getExtensions(0, true)->isTextureCompressionARBSupported()) {
-      if (s <= t && 32 <= s) {
-        texture->setInternalFormatMode(osg::Texture::USE_ARB_COMPRESSION);
-      } else if (t < s && 32 <= t) {
-        texture->setInternalFormatMode(osg::Texture::USE_ARB_COMPRESSION);
-      }
-    } else if (osg::Texture::getExtensions(0, true)->isTextureCompressionS3TCSupported()) {
-      if (s <= t && 32 <= s) {
-        texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
-      } else if (t < s && 32 <= t) {
-        texture->setInternalFormatMode(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
-      }
+    if (s <= t && 32 <= s) {
+      SGSceneFeatures::instance()->setTextureCompression(texture.get());
+    } else if (t < s && 32 <= t) {
+      SGSceneFeatures::instance()->setTextureCompression(texture.get());
     }
   }
 
@@ -433,7 +437,7 @@ sgLoad3DModel( const string &fg_root, const string &path,
                SGModelData *data,
                const SGPath& externalTexturePath )
 {
-  osg::Node* model = 0;
+  osg::ref_ptr<osg::Node> model;
   SGPropertyNode props;
 
   // Load the 3D aircraft object itself
@@ -455,7 +459,7 @@ sgLoad3DModel( const string &fg_root, const string &path,
         texturepath.append(props.getStringValue("/texture-path"));
       }
     } else {
-      if (model == 0)
+      if (!model)
         model = new osg::Switch;
     }
   }
@@ -465,7 +469,7 @@ sgLoad3DModel( const string &fg_root, const string &path,
 
   // Assume that textures are in
   // the same location as the XML file.
-  if (model == 0) {
+  if (!model) {
     if (texturepath.extension() != "")
           texturepath = texturepath.dir();
 
@@ -480,8 +484,8 @@ sgLoad3DModel( const string &fg_root, const string &path,
   osgDB::Registry::instance()->getDataFilePathList().push_front(externalTexturePath.str());
 
   // Set up the alignment node
-  osg::MatrixTransform* alignmainmodel = new osg::MatrixTransform;
-  alignmainmodel->addChild(model);
+  osg::ref_ptr<osg::MatrixTransform> alignmainmodel = new osg::MatrixTransform;
+  alignmainmodel->addChild(model.get());
   osg::Matrix res_matrix;
   res_matrix.makeRotate(
     props.getFloatValue("/offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
@@ -501,7 +505,7 @@ sgLoad3DModel( const string &fg_root, const string &path,
   vector<SGPropertyNode_ptr> model_nodes = props.getChildren("model");
   for (unsigned i = 0; i < model_nodes.size(); i++) {
     SGPropertyNode_ptr node = model_nodes[i];
-    osg::MatrixTransform* align = new osg::MatrixTransform;
+    osg::ref_ptr<osg::MatrixTransform> align = new osg::MatrixTransform;
     res_matrix.makeIdentity();
     res_matrix.makeRotate(
       node->getDoubleValue("offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
@@ -517,7 +521,7 @@ sgLoad3DModel( const string &fg_root, const string &path,
                        node->getDoubleValue("offsets/z-m", 0));
     align->setMatrix(res_matrix*tmat);
 
-    osg::Node* kid;
+    osg::ref_ptr<osg::Node> kid;
     const char* submodel = node->getStringValue("path");
     try {
       kid = sgLoad3DModel( fg_root, submodel, prop_root, sim_time_sec, load_panel );
@@ -526,19 +530,19 @@ sgLoad3DModel( const string &fg_root, const string &path,
       SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage());
       throw;
     }
-    align->addChild(kid);
+    align->addChild(kid.get());
 
     align->setName(node->getStringValue("name", ""));
 
     SGPropertyNode *cond = node->getNode("condition", false);
     if (cond) {
-      osg::Switch* sw = new osg::Switch;
+      osg::ref_ptr<osg::Switch> sw = new osg::Switch;
       sw->setUpdateCallback(new SGSwitchUpdateCallback(sgReadCondition(prop_root, cond)));
-      alignmainmodel->addChild(sw);
-      sw->addChild(align);
+      alignmainmodel->addChild(sw.get());
+      sw->addChild(align.get());
       sw->setName("submodel condition switch");
     } else {
-      alignmainmodel->addChild(align);
+      alignmainmodel->addChild(align.get());
     }
   }
 
@@ -547,23 +551,23 @@ sgLoad3DModel( const string &fg_root, const string &path,
     vector<SGPropertyNode_ptr> panel_nodes = props.getChildren("panel");
     for (unsigned i = 0; i < panel_nodes.size(); i++) {
         SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel");
-        osg::Node * panel = load_panel(panel_nodes[i]);
+        osg::ref_ptr<osg::Node> panel = load_panel(panel_nodes[i]);
         if (panel_nodes[i]->hasValue("name"))
             panel->setName((char *)panel_nodes[i]->getStringValue("name"));
-        alignmainmodel->addChild(panel);
+        alignmainmodel->addChild(panel.get());
     }
   }
 
   if (data) {
     alignmainmodel->setUserData(data);
-    data->modelLoaded(path, &props, alignmainmodel);
+    data->modelLoaded(path, &props, alignmainmodel.get());
   }
 
   std::vector<SGPropertyNode_ptr> animation_nodes;
   animation_nodes = props.getChildren("animation");
   for (unsigned i = 0; i < animation_nodes.size(); ++i)
     /// OSGFIXME: duh, why not only model?????
-    SGAnimation::animate(alignmainmodel, animation_nodes[i], prop_root);
+    SGAnimation::animate(alignmainmodel.get(), animation_nodes[i], prop_root);
 
   // restore old path list
   osgDB::setDataFilePathList(pathList);
@@ -574,7 +578,7 @@ sgLoad3DModel( const string &fg_root, const string &path,
     osgDB::writeNodeFile(*alignmainmodel, outputfile);
   }
 
-  return alignmainmodel;
+  return alignmainmodel.release();
 }
 
 // end of model.cxx