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"
31 #include "personality.hxx"
35 ////////////////////////////////////////////////////////////////////////
36 // Static utility functions.
37 ////////////////////////////////////////////////////////////////////////
40 * Set up the transform matrix for a spin or rotation.
43 set_rotation (osg::Matrix &matrix, double position_deg,
44 const osg::Vec3 ¢er, const osg::Vec3 &axis)
46 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
48 float s = (float) sin ( temp_angle ) ;
49 float c = (float) cos ( temp_angle ) ;
50 float t = SG_ONE - c ;
52 // axis was normalized at load time
53 // hint to the compiler to put these into FP registers
58 matrix(0, 0) = t * x * x + c ;
59 matrix(0, 1) = t * y * x - s * z ;
60 matrix(0, 2) = t * z * x + s * y ;
61 matrix(0, 3) = SG_ZERO;
63 matrix(1, 0) = t * x * y + s * z ;
64 matrix(1, 1) = t * y * y + c ;
65 matrix(1, 2) = t * z * y - s * x ;
66 matrix(1, 3) = SG_ZERO;
68 matrix(2, 0) = t * x * z - s * y ;
69 matrix(2, 1) = t * y * z + s * x ;
70 matrix(2, 2) = t * z * z + c ;
71 matrix(2, 3) = SG_ZERO;
73 // hint to the compiler to put these into FP registers
78 matrix(3, 0) = x - x*matrix(0, 0) - y*matrix(1, 0) - z*matrix(2, 0);
79 matrix(3, 1) = y - x*matrix(0, 1) - y*matrix(1, 1) - z*matrix(2, 1);
80 matrix(3, 2) = z - x*matrix(0, 2) - y*matrix(1, 2) - z*matrix(2, 2);
81 matrix(3, 3) = SG_ONE;
85 * Set up the transform matrix for a translation.
88 set_translation (osg::Matrix &matrix, double position_m, const osg::Vec3 &axis)
90 osg::Vec3 xyz = axis * position_m;
91 matrix.makeIdentity();
92 matrix(3, 0) = xyz[0];
93 matrix(3, 1) = xyz[1];
94 matrix(3, 2) = xyz[2];
98 * Set up the transform matrix for a scale operation.
101 set_scale (osg::Matrix &matrix, double x, double y, double z)
103 matrix.makeIdentity();
110 * Modify property value by step and scroll settings in texture translations
113 apply_mods(double property, double step, double scroll)
118 double scrollval = 0.0;
120 // calculate scroll amount (for odometer like movement)
121 double remainder = step - fmod(fabs(property), step);
122 if (remainder < scroll) {
123 scrollval = (scroll - remainder) / scroll * step;
126 // apply stepping of input value
128 modprop = ((floor(property/step) * step) + scrollval);
130 modprop = ((ceil(property/step) * step) + scrollval);
139 * Read an interpolation table from properties.
141 static SGInterpTable *
142 read_interpolation_table (SGPropertyNode_ptr props)
144 SGPropertyNode_ptr table_node = props->getNode("interpolation");
145 if (table_node != 0) {
146 SGInterpTable * table = new SGInterpTable();
147 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
148 for (unsigned int i = 0; i < entries.size(); i++)
149 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
150 entries[i]->getDoubleValue("dep", 0.0));
159 ////////////////////////////////////////////////////////////////////////
160 // Implementation of SGAnimation
161 ////////////////////////////////////////////////////////////////////////
163 // Initialize the static data member
164 double SGAnimation::sim_time_sec = 0.0;
165 SGPersonalityBranch *SGAnimation::current_object = 0;
167 SGAnimation::SGAnimation (SGPropertyNode_ptr props, osg::Group * branch)
171 _branch->setName(props->getStringValue("name", "Animation"));
172 if ( props->getBoolValue( "enable-hot", true ) ) {
173 _branch->setNodeMask(SG_NODEMASK_TERRAIN_BIT|_branch->getNodeMask());
175 _branch->setNodeMask(~SG_NODEMASK_TERRAIN_BIT&_branch->getNodeMask());
179 SGAnimation::~SGAnimation ()
189 SGAnimation::update()
195 SGAnimation::restore()
201 ////////////////////////////////////////////////////////////////////////
202 // Implementation of SGNullAnimation
203 ////////////////////////////////////////////////////////////////////////
205 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
206 : SGAnimation(props, new osg::Group)
210 SGNullAnimation::~SGNullAnimation ()
216 ////////////////////////////////////////////////////////////////////////
217 // Implementation of SGRangeAnimation
218 ////////////////////////////////////////////////////////////////////////
220 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
221 SGPropertyNode_ptr props)
222 : SGAnimation(props, new osg::LOD),
223 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
226 SGPropertyNode_ptr node = props->getChild("condition");
228 _condition = sgReadCondition(prop_root, node);
232 node = props->getChild( "min-factor" );
234 _min_factor = props->getFloatValue("min-factor", 1.0);
236 node = props->getChild( "max-factor" );
238 _max_factor = props->getFloatValue("max-factor", 1.0);
240 node = props->getChild( "min-property" );
242 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
243 ranges[0] = _min_prop->getFloatValue() * _min_factor;
245 _min = props->getFloatValue("min-m", 0);
246 ranges[0] = _min * _min_factor;
248 node = props->getChild( "max-property" );
250 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
251 ranges[1] = _max_prop->getFloatValue() * _max_factor;
253 _max = props->getFloatValue("max-m", 0);
254 ranges[1] = _max * _max_factor;
256 static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
259 SGRangeAnimation::~SGRangeAnimation ()
264 SGRangeAnimation::update()
267 if ( _condition == 0 || _condition->test() ) {
268 if (_min_prop != 0) {
269 ranges[0] = _min_prop->getFloatValue() * _min_factor;
271 ranges[0] = _min * _min_factor;
273 if (_max_prop != 0) {
274 ranges[1] = _max_prop->getFloatValue() * _max_factor;
276 ranges[1] = _max * _max_factor;
280 ranges[1] = 1000000000.f;
282 static_cast<osg::LOD*>(_branch)->setRange(0, ranges[0], ranges[1]);
288 ////////////////////////////////////////////////////////////////////////
289 // Implementation of SGBillboardAnimation
290 ////////////////////////////////////////////////////////////////////////
292 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
293 : SGAnimation(props, new osg::AutoTransform)
296 bool spherical = props->getBoolValue("spherical", true);
297 osg::AutoTransform* autoTrans = static_cast<osg::AutoTransform*>(_branch);
299 autoTrans->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
301 autoTrans->setAutoRotateMode(osg::AutoTransform::NO_ROTATION);
302 autoTrans->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
304 autoTrans->setAutoScaleToScreen(false);
307 SGBillboardAnimation::~SGBillboardAnimation ()
313 ////////////////////////////////////////////////////////////////////////
314 // Implementation of SGSelectAnimation
315 ////////////////////////////////////////////////////////////////////////
317 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
318 SGPropertyNode_ptr props )
319 : SGAnimation(props, new osg::Switch),
322 SGPropertyNode_ptr node = props->getChild("condition");
324 _condition = sgReadCondition(prop_root, node);
327 SGSelectAnimation::~SGSelectAnimation ()
333 SGSelectAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
335 if (_condition != 0 && _condition->test())
336 static_cast<osg::Switch*>(_branch)->setAllChildrenOn();
338 static_cast<osg::Switch*>(_branch)->setAllChildrenOff();
343 ////////////////////////////////////////////////////////////////////////
344 // Implementation of SGSpinAnimation
345 ////////////////////////////////////////////////////////////////////////
347 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
348 SGPropertyNode_ptr props,
349 double sim_time_sec )
350 : SGAnimation(props, new osg::MatrixTransform),
351 _use_personality( props->getBoolValue("use-personality",false) ),
352 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
353 _factor( props, "factor", 1.0 ),
354 _position_deg( props, "starting-position-deg", 0.0 ),
355 _last_time_sec( sim_time_sec ),
358 SGPropertyNode_ptr node = props->getChild("condition");
360 _condition = sgReadCondition(prop_root, node);
365 if (props->hasValue("axis/x1-m")) {
366 double x1,y1,z1,x2,y2,z2;
367 x1 = props->getFloatValue("axis/x1-m");
368 y1 = props->getFloatValue("axis/y1-m");
369 z1 = props->getFloatValue("axis/z1-m");
370 x2 = props->getFloatValue("axis/x2-m");
371 y2 = props->getFloatValue("axis/y2-m");
372 z2 = props->getFloatValue("axis/z2-m");
373 _center[0] = (x1+x2)/2;
374 _center[1]= (y1+y2)/2;
375 _center[2] = (z1+z2)/2;
376 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
377 _axis[0] = (x2-x1)/vector_length;
378 _axis[1] = (y2-y1)/vector_length;
379 _axis[2] = (z2-z1)/vector_length;
381 _axis[0] = props->getFloatValue("axis/x", 0);
382 _axis[1] = props->getFloatValue("axis/y", 0);
383 _axis[2] = props->getFloatValue("axis/z", 0);
385 if (props->hasValue("center/x-m")) {
386 _center[0] = props->getFloatValue("center/x-m", 0);
387 _center[1] = props->getFloatValue("center/y-m", 0);
388 _center[2] = props->getFloatValue("center/z-m", 0);
394 SGSpinAnimation::~SGSpinAnimation ()
399 SGSpinAnimation::update()
401 if ( _condition == 0 || _condition->test() ) {
404 if ( _use_personality && current_object ) {
405 SGPersonalityBranch *key = current_object;
406 if ( !key->getIntValue( this, INIT_SPIN ) ) {
407 key->setDoubleValue( _factor.shuffle(), this, FACTOR_SPIN );
408 key->setDoubleValue( _position_deg.shuffle(), this, POSITION_DEG_SPIN );
410 key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC_SPIN );
411 key->setIntValue( 1, this, INIT_SPIN );
414 _factor = key->getDoubleValue( this, FACTOR_SPIN );
415 _position_deg = key->getDoubleValue( this, POSITION_DEG_SPIN );
416 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_SPIN );
417 dt = sim_time_sec - _last_time_sec;
418 _last_time_sec = sim_time_sec;
419 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_SPIN );
421 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
422 _position_deg += (dt * velocity_rpms * 360);
423 _position_deg -= 360*floor(_position_deg/360);
424 key->setDoubleValue( _position_deg, this, POSITION_DEG_SPIN );
426 dt = sim_time_sec - _last_time_sec;
427 _last_time_sec = sim_time_sec;
429 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
430 _position_deg += (dt * velocity_rpms * 360);
431 _position_deg -= 360*floor(_position_deg/360);
435 set_rotation(_matrix, _position_deg, _center, _axis);
436 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
443 ////////////////////////////////////////////////////////////////////////
444 // Implementation of SGTimedAnimation
445 ////////////////////////////////////////////////////////////////////////
447 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
448 : SGAnimation(props, new osg::Switch),
449 _use_personality( props->getBoolValue("use-personality",false) ),
450 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
451 _last_time_sec( sim_time_sec ),
452 _total_duration_sec( 0 ),
456 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
457 size_t nb = nodes.size();
458 for ( size_t i = 0; i < nb; i++ ) {
459 size_t ind = nodes[ i ]->getIndex();
460 while ( ind >= _branch_duration_specs.size() ) {
461 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
463 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
465 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
467 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
468 rNode->getDoubleValue( "max", 1.0 ) );
473 SGTimedAnimation::~SGTimedAnimation ()
478 SGTimedAnimation::init()
480 if ( !_use_personality ) {
481 for ( unsigned i = 0; i < getBranch()->getNumChildren(); i++ ) {
483 if ( i < _branch_duration_specs.size() ) {
484 DurationSpec &sp = _branch_duration_specs[ i ];
485 v = sp._min + sg_random() * ( sp._max - sp._min );
489 _branch_duration_sec.push_back( v );
490 _total_duration_sec += v;
493 // Sanity check : total duration shouldn't equal zero
494 if (_duration_sec < 0.01)
495 _duration_sec = 0.01;
496 if ( _total_duration_sec < 0.01 )
497 _total_duration_sec = 0.01;
499 static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
503 SGTimedAnimation::update()
505 if ( _use_personality && current_object ) {
506 SGPersonalityBranch *key = current_object;
507 if ( !key->getIntValue( this, INIT_TIMED ) ) {
510 for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
511 DurationSpec &sp = _branch_duration_specs[ i ];
512 double v = sp._min + sg_random() * ( sp._max - sp._min );
513 key->setDoubleValue( v, this, BRANCH_DURATION_SEC_TIMED, i );
518 // Sanity check : total duration shouldn't equal zero
519 if ( total < 0.01 ) {
522 offset *= sg_random();
523 key->setDoubleValue( sim_time_sec - offset, this, LAST_TIME_SEC_TIMED );
524 key->setDoubleValue( total, this, TOTAL_DURATION_SEC_TIMED );
525 key->setIntValue( 0, this, STEP_TIMED );
526 key->setIntValue( 1, this, INIT_TIMED );
529 _step = key->getIntValue( this, STEP_TIMED );
530 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_TIMED );
531 _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC_TIMED );
532 _last_time_sec -= _total_duration_sec*floor((sim_time_sec - _last_time_sec)/_total_duration_sec);
533 double duration = _duration_sec;
534 if ( _step < _branch_duration_specs.size() ) {
535 duration = key->getDoubleValue( this, BRANCH_DURATION_SEC_TIMED, _step );
537 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
538 _last_time_sec += duration;
540 if ( _step >= getBranch()->getNumChildren() )
543 static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
544 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_TIMED );
545 key->setIntValue( _step, this, STEP_TIMED );
547 _last_time_sec -= _total_duration_sec*floor((sim_time_sec - _last_time_sec)/_total_duration_sec);
548 double duration = _duration_sec;
549 if ( _step < _branch_duration_sec.size() ) {
550 duration = _branch_duration_sec[ _step ];
552 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
553 _last_time_sec += duration;
555 if ( _step >= getBranch()->getNumChildren() )
557 static_cast<osg::Switch*>(getBranch())->setSingleChildOn(_step);
565 ////////////////////////////////////////////////////////////////////////
566 // Implementation of SGRotateAnimation
567 ////////////////////////////////////////////////////////////////////////
569 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
570 SGPropertyNode_ptr props )
571 : SGAnimation(props, new osg::MatrixTransform),
572 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
573 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
574 _factor(props->getDoubleValue("factor", 1.0)),
575 _table(read_interpolation_table(props)),
576 _has_min(props->hasValue("min-deg")),
577 _min_deg(props->getDoubleValue("min-deg")),
578 _has_max(props->hasValue("max-deg")),
579 _max_deg(props->getDoubleValue("max-deg")),
580 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
583 SGPropertyNode_ptr node = props->getChild("condition");
585 _condition = sgReadCondition(prop_root, node);
590 if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
591 _axis[0] = props->getFloatValue("axis/x", 0);
592 _axis[1] = props->getFloatValue("axis/y", 0);
593 _axis[2] = props->getFloatValue("axis/z", 0);
595 double x1,y1,z1,x2,y2,z2;
596 x1 = props->getFloatValue("axis/x1-m", 0);
597 y1 = props->getFloatValue("axis/y1-m", 0);
598 z1 = props->getFloatValue("axis/z1-m", 0);
599 x2 = props->getFloatValue("axis/x2-m", 0);
600 y2 = props->getFloatValue("axis/y2-m", 0);
601 z2 = props->getFloatValue("axis/z2-m", 0);
602 _center[0] = (x1+x2)/2;
603 _center[1]= (y1+y2)/2;
604 _center[2] = (z1+z2)/2;
605 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
606 _axis[0] = (x2-x1)/vector_length;
607 _axis[1] = (y2-y1)/vector_length;
608 _axis[2] = (z2-z1)/vector_length;
610 if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
611 || props->hasValue("center/z-m")) {
612 _center[0] = props->getFloatValue("center/x-m", 0);
613 _center[1] = props->getFloatValue("center/y-m", 0);
614 _center[2] = props->getFloatValue("center/z-m", 0);
619 SGRotateAnimation::~SGRotateAnimation ()
625 SGRotateAnimation::update()
627 if (_condition == 0 || _condition->test()) {
629 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
630 if (_has_min && _position_deg < _min_deg)
631 _position_deg = _min_deg;
632 if (_has_max && _position_deg > _max_deg)
633 _position_deg = _max_deg;
635 _position_deg = _table->interpolate(_prop->getDoubleValue());
638 set_rotation(_matrix, _position_deg, _center, _axis);
639 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
645 ////////////////////////////////////////////////////////////////////////
646 // Implementation of SGBlendAnimation
647 ////////////////////////////////////////////////////////////////////////
649 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
650 SGPropertyNode_ptr props )
651 : SGAnimation(props, new osg::Group),
652 _use_personality( props->getBoolValue("use-personality",false) ),
653 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
654 _table(read_interpolation_table(props)),
656 _offset(props,"offset",0.0),
657 _factor(props,"factor",1.0),
658 _has_min(props->hasValue("min")),
659 _min(props->getDoubleValue("min", 0.0)),
660 _has_max(props->hasValue("max")),
661 _max(props->getDoubleValue("max", 1.0))
663 // OSGFIXME: does ot work like that!!!
664 // depends on a not so wide available extension
666 _colorMatrix = new osg::ColorMatrix;
667 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
668 stateSet->setAttribute(_colorMatrix.get());
671 SGBlendAnimation::~SGBlendAnimation ()
677 SGBlendAnimation::update()
681 if ( _use_personality && current_object ) {
682 SGPersonalityBranch *key = current_object;
683 if ( !key->getIntValue( this, INIT_BLEND ) ) {
684 key->setDoubleValue( _factor.shuffle(), this, FACTOR_BLEND );
685 key->setDoubleValue( _offset.shuffle(), this, OFFSET_BLEND );
687 key->setIntValue( 1, this, INIT_BLEND );
690 _factor = key->getDoubleValue( this, FACTOR_BLEND );
691 _offset = key->getDoubleValue( this, OFFSET_BLEND );
695 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
697 if (_has_min && (_blend < _min))
699 if (_has_max && (_blend > _max))
702 _blend = _table->interpolate(_prop->getDoubleValue());
705 if (_blend != _prev_value) {
706 _prev_value = _blend;
707 _colorMatrix->getMatrix()(3, 3) = _blend;
714 ////////////////////////////////////////////////////////////////////////
715 // Implementation of SGTranslateAnimation
716 ////////////////////////////////////////////////////////////////////////
718 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
719 SGPropertyNode_ptr props )
720 : SGAnimation(props, new osg::MatrixTransform),
721 _use_personality( props->getBoolValue("use-personality",false) ),
722 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
723 _offset_m( props, "offset-m", 0.0 ),
724 _factor( props, "factor", 1.0 ),
725 _table(read_interpolation_table(props)),
726 _has_min(props->hasValue("min-m")),
727 _min_m(props->getDoubleValue("min-m")),
728 _has_max(props->hasValue("max-m")),
729 _max_m(props->getDoubleValue("max-m")),
730 _position_m(props->getDoubleValue("starting-position-m", 0)),
733 SGPropertyNode_ptr node = props->getChild("condition");
735 _condition = sgReadCondition(prop_root, node);
737 _axis[0] = props->getFloatValue("axis/x", 0);
738 _axis[1] = props->getFloatValue("axis/y", 0);
739 _axis[2] = props->getFloatValue("axis/z", 0);
743 SGTranslateAnimation::~SGTranslateAnimation ()
749 SGTranslateAnimation::update()
751 if (_condition == 0 || _condition->test()) {
752 if ( _use_personality && current_object ) {
753 SGPersonalityBranch *key = current_object;
754 if ( !key->getIntValue( this, INIT_TRANSLATE ) ) {
755 key->setDoubleValue( _factor.shuffle(), this, FACTOR_TRANSLATE );
756 key->setDoubleValue( _offset_m.shuffle(), this, OFFSET_TRANSLATE );
759 _factor = key->getDoubleValue( this, FACTOR_TRANSLATE );
760 _offset_m = key->getDoubleValue( this, OFFSET_TRANSLATE );
762 key->setIntValue( 1, this, INIT_TRANSLATE );
766 _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
767 if (_has_min && _position_m < _min_m)
768 _position_m = _min_m;
769 if (_has_max && _position_m > _max_m)
770 _position_m = _max_m;
772 _position_m = _table->interpolate(_prop->getDoubleValue());
776 set_translation(_matrix, _position_m, _axis);
777 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
784 ////////////////////////////////////////////////////////////////////////
785 // Implementation of SGScaleAnimation
786 ////////////////////////////////////////////////////////////////////////
788 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
789 SGPropertyNode_ptr props )
790 : SGAnimation(props, new osg::MatrixTransform),
791 _use_personality( props->getBoolValue("use-personality",false) ),
792 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
793 _x_factor(props,"x-factor",1.0),
794 _y_factor(props,"y-factor",1.0),
795 _z_factor(props,"z-factor",1.0),
796 _x_offset(props,"x-offset",1.0),
797 _y_offset(props,"y-offset",1.0),
798 _z_offset(props,"z-offset",1.0),
799 _table(read_interpolation_table(props)),
800 _has_min_x(props->hasValue("x-min")),
801 _has_min_y(props->hasValue("y-min")),
802 _has_min_z(props->hasValue("z-min")),
803 _min_x(props->getDoubleValue("x-min")),
804 _min_y(props->getDoubleValue("y-min")),
805 _min_z(props->getDoubleValue("z-min")),
806 _has_max_x(props->hasValue("x-max")),
807 _has_max_y(props->hasValue("y-max")),
808 _has_max_z(props->hasValue("z-max")),
809 _max_x(props->getDoubleValue("x-max")),
810 _max_y(props->getDoubleValue("y-max")),
811 _max_z(props->getDoubleValue("z-max"))
815 SGScaleAnimation::~SGScaleAnimation ()
821 SGScaleAnimation::update()
823 if ( _use_personality && current_object ) {
824 SGPersonalityBranch *key = current_object;
825 if ( !key->getIntValue( this, INIT_SCALE ) ) {
826 key->setDoubleValue( _x_factor.shuffle(), this, X_FACTOR_SCALE );
827 key->setDoubleValue( _x_offset.shuffle(), this, X_OFFSET_SCALE );
828 key->setDoubleValue( _y_factor.shuffle(), this, Y_FACTOR_SCALE );
829 key->setDoubleValue( _y_offset.shuffle(), this, Y_OFFSET_SCALE );
830 key->setDoubleValue( _z_factor.shuffle(), this, Z_FACTOR_SCALE );
831 key->setDoubleValue( _z_offset.shuffle(), this, Z_OFFSET_SCALE );
833 key->setIntValue( 1, this, INIT_SCALE );
836 _x_factor = key->getDoubleValue( this, X_FACTOR_SCALE );
837 _x_offset = key->getDoubleValue( this, X_OFFSET_SCALE );
838 _y_factor = key->getDoubleValue( this, Y_FACTOR_SCALE );
839 _y_offset = key->getDoubleValue( this, Y_OFFSET_SCALE );
840 _z_factor = key->getDoubleValue( this, Z_FACTOR_SCALE );
841 _z_offset = key->getDoubleValue( this, Z_OFFSET_SCALE );
845 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
846 if (_has_min_x && _x_scale < _min_x)
848 if (_has_max_x && _x_scale > _max_x)
851 _x_scale = _table->interpolate(_prop->getDoubleValue());
855 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
856 if (_has_min_y && _y_scale < _min_y)
858 if (_has_max_y && _y_scale > _max_y)
861 _y_scale = _table->interpolate(_prop->getDoubleValue());
865 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
866 if (_has_min_z && _z_scale < _min_z)
868 if (_has_max_z && _z_scale > _max_z)
871 _z_scale = _table->interpolate(_prop->getDoubleValue());
875 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
876 static_cast<osg::MatrixTransform*>(_branch)->setMatrix(_matrix);
881 ////////////////////////////////////////////////////////////////////////
882 // Implementation of SGTexRotateAnimation
883 ////////////////////////////////////////////////////////////////////////
885 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
886 SGPropertyNode_ptr props )
887 : SGAnimation(props, new osg::Group),
888 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
889 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
890 _factor(props->getDoubleValue("factor", 1.0)),
891 _table(read_interpolation_table(props)),
892 _has_min(props->hasValue("min-deg")),
893 _min_deg(props->getDoubleValue("min-deg")),
894 _has_max(props->hasValue("max-deg")),
895 _max_deg(props->getDoubleValue("max-deg")),
896 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
899 SGPropertyNode *node = props->getChild("condition");
901 _condition = sgReadCondition(prop_root, node);
903 _center[0] = props->getFloatValue("center/x", 0);
904 _center[1] = props->getFloatValue("center/y", 0);
905 _center[2] = props->getFloatValue("center/z", 0);
906 _axis[0] = props->getFloatValue("axis/x", 0);
907 _axis[1] = props->getFloatValue("axis/y", 0);
908 _axis[2] = props->getFloatValue("axis/z", 0);
911 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
912 _texMat = new osg::TexMat;
913 stateSet->setTextureAttribute(0, _texMat.get());
916 SGTexRotateAnimation::~SGTexRotateAnimation ()
922 SGTexRotateAnimation::update()
924 if (_condition && !_condition->test())
928 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
929 if (_has_min && _position_deg < _min_deg)
930 _position_deg = _min_deg;
931 if (_has_max && _position_deg > _max_deg)
932 _position_deg = _max_deg;
934 _position_deg = _table->interpolate(_prop->getDoubleValue());
937 set_rotation(_matrix, _position_deg, _center, _axis);
938 _texMat->setMatrix(_matrix);
943 ////////////////////////////////////////////////////////////////////////
944 // Implementation of SGTexTranslateAnimation
945 ////////////////////////////////////////////////////////////////////////
947 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
948 SGPropertyNode_ptr props )
949 : SGAnimation(props, new osg::Group),
950 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
951 _offset(props->getDoubleValue("offset", 0.0)),
952 _factor(props->getDoubleValue("factor", 1.0)),
953 _step(props->getDoubleValue("step",0.0)),
954 _scroll(props->getDoubleValue("scroll",0.0)),
955 _table(read_interpolation_table(props)),
956 _has_min(props->hasValue("min")),
957 _min(props->getDoubleValue("min")),
958 _has_max(props->hasValue("max")),
959 _max(props->getDoubleValue("max")),
960 _position(props->getDoubleValue("starting-position", 0)),
963 SGPropertyNode *node = props->getChild("condition");
965 _condition = sgReadCondition(prop_root, node);
967 _axis[0] = props->getFloatValue("axis/x", 0);
968 _axis[1] = props->getFloatValue("axis/y", 0);
969 _axis[2] = props->getFloatValue("axis/z", 0);
972 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
973 _texMat = new osg::TexMat;
974 stateSet->setTextureAttribute(0, _texMat.get());
977 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
983 SGTexTranslateAnimation::update()
985 if (_condition && !_condition->test())
989 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
990 if (_has_min && _position < _min)
992 if (_has_max && _position > _max)
995 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
998 set_translation(_matrix, _position, _axis);
999 _texMat->setMatrix(_matrix);
1004 ////////////////////////////////////////////////////////////////////////
1005 // Implementation of SGTexMultipleAnimation
1006 ////////////////////////////////////////////////////////////////////////
1008 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
1009 SGPropertyNode_ptr props )
1010 : SGAnimation(props, new osg::Group),
1011 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
1015 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
1016 _transform = new TexTransform [transform_nodes.size()];
1017 _num_transforms = 0;
1018 for (i = 0; i < transform_nodes.size(); i++) {
1019 SGPropertyNode_ptr transform_props = transform_nodes[i];
1021 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
1023 // transform is a translation
1024 _transform[i].subtype = 0;
1026 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
1028 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
1029 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
1030 _transform[i].step = transform_props->getDoubleValue("step",0.0);
1031 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
1032 _transform[i].table = read_interpolation_table(transform_props);
1033 _transform[i].has_min = transform_props->hasValue("min");
1034 _transform[i].min = transform_props->getDoubleValue("min");
1035 _transform[i].has_max = transform_props->hasValue("max");
1036 _transform[i].max = transform_props->getDoubleValue("max");
1037 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
1039 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
1040 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
1041 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
1042 _transform[i].axis.normalize();
1044 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
1046 // transform is a rotation
1047 _transform[i].subtype = 1;
1049 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
1050 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
1051 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
1052 _transform[i].table = read_interpolation_table(transform_props);
1053 _transform[i].has_min = transform_props->hasValue("min-deg");
1054 _transform[i].min = transform_props->getDoubleValue("min-deg");
1055 _transform[i].has_max = transform_props->hasValue("max-deg");
1056 _transform[i].max = transform_props->getDoubleValue("max-deg");
1057 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
1059 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
1060 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
1061 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
1062 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
1063 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
1064 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
1065 _transform[i].axis.normalize();
1069 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1070 _texMat = new osg::TexMat;
1071 stateSet->setTextureAttribute(0, _texMat.get());
1074 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
1076 delete [] _transform;
1080 SGTexMultipleAnimation::update()
1083 osg::Matrix tmatrix;
1084 tmatrix.makeIdentity();
1085 for (i = 0; i < _num_transforms; i++) {
1087 if(_transform[i].subtype == 0) {
1089 // subtype 0 is translation
1090 if (_transform[i].table == 0) {
1091 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
1092 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1093 _transform[i].position = _transform[i].min;
1094 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1095 _transform[i].position = _transform[i].max;
1097 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
1100 set_translation(matrix, _transform[i].position, _transform[i].axis);
1101 tmatrix = matrix*tmatrix;
1103 } else if (_transform[i].subtype == 1) {
1105 // subtype 1 is rotation
1107 if (_transform[i].table == 0) {
1108 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
1109 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1110 _transform[i].position = _transform[i].min;
1111 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1112 _transform[i].position = _transform[i].max;
1114 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
1118 set_rotation(matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
1119 tmatrix = matrix*tmatrix;
1122 _texMat->setMatrix(tmatrix);
1128 ////////////////////////////////////////////////////////////////////////
1129 // Implementation of SGAlphaTestAnimation
1130 ////////////////////////////////////////////////////////////////////////
1132 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
1133 : SGAnimation(props, new osg::Group)
1135 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
1138 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
1142 void SGAlphaTestAnimation::init()
1144 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1145 osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
1146 alphaFunc->setFunction(osg::AlphaFunc::GREATER);
1147 alphaFunc->setReferenceValue(_alpha_clamp);
1148 stateSet->setAttribute(alphaFunc);
1149 stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
1150 stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
1155 ////////////////////////////////////////////////////////////////////////
1156 // Implementation of SGMaterialAnimation
1157 ////////////////////////////////////////////////////////////////////////
1159 SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
1160 SGPropertyNode_ptr props, const SGPath &texture_path)
1161 : SGAnimation(props, new osg::Group),
1162 _last_condition(false),
1163 _prop_root(prop_root),
1165 _texture_base(texture_path),
1168 _global(props->getBoolValue("global", false))
1170 SGPropertyNode_ptr n;
1171 n = props->getChild("condition");
1172 _condition = n ? sgReadCondition(_prop_root, n) : 0;
1173 n = props->getChild("property-base");
1175 _prop_base = n->getStringValue();
1176 if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
1180 initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
1181 initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
1182 initColorGroup(props->getChild("emission"), &_emis, EMISSION);
1183 initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
1185 _shi = props->getFloatValue("shininess", -1.0);
1187 _update |= SHININESS;
1189 SGPropertyNode_ptr group = props->getChild("transparency");
1191 _trans.value = group->getFloatValue("alpha", -1.0);
1192 _trans.factor = group->getFloatValue("factor", 1.0);
1193 _trans.offset = group->getFloatValue("offset", 0.0);
1194 _trans.min = group->getFloatValue("min", 0.0);
1195 if (_trans.min < 0.0)
1197 _trans.max = group->getFloatValue("max", 1.0);
1198 if (_trans.max > 1.0)
1201 _update |= TRANSPARENCY;
1203 n = group->getChild("alpha-prop");
1204 _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1205 n = group->getChild("factor-prop");
1206 _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1207 n = group->getChild("offset-prop");
1208 _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1210 _read |= TRANSPARENCY;
1213 _thresh = props->getFloatValue("threshold", -1.0);
1215 _update |= THRESHOLD;
1217 string _texture_str = props->getStringValue("texture", "");
1218 if (!_texture_str.empty()) {
1219 _texture = _texture_base;
1220 _texture.append(_texture_str);
1224 n = props->getChild("shininess-prop");
1225 _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1226 n = props->getChild("threshold-prop");
1227 _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1228 n = props->getChild("texture-prop");
1229 _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1231 _static_update = _update;
1233 _alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0);
1234 _texture2D = SGLoadTexture2D(_texture);
1237 void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
1242 col->red = group->getFloatValue("red", -1.0);
1243 col->green = group->getFloatValue("green", -1.0);
1244 col->blue = group->getFloatValue("blue", -1.0);
1245 col->factor = group->getFloatValue("factor", 1.0);
1246 col->offset = group->getFloatValue("offset", 0.0);
1251 n = group->getChild("red-prop");
1252 col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1253 n = group->getChild("green-prop");
1254 col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1255 n = group->getChild("blue-prop");
1256 col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1257 n = group->getChild("factor-prop");
1258 col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1259 n = group->getChild("offset-prop");
1260 col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1265 void SGMaterialAnimation::init()
1268 cloneMaterials(_branch);
1271 osg::StateSet* stateSet = _branch->getOrCreateStateSet();
1272 if (_update & THRESHOLD) {
1273 stateSet->setAttribute(_alphaFunc.get(), osg::StateAttribute::OVERRIDE);
1274 stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
1276 if (_update & TEXTURE) {
1277 stateSet->setTextureAttribute(0, _texture2D.get(), osg::StateAttribute::OVERRIDE);
1278 stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
1282 int SGMaterialAnimation::update()
1285 bool cond = _condition->test();
1286 if (cond && !_last_condition)
1287 _update |= _static_update;
1289 _last_condition = cond;
1294 if (_read & DIFFUSE)
1295 updateColorGroup(&_diff, DIFFUSE);
1296 if (_read & AMBIENT)
1297 updateColorGroup(&_amb, AMBIENT);
1298 if (_read & EMISSION)
1299 updateColorGroup(&_emis, EMISSION);
1300 if (_read & SPECULAR)
1301 updateColorGroup(&_spec, SPECULAR);
1306 _shi = _shi_prop->getFloatValue();
1308 _update |= SHININESS;
1310 if (_read & TRANSPARENCY) {
1311 PropSpec tmp = _trans;
1312 if (_trans.value_prop)
1313 _trans.value = _trans.value_prop->getFloatValue();
1314 if (_trans.factor_prop)
1315 _trans.factor = _trans.factor_prop->getFloatValue();
1316 if (_trans.offset_prop)
1317 _trans.offset = _trans.offset_prop->getFloatValue();
1319 _update |= TRANSPARENCY;
1323 _thresh = _thresh_prop->getFloatValue();
1325 _update |= THRESHOLD;
1328 string t = _tex_prop->getStringValue();
1329 if (!t.empty() && t != _texture_str) {
1331 _texture = _texture_base;
1337 setMaterialBranch(_branch);
1343 void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
1345 ColorSpec tmp = *col;
1347 col->red = col->red_prop->getFloatValue();
1348 if (col->green_prop)
1349 col->green = col->green_prop->getFloatValue();
1351 col->blue = col->blue_prop->getFloatValue();
1352 if (col->factor_prop)
1353 col->factor = col->factor_prop->getFloatValue();
1354 if (col->offset_prop)
1355 col->offset = col->offset_prop->getFloatValue();
1360 class SGMaterialAnimationCloneVisitor : public osg::NodeVisitor {
1362 SGMaterialAnimationCloneVisitor() :
1363 osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
1365 setVisitorType(osg::NodeVisitor::NODE_VISITOR);
1367 virtual void apply(osg::Node& node)
1370 osg::StateSet* stateSet = node.getStateSet();
1373 if (1 < stateSet->referenceCount()) {
1374 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
1375 osg::Object* object = stateSet->clone(copyOp);
1376 stateSet = static_cast<osg::StateSet*>(object);
1377 node.setStateSet(stateSet);
1379 cloneMaterial(stateSet);
1381 virtual void apply(osg::Geode& node)
1383 apply((osg::Node&)node);
1385 unsigned nDrawables = node.getNumDrawables();
1386 for (unsigned i = 0; i < nDrawables; ++i) {
1387 osg::Drawable* drawable = node.getDrawable(i);
1388 osg::StateSet* stateSet = drawable->getStateSet();
1391 if (1 < stateSet->referenceCount()) {
1392 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATESETS);
1393 osg::Object* object = stateSet->clone(copyOp);
1394 stateSet = static_cast<osg::StateSet*>(object);
1395 drawable->setStateSet(stateSet);
1397 cloneMaterial(stateSet);
1400 void cloneMaterial(osg::StateSet* stateSet)
1403 osg::StateAttribute* stateAttr;
1404 stateAttr = stateSet->getAttribute(osg::StateAttribute::MATERIAL);
1407 osg::CopyOp copyOp(osg::CopyOp::DEEP_COPY_STATEATTRIBUTES);
1408 osg::Object* object = stateAttr->clone(copyOp);
1409 osg::Material* material = static_cast<osg::Material*>(object);
1410 materialList.push_back(material);
1411 while (stateSet->getAttribute(osg::StateAttribute::MATERIAL)) {
1412 stateSet->removeAttribute(osg::StateAttribute::MATERIAL);
1414 stateSet->setAttribute(material);
1416 std::vector<osg::Material*> materialList;
1419 void SGMaterialAnimation::cloneMaterials(osg::Group *b)
1421 SGMaterialAnimationCloneVisitor cloneVisitor;
1422 b->accept(cloneVisitor);
1423 _materialList.swap(cloneVisitor.materialList);
1426 void SGMaterialAnimation::setMaterialBranch(osg::Group *b)
1428 std::vector<osg::Material*>::iterator i;
1429 for (i = _materialList.begin(); i != _materialList.end(); ++i) {
1430 osg::Material* material = *i;
1431 if (_update & DIFFUSE) {
1432 osg::Vec4 v = _diff.rgba();
1433 float alpha = material->getDiffuse(osg::Material::FRONT_AND_BACK)[3];
1434 material->setColorMode(osg::Material::DIFFUSE);
1435 material->setDiffuse(osg::Material::FRONT_AND_BACK,
1436 osg::Vec4(v[0], v[1], v[2], alpha));
1438 if (_update & AMBIENT) {
1439 material->setColorMode(osg::Material::AMBIENT);
1440 material->setDiffuse(osg::Material::FRONT_AND_BACK, _amb.rgba());
1442 if (_update & EMISSION)
1443 material->setEmission(osg::Material::FRONT_AND_BACK, _emis.rgba());
1444 if (_update & SPECULAR)
1445 material->setSpecular(osg::Material::FRONT_AND_BACK, _spec.rgba());
1446 if (_update & SHININESS)
1447 material->setShininess(osg::Material::FRONT_AND_BACK,
1448 clamp(_shi, 0.0, 128.0));
1449 if (_update & TRANSPARENCY) {
1450 osg::Vec4 v = material->getDiffuse(osg::Material::FRONT_AND_BACK);
1451 float trans = _trans.value * _trans.factor + _trans.offset;
1452 trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
1453 material->setDiffuse(osg::Material::FRONT_AND_BACK,
1454 osg::Vec4(v[0], v[1], v[2], trans));
1456 if (_update & THRESHOLD)
1457 _alphaFunc->setReferenceValue(clamp(_thresh));
1459 // if (_update & TEXTURE)
1460 // s->setTexture(_texture.c_str());
1461 // if (_update & (TEXTURE|TRANSPARENCY)) {
1462 // SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
1463 // ssgTexture *tex = s->getTexture();
1464 // if ((tex && tex->hasAlpha()) || alpha < 0.999) {
1465 // s->setColourMaterial(GL_DIFFUSE);
1466 // s->enable(GL_COLOR_MATERIAL);
1467 // s->enable(GL_BLEND);
1468 // s->enable(GL_ALPHA_TEST);
1469 // s->setTranslucent();
1470 // s->disable(GL_COLOR_MATERIAL);
1472 // s->disable(GL_BLEND);
1473 // s->disable(GL_ALPHA_TEST);
1482 ////////////////////////////////////////////////////////////////////////
1483 // Implementation of SGFlashAnimation
1484 ////////////////////////////////////////////////////////////////////////
1485 class SGFlashAnimationTransform : public osg::Transform {
1487 SGFlashAnimationTransform(SGPropertyNode* props)
1489 getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
1491 _axis[0] = props->getFloatValue("axis/x", 0);
1492 _axis[1] = props->getFloatValue("axis/y", 0);
1493 _axis[2] = props->getFloatValue("axis/z", 1);
1496 _center[0] = props->getFloatValue("center/x-m", 0);
1497 _center[1] = props->getFloatValue("center/y-m", 0);
1498 _center[2] = props->getFloatValue("center/z-m", 0);
1500 _offset = props->getFloatValue("offset", 0.0);
1501 _factor = props->getFloatValue("factor", 1.0);
1502 _power = props->getFloatValue("power", 1.0);
1503 _two_sides = props->getBoolValue("two-sides", false);
1505 _min_v = props->getFloatValue("min", 0.0);
1506 _max_v = props->getFloatValue("max", 1.0);
1509 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
1510 osg::NodeVisitor* nv) const
1512 double scale_factor = computeScaleFactor(nv);
1513 osg::Matrix transform;
1514 transform(0,0) = scale_factor;
1515 transform(1,1) = scale_factor;
1516 transform(2,2) = scale_factor;
1517 transform(3,0) = _center[0] * ( 1 - scale_factor );
1518 transform(3,1) = _center[1] * ( 1 - scale_factor );
1519 transform(3,2) = _center[2] * ( 1 - scale_factor );
1520 if (_referenceFrame == RELATIVE_RF)
1521 matrix.preMult(transform);
1528 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
1529 osg::NodeVisitor* nv) const
1531 double scale_factor = computeScaleFactor(nv);
1532 if (fabs(scale_factor) <= std::numeric_limits<double>::min())
1534 osg::Matrix transform;
1535 double rScaleFactor = 1/scale_factor;
1536 transform(0,0) = rScaleFactor;
1537 transform(1,1) = rScaleFactor;
1538 transform(2,2) = rScaleFactor;
1539 transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
1540 transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
1541 transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
1542 if (_referenceFrame == RELATIVE_RF)
1543 matrix.postMult(transform);
1549 double computeScaleFactor(osg::NodeVisitor* nv) const
1554 osg::Vec3 localEyeToCenter = nv->getEyePoint() - _center;
1555 localEyeToCenter.normalize();
1557 double cos_angle = localEyeToCenter*_axis;
1558 double scale_factor = 0;
1559 if ( _two_sides && cos_angle < 0 )
1560 scale_factor = _factor * pow( -cos_angle, _power ) + _offset;
1561 else if ( cos_angle > 0 )
1562 scale_factor = _factor * pow( cos_angle, _power ) + _offset;
1564 if ( scale_factor < _min_v )
1565 scale_factor = _min_v;
1566 if ( scale_factor > _max_v )
1567 scale_factor = _max_v;
1569 return scale_factor;
1573 osg::Vec3 _axis, _center;
1574 double _power, _factor, _offset, _min_v, _max_v;
1578 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
1579 : SGAnimation( props, new SGFlashAnimationTransform(props) )
1583 SGFlashAnimation::~SGFlashAnimation()
1589 ////////////////////////////////////////////////////////////////////////
1590 // Implementation of SGDistScaleAnimation
1591 ////////////////////////////////////////////////////////////////////////
1592 class SGDistScaleTransform : public osg::Transform {
1594 SGDistScaleTransform(SGPropertyNode* props)
1596 getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
1598 _factor = props->getFloatValue("factor", 1.0);
1599 _offset = props->getFloatValue("offset", 0.0);
1600 _min_v = props->getFloatValue("min", 0.0);
1601 _max_v = props->getFloatValue("max", 1.0);
1602 _has_min = props->hasValue("min");
1603 _has_max = props->hasValue("max");
1604 _table = read_interpolation_table(props);
1605 _center[0] = props->getFloatValue("center/x-m", 0);
1606 _center[1] = props->getFloatValue("center/y-m", 0);
1607 _center[2] = props->getFloatValue("center/z-m", 0);
1609 ~SGDistScaleTransform()
1614 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
1615 osg::NodeVisitor* nv) const
1617 osg::Matrix transform;
1618 double scale_factor = computeScaleFactor(nv);
1619 transform(0,0) = scale_factor;
1620 transform(1,1) = scale_factor;
1621 transform(2,2) = scale_factor;
1622 transform(3,0) = _center[0] * ( 1 - scale_factor );
1623 transform(3,1) = _center[1] * ( 1 - scale_factor );
1624 transform(3,2) = _center[2] * ( 1 - scale_factor );
1625 if (_referenceFrame == RELATIVE_RF)
1626 matrix.preMult(transform);
1632 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
1633 osg::NodeVisitor* nv) const
1635 double scale_factor = computeScaleFactor(nv);
1636 if (fabs(scale_factor) <= std::numeric_limits<double>::min())
1638 osg::Matrix transform;
1639 double rScaleFactor = 1/scale_factor;
1640 transform(0,0) = rScaleFactor;
1641 transform(1,1) = rScaleFactor;
1642 transform(2,2) = rScaleFactor;
1643 transform(3,0) = rScaleFactor*_center[0] * ( scale_factor - 1 );
1644 transform(3,1) = rScaleFactor*_center[1] * ( scale_factor - 1 );
1645 transform(3,2) = rScaleFactor*_center[2] * ( scale_factor - 1 );
1646 if (_referenceFrame == RELATIVE_RF)
1647 matrix.postMult(transform);
1653 double computeScaleFactor(osg::NodeVisitor* nv) const
1658 osg::Vec3 localEyeToCenter = _center - nv->getEyePoint();
1659 double scale_factor = localEyeToCenter.length();
1661 scale_factor = _factor * scale_factor + _offset;
1662 if ( _has_min && scale_factor < _min_v )
1663 scale_factor = _min_v;
1664 if ( _has_max && scale_factor > _max_v )
1665 scale_factor = _max_v;
1667 scale_factor = _table->interpolate( scale_factor );
1670 return scale_factor;
1676 float _factor, _offset, _min_v, _max_v;
1677 bool _has_min, _has_max;
1678 SGInterpTable * _table;
1681 SGDistScaleAnimation::SGDistScaleAnimation(SGPropertyNode_ptr props)
1682 : SGAnimation( props, new SGDistScaleTransform(props) )
1686 SGDistScaleAnimation::~SGDistScaleAnimation()
1690 ////////////////////////////////////////////////////////////////////////
1691 // Implementation of SGShadowAnimation
1692 ////////////////////////////////////////////////////////////////////////
1694 SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
1695 SGPropertyNode_ptr props )
1696 : SGAnimation(props, new osg::Group),
1698 _condition_value(true)
1701 SGPropertyNode_ptr node = props->getChild("condition");
1703 _condition = sgReadCondition(prop_root, node);
1704 _condition_value = false;
1708 SGShadowAnimation::~SGShadowAnimation ()
1714 SGShadowAnimation::update()
1717 _condition_value = _condition->test();
1719 if ( _condition_value ) {
1720 _branch->setNodeMask(SG_NODEMASK_SHADOW_BIT|_branch->getNodeMask());
1722 _branch->setNodeMask(~SG_NODEMASK_SHADOW_BIT&_branch->getNodeMask());
1727 bool SGShadowAnimation::get_condition_value(void) {
1728 return _condition_value;
1731 // end of animation.cxx