]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/animation.cxx
- better error message when submodel loading failed
[simgear.git] / simgear / scene / model / animation.cxx
index dc991c2696c045dbec7694adc7fd384f358eaa58..5dddc5bd23f567dacef0b97eefc44fd3a4c5f43a 100644 (file)
@@ -3,6 +3,9 @@
 //
 // This file is in the Public Domain, and comes with no warranty.
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
 
 #include <string.h>             // for strcmp()
 #include <math.h>
@@ -179,7 +182,8 @@ double SGAnimation::sim_time_sec = 0.0;
 SGPersonalityBranch *SGAnimation::current_object = 0;
 
 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
-    : _branch(branch)
+    : _branch(branch),
+    animation_type(0)
 {
     _branch->setName(props->getStringValue("name", 0));
     if ( props->getBoolValue( "enable-hot", true ) ) {
@@ -630,14 +634,18 @@ SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
     _center[0] = 0;
     _center[1] = 0;
     _center[2] = 0;
-    if (props->hasValue("axis/x1-m")) {
+    if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
+       _axis[0] = props->getFloatValue("axis/x", 0);
+       _axis[1] = props->getFloatValue("axis/y", 0);
+       _axis[2] = props->getFloatValue("axis/z", 0);
+    } else {
         double x1,y1,z1,x2,y2,z2;
-        x1 = props->getFloatValue("axis/x1-m");
-        y1 = props->getFloatValue("axis/y1-m");
-        z1 = props->getFloatValue("axis/z1-m");
-        x2 = props->getFloatValue("axis/x2-m");
-        y2 = props->getFloatValue("axis/y2-m");
-        z2 = props->getFloatValue("axis/z2-m");
+        x1 = props->getFloatValue("axis/x1-m", 0);
+        y1 = props->getFloatValue("axis/y1-m", 0);
+        z1 = props->getFloatValue("axis/z1-m", 0);
+        x2 = props->getFloatValue("axis/x2-m", 0);
+        y2 = props->getFloatValue("axis/y2-m", 0);
+        z2 = props->getFloatValue("axis/z2-m", 0);
         _center[0] = (x1+x2)/2;
         _center[1]= (y1+y2)/2;
         _center[2] = (z1+z2)/2;
@@ -645,15 +653,12 @@ SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
         _axis[0] = (x2-x1)/vector_length;
         _axis[1] = (y2-y1)/vector_length;
         _axis[2] = (z2-z1)/vector_length;
-    } else {
-       _axis[0] = props->getFloatValue("axis/x", 0);
-       _axis[1] = props->getFloatValue("axis/y", 0);
-       _axis[2] = props->getFloatValue("axis/z", 0);
     }
-    if (props->hasValue("center/x-m")) {
-       _center[0] = props->getFloatValue("center/x-m", 0);
-       _center[1] = props->getFloatValue("center/y-m", 0);
-       _center[2] = props->getFloatValue("center/z-m", 0);
+    if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
+            || props->hasValue("center/z-m")) {
+        _center[0] = props->getFloatValue("center/x-m", 0);
+        _center[1] = props->getFloatValue("center/y-m", 0);
+        _center[2] = props->getFloatValue("center/z-m", 0);
     }
     sgNormalizeVec3(_axis);
 }
@@ -770,7 +775,7 @@ SGTranslateAnimation::update()
 {
   if (_condition == 0 || _condition->test()) {
     if (_table == 0) {
-      _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
+      _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
       if (_has_min && _position_m < _min_m)
         _position_m = _min_m;
       if (_has_max && _position_m > _max_m)
@@ -1118,52 +1123,58 @@ void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
 SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
         SGPropertyNode_ptr props, const SGPath &texture_path)
     : SGAnimation(props, new ssgBranch),
-    _base_dir(texture_path),
+    _last_condition(false),
+    _prop_root(prop_root),
+    _prop_base(""),
+    _texture_base(texture_path),
     _cached_material(0),
     _cloned_material(0),
     _read(0),
     _update(0),
     _global(props->getBoolValue("global", false))
 {
-    _diff.red = props->getFloatValue("diffuse-red", -1.0);
-    _diff.green = props->getFloatValue("diffuse-green", -1.0);
-    _diff.blue = props->getFloatValue("diffuse-blue", -1.0);
-    _diff.factor = props->getFloatValue("diffuse-factor", 1.0);
-    _diff.offset = props->getFloatValue("diffuse-offset", 0.0);
-    if (_diff.dirty())
-        _update |= DIFFUSE;
-
-    _amb.red = props->getFloatValue("ambient-red", -1.0);
-    _amb.green = props->getFloatValue("ambient-green", -1.0);
-    _amb.blue = props->getFloatValue("ambient-blue", -1.0);
-    _amb.factor = props->getFloatValue("ambient-factor", 1.0);
-    _amb.offset = props->getFloatValue("ambient-offset", 0.0);
-    if (_amb.dirty())
-        _update |= AMBIENT;
-
-    _spec.red = props->getFloatValue("specular-red", -1.0);
-    _spec.green = props->getFloatValue("specular-green", -1.0);
-    _spec.blue = props->getFloatValue("specular-blue", -1.0);
-    _spec.factor = props->getFloatValue("specular-factor", 1.0);
-    _spec.offset = props->getFloatValue("specular-offset", 0.0);
-    if (_spec.dirty())
-        _update |= SPECULAR;
-
-    _emis.red = props->getFloatValue("emission-red", -1.0);
-    _emis.green = props->getFloatValue("emission-green", -1.0);
-    _emis.blue = props->getFloatValue("emission-blue", -1.0);
-    _emis.factor = props->getFloatValue("emission-factor", 1.0);
-    _emis.offset = props->getFloatValue("emission-offset", 0.0);
-    if (_emis.dirty())
-        _update |= EMISSION;
+    SGPropertyNode_ptr n;
+    n = props->getChild("condition");
+    _condition = n ? sgReadCondition(_prop_root, n) : 0;
+    n = props->getChild("property-base");
+    if (n) {
+        _prop_base = n->getStringValue();
+        if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
+            _prop_base += '/';
+    }
+
+    initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
+    initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
+    initColorGroup(props->getChild("emission"), &_emis, EMISSION);
+    initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
 
     _shi = props->getFloatValue("shininess", -1.0);
     if (_shi >= 0.0)
         _update |= SHININESS;
 
-    _trans = props->getFloatValue("transparency", -1.0);
-    if (_trans >= 0.0)
-        _update |= TRANSPARENCY;
+    SGPropertyNode_ptr group = props->getChild("transparency");
+    if (group) {
+        _trans.value = group->getFloatValue("alpha", -1.0);
+        _trans.factor = group->getFloatValue("factor", 1.0);
+        _trans.offset = group->getFloatValue("offset", 0.0);
+        _trans.min = group->getFloatValue("min", 0.0);
+        if (_trans.min < 0.0)
+            _trans.min = 0.0;
+        _trans.max = group->getFloatValue("max", 1.0);
+        if (_trans.max > 1.0)
+            _trans.max = 1.0;
+        if (_trans.dirty())
+            _update |= TRANSPARENCY;
+
+        n = group->getChild("alpha-prop");
+        _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+        n = group->getChild("factor-prop");
+        _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+        n = group->getChild("offset-prop");
+        _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+        if (_trans.live())
+            _read |= TRANSPARENCY;
+    }
 
     _thresh = props->getFloatValue("threshold", -1.0);
     if (_thresh >= 0.0)
@@ -1171,74 +1182,47 @@ SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
 
     string _texture_str = props->getStringValue("texture", "");
     if (!_texture_str.empty()) {
-        _texture = _base_dir;
+        _texture = _texture_base;
         _texture.append(_texture_str);
         _update |= TEXTURE;
     }
 
-    SGPropertyNode_ptr node = props->getChild("condition");
-    _condition = node ? sgReadCondition(prop_root, node) : 0;
-
-    node = props->getChild("diffuse-red-prop");
-    _diff.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("diffuse-green-prop");
-    _diff.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("diffuse-blue-prop");
-    _diff.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("diffuse-factor-prop");
-    _diff.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("diffuse-offset-prop");
-    _diff.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    if (_diff.live())
-        _read |= DIFFUSE;
-
-    node = props->getChild("ambient-red-prop");
-    _amb.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("ambient-green-prop");
-    _amb.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("ambient-blue-prop");
-    _amb.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("ambient-factor-prop");
-    _amb.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("ambient-offset-prop");
-    _amb.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    if (_amb.live())
-        _read |= AMBIENT;
-
-    node = props->getChild("specular-red-prop");
-    _spec.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("specular-green-prop");
-    _spec.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("specular-blue-prop");
-    _spec.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("specular-factor-prop");
-    _spec.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("specular-offset-prop");
-    _spec.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    if (_spec.live())
-        _read |= SPECULAR;
-
-    node = props->getChild("emission-red-prop");
-    _emis.red_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("emission-green-prop");
-    _emis.green_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("emission-blue-prop");
-    _emis.blue_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("emission-factor-prop");
-    _emis.factor_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("emission-offset-prop");
-    _emis.offset_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    if (_emis.live())
-        _read |= EMISSION;
-
-    node = props->getChild("shininess-prop");
-    _shi_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("transparency-prop");
-    _trans_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("threshold-prop");
-    _thresh_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
-    node = props->getChild("texture-prop");
-    _tex_prop = node ? prop_root->getNode(node->getStringValue(), true) : 0;
+    n = props->getChild("shininess-prop");
+    _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+    n = props->getChild("threshold-prop");
+    _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+    n = props->getChild("texture-prop");
+    _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+
+    _static_update = _update;
+}
+
+void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
+{
+    if (!group)
+        return;
+
+    col->red = group->getFloatValue("red", -1.0);
+    col->green = group->getFloatValue("green", -1.0);
+    col->blue = group->getFloatValue("blue", -1.0);
+    col->factor = group->getFloatValue("factor", 1.0);
+    col->offset = group->getFloatValue("offset", 0.0);
+    if (col->dirty())
+        _update |= flag;
+
+    SGPropertyNode *n;
+    n = group->getChild("red-prop");
+    col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+    n = group->getChild("green-prop");
+    col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+    n = group->getChild("blue-prop");
+    col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+    n = group->getChild("factor-prop");
+    col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+    n = group->getChild("offset-prop");
+    col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
+    if (col->live())
+        _read |= flag;
 }
 
 void SGMaterialAnimation::init()
@@ -1249,69 +1233,25 @@ void SGMaterialAnimation::init()
 
 int SGMaterialAnimation::update()
 {
-    if (_condition && !_condition->test())
-        return 2;
-
-    if (_read & DIFFUSE) {
-        ColorSpec tmp = _diff;
-        if (_diff.red_prop)
-            _diff.red = _diff.red_prop->getFloatValue();
-        if (_diff.green_prop)
-            _diff.green = _diff.green_prop->getFloatValue();
-        if (_diff.blue_prop)
-            _diff.blue = _diff.blue_prop->getFloatValue();
-        if (_diff.factor_prop)
-            _diff.factor = _diff.factor_prop->getFloatValue();
-        if (_diff.offset_prop)
-            _diff.offset = _diff.offset_prop->getFloatValue();
-        if (_diff != tmp)
-            _update |= DIFFUSE;
-    }
-    if (_read & AMBIENT) {
-        ColorSpec tmp = _amb;
-        if (_amb.red_prop)
-            _amb.red = _amb.red_prop->getFloatValue();
-        if (_amb.green_prop)
-            _amb.green = _amb.green_prop->getFloatValue();
-        if (_amb.blue_prop)
-            _amb.blue = _amb.blue_prop->getFloatValue();
-        if (_amb.factor_prop)
-            _amb.factor = _amb.factor_prop->getFloatValue();
-        if (_amb.offset_prop)
-            _amb.offset = _amb.offset_prop->getFloatValue();
-        if (_amb != tmp)
-            _update |= AMBIENT;
-    }
-    if (_read & SPECULAR) {
-        ColorSpec tmp = _spec;
-        if (_spec.red_prop)
-            _spec.red = _spec.red_prop->getFloatValue();
-        if (_spec.green_prop)
-            _spec.green = _spec.green_prop->getFloatValue();
-        if (_spec.blue_prop)
-            _spec.blue = _spec.blue_prop->getFloatValue();
-        if (_spec.factor_prop)
-            _spec.factor = _spec.factor_prop->getFloatValue();
-        if (_spec.offset_prop)
-            _spec.offset = _spec.offset_prop->getFloatValue();
-        if (_spec != tmp)
-            _update |= SPECULAR;
-    }
-    if (_read & EMISSION) {
-        ColorSpec tmp = _emis;
-        if (_emis.red_prop)
-            _emis.red = _emis.red_prop->getFloatValue();
-        if (_emis.green_prop)
-            _emis.green = _emis.green_prop->getFloatValue();
-        if (_emis.blue_prop)
-            _emis.blue = _emis.blue_prop->getFloatValue();
-        if (_emis.factor_prop)
-            _emis.factor = _emis.factor_prop->getFloatValue();
-        if (_emis.offset_prop)
-            _emis.offset = _emis.offset_prop->getFloatValue();
-        if (_emis != tmp)
-            _update |= EMISSION;
+    if (_condition) {
+        bool cond = _condition->test();
+        if (cond && !_last_condition)
+            _update |= _static_update;
+
+        _last_condition = cond;
+        if (!cond)
+            return 2;
     }
+
+    if (_read & DIFFUSE)
+        updateColorGroup(&_diff, DIFFUSE);
+    if (_read & AMBIENT)
+        updateColorGroup(&_amb, AMBIENT);
+    if (_read & EMISSION)
+        updateColorGroup(&_emis, EMISSION);
+    if (_read & SPECULAR)
+        updateColorGroup(&_spec, SPECULAR);
+
     float f;
     if (_shi_prop) {
         f = _shi;
@@ -1319,10 +1259,15 @@ int SGMaterialAnimation::update()
         if (_shi != f)
             _update |= SHININESS;
     }
-    if (_trans_prop) {
-        f = _trans;
-        _trans = _trans_prop->getFloatValue();
-        if (_trans != f)
+    if (_read & TRANSPARENCY) {
+        PropSpec tmp = _trans;
+        if (_trans.value_prop)
+            _trans.value = _trans.value_prop->getFloatValue();
+        if (_trans.factor_prop)
+            _trans.factor = _trans.factor_prop->getFloatValue();
+        if (_trans.offset_prop)
+            _trans.offset = _trans.offset_prop->getFloatValue();
+        if (_trans != tmp)
             _update |= TRANSPARENCY;
     }
     if (_thresh_prop) {
@@ -1335,7 +1280,7 @@ int SGMaterialAnimation::update()
         string t = _tex_prop->getStringValue();
         if (!t.empty() && t != _texture_str) {
             _texture_str = t;
-            _texture = _base_dir;
+            _texture = _texture_base;
             _texture.append(t);
             _update |= TEXTURE;
         }
@@ -1347,6 +1292,23 @@ int SGMaterialAnimation::update()
     return 2;
 }
 
+void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
+{
+    ColorSpec tmp = *col;
+    if (col->red_prop)
+        col->red = col->red_prop->getFloatValue();
+    if (col->green_prop)
+        col->green = col->green_prop->getFloatValue();
+    if (col->blue_prop)
+        col->blue = col->blue_prop->getFloatValue();
+    if (col->factor_prop)
+        col->factor = col->factor_prop->getFloatValue();
+    if (col->offset_prop)
+        col->offset = col->offset_prop->getFloatValue();
+    if (*col != tmp)
+        _update |= flag;
+}
+
 void SGMaterialAnimation::cloneMaterials(ssgBranch *b)
 {
     for (int i = 0; i < b->getNumKids(); i++)
@@ -1372,25 +1334,32 @@ void SGMaterialAnimation::setMaterialBranch(ssgBranch *b)
         return;
 
     ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
-    s->disable(GL_COLOR_MATERIAL);
-    s->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
 
     if (_update & DIFFUSE) {
         float *v = _diff.rgba();
         SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
+        s->setColourMaterial(GL_DIFFUSE);
+        s->enable(GL_COLOR_MATERIAL);
         s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], alpha);
+        s->disable(GL_COLOR_MATERIAL);
     }
-    if (_update & AMBIENT)
+    if (_update & AMBIENT) {
+        s->setColourMaterial(GL_AMBIENT);
+        s->enable(GL_COLOR_MATERIAL);
         s->setMaterial(GL_AMBIENT, _amb.rgba());
-    if (_update & SPECULAR)
-        s->setMaterial(GL_SPECULAR, _spec.rgba());
+        s->disable(GL_COLOR_MATERIAL);
+    }
     if (_update & EMISSION)
         s->setMaterial(GL_EMISSION, _emis.rgba());
+    if (_update & SPECULAR)
+        s->setMaterial(GL_SPECULAR, _spec.rgba());
     if (_update & SHININESS)
         s->setShininess(clamp(_shi, 0.0, 128.0));
     if (_update & TRANSPARENCY) {
         SGfloat *v = s->getMaterial(GL_DIFFUSE);
-        s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], 1.0 - clamp(_trans));
+        float trans = _trans.value * _trans.factor + _trans.offset;
+        trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
+        s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], trans);
     }
     if (_update & THRESHOLD)
         s->setAlphaClamp(clamp(_thresh));
@@ -1400,9 +1369,12 @@ void SGMaterialAnimation::setMaterialBranch(ssgBranch *b)
         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);
@@ -1543,4 +1515,39 @@ void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
   sgPreMultMat4( r, transform );
 }
 
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGShadowAnimation
+////////////////////////////////////////////////////////////////////////
+
+SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
+                   SGPropertyNode_ptr props )
+  : SGAnimation(props, new ssgBranch),
+    _condition(0),
+       _condition_value(true)
+{
+       animation_type = 1;
+       SGPropertyNode_ptr node = props->getChild("condition");
+       if (node != 0) {
+               _condition = sgReadCondition(prop_root, node);
+               _condition_value = false;
+       }
+}
+
+SGShadowAnimation::~SGShadowAnimation ()
+{
+       delete _condition;
+}
+
+int
+SGShadowAnimation::update()
+{
+       if (_condition)
+               _condition_value = _condition->test();
+       return 2;
+}
+
+bool SGShadowAnimation::get_condition_value(void) {
+       return _condition_value;
+}
+
 // end of animation.cxx