X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fanimation.cxx;h=80c08be2bfc5b002f68728229b3644471df9b3b4;hb=d04cf4d8978866eb80a1639b6d4ddfe387338c77;hp=81040876016cc8d519c967b8d73b02ee3a7d8d7f;hpb=c3719f35e34b8942f1a2766cad1261deb8281fe9;p=simgear.git diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 81040876..80c08be2 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -30,6 +30,10 @@ #include #include #include +#include +#include +#include + #include #include @@ -46,6 +50,11 @@ #include "SGMaterialAnimation.hxx" #include "SGRotateTransform.hxx" #include "SGScaleTransform.hxx" +#include "SGInteractionAnimation.hxx" + +using OpenThreads::Mutex; +using OpenThreads::ReentrantMutex; +using OpenThreads::ScopedLock; //////////////////////////////////////////////////////////////////////// @@ -145,11 +154,11 @@ public: void setOffset(double offset) { _offset = offset; } - virtual void eval(double& value) const + virtual void eval(double& value, const simgear::expression::Binding* b) const { _offset.shuffle(); _scale.shuffle(); - value = _offset + _scale*getOperand()->getValue(); + value = _offset + _scale*getOperand()->getValue(b); } virtual bool isConst() const { return false; } @@ -174,6 +183,19 @@ read_factor_offset(const SGPropertyNode* configNode, SGExpressiond* expr, } static SGExpressiond* +read_offset_factor(const SGPropertyNode* configNode, SGExpressiond* expr, + const std::string& factor, const std::string& offset) +{ + double offsetValue = configNode->getDoubleValue(offset, 0); + if (offsetValue != 0) + expr = new SGBiasExpression(expr, offsetValue); + double factorValue = configNode->getDoubleValue(factor, 1); + if (factorValue != 1) + expr = new SGScaleExpression(expr, factorValue); + return expr; +} + +SGExpressiond* read_value(const SGPropertyNode* configNode, SGPropertyNode* modelRoot, const char* unit, double defMin, double defMax) { @@ -329,7 +351,7 @@ struct DoDrawArraysVisitor : public osg::NodeVisitor { using namespace osg; using namespace std; - for (int i = 0; i < geode.getNumDrawables(); ++i) + for (int i = 0; i < (int)geode.getNumDrawables(); ++i) geode.getDrawable(i)->setUseDisplayList(false); } }; @@ -384,6 +406,9 @@ SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode, } else if (type == "flash") { SGFlashAnimation animInst(configNode, modelRoot); animInst.apply(node); + } else if (type == "interaction") { + SGInteractionAnimation animInst(configNode, modelRoot); + animInst.apply(node); } else if (type == "material") { SGMaterialAnimation animInst(configNode, modelRoot, options); animInst.apply(node); @@ -638,9 +663,20 @@ SGTranslateAnimation::SGTranslateAnimation(const SGPropertyNode* configNode, else _initialValue = 0; - _axis[0] = configNode->getDoubleValue("axis/x", 0); - _axis[1] = configNode->getDoubleValue("axis/y", 0); - _axis[2] = configNode->getDoubleValue("axis/z", 0); + if (configNode->hasValue("axis/x1-m")) { + SGVec3d v1, v2; + v1[0] = configNode->getDoubleValue("axis/x1-m", 0); + v1[1] = configNode->getDoubleValue("axis/y1-m", 0); + v1[2] = configNode->getDoubleValue("axis/z1-m", 0); + v2[0] = configNode->getDoubleValue("axis/x2-m", 0); + v2[1] = configNode->getDoubleValue("axis/y2-m", 0); + v2[2] = configNode->getDoubleValue("axis/z2-m", 0); + _axis = v2 - v1; + } else { + _axis[0] = configNode->getDoubleValue("axis/x", 0); + _axis[1] = configNode->getDoubleValue("axis/y", 0); + _axis[2] = configNode->getDoubleValue("axis/z", 0); + } if (8*SGLimitsd::min() < norm(_axis)) _axis = normalize(_axis); } @@ -918,12 +954,12 @@ SGScaleAnimation::createAnimationGroup(osg::Group& parent) namespace { -OpenThreads::Mutex normalizeMutex; +Mutex normalizeMutex; osg::StateSet* getNormalizeStateSet() { static osg::ref_ptr normalizeStateSet; - OpenThreads::ScopedLock lock(normalizeMutex); + ScopedLock lock(normalizeMutex); if (!normalizeStateSet.valid()) { normalizeStateSet = new osg::StateSet; normalizeStateSet->setMode(GL_NORMALIZE, osg::StateAttribute::ON); @@ -939,6 +975,15 @@ osg::StateSet* getNormalizeStateSet() class SGDistScaleAnimation::Transform : public osg::Transform { public: + Transform() : _min_v(0.0), _max_v(0.0), _factor(0.0), _offset(0.0) {} + Transform(const Transform& rhs, + const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY) + : osg::Transform(rhs, copyOp), _table(rhs._table), _center(rhs._center), + _min_v(rhs._min_v), _max_v(rhs._max_v), _factor(rhs._factor), + _offset(rhs._offset) + { + } + META_Node(simgear, SGDistScaleAnimation::Transform); Transform(const SGPropertyNode* configNode) { setName(configNode->getStringValue("name", "dist scale animation")); @@ -986,13 +1031,23 @@ public: return true; } + static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw) + { + const Transform& trans = static_cast(obj); + fw.indent() << "center " << trans._center << "\n"; + fw.indent() << "min_v " << trans._min_v << "\n"; + fw.indent() << "max_v " << trans._max_v << "\n"; + fw.indent() << "factor " << trans._factor << "\n"; + fw.indent() << "offset " << trans._offset << "\n"; + return true; + } private: double computeScaleFactor(osg::NodeVisitor* nv) const { if (!nv) return 1; - double scale_factor = (_center.osg() - nv->getEyePoint()).length(); + double scale_factor = (toOsg(_center) - nv->getEyePoint()).length(); if (_table == 0) { scale_factor = _factor * scale_factor + _offset; } else { @@ -1029,6 +1084,17 @@ SGDistScaleAnimation::createAnimationGroup(osg::Group& parent) return transform; } +namespace +{ + osgDB::RegisterDotOsgWrapperProxy distScaleAnimationTransformProxy + ( + new SGDistScaleAnimation::Transform, + "SGDistScaleAnimation::Transform", + "Object Node Transform SGDistScaleAnimation::Transform Group", + 0, + &SGDistScaleAnimation::Transform::writeLocalData + ); +} //////////////////////////////////////////////////////////////////////// // Implementation of flash animation @@ -1036,6 +1102,19 @@ SGDistScaleAnimation::createAnimationGroup(osg::Group& parent) class SGFlashAnimation::Transform : public osg::Transform { public: + Transform() : _power(0.0), _factor(0.0), _offset(0.0), _min_v(0.0), + _max_v(0.0), _two_sides(false) + {} + + Transform(const Transform& rhs, + const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY) + : osg::Transform(rhs, copyOp), _center(rhs._center), _axis(rhs._axis), + _power(rhs._power), _factor(rhs._factor), _offset(rhs._offset), + _min_v(rhs._min_v), _max_v(rhs._max_v), _two_sides(rhs._two_sides) + { + } + META_Node(simgear, SGFlashAnimation::Transform); + Transform(const SGPropertyNode* configNode) { setReferenceFrame(RELATIVE_RF); @@ -1092,6 +1171,21 @@ public: return true; } + static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw) + { + const Transform& trans = static_cast(obj); + fw.indent() << "center " << trans._center[0] << " " + << trans._center[1] << " " << trans._center[2] << " " << "\n"; + fw.indent() << "axis " << trans._axis[0] << " " + << trans._axis[1] << " " << trans._axis[2] << " " << "\n"; + fw.indent() << "power " << trans._power << " \n"; + fw.indent() << "min_v " << trans._min_v << "\n"; + fw.indent() << "max_v " << trans._max_v << "\n"; + fw.indent() << "factor " << trans._factor << "\n"; + fw.indent() << "offset " << trans._offset << "\n"; + fw.indent() << "twosides " << (trans._two_sides ? "true" : "false") << "\n"; + return true; + } private: double computeScaleFactor(osg::NodeVisitor* nv) const { @@ -1146,13 +1240,29 @@ SGFlashAnimation::createAnimationGroup(osg::Group& parent) return transform; } +namespace +{ + osgDB::RegisterDotOsgWrapperProxy flashAnimationTransformProxy + ( + new SGFlashAnimation::Transform, + "SGFlashAnimation::Transform", + "Object Node Transform SGFlashAnimation::Transform Group", + 0, + &SGFlashAnimation::Transform::writeLocalData + ); +} //////////////////////////////////////////////////////////////////////// -// Implementation of flash animation +// Implementation of billboard animation //////////////////////////////////////////////////////////////////////// class SGBillboardAnimation::Transform : public osg::Transform { public: + Transform() : _spherical(true) {} + Transform(const Transform& rhs, + const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY) + : osg::Transform(rhs, copyOp), _spherical(rhs._spherical) {} + META_Node(simgear, SGBillboardAnimation::Transform); Transform(const SGPropertyNode* configNode) : _spherical(configNode->getBoolValue("spherical", true)) { @@ -1189,7 +1299,13 @@ public: // Hmm, don't yet know how to get that back ... return false; } + static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw) + { + const Transform& trans = static_cast(obj); + fw.indent() << (trans._spherical ? "true" : "false") << "\n"; + return true; + } private: bool _spherical; }; @@ -1209,6 +1325,17 @@ SGBillboardAnimation::createAnimationGroup(osg::Group& parent) return transform; } +namespace +{ + osgDB::RegisterDotOsgWrapperProxy billboardAnimationTransformProxy + ( + new SGBillboardAnimation::Transform, + "SGBillboardAnimation::Transform", + "Object Node Transform SGBillboardAnimation::Transform Group", + 0, + &SGBillboardAnimation::Transform::writeLocalData + ); +} //////////////////////////////////////////////////////////////////////// // Implementation of a range animation @@ -1374,13 +1501,12 @@ SGAlphaTestAnimation::SGAlphaTestAnimation(const SGPropertyNode* configNode, namespace { // Keep one copy of the most common alpha test its state set. -OpenThreads::ReentrantMutex alphaTestMutex; +ReentrantMutex alphaTestMutex; osg::ref_ptr standardAlphaFunc; osg::ref_ptr alphaFuncStateSet; osg::AlphaFunc* makeAlphaFunc(float clamp) { - using namespace OpenThreads; ScopedLock lock(alphaTestMutex); if (osg::equivalent(clamp, 0.01f)) { if (standardAlphaFunc.valid()) @@ -1726,8 +1852,6 @@ public: Translation(const SGVec3d& axis) : _axis(axis) { } - void setValue(double value) - { _value = value; } virtual void transform(osg::Matrix& matrix) { osg::Matrix tmp; @@ -1806,6 +1930,7 @@ SGTexTransformAnimation::createAnimationGroup(osg::Group& parent) osg::Group* group = new osg::Group; group->setName("texture transform group"); osg::StateSet* stateSet = group->getOrCreateStateSet(); + stateSet->setDataVariance(osg::Object::DYNAMIC); osg::TexMat* texMat = new osg::TexMat; UpdateCallback* updateCallback = new UpdateCallback(getCondition()); // interpret the configs ... @@ -1842,14 +1967,15 @@ void SGTexTransformAnimation::appendTexTranslate(const SGPropertyNode* config, UpdateCallback* updateCallback) { - std::string propertyName = config->getStringValue("property", "/null"); + std::string propertyName = config->getStringValue("property", ""); SGSharedPtr value; - if (getModelRoot()->hasChild(propertyName)) - value = new SGPropertyExpression(getModelRoot()->getNode(propertyName)); - else + if (propertyName.empty()) value = new SGConstExpression(0); + else { + SGPropertyNode* inputProperty = getModelRoot()->getNode(propertyName, true); + value = new SGPropertyExpression(inputProperty); + } - SGSharedPtr animationValue; SGInterpTable* table = read_interpolation_table(config); if (table) { value = new SGInterpTableExpression(value, table); @@ -1859,7 +1985,7 @@ SGTexTransformAnimation::appendTexTranslate(const SGPropertyNode* config, value = new SGStepExpression(value, config->getDoubleValue("step", 0), config->getDoubleValue("scroll", 0)); - animationValue = value->simplify(); + value = value->simplify(); } else { double biasValue = config->getDoubleValue("bias", 0); if (biasValue != 0) @@ -1867,14 +1993,14 @@ SGTexTransformAnimation::appendTexTranslate(const SGPropertyNode* config, value = new SGStepExpression(value, config->getDoubleValue("step", 0), config->getDoubleValue("scroll", 0)); - value = read_factor_offset(config, value, "factor", "offset"); + value = read_offset_factor(config, value, "factor", "offset"); if (config->hasChild("min") || config->hasChild("max")) { double minClip = config->getDoubleValue("min", -SGLimitsd::max()); double maxClip = config->getDoubleValue("max", SGLimitsd::max()); value = new SGClipExpression(value, minClip, maxClip); } - animationValue = value->simplify(); + value = value->simplify(); } SGVec3d axis(config->getDoubleValue("axis/x", 0), config->getDoubleValue("axis/y", 0), @@ -1882,21 +2008,22 @@ SGTexTransformAnimation::appendTexTranslate(const SGPropertyNode* config, Translation* translation; translation = new Translation(normalize(axis)); translation->setValue(config->getDoubleValue("starting-position", 0)); - updateCallback->appendTransform(translation, animationValue); + updateCallback->appendTransform(translation, value); } void SGTexTransformAnimation::appendTexRotate(const SGPropertyNode* config, UpdateCallback* updateCallback) { - std::string propertyName = config->getStringValue("property", "/null"); + std::string propertyName = config->getStringValue("property", ""); SGSharedPtr value; - if (getModelRoot()->hasChild(propertyName)) - value = new SGPropertyExpression(getModelRoot()->getNode(propertyName)); - else + if (propertyName.empty()) value = new SGConstExpression(0); + else { + SGPropertyNode* inputProperty = getModelRoot()->getNode(propertyName, true); + value = new SGPropertyExpression(inputProperty); + } - SGSharedPtr animationValue; SGInterpTable* table = read_interpolation_table(config); if (table) { value = new SGInterpTableExpression(value, table); @@ -1906,7 +2033,7 @@ SGTexTransformAnimation::appendTexRotate(const SGPropertyNode* config, value = new SGStepExpression(value, config->getDoubleValue("step", 0), config->getDoubleValue("scroll", 0)); - animationValue = value->simplify(); + value = value->simplify(); } else { double biasValue = config->getDoubleValue("bias", 0); if (biasValue != 0) @@ -1914,14 +2041,14 @@ SGTexTransformAnimation::appendTexRotate(const SGPropertyNode* config, value = new SGStepExpression(value, config->getDoubleValue("step", 0), config->getDoubleValue("scroll", 0)); - value = read_factor_offset(config, value, "factor", "offset-deg"); + value = read_offset_factor(config, value, "factor", "offset-deg"); if (config->hasChild("min-deg") || config->hasChild("max-deg")) { double minClip = config->getDoubleValue("min-deg", -SGLimitsd::max()); double maxClip = config->getDoubleValue("max-deg", SGLimitsd::max()); value = new SGClipExpression(value, minClip, maxClip); } - animationValue = value->simplify(); + value = value->simplify(); } SGVec3d axis(config->getDoubleValue("axis/x", 0), config->getDoubleValue("axis/y", 0), @@ -1932,7 +2059,7 @@ SGTexTransformAnimation::appendTexRotate(const SGPropertyNode* config, Rotation* rotation; rotation = new Rotation(normalize(axis), center); rotation->setValue(config->getDoubleValue("starting-position-deg", 0)); - updateCallback->appendTransform(rotation, animationValue); + updateCallback->appendTransform(rotation, value); } @@ -1944,12 +2071,16 @@ class SGPickAnimation::PickCallback : public SGPickCallback { public: PickCallback(const SGPropertyNode* configNode, SGPropertyNode* modelRoot) : - _button(configNode->getIntValue("button", -1)), _repeatable(configNode->getBoolValue("repeatable", false)), _repeatInterval(configNode->getDoubleValue("interval-sec", 0.1)) { SG_LOG(SG_INPUT, SG_DEBUG, "Reading all bindings"); std::vector bindings; + + bindings = configNode->getChildren("button"); + for (unsigned int i = 0; i < bindings.size(); ++i) { + _buttons.push_back( bindings[i]->getIntValue() ); + } bindings = configNode->getChildren("binding"); for (unsigned int i = 0; i < bindings.size(); ++i) { _bindingsDown.push_back(new SGBinding(bindings[i], modelRoot)); @@ -1965,12 +2096,19 @@ public: } virtual bool buttonPressed(int button, const Info&) { - if (0 <= _button && button != _button) + bool found = false; + for( std::vector::iterator it = _buttons.begin(); it != _buttons.end(); it++ ) { + if( *it == button ) { + found = true; + break; + } + } + if (!found ) return false; SGBindingList::const_iterator i; for (i = _bindingsDown.begin(); i != _bindingsDown.end(); ++i) (*i)->fire(); - _repeatTime = 0; + _repeatTime = -_repeatInterval; // anti-bobble: delay start of repeat return true; } virtual void buttonReleased(void) @@ -1995,7 +2133,7 @@ public: private: SGBindingList _bindingsDown; SGBindingList _bindingsUp; - int _button; + std::vector _buttons; bool _repeatable; double _repeatInterval; double _repeatTime; @@ -2014,14 +2152,16 @@ SGPickAnimation::createAnimationGroup(osg::Group& parent) // Contains the normal geometry that is interactive osg::ref_ptr normalGroup = new osg::Group; + normalGroup->setName("pick normal group"); normalGroup->addChild(commonGroup); // Used to render the geometry with just yellow edges osg::Group* highlightGroup = new osg::Group; + highlightGroup->setName("pick highlight group"); highlightGroup->setNodeMask(SG_NODEMASK_PICK_BIT); highlightGroup->addChild(commonGroup); SGSceneUserData* ud; - ud = SGSceneUserData::getOrCreateSceneUserData(highlightGroup); + ud = SGSceneUserData::getOrCreateSceneUserData(commonGroup); std::vector actions; actions = getConfig()->getChildren("action"); for (unsigned int i = 0; i < actions.size(); ++i)