00001
00002
00003
00004
00005
00006 #ifdef HAVE_CONFIG_H
00007 # include <simgear_config.h>
00008 #endif
00009
00010 #include <string.h>
00011 #include <math.h>
00012 #include <algorithm>
00013 #include <functional>
00014
00015 #include <OpenThreads/Mutex>
00016 #include <OpenThreads/ReentrantMutex>
00017 #include <OpenThreads/ScopedLock>
00018
00019 #include <osg/AlphaFunc>
00020 #include <osg/Drawable>
00021 #include <osg/Geode>
00022 #include <osg/Geometry>
00023 #include <osg/LOD>
00024 #include <osg/Math>
00025 #include <osg/PolygonMode>
00026 #include <osg/PolygonOffset>
00027 #include <osg/StateSet>
00028 #include <osg/Switch>
00029 #include <osg/TexMat>
00030 #include <osg/Texture2D>
00031 #include <osg/Transform>
00032 #include <osgDB/ReadFile>
00033 #include <osgDB/Registry>
00034 #include <osgDB/Input>
00035 #include <osgDB/ParameterOutput>
00036
00037
00038 #include <simgear/math/interpolater.hxx>
00039 #include <simgear/props/condition.hxx>
00040 #include <simgear/props/props.hxx>
00041 #include <simgear/structure/SGBinding.hxx>
00042 #include <simgear/scene/util/SGNodeMasks.hxx>
00043 #include <simgear/scene/util/SGSceneUserData.hxx>
00044 #include <simgear/scene/util/SGStateAttributeVisitor.hxx>
00045
00046 #include "animation.hxx"
00047 #include "model.hxx"
00048
00049 #include "SGTranslateTransform.hxx"
00050 #include "SGMaterialAnimation.hxx"
00051 #include "SGRotateTransform.hxx"
00052 #include "SGScaleTransform.hxx"
00053 #include "SGInteractionAnimation.hxx"
00054
00055 using OpenThreads::Mutex;
00056 using OpenThreads::ReentrantMutex;
00057 using OpenThreads::ScopedLock;
00058
00059
00061
00063
00067 static void
00068 set_rotation (osg::Matrix &matrix, double position_deg,
00069 const SGVec3d ¢er, const SGVec3d &axis)
00070 {
00071 double temp_angle = -SGMiscd::deg2rad(position_deg);
00072
00073 double s = sin(temp_angle);
00074 double c = cos(temp_angle);
00075 double t = 1 - c;
00076
00077
00078
00079 double x = axis[0];
00080 double y = axis[1];
00081 double z = axis[2];
00082
00083 matrix(0, 0) = t * x * x + c ;
00084 matrix(0, 1) = t * y * x - s * z ;
00085 matrix(0, 2) = t * z * x + s * y ;
00086 matrix(0, 3) = 0;
00087
00088 matrix(1, 0) = t * x * y + s * z ;
00089 matrix(1, 1) = t * y * y + c ;
00090 matrix(1, 2) = t * z * y - s * x ;
00091 matrix(1, 3) = 0;
00092
00093 matrix(2, 0) = t * x * z - s * y ;
00094 matrix(2, 1) = t * y * z + s * x ;
00095 matrix(2, 2) = t * z * z + c ;
00096 matrix(2, 3) = 0;
00097
00098
00099 x = center[0];
00100 y = center[1];
00101 z = center[2];
00102
00103 matrix(3, 0) = x - x*matrix(0, 0) - y*matrix(1, 0) - z*matrix(2, 0);
00104 matrix(3, 1) = y - x*matrix(0, 1) - y*matrix(1, 1) - z*matrix(2, 1);
00105 matrix(3, 2) = z - x*matrix(0, 2) - y*matrix(1, 2) - z*matrix(2, 2);
00106 matrix(3, 3) = 1;
00107 }
00108
00112 static void
00113 set_translation (osg::Matrix &matrix, double position_m, const SGVec3d &axis)
00114 {
00115 SGVec3d xyz = axis * position_m;
00116 matrix.makeIdentity();
00117 matrix(3, 0) = xyz[0];
00118 matrix(3, 1) = xyz[1];
00119 matrix(3, 2) = xyz[2];
00120 }
00121
00125 static SGInterpTable *
00126 read_interpolation_table(const SGPropertyNode* props)
00127 {
00128 const SGPropertyNode* table_node = props->getNode("interpolation");
00129 if (!table_node)
00130 return 0;
00131 return new SGInterpTable(table_node);
00132 }
00133
00134 static std::string
00135 unit_string(const char* value, const char* unit)
00136 {
00137 return std::string(value) + unit;
00138 }
00139
00140 class SGPersonalityScaleOffsetExpression : public SGUnaryExpression<double> {
00141 public:
00142 SGPersonalityScaleOffsetExpression(SGExpression<double>* expr,
00143 SGPropertyNode const* config,
00144 const std::string& scalename,
00145 const std::string& offsetname,
00146 double defScale = 1,
00147 double defOffset = 0) :
00148 SGUnaryExpression<double>(expr),
00149 _scale(config, scalename.c_str(), defScale),
00150 _offset(config, offsetname.c_str(), defOffset)
00151 { }
00152 void setScale(double scale)
00153 { _scale = scale; }
00154 void setOffset(double offset)
00155 { _offset = offset; }
00156
00157 virtual void eval(double& value, const simgear::expression::Binding* b) const
00158 {
00159 _offset.shuffle();
00160 _scale.shuffle();
00161 value = _offset + _scale*getOperand()->getValue(b);
00162 }
00163
00164 virtual bool isConst() const { return false; }
00165
00166 private:
00167 mutable SGPersonalityParameter<double> _scale;
00168 mutable SGPersonalityParameter<double> _offset;
00169 };
00170
00171
00172 static SGExpressiond*
00173 read_factor_offset(const SGPropertyNode* configNode, SGExpressiond* expr,
00174 const std::string& factor, const std::string& offset)
00175 {
00176 double factorValue = configNode->getDoubleValue(factor, 1);
00177 if (factorValue != 1)
00178 expr = new SGScaleExpression<double>(expr, factorValue);
00179 double offsetValue = configNode->getDoubleValue(offset, 0);
00180 if (offsetValue != 0)
00181 expr = new SGBiasExpression<double>(expr, offsetValue);
00182 return expr;
00183 }
00184
00185 static SGExpressiond*
00186 read_offset_factor(const SGPropertyNode* configNode, SGExpressiond* expr,
00187 const std::string& factor, const std::string& offset)
00188 {
00189 double offsetValue = configNode->getDoubleValue(offset, 0);
00190 if (offsetValue != 0)
00191 expr = new SGBiasExpression<double>(expr, offsetValue);
00192 double factorValue = configNode->getDoubleValue(factor, 1);
00193 if (factorValue != 1)
00194 expr = new SGScaleExpression<double>(expr, factorValue);
00195 return expr;
00196 }
00197
00198 SGExpressiond*
00199 read_value(const SGPropertyNode* configNode, SGPropertyNode* modelRoot,
00200 const char* unit, double defMin, double defMax)
00201 {
00202 SGExpression<double>* value = 0;
00203
00204 std::string inputPropertyName = configNode->getStringValue("property", "");
00205 if (inputPropertyName.empty()) {
00206 std::string spos = unit_string("starting-position", unit);
00207 double initPos = configNode->getDoubleValue(spos, 0);
00208 value = new SGConstExpression<double>(initPos);
00209 } else {
00210 SGPropertyNode* inputProperty;
00211 inputProperty = modelRoot->getNode(inputPropertyName, true);
00212 value = new SGPropertyExpression<double>(inputProperty);
00213 }
00214
00215 SGInterpTable* interpTable = read_interpolation_table(configNode);
00216 if (interpTable) {
00217 return new SGInterpTableExpression<double>(value, interpTable);
00218 } else {
00219 std::string offset = unit_string("offset", unit);
00220 std::string min = unit_string("min", unit);
00221 std::string max = unit_string("max", unit);
00222
00223 if (configNode->getBoolValue("use-personality", false)) {
00224 value = new SGPersonalityScaleOffsetExpression(value, configNode,
00225 "factor", offset);
00226 } else {
00227 value = read_factor_offset(configNode, value, "factor", offset);
00228 }
00229
00230 double minClip = configNode->getDoubleValue(min, defMin);
00231 double maxClip = configNode->getDoubleValue(max, defMax);
00232 if (minClip > SGMiscd::min(SGLimitsd::min(), -SGLimitsd::max()) ||
00233 maxClip < SGLimitsd::max())
00234 value = new SGClipExpression<double>(value, minClip, maxClip);
00235
00236 return value;
00237 }
00238 return 0;
00239 }
00240
00241
00243
00245
00246 class SGAnimation::RemoveModeVisitor : public SGStateAttributeVisitor {
00247 public:
00248 RemoveModeVisitor(osg::StateAttribute::GLMode mode) :
00249 _mode(mode)
00250 { }
00251 virtual void apply(osg::StateSet* stateSet)
00252 {
00253 if (!stateSet)
00254 return;
00255 stateSet->removeMode(_mode);
00256 }
00257 private:
00258 osg::StateAttribute::GLMode _mode;
00259 };
00260
00261 class SGAnimation::RemoveAttributeVisitor : public SGStateAttributeVisitor {
00262 public:
00263 RemoveAttributeVisitor(osg::StateAttribute::Type type) :
00264 _type(type)
00265 { }
00266 virtual void apply(osg::StateSet* stateSet)
00267 {
00268 if (!stateSet)
00269 return;
00270 while (stateSet->getAttribute(_type)) {
00271 stateSet->removeAttribute(_type);
00272 }
00273 }
00274 private:
00275 osg::StateAttribute::Type _type;
00276 };
00277
00278 class SGAnimation::RemoveTextureModeVisitor : public SGStateAttributeVisitor {
00279 public:
00280 RemoveTextureModeVisitor(unsigned unit, osg::StateAttribute::GLMode mode) :
00281 _unit(unit),
00282 _mode(mode)
00283 { }
00284 virtual void apply(osg::StateSet* stateSet)
00285 {
00286 if (!stateSet)
00287 return;
00288 stateSet->removeTextureMode(_unit, _mode);
00289 }
00290 private:
00291 unsigned _unit;
00292 osg::StateAttribute::GLMode _mode;
00293 };
00294
00295 class SGAnimation::RemoveTextureAttributeVisitor :
00296 public SGStateAttributeVisitor {
00297 public:
00298 RemoveTextureAttributeVisitor(unsigned unit,
00299 osg::StateAttribute::Type type) :
00300 _unit(unit),
00301 _type(type)
00302 { }
00303 virtual void apply(osg::StateSet* stateSet)
00304 {
00305 if (!stateSet)
00306 return;
00307 while (stateSet->getTextureAttribute(_unit, _type)) {
00308 stateSet->removeTextureAttribute(_unit, _type);
00309 }
00310 }
00311 private:
00312 unsigned _unit;
00313 osg::StateAttribute::Type _type;
00314 };
00315
00316 class SGAnimation::BinToInheritVisitor : public SGStateAttributeVisitor {
00317 public:
00318 virtual void apply(osg::StateSet* stateSet)
00319 {
00320 if (!stateSet)
00321 return;
00322 stateSet->setRenderBinToInherit();
00323 }
00324 };
00325
00326 class SGAnimation::DrawableCloneVisitor : public osg::NodeVisitor {
00327 public:
00328 DrawableCloneVisitor() :
00329 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
00330 {}
00331 void apply(osg::Geode& geode)
00332 {
00333 for (unsigned i = 0 ; i < geode.getNumDrawables(); ++i) {
00334 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_ALL &
00335 ~osg::CopyOp::DEEP_COPY_TEXTURES);
00336 geode.setDrawable(i, copyOp(geode.getDrawable(i)));
00337 }
00338 }
00339 };
00340
00341 namespace
00342 {
00343
00344
00345 struct DoDrawArraysVisitor : public osg::NodeVisitor {
00346 DoDrawArraysVisitor() :
00347 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
00348 {}
00349 void apply(osg::Geode& geode)
00350 {
00351 using namespace osg;
00352 using namespace std;
00353
00354 for (int i = 0; i < (int)geode.getNumDrawables(); ++i)
00355 geode.getDrawable(i)->setUseDisplayList(false);
00356 }
00357 };
00358 }
00359
00360 SGAnimation::SGAnimation(const SGPropertyNode* configNode,
00361 SGPropertyNode* modelRoot) :
00362 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
00363 _found(false),
00364 _configNode(configNode),
00365 _modelRoot(modelRoot)
00366 {
00367 _name = configNode->getStringValue("name", "");
00368 _enableHOT = configNode->getBoolValue("enable-hot", true);
00369 _disableShadow = configNode->getBoolValue("disable-shadow", false);
00370 std::vector<SGPropertyNode_ptr> objectNames =
00371 configNode->getChildren("object-name");
00372 for (unsigned i = 0; i < objectNames.size(); ++i)
00373 _objectNames.push_back(objectNames[i]->getStringValue());
00374 }
00375
00376 SGAnimation::~SGAnimation()
00377 {
00378 if (_found)
00379 return;
00380
00381 SG_LOG(SG_IO, SG_ALERT, "Could not find at least one of the following"
00382 " objects for animation:\n");
00383 std::list<std::string>::const_iterator i;
00384 for (i = _objectNames.begin(); i != _objectNames.end(); ++i)
00385 SG_LOG(SG_IO, SG_ALERT, *i << "\n");
00386 }
00387
00388 bool
00389 SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode,
00390 SGPropertyNode* modelRoot,
00391 const osgDB::ReaderWriter::Options* options)
00392 {
00393 std::string type = configNode->getStringValue("type", "none");
00394 if (type == "alpha-test") {
00395 SGAlphaTestAnimation animInst(configNode, modelRoot);
00396 animInst.apply(node);
00397 } else if (type == "billboard") {
00398 SGBillboardAnimation animInst(configNode, modelRoot);
00399 animInst.apply(node);
00400 } else if (type == "blend") {
00401 SGBlendAnimation animInst(configNode, modelRoot);
00402 animInst.apply(node);
00403 } else if (type == "dist-scale") {
00404 SGDistScaleAnimation animInst(configNode, modelRoot);
00405 animInst.apply(node);
00406 } else if (type == "flash") {
00407 SGFlashAnimation animInst(configNode, modelRoot);
00408 animInst.apply(node);
00409 } else if (type == "interaction") {
00410 SGInteractionAnimation animInst(configNode, modelRoot);
00411 animInst.apply(node);
00412 } else if (type == "material") {
00413 SGMaterialAnimation animInst(configNode, modelRoot, options);
00414 animInst.apply(node);
00415 } else if (type == "noshadow") {
00416 SGShadowAnimation animInst(configNode, modelRoot);
00417 animInst.apply(node);
00418 } else if (type == "pick") {
00419 SGPickAnimation animInst(configNode, modelRoot);
00420 animInst.apply(node);
00421 } else if (type == "range") {
00422 SGRangeAnimation animInst(configNode, modelRoot);
00423 animInst.apply(node);
00424 } else if (type == "rotate" || type == "spin") {
00425 SGRotateAnimation animInst(configNode, modelRoot);
00426 animInst.apply(node);
00427 } else if (type == "scale") {
00428 SGScaleAnimation animInst(configNode, modelRoot);
00429 animInst.apply(node);
00430 } else if (type == "select") {
00431 SGSelectAnimation animInst(configNode, modelRoot);
00432 animInst.apply(node);
00433 } else if (type == "shader") {
00434 SGShaderAnimation animInst(configNode, modelRoot, options);
00435 animInst.apply(node);
00436 } else if (type == "textranslate" || type == "texrotate" ||
00437 type == "texmultiple") {
00438 SGTexTransformAnimation animInst(configNode, modelRoot);
00439 animInst.apply(node);
00440 } else if (type == "timed") {
00441 SGTimedAnimation animInst(configNode, modelRoot);
00442 animInst.apply(node);
00443 } else if (type == "translate") {
00444 SGTranslateAnimation animInst(configNode, modelRoot);
00445 animInst.apply(node);
00446 } else if (type == "null" || type == "none" || type.empty()) {
00447 SGGroupAnimation animInst(configNode, modelRoot);
00448 animInst.apply(node);
00449 } else
00450 return false;
00451
00452 return true;
00453 }
00454
00455
00456 void
00457 SGAnimation::apply(osg::Node* node)
00458 {
00459
00460 if (_objectNames.empty()) {
00461 osg::Group* group = node->asGroup();
00462 if (group) {
00463 osg::ref_ptr<osg::Group> animationGroup;
00464 installInGroup(std::string(), *group, animationGroup);
00465 }
00466 } else
00467 node->accept(*this);
00468 }
00469
00470 void
00471 SGAnimation::install(osg::Node& node)
00472 {
00473 _found = true;
00474 if (_enableHOT)
00475 node.setNodeMask( SG_NODEMASK_TERRAIN_BIT | node.getNodeMask());
00476 else
00477 node.setNodeMask(~SG_NODEMASK_TERRAIN_BIT & node.getNodeMask());
00478 if (!_disableShadow)
00479 node.setNodeMask( SG_NODEMASK_CASTSHADOW_BIT | node.getNodeMask());
00480 else
00481 node.setNodeMask(~SG_NODEMASK_CASTSHADOW_BIT & node.getNodeMask());
00482 }
00483
00484 osg::Group*
00485 SGAnimation::createAnimationGroup(osg::Group& parent)
00486 {
00487
00488
00489
00490 return 0;
00491 }
00492
00493 void
00494 SGAnimation::apply(osg::Group& group)
00495 {
00496
00497
00498
00499
00500 traverse(group);
00501
00502
00503
00504
00505 osg::ref_ptr<osg::Group> animationGroup;
00506 std::list<std::string>::const_iterator nameIt;
00507 for (nameIt = _objectNames.begin(); nameIt != _objectNames.end(); ++nameIt)
00508 installInGroup(*nameIt, group, animationGroup);
00509 }
00510
00511 void
00512 SGAnimation::installInGroup(const std::string& name, osg::Group& group,
00513 osg::ref_ptr<osg::Group>& animationGroup)
00514 {
00515 int i = group.getNumChildren() - 1;
00516 for (; 0 <= i; --i) {
00517 osg::Node* child = group.getChild(i);
00518
00519
00520 if (std::find(_installedAnimations.begin(),
00521 _installedAnimations.end(), child)
00522 != _installedAnimations.end())
00523 continue;
00524
00525 if (name.empty() || child->getName() == name) {
00526
00527 install(*child);
00528
00529
00530 if (!animationGroup.valid()) {
00531 animationGroup = createAnimationGroup(group);
00532
00533
00534 if (animationGroup.valid() && !_name.empty())
00535 animationGroup->setName(_name);
00536 }
00537 if (animationGroup.valid()) {
00538 animationGroup->addChild(child);
00539 group.removeChild(i);
00540 }
00541
00542
00543
00544
00545 _installedAnimations.push_back(child);
00546 }
00547 }
00548 }
00549
00550 void
00551 SGAnimation::removeMode(osg::Node& node, osg::StateAttribute::GLMode mode)
00552 {
00553 RemoveModeVisitor visitor(mode);
00554 node.accept(visitor);
00555 }
00556
00557 void
00558 SGAnimation::removeAttribute(osg::Node& node, osg::StateAttribute::Type type)
00559 {
00560 RemoveAttributeVisitor visitor(type);
00561 node.accept(visitor);
00562 }
00563
00564 void
00565 SGAnimation::removeTextureMode(osg::Node& node, unsigned unit,
00566 osg::StateAttribute::GLMode mode)
00567 {
00568 RemoveTextureModeVisitor visitor(unit, mode);
00569 node.accept(visitor);
00570 }
00571
00572 void
00573 SGAnimation::removeTextureAttribute(osg::Node& node, unsigned unit,
00574 osg::StateAttribute::Type type)
00575 {
00576 RemoveTextureAttributeVisitor visitor(unit, type);
00577 node.accept(visitor);
00578 }
00579
00580 void
00581 SGAnimation::setRenderBinToInherit(osg::Node& node)
00582 {
00583 BinToInheritVisitor visitor;
00584 node.accept(visitor);
00585 }
00586
00587 void
00588 SGAnimation::cloneDrawables(osg::Node& node)
00589 {
00590 DrawableCloneVisitor visitor;
00591 node.accept(visitor);
00592 }
00593
00594 const SGCondition*
00595 SGAnimation::getCondition() const
00596 {
00597 const SGPropertyNode* conditionNode = _configNode->getChild("condition");
00598 if (!conditionNode)
00599 return 0;
00600 return sgReadCondition(_modelRoot, conditionNode);
00601 }
00602
00603
00604
00606
00608
00609
00610
00611
00612 SGGroupAnimation::SGGroupAnimation(const SGPropertyNode* configNode,
00613 SGPropertyNode* modelRoot):
00614 SGAnimation(configNode, modelRoot)
00615 {
00616 }
00617
00618 osg::Group*
00619 SGGroupAnimation::createAnimationGroup(osg::Group& parent)
00620 {
00621 osg::Group* group = new osg::Group;
00622 parent.addChild(group);
00623 return group;
00624 }
00625
00626
00628
00630
00631 class SGTranslateAnimation::UpdateCallback : public osg::NodeCallback {
00632 public:
00633 UpdateCallback(SGCondition const* condition,
00634 SGExpressiond const* animationValue) :
00635 _condition(condition),
00636 _animationValue(animationValue)
00637 { }
00638 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
00639 {
00640 if (!_condition || _condition->test()) {
00641 SGTranslateTransform* transform;
00642 transform = static_cast<SGTranslateTransform*>(node);
00643 transform->setValue(_animationValue->getValue());
00644 }
00645 traverse(node, nv);
00646 }
00647 public:
00648 SGSharedPtr<SGCondition const> _condition;
00649 SGSharedPtr<SGExpressiond const> _animationValue;
00650 };
00651
00652 SGTranslateAnimation::SGTranslateAnimation(const SGPropertyNode* configNode,
00653 SGPropertyNode* modelRoot) :
00654 SGAnimation(configNode, modelRoot)
00655 {
00656 _condition = getCondition();
00657 SGSharedPtr<SGExpressiond> value;
00658 value = read_value(configNode, modelRoot, "-m",
00659 -SGLimitsd::max(), SGLimitsd::max());
00660 _animationValue = value->simplify();
00661 if (_animationValue)
00662 _initialValue = _animationValue->getValue();
00663 else
00664 _initialValue = 0;
00665
00666 if (configNode->hasValue("axis/x1-m")) {
00667 SGVec3d v1, v2;
00668 v1[0] = configNode->getDoubleValue("axis/x1-m", 0);
00669 v1[1] = configNode->getDoubleValue("axis/y1-m", 0);
00670 v1[2] = configNode->getDoubleValue("axis/z1-m", 0);
00671 v2[0] = configNode->getDoubleValue("axis/x2-m", 0);
00672 v2[1] = configNode->getDoubleValue("axis/y2-m", 0);
00673 v2[2] = configNode->getDoubleValue("axis/z2-m", 0);
00674 _axis = v2 - v1;
00675 } else {
00676 _axis[0] = configNode->getDoubleValue("axis/x", 0);
00677 _axis[1] = configNode->getDoubleValue("axis/y", 0);
00678 _axis[2] = configNode->getDoubleValue("axis/z", 0);
00679 }
00680 if (8*SGLimitsd::min() < norm(_axis))
00681 _axis = normalize(_axis);
00682 }
00683
00684 osg::Group*
00685 SGTranslateAnimation::createAnimationGroup(osg::Group& parent)
00686 {
00687 SGTranslateTransform* transform = new SGTranslateTransform;
00688 transform->setName("translate animation");
00689 if (_animationValue && !_animationValue->isConst()) {
00690 UpdateCallback* uc = new UpdateCallback(_condition, _animationValue);
00691 transform->setUpdateCallback(uc);
00692 }
00693 transform->setAxis(_axis);
00694 transform->setValue(_initialValue);
00695 parent.addChild(transform);
00696 return transform;
00697 }
00698
00699
00701
00703
00704 class SGRotateAnimation::UpdateCallback : public osg::NodeCallback {
00705 public:
00706 UpdateCallback(SGCondition const* condition,
00707 SGExpressiond const* animationValue) :
00708 _condition(condition),
00709 _animationValue(animationValue)
00710 { }
00711 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
00712 {
00713 if (!_condition || _condition->test()) {
00714 SGRotateTransform* transform;
00715 transform = static_cast<SGRotateTransform*>(node);
00716 transform->setAngleDeg(_animationValue->getValue());
00717 }
00718 traverse(node, nv);
00719 }
00720 public:
00721 SGSharedPtr<SGCondition const> _condition;
00722 SGSharedPtr<SGExpressiond const> _animationValue;
00723 };
00724
00725 class SGRotateAnimation::SpinUpdateCallback : public osg::NodeCallback {
00726 public:
00727 SpinUpdateCallback(SGCondition const* condition,
00728 SGExpressiond const* animationValue) :
00729 _condition(condition),
00730 _animationValue(animationValue),
00731 _lastTime(-1)
00732 { }
00733 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
00734 {
00735 if (!_condition || _condition->test()) {
00736 SGRotateTransform* transform;
00737 transform = static_cast<SGRotateTransform*>(node);
00738
00739 double t = nv->getFrameStamp()->getReferenceTime();
00740 double dt = 0;
00741 if (0 <= _lastTime)
00742 dt = t - _lastTime;
00743 _lastTime = t;
00744 double velocity_rpms = _animationValue->getValue()/60;
00745 double angle = transform->getAngleDeg();
00746 angle += dt*velocity_rpms*360;
00747 angle -= 360*floor(angle/360);
00748 transform->setAngleDeg(angle);
00749 }
00750 traverse(node, nv);
00751 }
00752 public:
00753 SGSharedPtr<SGCondition const> _condition;
00754 SGSharedPtr<SGExpressiond const> _animationValue;
00755 double _lastTime;
00756 };
00757
00758 SGRotateAnimation::SGRotateAnimation(const SGPropertyNode* configNode,
00759 SGPropertyNode* modelRoot) :
00760 SGAnimation(configNode, modelRoot)
00761 {
00762 std::string type = configNode->getStringValue("type", "");
00763 _isSpin = (type == "spin");
00764
00765 _condition = getCondition();
00766 SGSharedPtr<SGExpressiond> value;
00767 value = read_value(configNode, modelRoot, "-deg",
00768 -SGLimitsd::max(), SGLimitsd::max());
00769 _animationValue = value->simplify();
00770 if (_animationValue)
00771 _initialValue = _animationValue->getValue();
00772 else
00773 _initialValue = 0;
00774
00775 _center = SGVec3d::zeros();
00776 if (configNode->hasValue("axis/x1-m")) {
00777 SGVec3d v1, v2;
00778 v1[0] = configNode->getDoubleValue("axis/x1-m", 0);
00779 v1[1] = configNode->getDoubleValue("axis/y1-m", 0);
00780 v1[2] = configNode->getDoubleValue("axis/z1-m", 0);
00781 v2[0] = configNode->getDoubleValue("axis/x2-m", 0);
00782 v2[1] = configNode->getDoubleValue("axis/y2-m", 0);
00783 v2[2] = configNode->getDoubleValue("axis/z2-m", 0);
00784 _center = 0.5*(v1+v2);
00785 _axis = v2 - v1;
00786 } else {
00787 _axis[0] = configNode->getDoubleValue("axis/x", 0);
00788 _axis[1] = configNode->getDoubleValue("axis/y", 0);
00789 _axis[2] = configNode->getDoubleValue("axis/z", 0);
00790 }
00791 if (8*SGLimitsd::min() < norm(_axis))
00792 _axis = normalize(_axis);
00793
00794 _center[0] = configNode->getDoubleValue("center/x-m", _center[0]);
00795 _center[1] = configNode->getDoubleValue("center/y-m", _center[1]);
00796 _center[2] = configNode->getDoubleValue("center/z-m", _center[2]);
00797 }
00798
00799 osg::Group*
00800 SGRotateAnimation::createAnimationGroup(osg::Group& parent)
00801 {
00802 SGRotateTransform* transform = new SGRotateTransform;
00803 transform->setName("rotate animation");
00804 if (_isSpin) {
00805 SpinUpdateCallback* uc;
00806 uc = new SpinUpdateCallback(_condition, _animationValue);
00807 transform->setUpdateCallback(uc);
00808 } else if (_animationValue || !_animationValue->isConst()) {
00809 UpdateCallback* uc = new UpdateCallback(_condition, _animationValue);
00810 transform->setUpdateCallback(uc);
00811 }
00812 transform->setCenter(_center);
00813 transform->setAxis(_axis);
00814 transform->setAngleDeg(_initialValue);
00815 parent.addChild(transform);
00816 return transform;
00817 }
00818
00819
00821
00823
00824 class SGScaleAnimation::UpdateCallback : public osg::NodeCallback {
00825 public:
00826 UpdateCallback(const SGCondition* condition,
00827 SGSharedPtr<const SGExpressiond> animationValue[3]) :
00828 _condition(condition)
00829 {
00830 _animationValue[0] = animationValue[0];
00831 _animationValue[1] = animationValue[1];
00832 _animationValue[2] = animationValue[2];
00833 }
00834 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
00835 {
00836 if (!_condition || _condition->test()) {
00837 SGScaleTransform* transform;
00838 transform = static_cast<SGScaleTransform*>(node);
00839 SGVec3d scale(_animationValue[0]->getValue(),
00840 _animationValue[1]->getValue(),
00841 _animationValue[2]->getValue());
00842 transform->setScaleFactor(scale);
00843 }
00844 traverse(node, nv);
00845 }
00846 public:
00847 SGSharedPtr<SGCondition const> _condition;
00848 SGSharedPtr<SGExpressiond const> _animationValue[3];
00849 };
00850
00851 SGScaleAnimation::SGScaleAnimation(const SGPropertyNode* configNode,
00852 SGPropertyNode* modelRoot) :
00853 SGAnimation(configNode, modelRoot)
00854 {
00855 _condition = getCondition();
00856
00857
00858 double offset = configNode->getDoubleValue("offset", 0);
00859 double factor = configNode->getDoubleValue("factor", 1);
00860
00861 SGSharedPtr<SGExpressiond> inPropExpr;
00862
00863 std::string inputPropertyName;
00864 inputPropertyName = configNode->getStringValue("property", "");
00865 if (inputPropertyName.empty()) {
00866 inPropExpr = new SGConstExpression<double>(0);
00867 } else {
00868 SGPropertyNode* inputProperty;
00869 inputProperty = modelRoot->getNode(inputPropertyName, true);
00870 inPropExpr = new SGPropertyExpression<double>(inputProperty);
00871 }
00872
00873 SGInterpTable* interpTable = read_interpolation_table(configNode);
00874 if (interpTable) {
00875 SGSharedPtr<SGExpressiond> value;
00876 value = new SGInterpTableExpression<double>(inPropExpr, interpTable);
00877 _animationValue[0] = value->simplify();
00878 _animationValue[1] = value->simplify();
00879 _animationValue[2] = value->simplify();
00880 } else if (configNode->getBoolValue("use-personality", false)) {
00881 SGSharedPtr<SGExpressiond> value;
00882 value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
00883 "x-factor", "x-offset",
00884 factor, offset);
00885 double minClip = configNode->getDoubleValue("x-min", 0);
00886 double maxClip = configNode->getDoubleValue("x-max", SGLimitsd::max());
00887 value = new SGClipExpression<double>(value, minClip, maxClip);
00888 _animationValue[0] = value->simplify();
00889
00890 value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
00891 "y-factor", "y-offset",
00892 factor, offset);
00893 minClip = configNode->getDoubleValue("y-min", 0);
00894 maxClip = configNode->getDoubleValue("y-max", SGLimitsd::max());
00895 value = new SGClipExpression<double>(value, minClip, maxClip);
00896 _animationValue[1] = value->simplify();
00897
00898 value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
00899 "z-factor", "z-offset",
00900 factor, offset);
00901 minClip = configNode->getDoubleValue("z-min", 0);
00902 maxClip = configNode->getDoubleValue("z-max", SGLimitsd::max());
00903 value = new SGClipExpression<double>(value, minClip, maxClip);
00904 _animationValue[2] = value->simplify();
00905 } else {
00906 SGSharedPtr<SGExpressiond> value;
00907 value = read_factor_offset(configNode, inPropExpr, "x-factor", "x-offset");
00908 double minClip = configNode->getDoubleValue("x-min", 0);
00909 double maxClip = configNode->getDoubleValue("x-max", SGLimitsd::max());
00910 value = new SGClipExpression<double>(value, minClip, maxClip);
00911 _animationValue[0] = value->simplify();
00912
00913 value = read_factor_offset(configNode, inPropExpr, "y-factor", "y-offset");
00914 minClip = configNode->getDoubleValue("y-min", 0);
00915 maxClip = configNode->getDoubleValue("y-max", SGLimitsd::max());
00916 value = new SGClipExpression<double>(value, minClip, maxClip);
00917 _animationValue[1] = value->simplify();
00918
00919 value = read_factor_offset(configNode, inPropExpr, "z-factor", "z-offset");
00920 minClip = configNode->getDoubleValue("z-min", 0);
00921 maxClip = configNode->getDoubleValue("z-max", SGLimitsd::max());
00922 value = new SGClipExpression<double>(value, minClip, maxClip);
00923 _animationValue[2] = value->simplify();
00924 }
00925 _initialValue[0] = configNode->getDoubleValue("x-starting-scale", 1);
00926 _initialValue[0] *= configNode->getDoubleValue("x-factor", factor);
00927 _initialValue[0] += configNode->getDoubleValue("x-offset", offset);
00928 _initialValue[1] = configNode->getDoubleValue("y-starting-scale", 1);
00929 _initialValue[1] *= configNode->getDoubleValue("y-factor", factor);
00930 _initialValue[1] += configNode->getDoubleValue("y-offset", offset);
00931 _initialValue[2] = configNode->getDoubleValue("z-starting-scale", 1);
00932 _initialValue[2] *= configNode->getDoubleValue("z-factor", factor);
00933 _initialValue[2] += configNode->getDoubleValue("z-offset", offset);
00934 _center[0] = configNode->getDoubleValue("center/x-m", 0);
00935 _center[1] = configNode->getDoubleValue("center/y-m", 0);
00936 _center[2] = configNode->getDoubleValue("center/z-m", 0);
00937 }
00938
00939 osg::Group*
00940 SGScaleAnimation::createAnimationGroup(osg::Group& parent)
00941 {
00942 SGScaleTransform* transform = new SGScaleTransform;
00943 transform->setName("scale animation");
00944 transform->setCenter(_center);
00945 transform->setScaleFactor(_initialValue);
00946 UpdateCallback* uc = new UpdateCallback(_condition, _animationValue);
00947 transform->setUpdateCallback(uc);
00948 parent.addChild(transform);
00949 return transform;
00950 }
00951
00952
00953
00954
00955 namespace
00956 {
00957 Mutex normalizeMutex;
00958
00959 osg::StateSet* getNormalizeStateSet()
00960 {
00961 static osg::ref_ptr<osg::StateSet> normalizeStateSet;
00962 ScopedLock<Mutex> lock(normalizeMutex);
00963 if (!normalizeStateSet.valid()) {
00964 normalizeStateSet = new osg::StateSet;
00965 normalizeStateSet->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
00966 normalizeStateSet->setDataVariance(osg::Object::STATIC);
00967 }
00968 return normalizeStateSet.get();
00969 }
00970 }
00971
00973
00975
00976 class SGDistScaleAnimation::Transform : public osg::Transform {
00977 public:
00978 Transform() : _min_v(0.0), _max_v(0.0), _factor(0.0), _offset(0.0) {}
00979 Transform(const Transform& rhs,
00980 const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
00981 : osg::Transform(rhs, copyOp), _table(rhs._table), _center(rhs._center),
00982 _min_v(rhs._min_v), _max_v(rhs._max_v), _factor(rhs._factor),
00983 _offset(rhs._offset)
00984 {
00985 }
00986 META_Node(simgear, SGDistScaleAnimation::Transform);
00987 Transform(const SGPropertyNode* configNode)
00988 {
00989 setName(configNode->getStringValue("name", "dist scale animation"));
00990 setReferenceFrame(RELATIVE_RF);
00991 setStateSet(getNormalizeStateSet());
00992 _factor = configNode->getFloatValue("factor", 1);
00993 _offset = configNode->getFloatValue("offset", 0);
00994 _min_v = configNode->getFloatValue("min", SGLimitsf::epsilon());
00995 _max_v = configNode->getFloatValue("max", SGLimitsf::max());
00996 _table = read_interpolation_table(configNode);
00997 _center[0] = configNode->getFloatValue("center/x-m", 0);
00998 _center[1] = configNode->getFloatValue("center/y-m", 0);
00999 _center[2] = configNode->getFloatValue("center/z-m", 0);
01000 }
01001 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
01002 osg::NodeVisitor* nv) const
01003 {
01004 osg::Matrix transform;
01005 double scale_factor = computeScaleFactor(nv);
01006 transform(0,0) = scale_factor;
01007 transform(1,1) = scale_factor;
01008 transform(2,2) = scale_factor;
01009 transform(3,0) = _center[0]*(1 - scale_factor);
01010 transform(3,1) = _center[1]*(1 - scale_factor);
01011 transform(3,2) = _center[2]*(1 - scale_factor);
01012 matrix.preMult(transform);
01013 return true;
01014 }
01015
01016 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
01017 osg::NodeVisitor* nv) const
01018 {
01019 double scale_factor = computeScaleFactor(nv);
01020 if (fabs(scale_factor) <= SGLimits<double>::min())
01021 return false;
01022 osg::Matrix transform;
01023 double rScaleFactor = 1/scale_factor;
01024 transform(0,0) = rScaleFactor;
01025 transform(1,1) = rScaleFactor;
01026 transform(2,2) = rScaleFactor;
01027 transform(3,0) = _center[0]*(1 - rScaleFactor);
01028 transform(3,1) = _center[1]*(1 - rScaleFactor);
01029 transform(3,2) = _center[2]*(1 - rScaleFactor);
01030 matrix.postMult(transform);
01031 return true;
01032 }
01033
01034 static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw)
01035 {
01036 const Transform& trans = static_cast<const Transform&>(obj);
01037 fw.indent() << "center " << trans._center << "\n";
01038 fw.indent() << "min_v " << trans._min_v << "\n";
01039 fw.indent() << "max_v " << trans._max_v << "\n";
01040 fw.indent() << "factor " << trans._factor << "\n";
01041 fw.indent() << "offset " << trans._offset << "\n";
01042 return true;
01043 }
01044 private:
01045 double computeScaleFactor(osg::NodeVisitor* nv) const
01046 {
01047 if (!nv)
01048 return 1;
01049
01050 double scale_factor = (toOsg(_center) - nv->getEyePoint()).length();
01051 if (_table == 0) {
01052 scale_factor = _factor * scale_factor + _offset;
01053 } else {
01054 scale_factor = _table->interpolate( scale_factor );
01055 }
01056 if (scale_factor < _min_v)
01057 scale_factor = _min_v;
01058 if (scale_factor > _max_v)
01059 scale_factor = _max_v;
01060
01061 return scale_factor;
01062 }
01063
01064 SGSharedPtr<SGInterpTable> _table;
01065 SGVec3d _center;
01066 double _min_v;
01067 double _max_v;
01068 double _factor;
01069 double _offset;
01070 };
01071
01072
01073 SGDistScaleAnimation::SGDistScaleAnimation(const SGPropertyNode* configNode,
01074 SGPropertyNode* modelRoot) :
01075 SGAnimation(configNode, modelRoot)
01076 {
01077 }
01078
01079 osg::Group*
01080 SGDistScaleAnimation::createAnimationGroup(osg::Group& parent)
01081 {
01082 Transform* transform = new Transform(getConfig());
01083 parent.addChild(transform);
01084 return transform;
01085 }
01086
01087 namespace
01088 {
01089 osgDB::RegisterDotOsgWrapperProxy distScaleAnimationTransformProxy
01090 (
01091 new SGDistScaleAnimation::Transform,
01092 "SGDistScaleAnimation::Transform",
01093 "Object Node Transform SGDistScaleAnimation::Transform Group",
01094 0,
01095 &SGDistScaleAnimation::Transform::writeLocalData
01096 );
01097 }
01098
01100
01102
01103 class SGFlashAnimation::Transform : public osg::Transform {
01104 public:
01105 Transform() : _power(0.0), _factor(0.0), _offset(0.0), _min_v(0.0),
01106 _max_v(0.0), _two_sides(false)
01107 {}
01108
01109 Transform(const Transform& rhs,
01110 const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
01111 : osg::Transform(rhs, copyOp), _center(rhs._center), _axis(rhs._axis),
01112 _power(rhs._power), _factor(rhs._factor), _offset(rhs._offset),
01113 _min_v(rhs._min_v), _max_v(rhs._max_v), _two_sides(rhs._two_sides)
01114 {
01115 }
01116 META_Node(simgear, SGFlashAnimation::Transform);
01117
01118 Transform(const SGPropertyNode* configNode)
01119 {
01120 setReferenceFrame(RELATIVE_RF);
01121 setName(configNode->getStringValue("name", "flash animation"));
01122 setStateSet(getNormalizeStateSet());
01123
01124 _axis[0] = configNode->getFloatValue("axis/x", 0);
01125 _axis[1] = configNode->getFloatValue("axis/y", 0);
01126 _axis[2] = configNode->getFloatValue("axis/z", 1);
01127 _axis.normalize();
01128
01129 _center[0] = configNode->getFloatValue("center/x-m", 0);
01130 _center[1] = configNode->getFloatValue("center/y-m", 0);
01131 _center[2] = configNode->getFloatValue("center/z-m", 0);
01132
01133 _offset = configNode->getFloatValue("offset", 0);
01134 _factor = configNode->getFloatValue("factor", 1);
01135 _power = configNode->getFloatValue("power", 1);
01136 _two_sides = configNode->getBoolValue("two-sides", false);
01137
01138 _min_v = configNode->getFloatValue("min", SGLimitsf::epsilon());
01139 _max_v = configNode->getFloatValue("max", 1);
01140 }
01141 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
01142 osg::NodeVisitor* nv) const
01143 {
01144 osg::Matrix transform;
01145 double scale_factor = computeScaleFactor(nv);
01146 transform(0,0) = scale_factor;
01147 transform(1,1) = scale_factor;
01148 transform(2,2) = scale_factor;
01149 transform(3,0) = _center[0]*(1 - scale_factor);
01150 transform(3,1) = _center[1]*(1 - scale_factor);
01151 transform(3,2) = _center[2]*(1 - scale_factor);
01152 matrix.preMult(transform);
01153 return true;
01154 }
01155
01156 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
01157 osg::NodeVisitor* nv) const
01158 {
01159 double scale_factor = computeScaleFactor(nv);
01160 if (fabs(scale_factor) <= SGLimits<double>::min())
01161 return false;
01162 osg::Matrix transform;
01163 double rScaleFactor = 1/scale_factor;
01164 transform(0,0) = rScaleFactor;
01165 transform(1,1) = rScaleFactor;
01166 transform(2,2) = rScaleFactor;
01167 transform(3,0) = _center[0]*(1 - rScaleFactor);
01168 transform(3,1) = _center[1]*(1 - rScaleFactor);
01169 transform(3,2) = _center[2]*(1 - rScaleFactor);
01170 matrix.postMult(transform);
01171 return true;
01172 }
01173
01174 static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw)
01175 {
01176 const Transform& trans = static_cast<const Transform&>(obj);
01177 fw.indent() << "center " << trans._center[0] << " "
01178 << trans._center[1] << " " << trans._center[2] << " " << "\n";
01179 fw.indent() << "axis " << trans._axis[0] << " "
01180 << trans._axis[1] << " " << trans._axis[2] << " " << "\n";
01181 fw.indent() << "power " << trans._power << " \n";
01182 fw.indent() << "min_v " << trans._min_v << "\n";
01183 fw.indent() << "max_v " << trans._max_v << "\n";
01184 fw.indent() << "factor " << trans._factor << "\n";
01185 fw.indent() << "offset " << trans._offset << "\n";
01186 fw.indent() << "twosides " << (trans._two_sides ? "true" : "false") << "\n";
01187 return true;
01188 }
01189 private:
01190 double computeScaleFactor(osg::NodeVisitor* nv) const
01191 {
01192 if (!nv)
01193 return 1;
01194
01195 osg::Vec3 localEyeToCenter = nv->getEyePoint() - _center;
01196 localEyeToCenter.normalize();
01197
01198 double cos_angle = localEyeToCenter*_axis;
01199 double scale_factor = 0;
01200 if ( _two_sides && cos_angle < 0 )
01201 scale_factor = _factor * pow( -cos_angle, _power ) + _offset;
01202 else if ( cos_angle > 0 )
01203 scale_factor = _factor * pow( cos_angle, _power ) + _offset;
01204
01205 if ( scale_factor < _min_v )
01206 scale_factor = _min_v;
01207 if ( scale_factor > _max_v )
01208 scale_factor = _max_v;
01209
01210 return scale_factor;
01211 }
01212
01213 virtual osg::BoundingSphere computeBound() const
01214 {
01215
01216 osg::BoundingSphere bs = osg::Group::computeBound();
01217 bs.radius() *= _max_v;
01218 return bs;
01219 }
01220
01221 private:
01222 osg::Vec3 _center;
01223 osg::Vec3 _axis;
01224 double _power, _factor, _offset, _min_v, _max_v;
01225 bool _two_sides;
01226 };
01227
01228
01229 SGFlashAnimation::SGFlashAnimation(const SGPropertyNode* configNode,
01230 SGPropertyNode* modelRoot) :
01231 SGAnimation(configNode, modelRoot)
01232 {
01233 }
01234
01235 osg::Group*
01236 SGFlashAnimation::createAnimationGroup(osg::Group& parent)
01237 {
01238 Transform* transform = new Transform(getConfig());
01239 parent.addChild(transform);
01240 return transform;
01241 }
01242
01243 namespace
01244 {
01245 osgDB::RegisterDotOsgWrapperProxy flashAnimationTransformProxy
01246 (
01247 new SGFlashAnimation::Transform,
01248 "SGFlashAnimation::Transform",
01249 "Object Node Transform SGFlashAnimation::Transform Group",
01250 0,
01251 &SGFlashAnimation::Transform::writeLocalData
01252 );
01253 }
01254
01256
01258
01259 class SGBillboardAnimation::Transform : public osg::Transform {
01260 public:
01261 Transform() : _spherical(true) {}
01262 Transform(const Transform& rhs,
01263 const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
01264 : osg::Transform(rhs, copyOp), _spherical(rhs._spherical) {}
01265 META_Node(simgear, SGBillboardAnimation::Transform);
01266 Transform(const SGPropertyNode* configNode) :
01267 _spherical(configNode->getBoolValue("spherical", true))
01268 {
01269 setReferenceFrame(RELATIVE_RF);
01270 setName(configNode->getStringValue("name", "billboard animation"));
01271 }
01272 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
01273 osg::NodeVisitor* nv) const
01274 {
01275
01276 if (_spherical) {
01277 matrix(0,0) = 1; matrix(0,1) = 0; matrix(0,2) = 0;
01278 matrix(1,0) = 0; matrix(1,1) = 0; matrix(1,2) = -1;
01279 matrix(2,0) = 0; matrix(2,1) = 1; matrix(2,2) = 0;
01280 } else {
01281 osg::Vec3 zAxis(matrix(2, 0), matrix(2, 1), matrix(2, 2));
01282 osg::Vec3 xAxis = osg::Vec3(0, 0, -1)^zAxis;
01283 osg::Vec3 yAxis = zAxis^xAxis;
01284
01285 xAxis.normalize();
01286 yAxis.normalize();
01287 zAxis.normalize();
01288
01289 matrix(0,0) = xAxis[0]; matrix(0,1) = xAxis[1]; matrix(0,2) = xAxis[2];
01290 matrix(1,0) = yAxis[0]; matrix(1,1) = yAxis[1]; matrix(1,2) = yAxis[2];
01291 matrix(2,0) = zAxis[0]; matrix(2,1) = zAxis[1]; matrix(2,2) = zAxis[2];
01292 }
01293 return true;
01294 }
01295
01296 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
01297 osg::NodeVisitor* nv) const
01298 {
01299
01300 return false;
01301 }
01302 static bool writeLocalData(const osg::Object& obj, osgDB::Output& fw)
01303 {
01304 const Transform& trans = static_cast<const Transform&>(obj);
01305
01306 fw.indent() << (trans._spherical ? "true" : "false") << "\n";
01307 return true;
01308 }
01309 private:
01310 bool _spherical;
01311 };
01312
01313
01314 SGBillboardAnimation::SGBillboardAnimation(const SGPropertyNode* configNode,
01315 SGPropertyNode* modelRoot) :
01316 SGAnimation(configNode, modelRoot)
01317 {
01318 }
01319
01320 osg::Group*
01321 SGBillboardAnimation::createAnimationGroup(osg::Group& parent)
01322 {
01323 Transform* transform = new Transform(getConfig());
01324 parent.addChild(transform);
01325 return transform;
01326 }
01327
01328 namespace
01329 {
01330 osgDB::RegisterDotOsgWrapperProxy billboardAnimationTransformProxy
01331 (
01332 new SGBillboardAnimation::Transform,
01333 "SGBillboardAnimation::Transform",
01334 "Object Node Transform SGBillboardAnimation::Transform Group",
01335 0,
01336 &SGBillboardAnimation::Transform::writeLocalData
01337 );
01338 }
01339
01341
01343
01344 class SGRangeAnimation::UpdateCallback : public osg::NodeCallback {
01345 public:
01346 UpdateCallback(const SGCondition* condition,
01347 const SGExpressiond* minAnimationValue,
01348 const SGExpressiond* maxAnimationValue,
01349 double minValue, double maxValue) :
01350 _condition(condition),
01351 _minAnimationValue(minAnimationValue),
01352 _maxAnimationValue(maxAnimationValue),
01353 _minStaticValue(minValue),
01354 _maxStaticValue(maxValue)
01355 {}
01356 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
01357 {
01358 osg::LOD* lod = static_cast<osg::LOD*>(node);
01359 if (!_condition || _condition->test()) {
01360 double minRange;
01361 if (_minAnimationValue)
01362 minRange = _minAnimationValue->getValue();
01363 else
01364 minRange = _minStaticValue;
01365 double maxRange;
01366 if (_maxAnimationValue)
01367 maxRange = _maxAnimationValue->getValue();
01368 else
01369 maxRange = _maxStaticValue;
01370 lod->setRange(0, minRange, maxRange);
01371 } else {
01372 lod->setRange(0, 0, SGLimitsf::max());
01373 }
01374 traverse(node, nv);
01375 }
01376
01377 private:
01378 SGSharedPtr<const SGCondition> _condition;
01379 SGSharedPtr<const SGExpressiond> _minAnimationValue;
01380 SGSharedPtr<const SGExpressiond> _maxAnimationValue;
01381 double _minStaticValue;
01382 double _maxStaticValue;
01383 };
01384
01385 SGRangeAnimation::SGRangeAnimation(const SGPropertyNode* configNode,
01386 SGPropertyNode* modelRoot) :
01387 SGAnimation(configNode, modelRoot)
01388 {
01389 _condition = getCondition();
01390
01391 std::string inputPropertyName;
01392 inputPropertyName = configNode->getStringValue("min-property", "");
01393 if (!inputPropertyName.empty()) {
01394 SGPropertyNode* inputProperty;
01395 inputProperty = modelRoot->getNode(inputPropertyName, true);
01396 SGSharedPtr<SGExpressiond> value;
01397 value = new SGPropertyExpression<double>(inputProperty);
01398
01399 value = read_factor_offset(configNode, value, "min-factor", "min-offset");
01400 _minAnimationValue = value->simplify();
01401 }
01402 inputPropertyName = configNode->getStringValue("max-property", "");
01403 if (!inputPropertyName.empty()) {
01404 SGPropertyNode* inputProperty;
01405 inputProperty = modelRoot->getNode(inputPropertyName.c_str(), true);
01406
01407 SGSharedPtr<SGExpressiond> value;
01408 value = new SGPropertyExpression<double>(inputProperty);
01409
01410 value = read_factor_offset(configNode, value, "max-factor", "max-offset");
01411 _maxAnimationValue = value->simplify();
01412 }
01413
01414 _initialValue[0] = configNode->getDoubleValue("min-m", 0);
01415 _initialValue[0] *= configNode->getDoubleValue("min-factor", 1);
01416 _initialValue[1] = configNode->getDoubleValue("max-m", SGLimitsf::max());
01417 _initialValue[1] *= configNode->getDoubleValue("max-factor", 1);
01418 }
01419
01420 osg::Group*
01421 SGRangeAnimation::createAnimationGroup(osg::Group& parent)
01422 {
01423 osg::Group* group = new osg::Group;
01424 group->setName("range animation group");
01425
01426 osg::LOD* lod = new osg::LOD;
01427 lod->setName("range animation node");
01428 parent.addChild(lod);
01429
01430 lod->addChild(group, _initialValue[0], _initialValue[1]);
01431 lod->setCenterMode(osg::LOD::USE_BOUNDING_SPHERE_CENTER);
01432 lod->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT);
01433 if (_minAnimationValue || _maxAnimationValue || _condition) {
01434 UpdateCallback* uc;
01435 uc = new UpdateCallback(_condition, _minAnimationValue, _maxAnimationValue,
01436 _initialValue[0], _initialValue[1]);
01437 lod->setUpdateCallback(uc);
01438 }
01439 return group;
01440 }
01441
01442
01444
01446
01447 class SGSelectAnimation::UpdateCallback : public osg::NodeCallback {
01448 public:
01449 UpdateCallback(const SGCondition* condition) :
01450 _condition(condition)
01451 {}
01452 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
01453 {
01454 osg::Switch* sw = static_cast<osg::Switch*>(node);
01455 if (_condition->test())
01456 sw->setAllChildrenOn();
01457 else
01458 sw->setAllChildrenOff();
01459 traverse(node, nv);
01460 }
01461
01462 private:
01463 SGSharedPtr<SGCondition const> _condition;
01464 };
01465
01466 SGSelectAnimation::SGSelectAnimation(const SGPropertyNode* configNode,
01467 SGPropertyNode* modelRoot) :
01468 SGAnimation(configNode, modelRoot)
01469 {
01470 }
01471
01472 osg::Group*
01473 SGSelectAnimation::createAnimationGroup(osg::Group& parent)
01474 {
01475
01476 SGSharedPtr<SGCondition const> condition = getCondition();
01477
01478
01479 if (!condition)
01480 return new osg::Group;
01481
01482 osg::Switch* sw = new osg::Switch;
01483 sw->setName("select animation node");
01484 sw->setUpdateCallback(new UpdateCallback(condition));
01485 parent.addChild(sw);
01486 return sw;
01487 }
01488
01489
01490
01492
01494
01495 SGAlphaTestAnimation::SGAlphaTestAnimation(const SGPropertyNode* configNode,
01496 SGPropertyNode* modelRoot) :
01497 SGAnimation(configNode, modelRoot)
01498 {
01499 }
01500
01501 namespace
01502 {
01503
01504 ReentrantMutex alphaTestMutex;
01505 osg::ref_ptr<osg::AlphaFunc> standardAlphaFunc;
01506 osg::ref_ptr<osg::StateSet> alphaFuncStateSet;
01507
01508 osg::AlphaFunc* makeAlphaFunc(float clamp)
01509 {
01510 ScopedLock<ReentrantMutex> lock(alphaTestMutex);
01511 if (osg::equivalent(clamp, 0.01f)) {
01512 if (standardAlphaFunc.valid())
01513 return standardAlphaFunc.get();
01514 clamp = .01;
01515 }
01516 osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
01517 alphaFunc->setFunction(osg::AlphaFunc::GREATER);
01518 alphaFunc->setReferenceValue(clamp);
01519 alphaFunc->setDataVariance(osg::Object::STATIC);
01520 if (osg::equivalent(clamp, 0.01f))
01521 standardAlphaFunc = alphaFunc;
01522 return alphaFunc;
01523 }
01524
01525 osg::StateSet* makeAlphaTestStateSet(float clamp)
01526 {
01527 using namespace OpenThreads;
01528 ScopedLock<ReentrantMutex> lock(alphaTestMutex);
01529 if (osg::equivalent(clamp, 0.01f)) {
01530 if (alphaFuncStateSet.valid())
01531 return alphaFuncStateSet.get();
01532 }
01533 osg::AlphaFunc* alphaFunc = makeAlphaFunc(clamp);
01534 osg::StateSet* stateSet = new osg::StateSet;
01535 stateSet->setAttributeAndModes(alphaFunc,
01536 (osg::StateAttribute::ON
01537 | osg::StateAttribute::OVERRIDE));
01538 stateSet->setDataVariance(osg::Object::STATIC);
01539 if (osg::equivalent(clamp, 0.01f))
01540 alphaFuncStateSet = stateSet;
01541 return stateSet;
01542 }
01543 }
01544 void
01545 SGAlphaTestAnimation::install(osg::Node& node)
01546 {
01547 SGAnimation::install(node);
01548
01549 float alphaClamp = getConfig()->getFloatValue("alpha-factor", 0);
01550 osg::StateSet* stateSet = node.getStateSet();
01551 if (!stateSet) {
01552 node.setStateSet(makeAlphaTestStateSet(alphaClamp));
01553 } else {
01554 stateSet->setAttributeAndModes(makeAlphaFunc(alphaClamp),
01555 (osg::StateAttribute::ON
01556 | osg::StateAttribute::OVERRIDE));
01557 }
01558 }
01559
01560
01562
01564
01565
01566
01567
01568 class SGBlendAnimation::BlendVisitor : public osg::NodeVisitor {
01569 public:
01570 BlendVisitor(float blend) :
01571 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
01572 _blend(blend)
01573 { setVisitorType(osg::NodeVisitor::NODE_VISITOR); }
01574 virtual void apply(osg::Node& node)
01575 {
01576 updateStateSet(node.getStateSet());
01577 traverse(node);
01578 }
01579 virtual void apply(osg::Geode& node)
01580 {
01581 apply((osg::Node&)node);
01582 unsigned nDrawables = node.getNumDrawables();
01583 for (unsigned i = 0; i < nDrawables; ++i) {
01584 osg::Drawable* drawable = node.getDrawable(i);
01585 osg::Geometry* geometry = drawable->asGeometry();
01586 if (!geometry)
01587 continue;
01588 osg::Array* array = geometry->getColorArray();
01589 if (!array)
01590 continue;
01591 osg::Vec4Array* vec4Array = dynamic_cast<osg::Vec4Array*>(array);
01592 if (!vec4Array)
01593 continue;
01594 for (unsigned k = 0; k < vec4Array->size(); ++k) {
01595 (*vec4Array)[k][3] = _blend;
01596 }
01597 vec4Array->dirty();
01598 updateStateSet(drawable->getStateSet());
01599 }
01600 }
01601 void updateStateSet(osg::StateSet* stateSet)
01602 {
01603 if (!stateSet)
01604 return;
01605 osg::StateAttribute* stateAttribute;
01606 stateAttribute = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
01607 if (!stateAttribute)
01608 return;
01609 osg::Material* material = dynamic_cast<osg::Material*>(stateAttribute);
01610 if (!material)
01611 return;
01612 material->setAlpha(osg::Material::FRONT_AND_BACK, _blend);
01613 if (_blend < 1) {
01614 stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
01615 stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
01616 } else {
01617 stateSet->setRenderingHint(osg::StateSet::DEFAULT_BIN);
01618 }
01619 }
01620 private:
01621 float _blend;
01622 };
01623
01624 class SGBlendAnimation::UpdateCallback : public osg::NodeCallback {
01625 public:
01626 UpdateCallback(const SGPropertyNode* configNode, const SGExpressiond* v) :
01627 _prev_value(-1),
01628 _animationValue(v)
01629 { }
01630 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
01631 {
01632 double blend = _animationValue->getValue();
01633 if (blend != _prev_value) {
01634 _prev_value = blend;
01635 BlendVisitor visitor(1-blend);
01636 node->accept(visitor);
01637 }
01638 traverse(node, nv);
01639 }
01640 public:
01641 double _prev_value;
01642 SGSharedPtr<SGExpressiond const> _animationValue;
01643 };
01644
01645
01646 SGBlendAnimation::SGBlendAnimation(const SGPropertyNode* configNode,
01647 SGPropertyNode* modelRoot)
01648 : SGAnimation(configNode, modelRoot),
01649 _animationValue(read_value(configNode, modelRoot, "", 0, 1))
01650 {
01651 }
01652
01653 osg::Group*
01654 SGBlendAnimation::createAnimationGroup(osg::Group& parent)
01655 {
01656 if (!_animationValue)
01657 return 0;
01658
01659 osg::Group* group = new osg::Switch;
01660 group->setName("blend animation node");
01661 group->setUpdateCallback(new UpdateCallback(getConfig(), _animationValue));
01662 parent.addChild(group);
01663 return group;
01664 }
01665
01666 void
01667 SGBlendAnimation::install(osg::Node& node)
01668 {
01669 SGAnimation::install(node);
01670
01671
01672 cloneDrawables(node);
01673 DoDrawArraysVisitor visitor;
01674 node.accept(visitor);
01675 }
01676
01677
01679
01681
01682
01683
01684 class SGTimedAnimation::UpdateCallback : public osg::NodeCallback {
01685 public:
01686 UpdateCallback(const SGPropertyNode* configNode) :
01687 _current_index(0),
01688 _reminder(0),
01689 _duration_sec(configNode->getDoubleValue("duration-sec", 1)),
01690 _last_time_sec(SGLimitsd::max()),
01691 _use_personality(configNode->getBoolValue("use-personality", false))
01692 {
01693 std::vector<SGSharedPtr<SGPropertyNode> > nodes;
01694 nodes = configNode->getChildren("branch-duration-sec");
01695 for (size_t i = 0; i < nodes.size(); ++i) {
01696 unsigned ind = nodes[ i ]->getIndex();
01697 while ( ind >= _durations.size() ) {
01698 _durations.push_back(DurationSpec(_duration_sec));
01699 }
01700 SGPropertyNode_ptr rNode = nodes[i]->getChild("random");
01701 if ( rNode == 0 ) {
01702 _durations[ind] = DurationSpec(nodes[ i ]->getDoubleValue());
01703 } else {
01704 _durations[ind] = DurationSpec(rNode->getDoubleValue( "min", 0),
01705 rNode->getDoubleValue( "max", 1));
01706 }
01707 }
01708 }
01709 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
01710 {
01711 assert(dynamic_cast<osg::Switch*>(node));
01712 osg::Switch* sw = static_cast<osg::Switch*>(node);
01713
01714 unsigned nChildren = sw->getNumChildren();
01715
01716
01717 while (_durations.size() < nChildren) {
01718 _durations.push_back(_duration_sec);
01719 }
01720
01721 _current_index = _current_index % nChildren;
01722
01723
01724 double t = nv->getFrameStamp()->getReferenceTime();
01725 if (_last_time_sec == SGLimitsd::max()) {
01726 _last_time_sec = t;
01727 } else {
01728 double dt = t - _last_time_sec;
01729 if (_use_personality)
01730 dt *= 1 + 0.2*(0.5 - sg_random());
01731 _reminder += dt;
01732 _last_time_sec = t;
01733 }
01734
01735 double currentDuration = _durations[_current_index].get();
01736 while (currentDuration < _reminder) {
01737 _reminder -= currentDuration;
01738 _current_index = (_current_index + 1) % nChildren;
01739 currentDuration = _durations[_current_index].get();
01740 }
01741
01742 sw->setSingleChildOn(_current_index);
01743
01744 traverse(node, nv);
01745 }
01746
01747 private:
01748 struct DurationSpec {
01749 DurationSpec(double t) :
01750 minTime(SGMiscd::max(0.01, t)),
01751 maxTime(SGMiscd::max(0.01, t))
01752 {}
01753 DurationSpec(double t0, double t1) :
01754 minTime(SGMiscd::max(0.01, t0)),
01755 maxTime(SGMiscd::max(0.01, t1))
01756 {}
01757 double get() const
01758 { return minTime + sg_random()*(maxTime - minTime); }
01759 double minTime;
01760 double maxTime;
01761 };
01762 std::vector<DurationSpec> _durations;
01763 unsigned _current_index;
01764 double _reminder;
01765 double _duration_sec;
01766 double _last_time_sec;
01767 bool _use_personality;
01768 };
01769
01770
01771 SGTimedAnimation::SGTimedAnimation(const SGPropertyNode* configNode,
01772 SGPropertyNode* modelRoot)
01773 : SGAnimation(configNode, modelRoot)
01774 {
01775 }
01776
01777 osg::Group*
01778 SGTimedAnimation::createAnimationGroup(osg::Group& parent)
01779 {
01780 osg::Switch* sw = new osg::Switch;
01781 sw->setName("timed animation node");
01782 sw->setUpdateCallback(new UpdateCallback(getConfig()));
01783 parent.addChild(sw);
01784 return sw;
01785 }
01786
01787
01789
01791
01792 class SGShadowAnimation::UpdateCallback : public osg::NodeCallback {
01793 public:
01794 UpdateCallback(const SGCondition* condition) :
01795 _condition(condition)
01796 {}
01797 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
01798 {
01799 if (_condition->test())
01800 node->setNodeMask( SG_NODEMASK_CASTSHADOW_BIT | node->getNodeMask());
01801 else
01802 node->setNodeMask(~SG_NODEMASK_CASTSHADOW_BIT & node->getNodeMask());
01803 traverse(node, nv);
01804 }
01805
01806 private:
01807 SGSharedPtr<const SGCondition> _condition;
01808 };
01809
01810 SGShadowAnimation::SGShadowAnimation(const SGPropertyNode* configNode,
01811 SGPropertyNode* modelRoot) :
01812 SGAnimation(configNode, modelRoot)
01813 {
01814 }
01815
01816 osg::Group*
01817 SGShadowAnimation::createAnimationGroup(osg::Group& parent)
01818 {
01819 SGSharedPtr<SGCondition const> condition = getCondition();
01820 if (!condition)
01821 return 0;
01822
01823 osg::Group* group = new osg::Group;
01824 group->setName("shadow animation");
01825 group->setUpdateCallback(new UpdateCallback(condition));
01826 parent.addChild(group);
01827 return group;
01828 }
01829
01830
01832
01834
01835 class SGTexTransformAnimation::Transform : public SGReferenced {
01836 public:
01837 Transform() :
01838 _value(0)
01839 {}
01840 virtual ~Transform()
01841 { }
01842 void setValue(double value)
01843 { _value = value; }
01844 virtual void transform(osg::Matrix&) = 0;
01845 protected:
01846 double _value;
01847 };
01848
01849 class SGTexTransformAnimation::Translation :
01850 public SGTexTransformAnimation::Transform {
01851 public:
01852 Translation(const SGVec3d& axis) :
01853 _axis(axis)
01854 { }
01855 virtual void transform(osg::Matrix& matrix)
01856 {
01857 osg::Matrix tmp;
01858 set_translation(tmp, _value, _axis);
01859 matrix.preMult(tmp);
01860 }
01861 private:
01862 SGVec3d _axis;
01863 };
01864
01865 class SGTexTransformAnimation::Rotation :
01866 public SGTexTransformAnimation::Transform {
01867 public:
01868 Rotation(const SGVec3d& axis, const SGVec3d& center) :
01869 _axis(axis),
01870 _center(center)
01871 { }
01872 virtual void transform(osg::Matrix& matrix)
01873 {
01874 osg::Matrix tmp;
01875 set_rotation(tmp, _value, _center, _axis);
01876 matrix.preMult(tmp);
01877 }
01878 private:
01879 SGVec3d _axis;
01880 SGVec3d _center;
01881 };
01882
01883 class SGTexTransformAnimation::UpdateCallback :
01884 public osg::StateAttribute::Callback {
01885 public:
01886 UpdateCallback(const SGCondition* condition) :
01887 _condition(condition)
01888 { }
01889 virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor*)
01890 {
01891 if (!_condition || _condition->test()) {
01892 TransformList::const_iterator i;
01893 for (i = _transforms.begin(); i != _transforms.end(); ++i)
01894 i->transform->setValue(i->value->getValue());
01895 }
01896 assert(dynamic_cast<osg::TexMat*>(sa));
01897 osg::TexMat* texMat = static_cast<osg::TexMat*>(sa);
01898 texMat->getMatrix().makeIdentity();
01899 TransformList::const_iterator i;
01900 for (i = _transforms.begin(); i != _transforms.end(); ++i)
01901 i->transform->transform(texMat->getMatrix());
01902 }
01903 void appendTransform(Transform* transform, SGExpressiond* value)
01904 {
01905 Entry entry = { transform, value };
01906 transform->transform(_matrix);
01907 _transforms.push_back(entry);
01908 }
01909
01910 private:
01911 struct Entry {
01912 SGSharedPtr<Transform> transform;
01913 SGSharedPtr<const SGExpressiond> value;
01914 };
01915 typedef std::vector<Entry> TransformList;
01916 TransformList _transforms;
01917 SGSharedPtr<const SGCondition> _condition;
01918 osg::Matrix _matrix;
01919 };
01920
01921 SGTexTransformAnimation::SGTexTransformAnimation(const SGPropertyNode* configNode,
01922 SGPropertyNode* modelRoot) :
01923 SGAnimation(configNode, modelRoot)
01924 {
01925 }
01926
01927 osg::Group*
01928 SGTexTransformAnimation::createAnimationGroup(osg::Group& parent)
01929 {
01930 osg::Group* group = new osg::Group;
01931 group->setName("texture transform group");
01932 osg::StateSet* stateSet = group->getOrCreateStateSet();
01933 stateSet->setDataVariance(osg::Object::DYNAMIC);
01934 osg::TexMat* texMat = new osg::TexMat;
01935 UpdateCallback* updateCallback = new UpdateCallback(getCondition());
01936
01937 std::string type = getType();
01938
01939 if (type == "textranslate") {
01940 appendTexTranslate(getConfig(), updateCallback);
01941 } else if (type == "texrotate") {
01942 appendTexRotate(getConfig(), updateCallback);
01943 } else if (type == "texmultiple") {
01944 std::vector<SGSharedPtr<SGPropertyNode> > transformConfigs;
01945 transformConfigs = getConfig()->getChildren("transform");
01946 for (unsigned i = 0; i < transformConfigs.size(); ++i) {
01947 std::string subtype = transformConfigs[i]->getStringValue("subtype", "");
01948 if (subtype == "textranslate")
01949 appendTexTranslate(transformConfigs[i], updateCallback);
01950 else if (subtype == "texrotate")
01951 appendTexRotate(transformConfigs[i], updateCallback);
01952 else
01953 SG_LOG(SG_INPUT, SG_ALERT,
01954 "Ignoring unknown texture transform subtype");
01955 }
01956 } else {
01957 SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unknown texture transform type");
01958 }
01959
01960 texMat->setUpdateCallback(updateCallback);
01961 stateSet->setTextureAttribute(0, texMat);
01962 parent.addChild(group);
01963 return group;
01964 }
01965
01966 void
01967 SGTexTransformAnimation::appendTexTranslate(const SGPropertyNode* config,
01968 UpdateCallback* updateCallback)
01969 {
01970 std::string propertyName = config->getStringValue("property", "");
01971 SGSharedPtr<SGExpressiond> value;
01972 if (propertyName.empty())
01973 value = new SGConstExpression<double>(0);
01974 else {
01975 SGPropertyNode* inputProperty = getModelRoot()->getNode(propertyName, true);
01976 value = new SGPropertyExpression<double>(inputProperty);
01977 }
01978
01979 SGInterpTable* table = read_interpolation_table(config);
01980 if (table) {
01981 value = new SGInterpTableExpression<double>(value, table);
01982 double biasValue = config->getDoubleValue("bias", 0);
01983 if (biasValue != 0)
01984 value = new SGBiasExpression<double>(value, biasValue);
01985 value = new SGStepExpression<double>(value,
01986 config->getDoubleValue("step", 0),
01987 config->getDoubleValue("scroll", 0));
01988 value = value->simplify();
01989 } else {
01990 double biasValue = config->getDoubleValue("bias", 0);
01991 if (biasValue != 0)
01992 value = new SGBiasExpression<double>(value, biasValue);
01993 value = new SGStepExpression<double>(value,
01994 config->getDoubleValue("step", 0),
01995 config->getDoubleValue("scroll", 0));
01996 value = read_offset_factor(config, value, "factor", "offset");
01997
01998 if (config->hasChild("min") || config->hasChild("max")) {
01999 double minClip = config->getDoubleValue("min", -SGLimitsd::max());
02000 double maxClip = config->getDoubleValue("max", SGLimitsd::max());
02001 value = new SGClipExpression<double>(value, minClip, maxClip);
02002 }
02003 value = value->simplify();
02004 }
02005 SGVec3d axis(config->getDoubleValue("axis/x", 0),
02006 config->getDoubleValue("axis/y", 0),
02007 config->getDoubleValue("axis/z", 0));
02008 Translation* translation;
02009 translation = new Translation(normalize(axis));
02010 translation->setValue(config->getDoubleValue("starting-position", 0));
02011 updateCallback->appendTransform(translation, value);
02012 }
02013
02014 void
02015 SGTexTransformAnimation::appendTexRotate(const SGPropertyNode* config,
02016 UpdateCallback* updateCallback)
02017 {
02018 std::string propertyName = config->getStringValue("property", "");
02019 SGSharedPtr<SGExpressiond> value;
02020 if (propertyName.empty())
02021 value = new SGConstExpression<double>(0);
02022 else {
02023 SGPropertyNode* inputProperty = getModelRoot()->getNode(propertyName, true);
02024 value = new SGPropertyExpression<double>(inputProperty);
02025 }
02026
02027 SGInterpTable* table = read_interpolation_table(config);
02028 if (table) {
02029 value = new SGInterpTableExpression<double>(value, table);
02030 double biasValue = config->getDoubleValue("bias", 0);
02031 if (biasValue != 0)
02032 value = new SGBiasExpression<double>(value, biasValue);
02033 value = new SGStepExpression<double>(value,
02034 config->getDoubleValue("step", 0),
02035 config->getDoubleValue("scroll", 0));
02036 value = value->simplify();
02037 } else {
02038 double biasValue = config->getDoubleValue("bias", 0);
02039 if (biasValue != 0)
02040 value = new SGBiasExpression<double>(value, biasValue);
02041 value = new SGStepExpression<double>(value,
02042 config->getDoubleValue("step", 0),
02043 config->getDoubleValue("scroll", 0));
02044 value = read_offset_factor(config, value, "factor", "offset-deg");
02045
02046 if (config->hasChild("min-deg") || config->hasChild("max-deg")) {
02047 double minClip = config->getDoubleValue("min-deg", -SGLimitsd::max());
02048 double maxClip = config->getDoubleValue("max-deg", SGLimitsd::max());
02049 value = new SGClipExpression<double>(value, minClip, maxClip);
02050 }
02051 value = value->simplify();
02052 }
02053 SGVec3d axis(config->getDoubleValue("axis/x", 0),
02054 config->getDoubleValue("axis/y", 0),
02055 config->getDoubleValue("axis/z", 0));
02056 SGVec3d center(config->getDoubleValue("center/x", 0),
02057 config->getDoubleValue("center/y", 0),
02058 config->getDoubleValue("center/z", 0));
02059 Rotation* rotation;
02060 rotation = new Rotation(normalize(axis), center);
02061 rotation->setValue(config->getDoubleValue("starting-position-deg", 0));
02062 updateCallback->appendTransform(rotation, value);
02063 }
02064
02065
02067
02069
02070 class SGPickAnimation::PickCallback : public SGPickCallback {
02071 public:
02072 PickCallback(const SGPropertyNode* configNode,
02073 SGPropertyNode* modelRoot) :
02074 _repeatable(configNode->getBoolValue("repeatable", false)),
02075 _repeatInterval(configNode->getDoubleValue("interval-sec", 0.1))
02076 {
02077 SG_LOG(SG_INPUT, SG_DEBUG, "Reading all bindings");
02078 std::vector<SGPropertyNode_ptr> bindings;
02079
02080 bindings = configNode->getChildren("button");
02081 for (unsigned int i = 0; i < bindings.size(); ++i) {
02082 _buttons.push_back( bindings[i]->getIntValue() );
02083 }
02084 bindings = configNode->getChildren("binding");
02085 for (unsigned int i = 0; i < bindings.size(); ++i) {
02086 _bindingsDown.push_back(new SGBinding(bindings[i], modelRoot));
02087 }
02088
02089 const SGPropertyNode* upNode = configNode->getChild("mod-up");
02090 if (!upNode)
02091 return;
02092 bindings = upNode->getChildren("binding");
02093 for (unsigned int i = 0; i < bindings.size(); ++i) {
02094 _bindingsUp.push_back(new SGBinding(bindings[i], modelRoot));
02095 }
02096 }
02097 virtual bool buttonPressed(int button, const Info&)
02098 {
02099 bool found = false;
02100 for( std::vector<int>::iterator it = _buttons.begin(); it != _buttons.end(); it++ ) {
02101 if( *it == button ) {
02102 found = true;
02103 break;
02104 }
02105 }
02106 if (!found )
02107 return false;
02108 SGBindingList::const_iterator i;
02109 for (i = _bindingsDown.begin(); i != _bindingsDown.end(); ++i)
02110 (*i)->fire();
02111 _repeatTime = -_repeatInterval;
02112 return true;
02113 }
02114 virtual void buttonReleased(void)
02115 {
02116 SGBindingList::const_iterator i;
02117 for (i = _bindingsUp.begin(); i != _bindingsUp.end(); ++i)
02118 (*i)->fire();
02119 }
02120 virtual void update(double dt)
02121 {
02122 if (!_repeatable)
02123 return;
02124
02125 _repeatTime += dt;
02126 while (_repeatInterval < _repeatTime) {
02127 _repeatTime -= _repeatInterval;
02128 SGBindingList::const_iterator i;
02129 for (i = _bindingsDown.begin(); i != _bindingsDown.end(); ++i)
02130 (*i)->fire();
02131 }
02132 }
02133 private:
02134 SGBindingList _bindingsDown;
02135 SGBindingList _bindingsUp;
02136 std::vector<int> _buttons;
02137 bool _repeatable;
02138 double _repeatInterval;
02139 double _repeatTime;
02140 };
02141
02142 SGPickAnimation::SGPickAnimation(const SGPropertyNode* configNode,
02143 SGPropertyNode* modelRoot) :
02144 SGAnimation(configNode, modelRoot)
02145 {
02146 }
02147
02148 osg::Group*
02149 SGPickAnimation::createAnimationGroup(osg::Group& parent)
02150 {
02151 osg::Group* commonGroup = new osg::Group;
02152
02153
02154 osg::ref_ptr<osg::Group> normalGroup = new osg::Group;
02155 normalGroup->setName("pick normal group");
02156 normalGroup->addChild(commonGroup);
02157
02158
02159 osg::Group* highlightGroup = new osg::Group;
02160 highlightGroup->setName("pick highlight group");
02161 highlightGroup->setNodeMask(SG_NODEMASK_PICK_BIT);
02162 highlightGroup->addChild(commonGroup);
02163 SGSceneUserData* ud;
02164 ud = SGSceneUserData::getOrCreateSceneUserData(commonGroup);
02165 std::vector<SGPropertyNode_ptr> actions;
02166 actions = getConfig()->getChildren("action");
02167 for (unsigned int i = 0; i < actions.size(); ++i)
02168 ud->addPickCallback(new PickCallback(actions[i], getModelRoot()));
02169
02170
02171 osg::StateSet* stateSet = highlightGroup->getOrCreateStateSet();
02172 stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
02173
02174 osg::PolygonOffset* polygonOffset = new osg::PolygonOffset;
02175 polygonOffset->setFactor(-1);
02176 polygonOffset->setUnits(-1);
02177 stateSet->setAttribute(polygonOffset, osg::StateAttribute::OVERRIDE);
02178 stateSet->setMode(GL_POLYGON_OFFSET_LINE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
02179
02180 osg::PolygonMode* polygonMode = new osg::PolygonMode;
02181 polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK,
02182 osg::PolygonMode::LINE);
02183 stateSet->setAttribute(polygonMode, osg::StateAttribute::OVERRIDE);
02184
02185 osg::Material* material = new osg::Material;
02186 material->setColorMode(osg::Material::OFF);
02187 material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 0, 1));
02188 material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 0, 1));
02189 material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 0, 1));
02190 material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, 0));
02191 stateSet->setAttribute(material, osg::StateAttribute::OVERRIDE);
02192
02193
02194 if (getConfig()->getBoolValue("visible", true))
02195 parent.addChild(normalGroup.get());
02196 parent.addChild(highlightGroup);
02197
02198 return commonGroup;
02199 }