1 // animation.cxx - classes to manage model animation.
2 // Written by David Megginson, started 2002.
4 // This file is in the Public Domain, and comes with no warranty.
7 # include <simgear_config.h>
10 #include <string.h> // for strcmp()
13 #include <osg/AlphaFunc>
14 #include <osg/AutoTransform>
15 #include <osg/Drawable>
17 #include <osg/Geometry>
19 #include <osg/MatrixTransform>
20 #include <osg/StateSet>
23 #include <osg/Texture2D>
24 #include <osgDB/ReadFile>
26 #include <simgear/math/interpolater.hxx>
27 #include <simgear/props/condition.hxx>
28 #include <simgear/props/props.hxx>
29 #include <simgear/math/sg_random.h>
30 #include <simgear/scene/util/SGNodeMasks.hxx>
32 #include "animation.hxx"
36 ////////////////////////////////////////////////////////////////////////
37 // Static utility functions.
38 ////////////////////////////////////////////////////////////////////////
41 * Set up the transform matrix for a spin or rotation.
44 set_rotation (osg::Matrix &matrix, double position_deg,
45 const osg::Vec3 ¢er, const osg::Vec3 &axis)
47 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
49 float s = (float) sin ( temp_angle ) ;
50 float c = (float) cos ( temp_angle ) ;
51 float t = SG_ONE - c ;
53 // axis was normalized at load time
54 // hint to the compiler to put these into FP registers
59 matrix(0, 0) = t * x * x + c ;
60 matrix(0, 1) = t * y * x - s * z ;
61 matrix(0, 2) = t * z * x + s * y ;
62 matrix(0, 3) = SG_ZERO;
64 matrix(1, 0) = t * x * y + s * z ;
65 matrix(1, 1) = t * y * y + c ;
66 matrix(1, 2) = t * z * y - s * x ;
67 matrix(1, 3) = SG_ZERO;
69 matrix(2, 0) = t * x * z - s * y ;
70 matrix(2, 1) = t * y * z + s * x ;
71 matrix(2, 2) = t * z * z + c ;
72 matrix(2, 3) = SG_ZERO;
74 // hint to the compiler to put these into FP registers
79 matrix(3, 0) = x - x*matrix(0, 0) - y*matrix(1, 0) - z*matrix(2, 0);
80 matrix(3, 1) = y - x*matrix(0, 1) - y*matrix(1, 1) - z*matrix(2, 1);
81 matrix(3, 2) = z - x*matrix(0, 2) - y*matrix(1, 2) - z*matrix(2, 2);
82 matrix(3, 3) = SG_ONE;
86 * Set up the transform matrix for a translation.
89 set_translation (osg::Matrix &matrix, double position_m, const osg::Vec3 &axis)
91 osg::Vec3 xyz = axis * position_m;
92 matrix.makeIdentity();
93 matrix(3, 0) = xyz[0];
94 matrix(3, 1) = xyz[1];
95 matrix(3, 2) = xyz[2];
99 * Set up the transform matrix for a scale operation.
102 set_scale (osg::Matrix &matrix, double x, double y, double z)
104 matrix.makeIdentity();
111 * Modify property value by step and scroll settings in texture translations
114 apply_mods(double property, double step, double scroll)
119 double scrollval = 0.0;
121 // calculate scroll amount (for odometer like movement)
122 double remainder = step - fmod(fabs(property), step);
123 if (remainder < scroll) {
124 scrollval = (scroll - remainder) / scroll * step;
127 // apply stepping of input value
129 modprop = ((floor(property/step) * step) + scrollval);
131 modprop = ((ceil(property/step) * step) + scrollval);
140 * Read an interpolation table from properties.
142 static SGInterpTable *
143 read_interpolation_table (SGPropertyNode_ptr props)
145 SGPropertyNode_ptr table_node = props->getNode("interpolation");
146 if (table_node != 0) {
147 SGInterpTable * table = new SGInterpTable();
148 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
149 for (unsigned int i = 0; i < entries.size(); i++)
150 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
151 entries[i]->getDoubleValue("dep", 0.0));
160 ////////////////////////////////////////////////////////////////////////
161 // Implementation of SGAnimation
162 ////////////////////////////////////////////////////////////////////////
164 SGAnimation::SGAnimation (SGPropertyNode_ptr props, osg::Group * branch)
168 _branch->setName(props->getStringValue("name", "Animation"));
169 if ( props->getBoolValue( "enable-hot", true ) ) {
170 _branch->setNodeMask(SG_NODEMASK_TERRAIN_BIT|_branch->getNodeMask());
172 _branch->setNodeMask(~SG_NODEMASK_TERRAIN_BIT&_branch->getNodeMask());
176 SGAnimation::~SGAnimation ()
186 SGAnimation::restore()
191 SGAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
197 ////////////////////////////////////////////////////////////////////////
198 // Implementation of SGNullAnimation
199 ////////////////////////////////////////////////////////////////////////
201 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
202 : SGAnimation(props, new osg::Group)
206 SGNullAnimation::~SGNullAnimation ()
212 ////////////////////////////////////////////////////////////////////////
213 // Implementation of SGRangeAnimation
214 ////////////////////////////////////////////////////////////////////////
216 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
217 SGPropertyNode_ptr props)
218 : SGAnimation(props, new osg::LOD),
219 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
222 SGPropertyNode_ptr node = props->getChild("condition");
224 _condition = sgReadCondition(prop_root, node);
228 node = props->getChild( "min-factor" );
230 _min_factor = props->getFloatValue("min-factor", 1.0);
232 node = props->getChild( "max-factor" );
234 _max_factor = props->getFloatValue("max-factor", 1.0);
236 node = props->getChild( "min-property" );
238 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
239 ranges[0] = _min_prop->getFloatValue() * _min_factor;
241 _min = props->getFloatValue("min-m", 0);
242 ranges[0] = _min * _min_factor;
244 node = props->getChild( "max-property" );
246 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
247 ranges[1] = _max_prop->getFloatValue() * _max_factor;
249 _max = props->getFloatValue("max-m", 0);
250 ranges[1] = _max * _max_factor;
252 static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
255 SGRangeAnimation::~SGRangeAnimation ()
260 SGRangeAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
263 if ( _condition == 0 || _condition->test() ) {
264 if (_min_prop != 0) {
265 ranges[0] = _min_prop->getFloatValue() * _min_factor;
267 ranges[0] = _min * _min_factor;
269 if (_max_prop != 0) {
270 ranges[1] = _max_prop->getFloatValue() * _max_factor;
272 ranges[1] = _max * _max_factor;
276 ranges[1] = 1000000000.f;
278 static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
284 ////////////////////////////////////////////////////////////////////////
285 // Implementation of SGBillboardAnimation
286 ////////////////////////////////////////////////////////////////////////
288 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
289 : SGAnimation(props, new osg::AutoTransform)
292 bool spherical = props->getBoolValue("spherical", true);
293 osg::AutoTransform* autoTrans = static_cast<osg::AutoTransform*>(_branch);
295 autoTrans->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
297 autoTrans->setAutoRotateMode(osg::AutoTransform::NO_ROTATION);
298 autoTrans->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
300 autoTrans->setAutoScaleToScreen(false);
303 SGBillboardAnimation::~SGBillboardAnimation ()
309 ////////////////////////////////////////////////////////////////////////
310 // Implementation of SGSelectAnimation
311 ////////////////////////////////////////////////////////////////////////
313 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
314 SGPropertyNode_ptr props )
315 : SGAnimation(props, new osg::Switch),
318 SGPropertyNode_ptr node = props->getChild("condition");
320 _condition = sgReadCondition(prop_root, node);
323 SGSelectAnimation::~SGSelectAnimation ()
328 SGSelectAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
330 if (_condition != 0 && _condition->test())
331 static_cast<osg::Switch*>(_branch)->setAllChildrenOn();
333 static_cast<osg::Switch*>(_branch)->setAllChildrenOff();
338 ////////////////////////////////////////////////////////////////////////
339 // Implementation of SGSpinAnimation
340 ////////////////////////////////////////////////////////////////////////
342 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
343 SGPropertyNode_ptr props,
344 double sim_time_sec )
345 : SGAnimation(props, new osg::MatrixTransform),
346 _use_personality( props->getBoolValue("use-personality",false) ),
347 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
348 _factor( props, "factor", 1.0 ),
349 _position_deg( props, "starting-position-deg", 0.0 ),
350 _last_time_sec( sim_time_sec ),
353 SGPropertyNode_ptr node = props->getChild("condition");
355 _condition = sgReadCondition(prop_root, node);
360 if (props->hasValue("axis/x1-m")) {
361 double x1,y1,z1,x2,y2,z2;
362 x1 = props->getFloatValue("axis/x1-m");
363 y1 = props->getFloatValue("axis/y1-m");
364 z1 = props->getFloatValue("axis/z1-m");
365 x2 = props->getFloatValue("axis/x2-m");
366 y2 = props->getFloatValue("axis/y2-m");
367 z2 = props->getFloatValue("axis/z2-m");
368 _center[0] = (x1+x2)/2;
369 _center[1]= (y1+y2)/2;
370 _center[2] = (z1+z2)/2;
371 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
372 _axis[0] = (x2-x1)/vector_length;
373 _axis[1] = (y2-y1)/vector_length;
374 _axis[2] = (z2-z1)/vector_length;
376 _axis[0] = props->getFloatValue("axis/x", 0);
377 _axis[1] = props->getFloatValue("axis/y", 0);
378 _axis[2] = props->getFloatValue("axis/z", 0);
380 if (props->hasValue("center/x-m")) {
381 _center[0] = props->getFloatValue("center/x-m", 0);
382 _center[1] = props->getFloatValue("center/y-m", 0);
383 _center[2] = props->getFloatValue("center/z-m", 0);
388 if ( _use_personality ) {
390 _position_deg.shuffle();
394 SGSpinAnimation::~SGSpinAnimation ()
399 SGSpinAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
401 double sim_time_sec = nv->getFrameStamp()->getReferenceTime();
402 if ( _condition == 0 || _condition->test() ) {
405 dt = sim_time_sec - _last_time_sec;
406 _last_time_sec = sim_time_sec;
408 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
409 _position_deg += (dt * velocity_rpms * 360);
410 _position_deg -= 360*floor(_position_deg/360);
413 set_rotation(_matrix, _position_deg, _center, _axis);
414 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
421 ////////////////////////////////////////////////////////////////////////
422 // Implementation of SGTimedAnimation
423 ////////////////////////////////////////////////////////////////////////
425 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
426 : SGAnimation(props, new osg::Switch),
427 _use_personality( props->getBoolValue("use-personality",false) ),
428 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
430 _total_duration_sec( 0 ),
434 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
435 size_t nb = nodes.size();
436 for ( size_t i = 0; i < nb; i++ ) {
437 size_t ind = nodes[ i ]->getIndex();
438 while ( ind >= _branch_duration_specs.size() ) {
439 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
441 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
443 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
445 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
446 rNode->getDoubleValue( "max", 1.0 ) );
451 SGTimedAnimation::~SGTimedAnimation ()
456 SGTimedAnimation::init()
458 if ( !_use_personality ) {
459 for ( unsigned i = 0; i < getBranch()->getNumChildren(); i++ ) {
461 if ( i < _branch_duration_specs.size() ) {
462 DurationSpec &sp = _branch_duration_specs[ i ];
463 v = sp._min + sg_random() * ( sp._max - sp._min );
467 _branch_duration_sec.push_back( v );
468 _total_duration_sec += v;
471 // Sanity check : total duration shouldn't equal zero
472 if (_duration_sec < 0.01)
473 _duration_sec = 0.01;
474 if ( _total_duration_sec < 0.01 )
475 _total_duration_sec = 0.01;
477 static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
481 SGTimedAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
483 double sim_time_sec = nv->getFrameStamp()->getReferenceTime();
484 _last_time_sec -= _total_duration_sec*floor((sim_time_sec - _last_time_sec)/_total_duration_sec);
485 double duration = _duration_sec;
486 if ( _step < _branch_duration_sec.size() ) {
487 duration = _branch_duration_sec[ _step ];
489 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
490 _last_time_sec += duration;
492 if ( _step >= getBranch()->getNumChildren() )
494 static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
501 ////////////////////////////////////////////////////////////////////////
502 // Implementation of SGRotateAnimation
503 ////////////////////////////////////////////////////////////////////////
505 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
506 SGPropertyNode_ptr props )
507 : SGAnimation(props, new osg::MatrixTransform),
508 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
509 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
510 _factor(props->getDoubleValue("factor", 1.0)),
511 _table(read_interpolation_table(props)),
512 _has_min(props->hasValue("min-deg")),
513 _min_deg(props->getDoubleValue("min-deg")),
514 _has_max(props->hasValue("max-deg")),
515 _max_deg(props->getDoubleValue("max-deg")),
516 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
519 SGPropertyNode_ptr node = props->getChild("condition");
521 _condition = sgReadCondition(prop_root, node);
526 if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
527 _axis[0] = props->getFloatValue("axis/x", 0);
528 _axis[1] = props->getFloatValue("axis/y", 0);
529 _axis[2] = props->getFloatValue("axis/z", 0);
531 double x1,y1,z1,x2,y2,z2;
532 x1 = props->getFloatValue("axis/x1-m", 0);
533 y1 = props->getFloatValue("axis/y1-m", 0);
534 z1 = props->getFloatValue("axis/z1-m", 0);
535 x2 = props->getFloatValue("axis/x2-m", 0);
536 y2 = props->getFloatValue("axis/y2-m", 0);
537 z2 = props->getFloatValue("axis/z2-m", 0);
538 _center[0] = (x1+x2)/2;
539 _center[1]= (y1+y2)/2;
540 _center[2] = (z1+z2)/2;
541 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
542 _axis[0] = (x2-x1)/vector_length;
543 _axis[1] = (y2-y1)/vector_length;
544 _axis[2] = (z2-z1)/vector_length;
546 if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
547 || props->hasValue("center/z-m")) {
548 _center[0] = props->getFloatValue("center/x-m", 0);
549 _center[1] = props->getFloatValue("center/y-m", 0);
550 _center[2] = props->getFloatValue("center/z-m", 0);
555 SGRotateAnimation::~SGRotateAnimation ()
560 SGRotateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
562 if (_condition == 0 || _condition->test()) {
564 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
565 if (_has_min && _position_deg < _min_deg)
566 _position_deg = _min_deg;
567 if (_has_max && _position_deg > _max_deg)
568 _position_deg = _max_deg;
570 _position_deg = _table->interpolate(_prop->getDoubleValue());
573 set_rotation(_matrix, _position_deg, _center, _axis);
574 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
580 ////////////////////////////////////////////////////////////////////////
581 // Implementation of SGBlendAnimation
582 ////////////////////////////////////////////////////////////////////////
584 class SGBlendAnimationVisitor : public osg::NodeVisitor {
586 SGBlendAnimationVisitor(float blend) :
587 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
590 setVisitorType(osg::NodeVisitor::NODE_VISITOR);
592 virtual void apply(osg::Node& node)
594 updateStateSet(node.getStateSet());
597 virtual void apply(osg::Geode& node)
599 apply((osg::Node&)node);
600 unsigned nDrawables = node.getNumDrawables();
601 for (unsigned i = 0; i < nDrawables; ++i) {
602 osg::Drawable* drawable = node.getDrawable(i);
603 updateStateSet(drawable->getStateSet());
604 osg::Geometry* geometry = drawable->asGeometry();
607 osg::Array* array = geometry->getColorArray();
610 osg::Vec4Array* vec4Array = dynamic_cast<osg::Vec4Array*>(array);
613 geometry->dirtyDisplayList();
615 for (unsigned k = 0; k < vec4Array->size(); ++k) {
616 (*vec4Array)[k][3] = _blend;
620 void updateStateSet(osg::StateSet* stateSet)
624 osg::StateAttribute* stateAttribute = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
627 osg::Material* material = dynamic_cast<osg::Material*>(stateAttribute);
630 material->setAlpha(osg::Material::FRONT_AND_BACK, _blend);
637 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
638 SGPropertyNode_ptr props )
639 : SGAnimation(props, new osg::Group),
640 _use_personality( props->getBoolValue("use-personality",false) ),
641 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
642 _table(read_interpolation_table(props)),
644 _offset(props,"offset",0.0),
645 _factor(props,"factor",1.0),
646 _min(props->getDoubleValue("min", 0.0)),
647 _max(props->getDoubleValue("max", 1.0))
649 if ( _use_personality ) {
655 SGBlendAnimation::~SGBlendAnimation ()
660 SGBlendAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
665 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
667 _blend = _table->interpolate(_prop->getDoubleValue());
674 if (_blend != _prev_value) {
675 _prev_value = _blend;
676 SGBlendAnimationVisitor visitor(1-_blend);
677 _branch->accept(visitor);
684 ////////////////////////////////////////////////////////////////////////
685 // Implementation of SGTranslateAnimation
686 ////////////////////////////////////////////////////////////////////////
688 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
689 SGPropertyNode_ptr props )
690 : SGAnimation(props, new osg::MatrixTransform),
691 _use_personality( props->getBoolValue("use-personality",false) ),
692 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
693 _offset_m( props, "offset-m", 0.0 ),
694 _factor( props, "factor", 1.0 ),
695 _table(read_interpolation_table(props)),
696 _has_min(props->hasValue("min-m")),
697 _min_m(props->getDoubleValue("min-m")),
698 _has_max(props->hasValue("max-m")),
699 _max_m(props->getDoubleValue("max-m")),
700 _position_m(props->getDoubleValue("starting-position-m", 0)),
703 SGPropertyNode_ptr node = props->getChild("condition");
705 _condition = sgReadCondition(prop_root, node);
707 _axis[0] = props->getFloatValue("axis/x", 0);
708 _axis[1] = props->getFloatValue("axis/y", 0);
709 _axis[2] = props->getFloatValue("axis/z", 0);
712 if ( _use_personality ) {
718 SGTranslateAnimation::~SGTranslateAnimation ()
723 SGTranslateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
725 if (_condition == 0 || _condition->test()) {
728 _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
729 if (_has_min && _position_m < _min_m)
730 _position_m = _min_m;
731 if (_has_max && _position_m > _max_m)
732 _position_m = _max_m;
734 _position_m = _table->interpolate(_prop->getDoubleValue());
738 set_translation(_matrix, _position_m, _axis);
739 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
746 ////////////////////////////////////////////////////////////////////////
747 // Implementation of SGScaleAnimation
748 ////////////////////////////////////////////////////////////////////////
750 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
751 SGPropertyNode_ptr props )
752 : SGAnimation(props, new osg::MatrixTransform),
753 _use_personality( props->getBoolValue("use-personality",false) ),
754 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
755 _x_factor(props,"x-factor",1.0),
756 _y_factor(props,"y-factor",1.0),
757 _z_factor(props,"z-factor",1.0),
758 _x_offset(props,"x-offset",1.0),
759 _y_offset(props,"y-offset",1.0),
760 _z_offset(props,"z-offset",1.0),
761 _table(read_interpolation_table(props)),
762 _has_min_x(props->hasValue("x-min")),
763 _has_min_y(props->hasValue("y-min")),
764 _has_min_z(props->hasValue("z-min")),
765 _min_x(props->getDoubleValue("x-min")),
766 _min_y(props->getDoubleValue("y-min")),
767 _min_z(props->getDoubleValue("z-min")),
768 _has_max_x(props->hasValue("x-max")),
769 _has_max_y(props->hasValue("y-max")),
770 _has_max_z(props->hasValue("z-max")),
771 _max_x(props->getDoubleValue("x-max")),
772 _max_y(props->getDoubleValue("y-max")),
773 _max_z(props->getDoubleValue("z-max"))
775 if ( _use_personality ) {
785 SGScaleAnimation::~SGScaleAnimation ()
790 SGScaleAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
793 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
794 if (_has_min_x && _x_scale < _min_x)
796 if (_has_max_x && _x_scale > _max_x)
799 _x_scale = _table->interpolate(_prop->getDoubleValue());
803 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
804 if (_has_min_y && _y_scale < _min_y)
806 if (_has_max_y && _y_scale > _max_y)
809 _y_scale = _table->interpolate(_prop->getDoubleValue());
813 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
814 if (_has_min_z && _z_scale < _min_z)
816 if (_has_max_z && _z_scale > _max_z)
819 _z_scale = _table->interpolate(_prop->getDoubleValue());
823 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
824 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
829 ////////////////////////////////////////////////////////////////////////
830 // Implementation of SGTexRotateAnimation
831 ////////////////////////////////////////////////////////////////////////
833 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
834 SGPropertyNode_ptr props )
835 : SGAnimation(props, new osg::Group),
836 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
837 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
838 _factor(props->getDoubleValue("factor", 1.0)),
839 _table(read_interpolation_table(props)),
840 _has_min(props->hasValue("min-deg")),
841 _min_deg(props->getDoubleValue("min-deg")),
842 _has_max(props->hasValue("max-deg")),
843 _max_deg(props->getDoubleValue("max-deg")),
844 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
847 SGPropertyNode *node = props->getChild("condition");
849 _condition = sgReadCondition(prop_root, node);
851 _center[0] = props->getFloatValue("center/x", 0);
852 _center[1] = props->getFloatValue("center/y", 0);
853 _center[2] = props->getFloatValue("center/z", 0);
854 _axis[0] = props->getFloatValue("axis/x", 0);
855 _axis[1] = props->getFloatValue("axis/y", 0);
856 _axis[2] = props->getFloatValue("axis/z", 0);
859 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
860 _texMat = new osg::TexMat;
861 stateSet->setTextureAttribute(0, _texMat.get());
864 SGTexRotateAnimation::~SGTexRotateAnimation ()
869 SGTexRotateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
871 if (!_condition || _condition->test()) {
873 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
874 if (_has_min && _position_deg < _min_deg)
875 _position_deg = _min_deg;
876 if (_has_max && _position_deg > _max_deg)
877 _position_deg = _max_deg;
879 _position_deg = _table->interpolate(_prop->getDoubleValue());
882 set_rotation(_matrix, _position_deg, _center, _axis);
883 _texMat->setMatrix(_matrix);
889 ////////////////////////////////////////////////////////////////////////
890 // Implementation of SGTexTranslateAnimation
891 ////////////////////////////////////////////////////////////////////////
893 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
894 SGPropertyNode_ptr props )
895 : SGAnimation(props, new osg::Group),
896 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
897 _offset(props->getDoubleValue("offset", 0.0)),
898 _factor(props->getDoubleValue("factor", 1.0)),
899 _step(props->getDoubleValue("step",0.0)),
900 _scroll(props->getDoubleValue("scroll",0.0)),
901 _table(read_interpolation_table(props)),
902 _has_min(props->hasValue("min")),
903 _min(props->getDoubleValue("min")),
904 _has_max(props->hasValue("max")),
905 _max(props->getDoubleValue("max")),
906 _position(props->getDoubleValue("starting-position", 0)),
909 SGPropertyNode *node = props->getChild("condition");
911 _condition = sgReadCondition(prop_root, node);
913 _axis[0] = props->getFloatValue("axis/x", 0);
914 _axis[1] = props->getFloatValue("axis/y", 0);
915 _axis[2] = props->getFloatValue("axis/z", 0);
918 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
919 _texMat = new osg::TexMat;
920 stateSet->setTextureAttribute(0, _texMat.get());
923 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
928 SGTexTranslateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
930 if (!_condition || _condition->test()) {
932 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
933 if (_has_min && _position < _min)
935 if (_has_max && _position > _max)
938 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
941 set_translation(_matrix, _position, _axis);
942 _texMat->setMatrix(_matrix);
948 ////////////////////////////////////////////////////////////////////////
949 // Implementation of SGTexMultipleAnimation
950 ////////////////////////////////////////////////////////////////////////
952 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
953 SGPropertyNode_ptr props )
954 : SGAnimation(props, new osg::Group),
955 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
959 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
960 _transform = new TexTransform [transform_nodes.size()];
962 for (i = 0; i < transform_nodes.size(); i++) {
963 SGPropertyNode_ptr transform_props = transform_nodes[i];
965 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
967 // transform is a translation
968 _transform[i].subtype = 0;
970 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
972 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
973 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
974 _transform[i].step = transform_props->getDoubleValue("step",0.0);
975 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
976 _transform[i].table = read_interpolation_table(transform_props);
977 _transform[i].has_min = transform_props->hasValue("min");
978 _transform[i].min = transform_props->getDoubleValue("min");
979 _transform[i].has_max = transform_props->hasValue("max");
980 _transform[i].max = transform_props->getDoubleValue("max");
981 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
983 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
984 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
985 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
986 _transform[i].axis.normalize();
988 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
990 // transform is a rotation
991 _transform[i].subtype = 1;
993 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
994 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
995 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
996 _transform[i].table = read_interpolation_table(transform_props);
997 _transform[i].has_min = transform_props->hasValue("min-deg");
998 _transform[i].min = transform_props->getDoubleValue("min-deg");
999 _transform[i].has_max = transform_props->hasValue("max-deg");
1000 _transform[i].max = transform_props->getDoubleValue("max-deg");
1001 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
1003 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
1004 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
1005 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
1006 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
1007 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
1008 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
1009 _transform[i].axis.normalize();
1013 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1014 _texMat = new osg::TexMat;
1015 stateSet->setTextureAttribute(0, _texMat.get());
1018 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
1020 delete [] _transform;
1024 SGTexMultipleAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
1027 osg::Matrix tmatrix;
1028 tmatrix.makeIdentity();
1029 for (i = 0; i < _num_transforms; i++) {
1031 if(_transform[i].subtype == 0) {
1033 // subtype 0 is translation
1034 if (_transform[i].table == 0) {
1035 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
1036 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1037 _transform[i].position = _transform[i].min;
1038 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1039 _transform[i].position = _transform[i].max;
1041 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
1044 set_translation(matrix, _transform[i].position, _transform[i].axis);
1045 tmatrix = matrix*tmatrix;
1047 } else if (_transform[i].subtype == 1) {
1049 // subtype 1 is rotation
1051 if (_transform[i].table == 0) {
1052 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
1053 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1054 _transform[i].position = _transform[i].min;
1055 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1056 _transform[i].position = _transform[i].max;
1058 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
1062 set_rotation(matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
1063 tmatrix = matrix*tmatrix;
1066 _texMat->setMatrix(tmatrix);
1072 ////////////////////////////////////////////////////////////////////////
1073 // Implementation of SGAlphaTestAnimation
1074 ////////////////////////////////////////////////////////////////////////
1076 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
1077 : SGAnimation(props, new osg::Group)
1079 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
1082 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
1086 void SGAlphaTestAnimation::init()
1088 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1089 osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
1090 alphaFunc->setFunction(osg::AlphaFunc::GREATER);
1091 alphaFunc->setReferenceValue(_alpha_clamp);
1092 stateSet->setAttribute(alphaFunc);
1093 stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
1094 stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
1095 stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
1100 ////////////////////////////////////////////////////////////////////////
1101 // Implementation of SGMaterialAnimation
1102 ////////////////////////////////////////////////////////////////////////
1104 SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
1105 SGPropertyNode_ptr props, const SGPath &texture_path)
1106 : SGAnimation(props, new osg::Group),
1107 _last_condition(false),
1108 _prop_root(prop_root),
1110 _texture_base(texture_path),
1113 _global(props->getBoolValue("global", false))
1115 SGPropertyNode_ptr n;
1116 n = props->getChild("condition");
1117 _condition = n ? sgReadCondition(_prop_root, n) : 0;
1118 n = props->getChild("property-base");
1120 _prop_base = n->getStringValue();
1121 if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
1125 initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
1126 initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
1127 initColorGroup(props->getChild("emission"), &_emis, EMISSION);
1128 initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
1130 _shi = props->getFloatValue("shininess", -1.0);
1132 _update |= SHININESS;
1134 SGPropertyNode_ptr group = props->getChild("transparency");
1136 _trans.value = group->getFloatValue("alpha", -1.0);
1137 _trans.factor = group->getFloatValue("factor", 1.0);
1138 _trans.offset = group->getFloatValue("offset", 0.0);
1139 _trans.min = group->getFloatValue("min", 0.0);
1140 if (_trans.min < 0.0)
1142 _trans.max = group->getFloatValue("max", 1.0);
1143 if (_trans.max > 1.0)
1146 _update |= TRANSPARENCY;
1148 n = group->getChild("alpha-prop");
1149 _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1150 n = group->getChild("factor-prop");
1151 _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1152 n = group->getChild("offset-prop");
1153 _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1155 _read |= TRANSPARENCY;
1158 _thresh = props->getFloatValue("threshold", -1.0);
1160 _update |= THRESHOLD;
1162 string _texture_str = props->getStringValue("texture", "");
1163 if (!_texture_str.empty()) {
1164 _texture = _texture_base;
1165 _texture.append(_texture_str);
1166 _texture2D = SGLoadTexture2D(_texture);
1170 n = props->getChild("shininess-prop");
1171 _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1172 n = props->getChild("threshold-prop");
1173 _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1174 n = props->getChild("texture-prop");
1175 _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1177 _static_update = _update;
1179 _alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0);
1182 SGMaterialAnimation::~SGMaterialAnimation()
1186 void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
1191 col->red = group->getFloatValue("red", -1.0);
1192 col->green = group->getFloatValue("green", -1.0);
1193 col->blue = group->getFloatValue("blue", -1.0);
1194 col->factor = group->getFloatValue("factor", 1.0);
1195 col->offset = group->getFloatValue("offset", 0.0);
1200 n = group->getChild("red-prop");
1201 col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1202 n = group->getChild("green-prop");
1203 col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1204 n = group->getChild("blue-prop");
1205 col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1206 n = group->getChild("factor-prop");
1207 col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1208 n = group->getChild("offset-prop");
1209 col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1214 void SGMaterialAnimation::init()
1217 cloneMaterials(_branch);
1220 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1221 if (_update & THRESHOLD) {
1222 stateSet->setAttribute(_alphaFunc.get(), osg::StateAttribute::OVERRIDE);
1223 stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
1225 if ((_update & TEXTURE) && _texture2D.valid()) {
1226 stateSet->setTextureAttribute(0, _texture2D.get(), osg::StateAttribute::OVERRIDE);
1227 stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
1232 SGMaterialAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
1235 bool cond = _condition->test();
1236 if (cond && !_last_condition)
1237 _update |= _static_update;
1239 _last_condition = cond;
1246 if (_read & DIFFUSE)
1247 updateColorGroup(&_diff, DIFFUSE);
1248 if (_read & AMBIENT)
1249 updateColorGroup(&_amb, AMBIENT);
1250 if (_read & EMISSION)
1251 updateColorGroup(&_emis, EMISSION);
1252 if (_read & SPECULAR)
1253 updateColorGroup(&_spec, SPECULAR);
1258 _shi = _shi_prop->getFloatValue();
1260 _update |= SHININESS;
1262 if (_read & TRANSPARENCY) {
1263 PropSpec tmp = _trans;
1264 if (_trans.value_prop)
1265 _trans.value = _trans.value_prop->getFloatValue();
1266 if (_trans.factor_prop)
1267 _trans.factor = _trans.factor_prop->getFloatValue();
1268 if (_trans.offset_prop)
1269 _trans.offset = _trans.offset_prop->getFloatValue();
1271 _update |= TRANSPARENCY;
1275 _thresh = _thresh_prop->getFloatValue();
1277 _update |= THRESHOLD;
1280 string t = _tex_prop->getStringValue();
1281 if (!t.empty() && t != _texture_str) {
1283 _texture = _texture_base;
1289 setMaterialBranch(_branch);
1295 void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
1297 ColorSpec tmp = *col;
1299 col->red = col->red_prop->getFloatValue();
1300 if (col->green_prop)
1301 col->green = col->green_prop->getFloatValue();
1303 col->blue = col->blue_prop->getFloatValue();
1304 if (col->factor_prop)
1305 col->factor = col->factor_prop->getFloatValue();
1306 if (col->offset_prop)
1307 col->offset = col->offset_prop->getFloatValue();
1312 class SGMaterialAnimationCloneVisitor : public osg::NodeVisitor {
1314 SGMaterialAnimationCloneVisitor() :
1315 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
1317 setVisitorType(osg::NodeVisitor::NODE_VISITOR);
1319 virtual void apply(osg::Node& node)
1322 osg::StateSet* stateSet = node.getStateSet();
1325 if (1 < stateSet->referenceCount()) {
1326 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
1327 osg::Object* object = stateSet->clone(copyOp);
1328 stateSet = static_cast<osg::StateSet*>(object);
1329 node.setStateSet(stateSet);
1331 cloneMaterial(stateSet);
1333 virtual void apply(osg::Geode& node)
1335 apply((osg::Node&)node);
1337 unsigned nDrawables = node.getNumDrawables();
1338 for (unsigned i = 0; i < nDrawables; ++i) {
1339 osg::Drawable* drawable = node.getDrawable(i);
1340 osg::StateSet* stateSet = drawable->getStateSet();
1343 if (1 < stateSet->referenceCount()) {
1344 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
1345 osg::Object* object = stateSet->clone(copyOp);
1346 stateSet = static_cast<osg::StateSet*>(object);
1347 drawable->setStateSet(stateSet);
1349 cloneMaterial(stateSet);
1352 void cloneMaterial(osg::StateSet* stateSet)
1354 osg::StateAttribute* stateAttr;
1355 stateAttr = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
1358 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATEATTRIBUTES);
1359 osg::Object* object = stateAttr->clone(copyOp);
1360 osg::Material* material = static_cast<osg::Material*>(object);
1361 materialList.push_back(material);
1362 while (stateSet->getAttribute(osg::StateAttribute::MATERIAL)) {
1363 stateSet->removeAttribute(osg::StateAttribute::MATERIAL);
1365 stateSet->setAttribute(material);
1367 std::vector<osg::ref_ptr<osg::Material> > materialList;
1370 void SGMaterialAnimation::cloneMaterials(osg::Group *b)
1372 SGMaterialAnimationCloneVisitor cloneVisitor;
1373 b->accept(cloneVisitor);
1374 _materialList.swap(cloneVisitor.materialList);
1377 void SGMaterialAnimation::setMaterialBranch(osg::Group *b)
1379 std::vector<osg::ref_ptr<osg::Material> >::iterator i;
1380 for (i = _materialList.begin(); i != _materialList.end(); ++i) {
1381 osg::Material* material = i->get();
1382 if (_update & DIFFUSE) {
1383 osg::Vec4 v = _diff.rgba();
1384 float alpha = material->getDiffuse(osg::Material::FRONT_AND_BACK)[3];
1385 material->setColorMode(osg::Material::DIFFUSE);
1386 material->setDiffuse(osg::Material::FRONT_AND_BACK,
1387 osg::Vec4(v[0], v[1], v[2], alpha));
1389 if (_update & AMBIENT) {
1390 material->setColorMode(osg::Material::AMBIENT);
1391 material->setDiffuse(osg::Material::FRONT_AND_BACK, _amb.rgba());
1393 if (_update & EMISSION)
1394 material->setEmission(osg::Material::FRONT_AND_BACK, _emis.rgba());
1395 if (_update & SPECULAR)
1396 material->setSpecular(osg::Material::FRONT_AND_BACK, _spec.rgba());
1397 if (_update & SHININESS)
1398 material->setShininess(osg::Material::FRONT_AND_BACK,
1399 clamp(_shi, 0.0, 128.0));
1400 if (_update & THRESHOLD)
1401 _alphaFunc->setReferenceValue(clamp(_thresh));
1404 if (_update & TRANSPARENCY) {
1405 float trans = _trans.value * _trans.factor + _trans.offset;
1406 trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
1407 SGBlendAnimationVisitor visitor(trans);
1408 _branch->accept(visitor);
1410 if (_update & TEXTURE) {
1412 _texture2D = new osg::Texture2D;
1413 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1414 stateSet->setTextureAttribute(0, _texture2D.get(), osg::StateAttribute::OVERRIDE);
1415 stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
1417 osg::Image* image = osgDB::readImageFile(_texture.str());
1419 _texture2D->setImage(image);
1420 if (image->isImageTranslucent()) {
1421 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1422 stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
1423 stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
1424 stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
1432 ////////////////////////////////////////////////////////////////////////
1433 // Implementation of SGFlashAnimation
1434 ////////////////////////////////////////////////////////////////////////
1435 class SGFlashAnimationTransform : public osg::Transform {
1437 SGFlashAnimationTransform(SGPropertyNode* props)
1439 getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
1441 _axis[0] = props->getFloatValue("axis/x", 0);
1442 _axis[1] = props->getFloatValue("axis/y", 0);
1443 _axis[2] = props->getFloatValue("axis/z", 1);
1446 _center[0] = props->getFloatValue("center/x-m", 0);
1447 _center[1] = props->getFloatValue("center/y-m", 0);
1448 _center[2] = props->getFloatValue("center/z-m", 0);
1450 _offset = props->getFloatValue("offset", 0.0);
1451 _factor = props->getFloatValue("factor", 1.0);
1452 _power = props->getFloatValue("power", 1.0);
1453 _two_sides = props->getBoolValue("two-sides", false);
1455 _min_v = props->getFloatValue("min", 0.0);
1456 _max_v = props->getFloatValue("max", 1.0);
1459 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
1460 osg::NodeVisitor* nv) const
1462 double scale_factor = computeScaleFactor(nv);
1463 osg::Matrix transform;
1464 transform(0,0) = scale_factor;
1465 transform(1,1) = scale_factor;
1466 transform(2,2) = scale_factor;
1467 transform(3,0) = _center[0] * ( 1 - scale_factor );
1468 transform(3,1) = _center[1] * ( 1 - scale_factor );
1469 transform(3,2) = _center[2] * ( 1 - scale_factor );
1470 if (_referenceFrame == RELATIVE_RF)
1471 matrix.preMult(transform);
1478 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
1479 osg::NodeVisitor* nv) const
1481 double scale_factor = computeScaleFactor(nv);
1482 if (fabs(scale_factor) <= std::numeric_limits<double>::min())
1484 osg::Matrix transform;
1485 double rScaleFactor = 1/scale_factor;
1486 transform(0,0) = rScaleFactor;
1487 transform(1,1) = rScaleFactor;
1488 transform(2,2) = rScaleFactor;
1489 transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
1490 transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
1491 transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
1492 if (_referenceFrame == RELATIVE_RF)
1493 matrix.postMult(transform);
1499 double computeScaleFactor(osg::NodeVisitor* nv) const
1504 osg::Vec3 localEyeToCenter = nv->getEyePoint() - _center;
1505 localEyeToCenter.normalize();
1507 double cos_angle = localEyeToCenter*_axis;
1508 double scale_factor = 0;
1509 if ( _two_sides && cos_angle < 0 )
1510 scale_factor = _factor * pow( -cos_angle, _power ) + _offset;
1511 else if ( cos_angle > 0 )
1512 scale_factor = _factor * pow( cos_angle, _power ) + _offset;
1514 if ( scale_factor < _min_v )
1515 scale_factor = _min_v;
1516 if ( scale_factor > _max_v )
1517 scale_factor = _max_v;
1519 return scale_factor;
1523 osg::Vec3 _axis, _center;
1524 double _power, _factor, _offset, _min_v, _max_v;
1528 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
1529 : SGAnimation( props, new SGFlashAnimationTransform(props) )
1533 SGFlashAnimation::~SGFlashAnimation()
1539 ////////////////////////////////////////////////////////////////////////
1540 // Implementation of SGDistScaleAnimation
1541 ////////////////////////////////////////////////////////////////////////
1542 class SGDistScaleTransform : public osg::Transform {
1544 SGDistScaleTransform(SGPropertyNode* props)
1546 getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
1548 _factor = props->getFloatValue("factor", 1.0);
1549 _offset = props->getFloatValue("offset", 0.0);
1550 _min_v = props->getFloatValue("min", 0.0);
1551 _max_v = props->getFloatValue("max", 1.0);
1552 _has_min = props->hasValue("min");
1553 _has_max = props->hasValue("max");
1554 _table = read_interpolation_table(props);
1555 _center[0] = props->getFloatValue("center/x-m", 0);
1556 _center[1] = props->getFloatValue("center/y-m", 0);
1557 _center[2] = props->getFloatValue("center/z-m", 0);
1559 ~SGDistScaleTransform()
1563 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
1564 osg::NodeVisitor* nv) const
1566 osg::Matrix transform;
1567 double scale_factor = computeScaleFactor(nv);
1568 transform(0,0) = scale_factor;
1569 transform(1,1) = scale_factor;
1570 transform(2,2) = scale_factor;
1571 transform(3,0) = _center[0] * ( 1 - scale_factor );
1572 transform(3,1) = _center[1] * ( 1 - scale_factor );
1573 transform(3,2) = _center[2] * ( 1 - scale_factor );
1574 if (_referenceFrame == RELATIVE_RF)
1575 matrix.preMult(transform);
1581 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
1582 osg::NodeVisitor* nv) const
1584 double scale_factor = computeScaleFactor(nv);
1585 if (fabs(scale_factor) <= std::numeric_limits<double>::min())
1587 osg::Matrix transform;
1588 double rScaleFactor = 1/scale_factor;
1589 transform(0,0) = rScaleFactor;
1590 transform(1,1) = rScaleFactor;
1591 transform(2,2) = rScaleFactor;
1592 transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
1593 transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
1594 transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
1595 if (_referenceFrame == RELATIVE_RF)
1596 matrix.postMult(transform);
1602 double computeScaleFactor(osg::NodeVisitor* nv) const
1607 osg::Vec3 localEyeToCenter = _center - nv->getEyePoint();
1608 double scale_factor = localEyeToCenter.length();
1610 scale_factor = _factor * scale_factor + _offset;
1611 if ( _has_min && scale_factor < _min_v )
1612 scale_factor = _min_v;
1613 if ( _has_max && scale_factor > _max_v )
1614 scale_factor = _max_v;
1616 scale_factor = _table->interpolate( scale_factor );
1619 return scale_factor;
1625 float _factor, _offset, _min_v, _max_v;
1626 bool _has_min, _has_max;
1627 SGSharedPtr<SGInterpTable> _table;
1630 SGDistScaleAnimation::SGDistScaleAnimation(SGPropertyNode_ptr props)
1631 : SGAnimation( props, new SGDistScaleTransform(props) )
1635 SGDistScaleAnimation::~SGDistScaleAnimation()
1639 ////////////////////////////////////////////////////////////////////////
1640 // Implementation of SGShadowAnimation
1641 ////////////////////////////////////////////////////////////////////////
1643 SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
1644 SGPropertyNode_ptr props )
1645 : SGAnimation(props, new osg::Group),
1647 _condition_value(true)
1650 SGPropertyNode_ptr node = props->getChild("condition");
1652 _condition = sgReadCondition(prop_root, node);
1653 _condition_value = false;
1657 SGShadowAnimation::~SGShadowAnimation ()
1662 SGShadowAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
1665 _condition_value = _condition->test();
1667 if ( _condition_value ) {
1668 _branch->setNodeMask(SG_NODEMASK_SHADOW_BIT|_branch->getNodeMask());
1670 _branch->setNodeMask(~SG_NODEMASK_SHADOW_BIT&_branch->getNodeMask());
1675 bool SGShadowAnimation::get_condition_value(void) {
1676 return _condition_value;
1679 // end of animation.cxx