]> git.mxchange.org Git - simgear.git/commitdiff
Modified Files:
authorfrohlich <frohlich>
Tue, 14 Nov 2006 21:09:44 +0000 (21:09 +0000)
committerfrohlich <frohlich>
Tue, 14 Nov 2006 21:09:44 +0000 (21:09 +0000)
animation.hxx animation.cxx: Improove material/texture/blend animation

simgear/scene/model/animation.cxx
simgear/scene/model/animation.hxx

index 7cc25afcd92a4faa16a7b9d5f548eea0b50e9c27..925f52f8b120c28d1835698dbe54ce4e81915422 100644 (file)
 
 #include <osg/AlphaFunc>
 #include <osg/AutoTransform>
-#include <osg/ColorMatrix>
 #include <osg/Drawable>
 #include <osg/Geode>
+#include <osg/Geometry>
 #include <osg/LOD>
 #include <osg/MatrixTransform>
 #include <osg/StateSet>
 #include <osg/Switch>
 #include <osg/TexMat>
+#include <osg/Texture2D>
+#include <osgDB/ReadFile>
 
 #include <simgear/math/interpolater.hxx>
 #include <simgear/props/condition.hxx>
@@ -581,6 +583,59 @@ SGRotateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
 // Implementation of SGBlendAnimation
 ////////////////////////////////////////////////////////////////////////
 
+class SGBlendAnimationVisitor : public osg::NodeVisitor {
+public:
+  SGBlendAnimationVisitor(float blend) :
+    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+    _blend(blend)
+  {
+    setVisitorType(osg::NodeVisitor::NODE_VISITOR);
+  }
+  virtual void apply(osg::Node& node)
+  {
+    updateStateSet(node.getStateSet());
+    traverse(node);
+  }
+  virtual void apply(osg::Geode& node)
+  {
+    apply((osg::Node&)node);
+    unsigned nDrawables = node.getNumDrawables();
+    for (unsigned i = 0; i < nDrawables; ++i) {
+      osg::Drawable* drawable = node.getDrawable(i);
+      updateStateSet(drawable->getStateSet());
+      osg::Geometry* geometry = drawable->asGeometry();
+      if (!geometry)
+        continue;
+      osg::Array* array = geometry->getColorArray();
+      if (!array)
+        continue;
+      osg::Vec4Array* vec4Array = dynamic_cast<osg::Vec4Array*>(array);
+      if (!vec4Array)
+        continue;
+      geometry->dirtyDisplayList();
+      vec4Array->dirty();
+      for (unsigned k = 0; k < vec4Array->size(); ++k) {
+        (*vec4Array)[k][3] = _blend;
+      }
+    }
+  }
+  void updateStateSet(osg::StateSet* stateSet)
+  {
+    if (!stateSet)
+      return;
+    osg::StateAttribute* stateAttribute = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
+    if (!stateAttribute)
+      return;
+    osg::Material* material = dynamic_cast<osg::Material*>(stateAttribute);
+    if (!material)
+      return;
+    material->setAlpha(osg::Material::FRONT_AND_BACK, _blend);
+  }
+private:
+  float _blend;
+};
+
+
 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
                                         SGPropertyNode_ptr props )
   : SGAnimation(props, new osg::Group),
@@ -590,18 +645,9 @@ SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
     _prev_value(1.0),
     _offset(props,"offset",0.0),
     _factor(props,"factor",1.0),
-    _has_min(props->hasValue("min")),
     _min(props->getDoubleValue("min", 0.0)),
-    _has_max(props->hasValue("max")),
     _max(props->getDoubleValue("max", 1.0))
 {
-  // OSGFIXME: does ot work like that!!!
-  // depends on a not so wide available extension
-
-  _colorMatrix = new osg::ColorMatrix;
-  osg::StateSet* stateSet = _branch->getOrCreateStateSet();
-  stateSet->setAttribute(_colorMatrix.get());
-
   if ( _use_personality ) {
     _factor.shuffle();
     _offset.shuffle();
@@ -620,18 +666,18 @@ SGBlendAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
 
   if (_table == 0) {
     _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
-
-    if (_has_min && (_blend < _min))
-      _blend = _min;
-    if (_has_max && (_blend > _max))
-      _blend = _max;
   } else {
     _blend = _table->interpolate(_prop->getDoubleValue());
   }
+  if (_blend < _min)
+    _blend = _min;
+  if (_blend > _max)
+    _blend = _max;
 
   if (_blend != _prev_value) {
     _prev_value = _blend;
-    _colorMatrix->getMatrix()(3, 3) = _blend;
+    SGBlendAnimationVisitor visitor(1-_blend);
+    _branch->accept(visitor);
   }
   traverse(node, nv);
 }
@@ -1179,7 +1225,7 @@ void SGMaterialAnimation::init()
       stateSet->setAttribute(_alphaFunc.get(), osg::StateAttribute::OVERRIDE);
       stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
     }
-    if (_update & TEXTURE) {
+    if ((_update & TEXTURE) && _texture2D.valid()) {
       stateSet->setTextureAttribute(0, _texture2D.get(), osg::StateAttribute::OVERRIDE);
       stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
     }
@@ -1354,34 +1400,33 @@ void SGMaterialAnimation::setMaterialBranch(osg::Group *b)
     if (_update & SHININESS)
       material->setShininess(osg::Material::FRONT_AND_BACK,
                              clamp(_shi, 0.0, 128.0));
-    if (_update & TRANSPARENCY) {
-      osg::Vec4 v = material->getDiffuse(osg::Material::FRONT_AND_BACK);
-      float trans = _trans.value * _trans.factor + _trans.offset;
-      trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
-      material->setDiffuse(osg::Material::FRONT_AND_BACK,
-                           osg::Vec4(v[0], v[1], v[2], trans));
-    }
     if (_update & THRESHOLD)
         _alphaFunc->setReferenceValue(clamp(_thresh));
-    // OSGFIXME
-//     if (_update & TEXTURE)
-//         s->setTexture(_texture.c_str());
-//     if (_update & (TEXTURE|TRANSPARENCY)) {
-//         SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
-//         ssgTexture *tex = s->getTexture();
-//         if ((tex && tex->hasAlpha()) || alpha < 0.999) {
-//             s->setColourMaterial(GL_DIFFUSE);
-//             s->enable(GL_COLOR_MATERIAL);
-//             s->enable(GL_BLEND);
-//             s->enable(GL_ALPHA_TEST);
-//             s->setTranslucent();
-//             s->disable(GL_COLOR_MATERIAL);
-//         } else {
-//             s->disable(GL_BLEND);
-//             s->disable(GL_ALPHA_TEST);
-//             s->setOpaque();
-//         }
-//     }
+  }
+
+  if (_update & TRANSPARENCY) {
+    float trans = _trans.value * _trans.factor + _trans.offset;
+    trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
+    SGBlendAnimationVisitor visitor(trans);
+    _branch->accept(visitor);
+  }
+  if (_update & TEXTURE) {
+    if (!_texture2D) {
+      _texture2D = new osg::Texture2D;
+      osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+      stateSet->setTextureAttribute(0, _texture2D.get(), osg::StateAttribute::OVERRIDE);
+      stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
+    }
+    osg::Image* image = osgDB::readImageFile(_texture.str());
+    if (image) {
+      _texture2D->setImage(image);
+      if (image->isImageTranslucent()) {
+        osg::StateSet* stateSet = _branch->getOrCreateStateSet();
+        stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+        stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+        stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+      }
+    }
   }
 }
 
index 504210811ba17d08d898daf0a2f48e832920fdf0..a75e58432ef28b642d4d6b1e93bf746ff939a1bf 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <osg/ref_ptr>
 #include <osg/AlphaFunc>
-#include <osg/ColorMatrix>
 #include <osg/Group>
 #include <osg/Material>
 #include <osg/Node>
@@ -275,11 +274,8 @@ private:
   double _prev_value;
   SGPersonalityParameter<double> _offset;
   SGPersonalityParameter<double> _factor;
-  bool _has_min;
   double _min;
-  bool _has_max;
   double _max;
-  osg::ref_ptr<osg::ColorMatrix> _colorMatrix;
 };
 
 /**