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/ColorMatrix>
16 #include <osg/Drawable>
19 #include <osg/MatrixTransform>
20 #include <osg/StateSet>
24 #include <simgear/math/interpolater.hxx>
25 #include <simgear/props/condition.hxx>
26 #include <simgear/props/props.hxx>
27 #include <simgear/math/sg_random.h>
28 #include <simgear/scene/util/SGNodeMasks.hxx>
30 #include "animation.hxx"
34 ////////////////////////////////////////////////////////////////////////
35 // Static utility functions.
36 ////////////////////////////////////////////////////////////////////////
39 * Set up the transform matrix for a spin or rotation.
42 set_rotation (osg::Matrix &matrix, double position_deg,
43 const osg::Vec3 ¢er, const osg::Vec3 &axis)
45 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
47 float s = (float) sin ( temp_angle ) ;
48 float c = (float) cos ( temp_angle ) ;
49 float t = SG_ONE - c ;
51 // axis was normalized at load time
52 // hint to the compiler to put these into FP registers
57 matrix(0, 0) = t * x * x + c ;
58 matrix(0, 1) = t * y * x - s * z ;
59 matrix(0, 2) = t * z * x + s * y ;
60 matrix(0, 3) = SG_ZERO;
62 matrix(1, 0) = t * x * y + s * z ;
63 matrix(1, 1) = t * y * y + c ;
64 matrix(1, 2) = t * z * y - s * x ;
65 matrix(1, 3) = SG_ZERO;
67 matrix(2, 0) = t * x * z - s * y ;
68 matrix(2, 1) = t * y * z + s * x ;
69 matrix(2, 2) = t * z * z + c ;
70 matrix(2, 3) = SG_ZERO;
72 // hint to the compiler to put these into FP registers
77 matrix(3, 0) = x - x*matrix(0, 0) - y*matrix(1, 0) - z*matrix(2, 0);
78 matrix(3, 1) = y - x*matrix(0, 1) - y*matrix(1, 1) - z*matrix(2, 1);
79 matrix(3, 2) = z - x*matrix(0, 2) - y*matrix(1, 2) - z*matrix(2, 2);
80 matrix(3, 3) = SG_ONE;
84 * Set up the transform matrix for a translation.
87 set_translation (osg::Matrix &matrix, double position_m, const osg::Vec3 &axis)
89 osg::Vec3 xyz = axis * position_m;
90 matrix.makeIdentity();
91 matrix(3, 0) = xyz[0];
92 matrix(3, 1) = xyz[1];
93 matrix(3, 2) = xyz[2];
97 * Set up the transform matrix for a scale operation.
100 set_scale (osg::Matrix &matrix, double x, double y, double z)
102 matrix.makeIdentity();
109 * Modify property value by step and scroll settings in texture translations
112 apply_mods(double property, double step, double scroll)
117 double scrollval = 0.0;
119 // calculate scroll amount (for odometer like movement)
120 double remainder = step - fmod(fabs(property), step);
121 if (remainder < scroll) {
122 scrollval = (scroll - remainder) / scroll * step;
125 // apply stepping of input value
127 modprop = ((floor(property/step) * step) + scrollval);
129 modprop = ((ceil(property/step) * step) + scrollval);
138 * Read an interpolation table from properties.
140 static SGInterpTable *
141 read_interpolation_table (SGPropertyNode_ptr props)
143 SGPropertyNode_ptr table_node = props->getNode("interpolation");
144 if (table_node != 0) {
145 SGInterpTable * table = new SGInterpTable();
146 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
147 for (unsigned int i = 0; i < entries.size(); i++)
148 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
149 entries[i]->getDoubleValue("dep", 0.0));
158 ////////////////////////////////////////////////////////////////////////
159 // Implementation of SGAnimation
160 ////////////////////////////////////////////////////////////////////////
162 SGAnimation::SGAnimation (SGPropertyNode_ptr props, osg::Group * branch)
166 _branch->setName(props->getStringValue("name", "Animation"));
167 if ( props->getBoolValue( "enable-hot", true ) ) {
168 _branch->setNodeMask(SG_NODEMASK_TERRAIN_BIT|_branch->getNodeMask());
170 _branch->setNodeMask(~SG_NODEMASK_TERRAIN_BIT&_branch->getNodeMask());
174 SGAnimation::~SGAnimation ()
184 SGAnimation::restore()
189 SGAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
195 ////////////////////////////////////////////////////////////////////////
196 // Implementation of SGNullAnimation
197 ////////////////////////////////////////////////////////////////////////
199 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
200 : SGAnimation(props, new osg::Group)
204 SGNullAnimation::~SGNullAnimation ()
210 ////////////////////////////////////////////////////////////////////////
211 // Implementation of SGRangeAnimation
212 ////////////////////////////////////////////////////////////////////////
214 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
215 SGPropertyNode_ptr props)
216 : SGAnimation(props, new osg::LOD),
217 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
220 SGPropertyNode_ptr node = props->getChild("condition");
222 _condition = sgReadCondition(prop_root, node);
226 node = props->getChild( "min-factor" );
228 _min_factor = props->getFloatValue("min-factor", 1.0);
230 node = props->getChild( "max-factor" );
232 _max_factor = props->getFloatValue("max-factor", 1.0);
234 node = props->getChild( "min-property" );
236 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
237 ranges[0] = _min_prop->getFloatValue() * _min_factor;
239 _min = props->getFloatValue("min-m", 0);
240 ranges[0] = _min * _min_factor;
242 node = props->getChild( "max-property" );
244 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
245 ranges[1] = _max_prop->getFloatValue() * _max_factor;
247 _max = props->getFloatValue("max-m", 0);
248 ranges[1] = _max * _max_factor;
250 static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
253 SGRangeAnimation::~SGRangeAnimation ()
258 SGRangeAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
261 if ( _condition == 0 || _condition->test() ) {
262 if (_min_prop != 0) {
263 ranges[0] = _min_prop->getFloatValue() * _min_factor;
265 ranges[0] = _min * _min_factor;
267 if (_max_prop != 0) {
268 ranges[1] = _max_prop->getFloatValue() * _max_factor;
270 ranges[1] = _max * _max_factor;
274 ranges[1] = 1000000000.f;
276 static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
282 ////////////////////////////////////////////////////////////////////////
283 // Implementation of SGBillboardAnimation
284 ////////////////////////////////////////////////////////////////////////
286 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
287 : SGAnimation(props, new osg::AutoTransform)
290 bool spherical = props->getBoolValue("spherical", true);
291 osg::AutoTransform* autoTrans = static_cast<osg::AutoTransform*>(_branch);
293 autoTrans->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
295 autoTrans->setAutoRotateMode(osg::AutoTransform::NO_ROTATION);
296 autoTrans->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
298 autoTrans->setAutoScaleToScreen(false);
301 SGBillboardAnimation::~SGBillboardAnimation ()
307 ////////////////////////////////////////////////////////////////////////
308 // Implementation of SGSelectAnimation
309 ////////////////////////////////////////////////////////////////////////
311 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
312 SGPropertyNode_ptr props )
313 : SGAnimation(props, new osg::Switch),
316 SGPropertyNode_ptr node = props->getChild("condition");
318 _condition = sgReadCondition(prop_root, node);
321 SGSelectAnimation::~SGSelectAnimation ()
327 SGSelectAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
329 if (_condition != 0 && _condition->test())
330 static_cast<osg::Switch*>(_branch)->setAllChildrenOn();
332 static_cast<osg::Switch*>(_branch)->setAllChildrenOff();
337 ////////////////////////////////////////////////////////////////////////
338 // Implementation of SGSpinAnimation
339 ////////////////////////////////////////////////////////////////////////
341 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
342 SGPropertyNode_ptr props,
343 double sim_time_sec )
344 : SGAnimation(props, new osg::MatrixTransform),
345 _use_personality( props->getBoolValue("use-personality",false) ),
346 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
347 _factor( props, "factor", 1.0 ),
348 _position_deg( props, "starting-position-deg", 0.0 ),
349 _last_time_sec( sim_time_sec ),
352 SGPropertyNode_ptr node = props->getChild("condition");
354 _condition = sgReadCondition(prop_root, node);
359 if (props->hasValue("axis/x1-m")) {
360 double x1,y1,z1,x2,y2,z2;
361 x1 = props->getFloatValue("axis/x1-m");
362 y1 = props->getFloatValue("axis/y1-m");
363 z1 = props->getFloatValue("axis/z1-m");
364 x2 = props->getFloatValue("axis/x2-m");
365 y2 = props->getFloatValue("axis/y2-m");
366 z2 = props->getFloatValue("axis/z2-m");
367 _center[0] = (x1+x2)/2;
368 _center[1]= (y1+y2)/2;
369 _center[2] = (z1+z2)/2;
370 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
371 _axis[0] = (x2-x1)/vector_length;
372 _axis[1] = (y2-y1)/vector_length;
373 _axis[2] = (z2-z1)/vector_length;
375 _axis[0] = props->getFloatValue("axis/x", 0);
376 _axis[1] = props->getFloatValue("axis/y", 0);
377 _axis[2] = props->getFloatValue("axis/z", 0);
379 if (props->hasValue("center/x-m")) {
380 _center[0] = props->getFloatValue("center/x-m", 0);
381 _center[1] = props->getFloatValue("center/y-m", 0);
382 _center[2] = props->getFloatValue("center/z-m", 0);
387 if ( _use_personality ) {
389 _position_deg.shuffle();
393 SGSpinAnimation::~SGSpinAnimation ()
398 SGSpinAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
400 double sim_time_sec = nv->getFrameStamp()->getReferenceTime();
401 if ( _condition == 0 || _condition->test() ) {
404 dt = sim_time_sec - _last_time_sec;
405 _last_time_sec = sim_time_sec;
407 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
408 _position_deg += (dt * velocity_rpms * 360);
409 _position_deg -= 360*floor(_position_deg/360);
412 set_rotation(_matrix, _position_deg, _center, _axis);
413 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
420 ////////////////////////////////////////////////////////////////////////
421 // Implementation of SGTimedAnimation
422 ////////////////////////////////////////////////////////////////////////
424 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
425 : SGAnimation(props, new osg::Switch),
426 _use_personality( props->getBoolValue("use-personality",false) ),
427 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
429 _total_duration_sec( 0 ),
433 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
434 size_t nb = nodes.size();
435 for ( size_t i = 0; i < nb; i++ ) {
436 size_t ind = nodes[ i ]->getIndex();
437 while ( ind >= _branch_duration_specs.size() ) {
438 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
440 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
442 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
444 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
445 rNode->getDoubleValue( "max", 1.0 ) );
450 SGTimedAnimation::~SGTimedAnimation ()
455 SGTimedAnimation::init()
457 if ( !_use_personality ) {
458 for ( unsigned i = 0; i < getBranch()->getNumChildren(); i++ ) {
460 if ( i < _branch_duration_specs.size() ) {
461 DurationSpec &sp = _branch_duration_specs[ i ];
462 v = sp._min + sg_random() * ( sp._max - sp._min );
466 _branch_duration_sec.push_back( v );
467 _total_duration_sec += v;
470 // Sanity check : total duration shouldn't equal zero
471 if (_duration_sec < 0.01)
472 _duration_sec = 0.01;
473 if ( _total_duration_sec < 0.01 )
474 _total_duration_sec = 0.01;
476 static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
480 SGTimedAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
482 double sim_time_sec = nv->getFrameStamp()->getReferenceTime();
483 _last_time_sec -= _total_duration_sec*floor((sim_time_sec - _last_time_sec)/_total_duration_sec);
484 double duration = _duration_sec;
485 if ( _step < _branch_duration_sec.size() ) {
486 duration = _branch_duration_sec[ _step ];
488 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
489 _last_time_sec += duration;
491 if ( _step >= getBranch()->getNumChildren() )
493 static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
500 ////////////////////////////////////////////////////////////////////////
501 // Implementation of SGRotateAnimation
502 ////////////////////////////////////////////////////////////////////////
504 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
505 SGPropertyNode_ptr props )
506 : SGAnimation(props, new osg::MatrixTransform),
507 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
508 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
509 _factor(props->getDoubleValue("factor", 1.0)),
510 _table(read_interpolation_table(props)),
511 _has_min(props->hasValue("min-deg")),
512 _min_deg(props->getDoubleValue("min-deg")),
513 _has_max(props->hasValue("max-deg")),
514 _max_deg(props->getDoubleValue("max-deg")),
515 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
518 SGPropertyNode_ptr node = props->getChild("condition");
520 _condition = sgReadCondition(prop_root, node);
525 if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
526 _axis[0] = props->getFloatValue("axis/x", 0);
527 _axis[1] = props->getFloatValue("axis/y", 0);
528 _axis[2] = props->getFloatValue("axis/z", 0);
530 double x1,y1,z1,x2,y2,z2;
531 x1 = props->getFloatValue("axis/x1-m", 0);
532 y1 = props->getFloatValue("axis/y1-m", 0);
533 z1 = props->getFloatValue("axis/z1-m", 0);
534 x2 = props->getFloatValue("axis/x2-m", 0);
535 y2 = props->getFloatValue("axis/y2-m", 0);
536 z2 = props->getFloatValue("axis/z2-m", 0);
537 _center[0] = (x1+x2)/2;
538 _center[1]= (y1+y2)/2;
539 _center[2] = (z1+z2)/2;
540 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
541 _axis[0] = (x2-x1)/vector_length;
542 _axis[1] = (y2-y1)/vector_length;
543 _axis[2] = (z2-z1)/vector_length;
545 if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
546 || props->hasValue("center/z-m")) {
547 _center[0] = props->getFloatValue("center/x-m", 0);
548 _center[1] = props->getFloatValue("center/y-m", 0);
549 _center[2] = props->getFloatValue("center/z-m", 0);
554 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 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
585 SGPropertyNode_ptr props )
586 : SGAnimation(props, new osg::Group),
587 _use_personality( props->getBoolValue("use-personality",false) ),
588 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
589 _table(read_interpolation_table(props)),
591 _offset(props,"offset",0.0),
592 _factor(props,"factor",1.0),
593 _has_min(props->hasValue("min")),
594 _min(props->getDoubleValue("min", 0.0)),
595 _has_max(props->hasValue("max")),
596 _max(props->getDoubleValue("max", 1.0))
598 // OSGFIXME: does ot work like that!!!
599 // depends on a not so wide available extension
601 _colorMatrix = new osg::ColorMatrix;
602 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
603 stateSet->setAttribute(_colorMatrix.get());
605 if ( _use_personality ) {
611 SGBlendAnimation::~SGBlendAnimation ()
617 SGBlendAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
622 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
624 if (_has_min && (_blend < _min))
626 if (_has_max && (_blend > _max))
629 _blend = _table->interpolate(_prop->getDoubleValue());
632 if (_blend != _prev_value) {
633 _prev_value = _blend;
634 _colorMatrix->getMatrix()(3, 3) = _blend;
641 ////////////////////////////////////////////////////////////////////////
642 // Implementation of SGTranslateAnimation
643 ////////////////////////////////////////////////////////////////////////
645 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
646 SGPropertyNode_ptr props )
647 : SGAnimation(props, new osg::MatrixTransform),
648 _use_personality( props->getBoolValue("use-personality",false) ),
649 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
650 _offset_m( props, "offset-m", 0.0 ),
651 _factor( props, "factor", 1.0 ),
652 _table(read_interpolation_table(props)),
653 _has_min(props->hasValue("min-m")),
654 _min_m(props->getDoubleValue("min-m")),
655 _has_max(props->hasValue("max-m")),
656 _max_m(props->getDoubleValue("max-m")),
657 _position_m(props->getDoubleValue("starting-position-m", 0)),
660 SGPropertyNode_ptr node = props->getChild("condition");
662 _condition = sgReadCondition(prop_root, node);
664 _axis[0] = props->getFloatValue("axis/x", 0);
665 _axis[1] = props->getFloatValue("axis/y", 0);
666 _axis[2] = props->getFloatValue("axis/z", 0);
669 if ( _use_personality ) {
675 SGTranslateAnimation::~SGTranslateAnimation ()
681 SGTranslateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
683 if (_condition == 0 || _condition->test()) {
686 _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
687 if (_has_min && _position_m < _min_m)
688 _position_m = _min_m;
689 if (_has_max && _position_m > _max_m)
690 _position_m = _max_m;
692 _position_m = _table->interpolate(_prop->getDoubleValue());
696 set_translation(_matrix, _position_m, _axis);
697 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
704 ////////////////////////////////////////////////////////////////////////
705 // Implementation of SGScaleAnimation
706 ////////////////////////////////////////////////////////////////////////
708 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
709 SGPropertyNode_ptr props )
710 : SGAnimation(props, new osg::MatrixTransform),
711 _use_personality( props->getBoolValue("use-personality",false) ),
712 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
713 _x_factor(props,"x-factor",1.0),
714 _y_factor(props,"y-factor",1.0),
715 _z_factor(props,"z-factor",1.0),
716 _x_offset(props,"x-offset",1.0),
717 _y_offset(props,"y-offset",1.0),
718 _z_offset(props,"z-offset",1.0),
719 _table(read_interpolation_table(props)),
720 _has_min_x(props->hasValue("x-min")),
721 _has_min_y(props->hasValue("y-min")),
722 _has_min_z(props->hasValue("z-min")),
723 _min_x(props->getDoubleValue("x-min")),
724 _min_y(props->getDoubleValue("y-min")),
725 _min_z(props->getDoubleValue("z-min")),
726 _has_max_x(props->hasValue("x-max")),
727 _has_max_y(props->hasValue("y-max")),
728 _has_max_z(props->hasValue("z-max")),
729 _max_x(props->getDoubleValue("x-max")),
730 _max_y(props->getDoubleValue("y-max")),
731 _max_z(props->getDoubleValue("z-max"))
733 if ( _use_personality ) {
743 SGScaleAnimation::~SGScaleAnimation ()
749 SGScaleAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
752 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
753 if (_has_min_x && _x_scale < _min_x)
755 if (_has_max_x && _x_scale > _max_x)
758 _x_scale = _table->interpolate(_prop->getDoubleValue());
762 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
763 if (_has_min_y && _y_scale < _min_y)
765 if (_has_max_y && _y_scale > _max_y)
768 _y_scale = _table->interpolate(_prop->getDoubleValue());
772 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
773 if (_has_min_z && _z_scale < _min_z)
775 if (_has_max_z && _z_scale > _max_z)
778 _z_scale = _table->interpolate(_prop->getDoubleValue());
782 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
783 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
788 ////////////////////////////////////////////////////////////////////////
789 // Implementation of SGTexRotateAnimation
790 ////////////////////////////////////////////////////////////////////////
792 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
793 SGPropertyNode_ptr props )
794 : SGAnimation(props, new osg::Group),
795 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
796 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
797 _factor(props->getDoubleValue("factor", 1.0)),
798 _table(read_interpolation_table(props)),
799 _has_min(props->hasValue("min-deg")),
800 _min_deg(props->getDoubleValue("min-deg")),
801 _has_max(props->hasValue("max-deg")),
802 _max_deg(props->getDoubleValue("max-deg")),
803 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
806 SGPropertyNode *node = props->getChild("condition");
808 _condition = sgReadCondition(prop_root, node);
810 _center[0] = props->getFloatValue("center/x", 0);
811 _center[1] = props->getFloatValue("center/y", 0);
812 _center[2] = props->getFloatValue("center/z", 0);
813 _axis[0] = props->getFloatValue("axis/x", 0);
814 _axis[1] = props->getFloatValue("axis/y", 0);
815 _axis[2] = props->getFloatValue("axis/z", 0);
818 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
819 _texMat = new osg::TexMat;
820 stateSet->setTextureAttribute(0, _texMat.get());
823 SGTexRotateAnimation::~SGTexRotateAnimation ()
829 SGTexRotateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
831 if (!_condition || _condition->test()) {
833 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
834 if (_has_min && _position_deg < _min_deg)
835 _position_deg = _min_deg;
836 if (_has_max && _position_deg > _max_deg)
837 _position_deg = _max_deg;
839 _position_deg = _table->interpolate(_prop->getDoubleValue());
842 set_rotation(_matrix, _position_deg, _center, _axis);
843 _texMat->setMatrix(_matrix);
849 ////////////////////////////////////////////////////////////////////////
850 // Implementation of SGTexTranslateAnimation
851 ////////////////////////////////////////////////////////////////////////
853 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
854 SGPropertyNode_ptr props )
855 : SGAnimation(props, new osg::Group),
856 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
857 _offset(props->getDoubleValue("offset", 0.0)),
858 _factor(props->getDoubleValue("factor", 1.0)),
859 _step(props->getDoubleValue("step",0.0)),
860 _scroll(props->getDoubleValue("scroll",0.0)),
861 _table(read_interpolation_table(props)),
862 _has_min(props->hasValue("min")),
863 _min(props->getDoubleValue("min")),
864 _has_max(props->hasValue("max")),
865 _max(props->getDoubleValue("max")),
866 _position(props->getDoubleValue("starting-position", 0)),
869 SGPropertyNode *node = props->getChild("condition");
871 _condition = sgReadCondition(prop_root, node);
873 _axis[0] = props->getFloatValue("axis/x", 0);
874 _axis[1] = props->getFloatValue("axis/y", 0);
875 _axis[2] = props->getFloatValue("axis/z", 0);
878 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
879 _texMat = new osg::TexMat;
880 stateSet->setTextureAttribute(0, _texMat.get());
883 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
889 SGTexTranslateAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
891 if (!_condition || _condition->test()) {
893 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
894 if (_has_min && _position < _min)
896 if (_has_max && _position > _max)
899 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
902 set_translation(_matrix, _position, _axis);
903 _texMat->setMatrix(_matrix);
909 ////////////////////////////////////////////////////////////////////////
910 // Implementation of SGTexMultipleAnimation
911 ////////////////////////////////////////////////////////////////////////
913 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
914 SGPropertyNode_ptr props )
915 : SGAnimation(props, new osg::Group),
916 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
920 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
921 _transform = new TexTransform [transform_nodes.size()];
923 for (i = 0; i < transform_nodes.size(); i++) {
924 SGPropertyNode_ptr transform_props = transform_nodes[i];
926 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
928 // transform is a translation
929 _transform[i].subtype = 0;
931 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
933 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
934 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
935 _transform[i].step = transform_props->getDoubleValue("step",0.0);
936 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
937 _transform[i].table = read_interpolation_table(transform_props);
938 _transform[i].has_min = transform_props->hasValue("min");
939 _transform[i].min = transform_props->getDoubleValue("min");
940 _transform[i].has_max = transform_props->hasValue("max");
941 _transform[i].max = transform_props->getDoubleValue("max");
942 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
944 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
945 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
946 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
947 _transform[i].axis.normalize();
949 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
951 // transform is a rotation
952 _transform[i].subtype = 1;
954 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
955 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
956 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
957 _transform[i].table = read_interpolation_table(transform_props);
958 _transform[i].has_min = transform_props->hasValue("min-deg");
959 _transform[i].min = transform_props->getDoubleValue("min-deg");
960 _transform[i].has_max = transform_props->hasValue("max-deg");
961 _transform[i].max = transform_props->getDoubleValue("max-deg");
962 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
964 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
965 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
966 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
967 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
968 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
969 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
970 _transform[i].axis.normalize();
974 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
975 _texMat = new osg::TexMat;
976 stateSet->setTextureAttribute(0, _texMat.get());
979 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
981 delete [] _transform;
985 SGTexMultipleAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
989 tmatrix.makeIdentity();
990 for (i = 0; i < _num_transforms; i++) {
992 if(_transform[i].subtype == 0) {
994 // subtype 0 is translation
995 if (_transform[i].table == 0) {
996 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
997 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
998 _transform[i].position = _transform[i].min;
999 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1000 _transform[i].position = _transform[i].max;
1002 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
1005 set_translation(matrix, _transform[i].position, _transform[i].axis);
1006 tmatrix = matrix*tmatrix;
1008 } else if (_transform[i].subtype == 1) {
1010 // subtype 1 is rotation
1012 if (_transform[i].table == 0) {
1013 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
1014 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1015 _transform[i].position = _transform[i].min;
1016 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1017 _transform[i].position = _transform[i].max;
1019 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
1023 set_rotation(matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
1024 tmatrix = matrix*tmatrix;
1027 _texMat->setMatrix(tmatrix);
1033 ////////////////////////////////////////////////////////////////////////
1034 // Implementation of SGAlphaTestAnimation
1035 ////////////////////////////////////////////////////////////////////////
1037 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
1038 : SGAnimation(props, new osg::Group)
1040 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
1043 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
1047 void SGAlphaTestAnimation::init()
1049 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1050 osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
1051 alphaFunc->setFunction(osg::AlphaFunc::GREATER);
1052 alphaFunc->setReferenceValue(_alpha_clamp);
1053 stateSet->setAttribute(alphaFunc);
1054 stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
1055 stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
1060 ////////////////////////////////////////////////////////////////////////
1061 // Implementation of SGMaterialAnimation
1062 ////////////////////////////////////////////////////////////////////////
1064 SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
1065 SGPropertyNode_ptr props, const SGPath &texture_path)
1066 : SGAnimation(props, new osg::Group),
1067 _last_condition(false),
1068 _prop_root(prop_root),
1070 _texture_base(texture_path),
1073 _global(props->getBoolValue("global", false))
1075 SGPropertyNode_ptr n;
1076 n = props->getChild("condition");
1077 _condition = n ? sgReadCondition(_prop_root, n) : 0;
1078 n = props->getChild("property-base");
1080 _prop_base = n->getStringValue();
1081 if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
1085 initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
1086 initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
1087 initColorGroup(props->getChild("emission"), &_emis, EMISSION);
1088 initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
1090 _shi = props->getFloatValue("shininess", -1.0);
1092 _update |= SHININESS;
1094 SGPropertyNode_ptr group = props->getChild("transparency");
1096 _trans.value = group->getFloatValue("alpha", -1.0);
1097 _trans.factor = group->getFloatValue("factor", 1.0);
1098 _trans.offset = group->getFloatValue("offset", 0.0);
1099 _trans.min = group->getFloatValue("min", 0.0);
1100 if (_trans.min < 0.0)
1102 _trans.max = group->getFloatValue("max", 1.0);
1103 if (_trans.max > 1.0)
1106 _update |= TRANSPARENCY;
1108 n = group->getChild("alpha-prop");
1109 _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1110 n = group->getChild("factor-prop");
1111 _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1112 n = group->getChild("offset-prop");
1113 _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1115 _read |= TRANSPARENCY;
1118 _thresh = props->getFloatValue("threshold", -1.0);
1120 _update |= THRESHOLD;
1122 string _texture_str = props->getStringValue("texture", "");
1123 if (!_texture_str.empty()) {
1124 _texture = _texture_base;
1125 _texture.append(_texture_str);
1126 _texture2D = SGLoadTexture2D(_texture);
1130 n = props->getChild("shininess-prop");
1131 _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1132 n = props->getChild("threshold-prop");
1133 _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1134 n = props->getChild("texture-prop");
1135 _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1137 _static_update = _update;
1139 _alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0);
1142 void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
1147 col->red = group->getFloatValue("red", -1.0);
1148 col->green = group->getFloatValue("green", -1.0);
1149 col->blue = group->getFloatValue("blue", -1.0);
1150 col->factor = group->getFloatValue("factor", 1.0);
1151 col->offset = group->getFloatValue("offset", 0.0);
1156 n = group->getChild("red-prop");
1157 col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1158 n = group->getChild("green-prop");
1159 col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1160 n = group->getChild("blue-prop");
1161 col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1162 n = group->getChild("factor-prop");
1163 col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1164 n = group->getChild("offset-prop");
1165 col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1170 void SGMaterialAnimation::init()
1173 cloneMaterials(_branch);
1176 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1177 if (_update & THRESHOLD) {
1178 stateSet->setAttribute(_alphaFunc.get(), osg::StateAttribute::OVERRIDE);
1179 stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
1181 if (_update & TEXTURE) {
1182 stateSet->setTextureAttribute(0, _texture2D.get(), osg::StateAttribute::OVERRIDE);
1183 stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
1188 SGMaterialAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
1191 bool cond = _condition->test();
1192 if (cond && !_last_condition)
1193 _update |= _static_update;
1195 _last_condition = cond;
1202 if (_read & DIFFUSE)
1203 updateColorGroup(&_diff, DIFFUSE);
1204 if (_read & AMBIENT)
1205 updateColorGroup(&_amb, AMBIENT);
1206 if (_read & EMISSION)
1207 updateColorGroup(&_emis, EMISSION);
1208 if (_read & SPECULAR)
1209 updateColorGroup(&_spec, SPECULAR);
1214 _shi = _shi_prop->getFloatValue();
1216 _update |= SHININESS;
1218 if (_read & TRANSPARENCY) {
1219 PropSpec tmp = _trans;
1220 if (_trans.value_prop)
1221 _trans.value = _trans.value_prop->getFloatValue();
1222 if (_trans.factor_prop)
1223 _trans.factor = _trans.factor_prop->getFloatValue();
1224 if (_trans.offset_prop)
1225 _trans.offset = _trans.offset_prop->getFloatValue();
1227 _update |= TRANSPARENCY;
1231 _thresh = _thresh_prop->getFloatValue();
1233 _update |= THRESHOLD;
1236 string t = _tex_prop->getStringValue();
1237 if (!t.empty() && t != _texture_str) {
1239 _texture = _texture_base;
1245 setMaterialBranch(_branch);
1251 void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
1253 ColorSpec tmp = *col;
1255 col->red = col->red_prop->getFloatValue();
1256 if (col->green_prop)
1257 col->green = col->green_prop->getFloatValue();
1259 col->blue = col->blue_prop->getFloatValue();
1260 if (col->factor_prop)
1261 col->factor = col->factor_prop->getFloatValue();
1262 if (col->offset_prop)
1263 col->offset = col->offset_prop->getFloatValue();
1268 class SGMaterialAnimationCloneVisitor : public osg::NodeVisitor {
1270 SGMaterialAnimationCloneVisitor() :
1271 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
1273 setVisitorType(osg::NodeVisitor::NODE_VISITOR);
1275 virtual void apply(osg::Node& node)
1278 osg::StateSet* stateSet = node.getStateSet();
1281 if (1 < stateSet->referenceCount()) {
1282 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
1283 osg::Object* object = stateSet->clone(copyOp);
1284 stateSet = static_cast<osg::StateSet*>(object);
1285 node.setStateSet(stateSet);
1287 cloneMaterial(stateSet);
1289 virtual void apply(osg::Geode& node)
1291 apply((osg::Node&)node);
1293 unsigned nDrawables = node.getNumDrawables();
1294 for (unsigned i = 0; i < nDrawables; ++i) {
1295 osg::Drawable* drawable = node.getDrawable(i);
1296 osg::StateSet* stateSet = drawable->getStateSet();
1299 if (1 < stateSet->referenceCount()) {
1300 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
1301 osg::Object* object = stateSet->clone(copyOp);
1302 stateSet = static_cast<osg::StateSet*>(object);
1303 drawable->setStateSet(stateSet);
1305 cloneMaterial(stateSet);
1308 void cloneMaterial(osg::StateSet* stateSet)
1311 osg::StateAttribute* stateAttr;
1312 stateAttr = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
1315 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATEATTRIBUTES);
1316 osg::Object* object = stateAttr->clone(copyOp);
1317 osg::Material* material = static_cast<osg::Material*>(object);
1318 materialList.push_back(material);
1319 while (stateSet->getAttribute(osg::StateAttribute::MATERIAL)) {
1320 stateSet->removeAttribute(osg::StateAttribute::MATERIAL);
1322 stateSet->setAttribute(material);
1324 std::vector<osg::Material*> materialList;
1327 void SGMaterialAnimation::cloneMaterials(osg::Group *b)
1329 SGMaterialAnimationCloneVisitor cloneVisitor;
1330 b->accept(cloneVisitor);
1331 _materialList.swap(cloneVisitor.materialList);
1334 void SGMaterialAnimation::setMaterialBranch(osg::Group *b)
1336 std::vector<osg::Material*>::iterator i;
1337 for (i = _materialList.begin(); i != _materialList.end(); ++i) {
1338 osg::Material* material = *i;
1339 if (_update & DIFFUSE) {
1340 osg::Vec4 v = _diff.rgba();
1341 float alpha = material->getDiffuse(osg::Material::FRONT_AND_BACK)[3];
1342 material->setColorMode(osg::Material::DIFFUSE);
1343 material->setDiffuse(osg::Material::FRONT_AND_BACK,
1344 osg::Vec4(v[0], v[1], v[2], alpha));
1346 if (_update & AMBIENT) {
1347 material->setColorMode(osg::Material::AMBIENT);
1348 material->setDiffuse(osg::Material::FRONT_AND_BACK, _amb.rgba());
1350 if (_update & EMISSION)
1351 material->setEmission(osg::Material::FRONT_AND_BACK, _emis.rgba());
1352 if (_update & SPECULAR)
1353 material->setSpecular(osg::Material::FRONT_AND_BACK, _spec.rgba());
1354 if (_update & SHININESS)
1355 material->setShininess(osg::Material::FRONT_AND_BACK,
1356 clamp(_shi, 0.0, 128.0));
1357 if (_update & TRANSPARENCY) {
1358 osg::Vec4 v = material->getDiffuse(osg::Material::FRONT_AND_BACK);
1359 float trans = _trans.value * _trans.factor + _trans.offset;
1360 trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
1361 material->setDiffuse(osg::Material::FRONT_AND_BACK,
1362 osg::Vec4(v[0], v[1], v[2], trans));
1364 if (_update & THRESHOLD)
1365 _alphaFunc->setReferenceValue(clamp(_thresh));
1367 // if (_update & TEXTURE)
1368 // s->setTexture(_texture.c_str());
1369 // if (_update & (TEXTURE|TRANSPARENCY)) {
1370 // SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
1371 // ssgTexture *tex = s->getTexture();
1372 // if ((tex && tex->hasAlpha()) || alpha < 0.999) {
1373 // s->setColourMaterial(GL_DIFFUSE);
1374 // s->enable(GL_COLOR_MATERIAL);
1375 // s->enable(GL_BLEND);
1376 // s->enable(GL_ALPHA_TEST);
1377 // s->setTranslucent();
1378 // s->disable(GL_COLOR_MATERIAL);
1380 // s->disable(GL_BLEND);
1381 // s->disable(GL_ALPHA_TEST);
1390 ////////////////////////////////////////////////////////////////////////
1391 // Implementation of SGFlashAnimation
1392 ////////////////////////////////////////////////////////////////////////
1393 class SGFlashAnimationTransform : public osg::Transform {
1395 SGFlashAnimationTransform(SGPropertyNode* props)
1397 getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
1399 _axis[0] = props->getFloatValue("axis/x", 0);
1400 _axis[1] = props->getFloatValue("axis/y", 0);
1401 _axis[2] = props->getFloatValue("axis/z", 1);
1404 _center[0] = props->getFloatValue("center/x-m", 0);
1405 _center[1] = props->getFloatValue("center/y-m", 0);
1406 _center[2] = props->getFloatValue("center/z-m", 0);
1408 _offset = props->getFloatValue("offset", 0.0);
1409 _factor = props->getFloatValue("factor", 1.0);
1410 _power = props->getFloatValue("power", 1.0);
1411 _two_sides = props->getBoolValue("two-sides", false);
1413 _min_v = props->getFloatValue("min", 0.0);
1414 _max_v = props->getFloatValue("max", 1.0);
1417 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
1418 osg::NodeVisitor* nv) const
1420 double scale_factor = computeScaleFactor(nv);
1421 osg::Matrix transform;
1422 transform(0,0) = scale_factor;
1423 transform(1,1) = scale_factor;
1424 transform(2,2) = scale_factor;
1425 transform(3,0) = _center[0] * ( 1 - scale_factor );
1426 transform(3,1) = _center[1] * ( 1 - scale_factor );
1427 transform(3,2) = _center[2] * ( 1 - scale_factor );
1428 if (_referenceFrame == RELATIVE_RF)
1429 matrix.preMult(transform);
1436 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
1437 osg::NodeVisitor* nv) const
1439 double scale_factor = computeScaleFactor(nv);
1440 if (fabs(scale_factor) <= std::numeric_limits<double>::min())
1442 osg::Matrix transform;
1443 double rScaleFactor = 1/scale_factor;
1444 transform(0,0) = rScaleFactor;
1445 transform(1,1) = rScaleFactor;
1446 transform(2,2) = rScaleFactor;
1447 transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
1448 transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
1449 transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
1450 if (_referenceFrame == RELATIVE_RF)
1451 matrix.postMult(transform);
1457 double computeScaleFactor(osg::NodeVisitor* nv) const
1462 osg::Vec3 localEyeToCenter = nv->getEyePoint() - _center;
1463 localEyeToCenter.normalize();
1465 double cos_angle = localEyeToCenter*_axis;
1466 double scale_factor = 0;
1467 if ( _two_sides && cos_angle < 0 )
1468 scale_factor = _factor * pow( -cos_angle, _power ) + _offset;
1469 else if ( cos_angle > 0 )
1470 scale_factor = _factor * pow( cos_angle, _power ) + _offset;
1472 if ( scale_factor < _min_v )
1473 scale_factor = _min_v;
1474 if ( scale_factor > _max_v )
1475 scale_factor = _max_v;
1477 return scale_factor;
1481 osg::Vec3 _axis, _center;
1482 double _power, _factor, _offset, _min_v, _max_v;
1486 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
1487 : SGAnimation( props, new SGFlashAnimationTransform(props) )
1491 SGFlashAnimation::~SGFlashAnimation()
1497 ////////////////////////////////////////////////////////////////////////
1498 // Implementation of SGDistScaleAnimation
1499 ////////////////////////////////////////////////////////////////////////
1500 class SGDistScaleTransform : public osg::Transform {
1502 SGDistScaleTransform(SGPropertyNode* props)
1504 getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
1506 _factor = props->getFloatValue("factor", 1.0);
1507 _offset = props->getFloatValue("offset", 0.0);
1508 _min_v = props->getFloatValue("min", 0.0);
1509 _max_v = props->getFloatValue("max", 1.0);
1510 _has_min = props->hasValue("min");
1511 _has_max = props->hasValue("max");
1512 _table = read_interpolation_table(props);
1513 _center[0] = props->getFloatValue("center/x-m", 0);
1514 _center[1] = props->getFloatValue("center/y-m", 0);
1515 _center[2] = props->getFloatValue("center/z-m", 0);
1517 ~SGDistScaleTransform()
1522 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
1523 osg::NodeVisitor* nv) const
1525 osg::Matrix transform;
1526 double scale_factor = computeScaleFactor(nv);
1527 transform(0,0) = scale_factor;
1528 transform(1,1) = scale_factor;
1529 transform(2,2) = scale_factor;
1530 transform(3,0) = _center[0] * ( 1 - scale_factor );
1531 transform(3,1) = _center[1] * ( 1 - scale_factor );
1532 transform(3,2) = _center[2] * ( 1 - scale_factor );
1533 if (_referenceFrame == RELATIVE_RF)
1534 matrix.preMult(transform);
1540 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
1541 osg::NodeVisitor* nv) const
1543 double scale_factor = computeScaleFactor(nv);
1544 if (fabs(scale_factor) <= std::numeric_limits<double>::min())
1546 osg::Matrix transform;
1547 double rScaleFactor = 1/scale_factor;
1548 transform(0,0) = rScaleFactor;
1549 transform(1,1) = rScaleFactor;
1550 transform(2,2) = rScaleFactor;
1551 transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
1552 transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
1553 transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
1554 if (_referenceFrame == RELATIVE_RF)
1555 matrix.postMult(transform);
1561 double computeScaleFactor(osg::NodeVisitor* nv) const
1566 osg::Vec3 localEyeToCenter = _center - nv->getEyePoint();
1567 double scale_factor = localEyeToCenter.length();
1569 scale_factor = _factor * scale_factor + _offset;
1570 if ( _has_min && scale_factor < _min_v )
1571 scale_factor = _min_v;
1572 if ( _has_max && scale_factor > _max_v )
1573 scale_factor = _max_v;
1575 scale_factor = _table->interpolate( scale_factor );
1578 return scale_factor;
1584 float _factor, _offset, _min_v, _max_v;
1585 bool _has_min, _has_max;
1586 SGInterpTable * _table;
1589 SGDistScaleAnimation::SGDistScaleAnimation(SGPropertyNode_ptr props)
1590 : SGAnimation( props, new SGDistScaleTransform(props) )
1594 SGDistScaleAnimation::~SGDistScaleAnimation()
1598 ////////////////////////////////////////////////////////////////////////
1599 // Implementation of SGShadowAnimation
1600 ////////////////////////////////////////////////////////////////////////
1602 SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
1603 SGPropertyNode_ptr props )
1604 : SGAnimation(props, new osg::Group),
1606 _condition_value(true)
1609 SGPropertyNode_ptr node = props->getChild("condition");
1611 _condition = sgReadCondition(prop_root, node);
1612 _condition_value = false;
1616 SGShadowAnimation::~SGShadowAnimation ()
1622 SGShadowAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
1625 _condition_value = _condition->test();
1627 if ( _condition_value ) {
1628 _branch->setNodeMask(SG_NODEMASK_SHADOW_BIT|_branch->getNodeMask());
1630 _branch->setNodeMask(~SG_NODEMASK_SHADOW_BIT&_branch->getNodeMask());
1635 bool SGShadowAnimation::get_condition_value(void) {
1636 return _condition_value;
1639 // end of animation.cxx