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 <string.h> // for strcmp()
14 #include <simgear/math/interpolater.hxx>
15 #include <simgear/props/condition.hxx>
16 #include <simgear/props/props.hxx>
17 #include <simgear/math/sg_random.h>
19 #include "animation.hxx"
21 #include "personality.hxx"
24 ////////////////////////////////////////////////////////////////////////
25 // Static utility functions.
26 ////////////////////////////////////////////////////////////////////////
29 * Set up the transform matrix for a spin or rotation.
32 set_rotation (sgMat4 &matrix, double position_deg,
33 sgVec3 ¢er, sgVec3 &axis)
35 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
37 float s = (float) sin ( temp_angle ) ;
38 float c = (float) cos ( temp_angle ) ;
39 float t = SG_ONE - c ;
41 // axis was normalized at load time
42 // hint to the compiler to put these into FP registers
47 matrix[0][0] = t * x * x + c ;
48 matrix[0][1] = t * y * x - s * z ;
49 matrix[0][2] = t * z * x + s * y ;
50 matrix[0][3] = SG_ZERO;
52 matrix[1][0] = t * x * y + s * z ;
53 matrix[1][1] = t * y * y + c ;
54 matrix[1][2] = t * z * y - s * x ;
55 matrix[1][3] = SG_ZERO;
57 matrix[2][0] = t * x * z - s * y ;
58 matrix[2][1] = t * y * z + s * x ;
59 matrix[2][2] = t * z * z + c ;
60 matrix[2][3] = SG_ZERO;
62 // hint to the compiler to put these into FP registers
67 matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0];
68 matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1];
69 matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2];
70 matrix[3][3] = SG_ONE;
74 * Set up the transform matrix for a translation.
77 set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
80 sgScaleVec3(xyz, axis, position_m);
81 sgMakeTransMat4(matrix, xyz);
85 * Set up the transform matrix for a scale operation.
88 set_scale (sgMat4 &matrix, double x, double y, double z)
90 sgMakeIdentMat4( matrix );
97 * Recursively process all kids to change the alpha values
100 change_alpha( ssgBase *_branch, float _blend )
104 for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
105 change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
107 if ( !_branch->isAKindOf(ssgTypeLeaf())
108 && !_branch->isAKindOf(ssgTypeVtxTable())
109 && !_branch->isAKindOf(ssgTypeVTable()) )
112 int num_colors = ((ssgLeaf *)_branch)->getNumColours();
113 // unsigned int select_ = (_blend == 1.0) ? false : true;
115 for (i = 0; i < num_colors; i++)
117 // ((ssgSelector *)_branch)->select( select_ );
118 float *color = ((ssgLeaf *)_branch)->getColour(i);
124 * Modify property value by step and scroll settings in texture translations
127 apply_mods(double property, double step, double scroll)
132 double scrollval = 0.0;
134 // calculate scroll amount (for odometer like movement)
135 double remainder = step - fmod(fabs(property), step);
136 if (remainder < scroll) {
137 scrollval = (scroll - remainder) / scroll * step;
140 // apply stepping of input value
142 modprop = ((floor(property/step) * step) + scrollval);
144 modprop = ((ceil(property/step) * step) + scrollval);
153 * Read an interpolation table from properties.
155 static SGInterpTable *
156 read_interpolation_table (SGPropertyNode_ptr props)
158 SGPropertyNode_ptr table_node = props->getNode("interpolation");
159 if (table_node != 0) {
160 SGInterpTable * table = new SGInterpTable();
161 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
162 for (unsigned int i = 0; i < entries.size(); i++)
163 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
164 entries[i]->getDoubleValue("dep", 0.0));
173 ////////////////////////////////////////////////////////////////////////
174 // Implementation of SGAnimation
175 ////////////////////////////////////////////////////////////////////////
177 // Initialize the static data member
178 double SGAnimation::sim_time_sec = 0.0;
179 SGPersonalityBranch *SGAnimation::current_object = 0;
181 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
184 _branch->setName(props->getStringValue("name", 0));
187 SGAnimation::~SGAnimation ()
197 SGAnimation::update()
203 SGAnimation::restore()
209 ////////////////////////////////////////////////////////////////////////
210 // Implementation of SGNullAnimation
211 ////////////////////////////////////////////////////////////////////////
213 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
214 : SGAnimation(props, new ssgBranch)
218 SGNullAnimation::~SGNullAnimation ()
224 ////////////////////////////////////////////////////////////////////////
225 // Implementation of SGRangeAnimation
226 ////////////////////////////////////////////////////////////////////////
228 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
229 SGPropertyNode_ptr props)
230 : SGAnimation(props, new ssgRangeSelector),
231 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
234 SGPropertyNode_ptr node = props->getChild("condition");
236 _condition = sgReadCondition(prop_root, node);
240 node = props->getChild( "min-factor" );
242 _min_factor = props->getFloatValue("min-factor", 1.0);
244 node = props->getChild( "max-factor" );
246 _max_factor = props->getFloatValue("max-factor", 1.0);
248 node = props->getChild( "min-property" );
250 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
251 ranges[0] = _min_prop->getFloatValue() * _min_factor;
253 _min = props->getFloatValue("min-m", 0);
254 ranges[0] = _min * _min_factor;
256 node = props->getChild( "max-property" );
258 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
259 ranges[1] = _max_prop->getFloatValue() * _max_factor;
261 _max = props->getFloatValue("max-m", 0);
262 ranges[1] = _max * _max_factor;
264 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
267 SGRangeAnimation::~SGRangeAnimation ()
272 SGRangeAnimation::update()
275 if ( _condition == 0 || _condition->test() ) {
276 if (_min_prop != 0) {
277 ranges[0] = _min_prop->getFloatValue() * _min_factor;
279 ranges[0] = _min * _min_factor;
281 if (_max_prop != 0) {
282 ranges[1] = _max_prop->getFloatValue() * _max_factor;
284 ranges[1] = _max * _max_factor;
288 ranges[1] = 1000000000.f;
290 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
296 ////////////////////////////////////////////////////////////////////////
297 // Implementation of SGBillboardAnimation
298 ////////////////////////////////////////////////////////////////////////
300 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
301 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
305 SGBillboardAnimation::~SGBillboardAnimation ()
311 ////////////////////////////////////////////////////////////////////////
312 // Implementation of SGSelectAnimation
313 ////////////////////////////////////////////////////////////////////////
315 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
316 SGPropertyNode_ptr props )
317 : SGAnimation(props, new ssgSelector),
320 SGPropertyNode_ptr node = props->getChild("condition");
322 _condition = sgReadCondition(prop_root, node);
325 SGSelectAnimation::~SGSelectAnimation ()
331 SGSelectAnimation::update()
333 if (_condition != 0 && _condition->test())
334 ((ssgSelector *)_branch)->select(0xffff);
336 ((ssgSelector *)_branch)->select(0x0000);
342 ////////////////////////////////////////////////////////////////////////
343 // Implementation of SGSpinAnimation
344 ////////////////////////////////////////////////////////////////////////
346 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
347 SGPropertyNode_ptr props,
348 double sim_time_sec )
349 : SGAnimation(props, new ssgTransform),
350 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
351 _factor(props->getDoubleValue("factor", 1.0)),
352 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
353 _last_time_sec( sim_time_sec ),
356 SGPropertyNode_ptr node = props->getChild("condition");
358 _condition = sgReadCondition(prop_root, node);
363 if (props->hasValue("axis/x1-m")) {
364 double x1,y1,z1,x2,y2,z2;
365 x1 = props->getFloatValue("axis/x1-m");
366 y1 = props->getFloatValue("axis/y1-m");
367 z1 = props->getFloatValue("axis/z1-m");
368 x2 = props->getFloatValue("axis/x2-m");
369 y2 = props->getFloatValue("axis/y2-m");
370 z2 = props->getFloatValue("axis/z2-m");
371 _center[0] = (x1+x2)/2;
372 _center[1]= (y1+y2)/2;
373 _center[2] = (z1+z2)/2;
374 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
375 _axis[0] = (x2-x1)/vector_length;
376 _axis[1] = (y2-y1)/vector_length;
377 _axis[2] = (z2-z1)/vector_length;
379 _axis[0] = props->getFloatValue("axis/x", 0);
380 _axis[1] = props->getFloatValue("axis/y", 0);
381 _axis[2] = props->getFloatValue("axis/z", 0);
383 if (props->hasValue("center/x-m")) {
384 _center[0] = props->getFloatValue("center/x-m", 0);
385 _center[1] = props->getFloatValue("center/y-m", 0);
386 _center[2] = props->getFloatValue("center/z-m", 0);
388 sgNormalizeVec3(_axis);
391 SGSpinAnimation::~SGSpinAnimation ()
396 SGSpinAnimation::update()
398 if ( _condition == 0 || _condition->test() ) {
399 double dt = sim_time_sec - _last_time_sec;
400 _last_time_sec = sim_time_sec;
402 float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
403 _position_deg += (dt * velocity_rpms * 360);
404 while (_position_deg < 0)
405 _position_deg += 360.0;
406 while (_position_deg >= 360.0)
407 _position_deg -= 360.0;
408 set_rotation(_matrix, _position_deg, _center, _axis);
409 ((ssgTransform *)_branch)->setTransform(_matrix);
416 ////////////////////////////////////////////////////////////////////////
417 // Implementation of SGTimedAnimation
418 ////////////////////////////////////////////////////////////////////////
420 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
421 : SGAnimation(props, new ssgSelector),
422 _use_personality( props->getBoolValue("use-personality",false) ),
423 _total_duration_sec( 0 ),
427 SGPropertyNode_ptr dNode = props->getChild( "duration-sec" );
431 SGPropertyNode_ptr rNode = dNode->getChild("random");
433 _duration_sec = dNode->getDoubleValue();
435 double dmin = rNode->getDoubleValue( "min", 0.0 ),
436 dmax = rNode->getDoubleValue( "max", 1.0 );
437 _duration_sec = dmin + sg_random() * ( dmax - dmin );
441 _last_time_sec = sim_time_sec - _duration_sec;
443 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
444 size_t nb = nodes.size();
445 for ( size_t i = 0; i < nb; i++ ) {
446 size_t ind = nodes[ i ]->getIndex();
447 while ( ind >= _branch_duration_specs.size() ) {
448 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
450 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
452 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
454 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
455 rNode->getDoubleValue( "max", 1.0 ) );
458 if ( !_use_personality ) {
459 for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
460 DurationSpec &sp = _branch_duration_specs[ i ];
461 double v = sp._min + sg_random() * ( sp._max - sp._min );
462 _branch_duration_sec.push_back( v );
463 _total_duration_sec += v;
466 ((ssgSelector *)getBranch())->selectStep(_step);
469 SGTimedAnimation::~SGTimedAnimation ()
474 SGTimedAnimation::update()
476 if ( _use_personality ) {
477 SGPersonalityBranch *key = current_object;
478 if ( !key->getIntValue( this, INIT ) ) {
480 for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
481 DurationSpec &sp = _branch_duration_specs[ i ];
482 double v = sp._min + sg_random() * ( sp._max - sp._min );
483 key->setDoubleValue( v, this, BRANCH_DURATION_SEC, i );
486 key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC );
487 key->setDoubleValue( total, this, TOTAL_DURATION_SEC );
488 key->setIntValue( 0, this, STEP );
489 key->setIntValue( 1, this, INIT );
492 _step = key->getIntValue( this, STEP );
493 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC );
494 _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC );
495 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
496 _last_time_sec += _total_duration_sec;
498 double duration = _duration_sec;
499 if ( _step < (int)_branch_duration_specs.size() ) {
500 duration = key->getDoubleValue( this, BRANCH_DURATION_SEC, _step );
502 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
503 _last_time_sec += duration;
505 if ( _step >= getBranch()->getNumKids() )
508 ((ssgSelector *)getBranch())->selectStep( _step );
509 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC );
510 key->setIntValue( _step, this, STEP );
512 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
513 _last_time_sec += _total_duration_sec;
515 double duration = _duration_sec;
516 if ( _step < (int)_branch_duration_sec.size() ) {
517 duration = _branch_duration_sec[ _step ];
519 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
520 _last_time_sec += duration;
522 if ( _step >= getBranch()->getNumKids() )
524 ((ssgSelector *)getBranch())->selectStep( _step );
532 ////////////////////////////////////////////////////////////////////////
533 // Implementation of SGRotateAnimation
534 ////////////////////////////////////////////////////////////////////////
536 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
537 SGPropertyNode_ptr props )
538 : SGAnimation(props, new ssgTransform),
539 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
540 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
541 _factor(props->getDoubleValue("factor", 1.0)),
542 _table(read_interpolation_table(props)),
543 _has_min(props->hasValue("min-deg")),
544 _min_deg(props->getDoubleValue("min-deg")),
545 _has_max(props->hasValue("max-deg")),
546 _max_deg(props->getDoubleValue("max-deg")),
547 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
550 SGPropertyNode_ptr node = props->getChild("condition");
552 _condition = sgReadCondition(prop_root, node);
557 if (props->hasValue("axis/x1-m")) {
558 double x1,y1,z1,x2,y2,z2;
559 x1 = props->getFloatValue("axis/x1-m");
560 y1 = props->getFloatValue("axis/y1-m");
561 z1 = props->getFloatValue("axis/z1-m");
562 x2 = props->getFloatValue("axis/x2-m");
563 y2 = props->getFloatValue("axis/y2-m");
564 z2 = props->getFloatValue("axis/z2-m");
565 _center[0] = (x1+x2)/2;
566 _center[1]= (y1+y2)/2;
567 _center[2] = (z1+z2)/2;
568 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
569 _axis[0] = (x2-x1)/vector_length;
570 _axis[1] = (y2-y1)/vector_length;
571 _axis[2] = (z2-z1)/vector_length;
573 _axis[0] = props->getFloatValue("axis/x", 0);
574 _axis[1] = props->getFloatValue("axis/y", 0);
575 _axis[2] = props->getFloatValue("axis/z", 0);
577 if (props->hasValue("center/x-m")) {
578 _center[0] = props->getFloatValue("center/x-m", 0);
579 _center[1] = props->getFloatValue("center/y-m", 0);
580 _center[2] = props->getFloatValue("center/z-m", 0);
582 sgNormalizeVec3(_axis);
585 SGRotateAnimation::~SGRotateAnimation ()
591 SGRotateAnimation::update()
593 if (_condition == 0 || _condition->test()) {
595 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
596 if (_has_min && _position_deg < _min_deg)
597 _position_deg = _min_deg;
598 if (_has_max && _position_deg > _max_deg)
599 _position_deg = _max_deg;
601 _position_deg = _table->interpolate(_prop->getDoubleValue());
603 set_rotation(_matrix, _position_deg, _center, _axis);
604 ((ssgTransform *)_branch)->setTransform(_matrix);
610 ////////////////////////////////////////////////////////////////////////
611 // Implementation of SGBlendAnimation
612 ////////////////////////////////////////////////////////////////////////
614 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
615 SGPropertyNode_ptr props )
616 : SGAnimation(props, new ssgTransform),
617 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
618 _table(read_interpolation_table(props)),
620 _offset(props->getDoubleValue("offset", 0.0)),
621 _factor(props->getDoubleValue("factor", 1.0)),
622 _has_min(props->hasValue("min")),
623 _min(props->getDoubleValue("min", 0.0)),
624 _has_max(props->hasValue("max")),
625 _max(props->getDoubleValue("max", 1.0))
629 SGBlendAnimation::~SGBlendAnimation ()
635 SGBlendAnimation::update()
640 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
642 if (_has_min && (_blend < _min))
644 if (_has_max && (_blend > _max))
647 _blend = _table->interpolate(_prop->getDoubleValue());
650 if (_blend != _prev_value) {
651 _prev_value = _blend;
652 change_alpha( _branch, _blend );
659 ////////////////////////////////////////////////////////////////////////
660 // Implementation of SGTranslateAnimation
661 ////////////////////////////////////////////////////////////////////////
663 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
664 SGPropertyNode_ptr props )
665 : SGAnimation(props, new ssgTransform),
666 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
667 _offset_m(props->getDoubleValue("offset-m", 0.0)),
668 _factor(props->getDoubleValue("factor", 1.0)),
669 _table(read_interpolation_table(props)),
670 _has_min(props->hasValue("min-m")),
671 _min_m(props->getDoubleValue("min-m")),
672 _has_max(props->hasValue("max-m")),
673 _max_m(props->getDoubleValue("max-m")),
674 _position_m(props->getDoubleValue("starting-position-m", 0)),
677 SGPropertyNode_ptr node = props->getChild("condition");
679 _condition = sgReadCondition(prop_root, node);
681 _axis[0] = props->getFloatValue("axis/x", 0);
682 _axis[1] = props->getFloatValue("axis/y", 0);
683 _axis[2] = props->getFloatValue("axis/z", 0);
684 sgNormalizeVec3(_axis);
687 SGTranslateAnimation::~SGTranslateAnimation ()
693 SGTranslateAnimation::update()
695 if (_condition == 0 || _condition->test()) {
697 _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
698 if (_has_min && _position_m < _min_m)
699 _position_m = _min_m;
700 if (_has_max && _position_m > _max_m)
701 _position_m = _max_m;
703 _position_m = _table->interpolate(_prop->getDoubleValue());
705 set_translation(_matrix, _position_m, _axis);
706 ((ssgTransform *)_branch)->setTransform(_matrix);
713 ////////////////////////////////////////////////////////////////////////
714 // Implementation of SGScaleAnimation
715 ////////////////////////////////////////////////////////////////////////
717 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
718 SGPropertyNode_ptr props )
719 : SGAnimation(props, new ssgTransform),
720 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
721 _x_factor(props->getDoubleValue("x-factor", 1.0)),
722 _y_factor(props->getDoubleValue("y-factor", 1.0)),
723 _z_factor(props->getDoubleValue("z-factor", 1.0)),
724 _x_offset(props->getDoubleValue("x-offset", 1.0)),
725 _y_offset(props->getDoubleValue("y-offset", 1.0)),
726 _z_offset(props->getDoubleValue("z-offset", 1.0)),
727 _table(read_interpolation_table(props)),
728 _has_min_x(props->hasValue("x-min")),
729 _has_min_y(props->hasValue("y-min")),
730 _has_min_z(props->hasValue("z-min")),
731 _min_x(props->getDoubleValue("x-min")),
732 _min_y(props->getDoubleValue("y-min")),
733 _min_z(props->getDoubleValue("z-min")),
734 _has_max_x(props->hasValue("x-max")),
735 _has_max_y(props->hasValue("y-max")),
736 _has_max_z(props->hasValue("z-max")),
737 _max_x(props->getDoubleValue("x-max")),
738 _max_y(props->getDoubleValue("y-max")),
739 _max_z(props->getDoubleValue("z-max"))
743 SGScaleAnimation::~SGScaleAnimation ()
749 SGScaleAnimation::update()
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());
781 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
782 ((ssgTransform *)_branch)->setTransform(_matrix);
787 ////////////////////////////////////////////////////////////////////////
788 // Implementation of SGTexRotateAnimation
789 ////////////////////////////////////////////////////////////////////////
791 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
792 SGPropertyNode_ptr props )
793 : SGAnimation(props, new ssgTexTrans),
794 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
795 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
796 _factor(props->getDoubleValue("factor", 1.0)),
797 _table(read_interpolation_table(props)),
798 _has_min(props->hasValue("min-deg")),
799 _min_deg(props->getDoubleValue("min-deg")),
800 _has_max(props->hasValue("max-deg")),
801 _max_deg(props->getDoubleValue("max-deg")),
802 _position_deg(props->getDoubleValue("starting-position-deg", 0))
804 _center[0] = props->getFloatValue("center/x", 0);
805 _center[1] = props->getFloatValue("center/y", 0);
806 _center[2] = props->getFloatValue("center/z", 0);
807 _axis[0] = props->getFloatValue("axis/x", 0);
808 _axis[1] = props->getFloatValue("axis/y", 0);
809 _axis[2] = props->getFloatValue("axis/z", 0);
810 sgNormalizeVec3(_axis);
813 SGTexRotateAnimation::~SGTexRotateAnimation ()
819 SGTexRotateAnimation::update()
822 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
823 if (_has_min && _position_deg < _min_deg)
824 _position_deg = _min_deg;
825 if (_has_max && _position_deg > _max_deg)
826 _position_deg = _max_deg;
828 _position_deg = _table->interpolate(_prop->getDoubleValue());
830 set_rotation(_matrix, _position_deg, _center, _axis);
831 ((ssgTexTrans *)_branch)->setTransform(_matrix);
836 ////////////////////////////////////////////////////////////////////////
837 // Implementation of SGTexTranslateAnimation
838 ////////////////////////////////////////////////////////////////////////
840 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
841 SGPropertyNode_ptr props )
842 : SGAnimation(props, new ssgTexTrans),
843 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
844 _offset(props->getDoubleValue("offset", 0.0)),
845 _factor(props->getDoubleValue("factor", 1.0)),
846 _step(props->getDoubleValue("step",0.0)),
847 _scroll(props->getDoubleValue("scroll",0.0)),
848 _table(read_interpolation_table(props)),
849 _has_min(props->hasValue("min")),
850 _min(props->getDoubleValue("min")),
851 _has_max(props->hasValue("max")),
852 _max(props->getDoubleValue("max")),
853 _position(props->getDoubleValue("starting-position", 0))
855 _axis[0] = props->getFloatValue("axis/x", 0);
856 _axis[1] = props->getFloatValue("axis/y", 0);
857 _axis[2] = props->getFloatValue("axis/z", 0);
858 sgNormalizeVec3(_axis);
861 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
867 SGTexTranslateAnimation::update()
870 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
871 if (_has_min && _position < _min)
873 if (_has_max && _position > _max)
876 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
878 set_translation(_matrix, _position, _axis);
879 ((ssgTexTrans *)_branch)->setTransform(_matrix);
884 ////////////////////////////////////////////////////////////////////////
885 // Implementation of SGTexMultipleAnimation
886 ////////////////////////////////////////////////////////////////////////
888 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
889 SGPropertyNode_ptr props )
890 : SGAnimation(props, new ssgTexTrans),
891 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
895 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
896 _transform = new TexTransform [transform_nodes.size()];
898 for (i = 0; i < transform_nodes.size(); i++) {
899 SGPropertyNode_ptr transform_props = transform_nodes[i];
901 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
903 // transform is a translation
904 _transform[i].subtype = 0;
906 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
908 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
909 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
910 _transform[i].step = transform_props->getDoubleValue("step",0.0);
911 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
912 _transform[i].table = read_interpolation_table(transform_props);
913 _transform[i].has_min = transform_props->hasValue("min");
914 _transform[i].min = transform_props->getDoubleValue("min");
915 _transform[i].has_max = transform_props->hasValue("max");
916 _transform[i].max = transform_props->getDoubleValue("max");
917 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
919 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
920 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
921 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
922 sgNormalizeVec3(_transform[i].axis);
924 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
926 // transform is a rotation
927 _transform[i].subtype = 1;
929 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
930 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
931 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
932 _transform[i].table = read_interpolation_table(transform_props);
933 _transform[i].has_min = transform_props->hasValue("min-deg");
934 _transform[i].min = transform_props->getDoubleValue("min-deg");
935 _transform[i].has_max = transform_props->hasValue("max-deg");
936 _transform[i].max = transform_props->getDoubleValue("max-deg");
937 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
939 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
940 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
941 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
942 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
943 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
944 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
945 sgNormalizeVec3(_transform[i].axis);
951 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
958 SGTexMultipleAnimation::update()
962 sgMakeIdentMat4(tmatrix);
963 for (i = 0; i < _num_transforms; i++) {
965 if(_transform[i].subtype == 0) {
967 // subtype 0 is translation
968 if (_transform[i].table == 0) {
969 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
970 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
971 _transform[i].position = _transform[i].min;
972 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
973 _transform[i].position = _transform[i].max;
975 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
977 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
978 sgPreMultMat4(tmatrix, _transform[i].matrix);
980 } else if (_transform[i].subtype == 1) {
982 // subtype 1 is rotation
984 if (_transform[i].table == 0) {
985 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
986 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
987 _transform[i].position = _transform[i].min;
988 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
989 _transform[i].position = _transform[i].max;
991 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
993 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
994 sgPreMultMat4(tmatrix, _transform[i].matrix);
997 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
1003 ////////////////////////////////////////////////////////////////////////
1004 // Implementation of SGAlphaTestAnimation
1005 ////////////////////////////////////////////////////////////////////////
1007 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
1008 : SGAnimation(props, new ssgBranch)
1010 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
1013 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
1017 void SGAlphaTestAnimation::init()
1019 setAlphaClampToBranch(_branch,_alpha_clamp);
1022 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
1024 int nb = b->getNumKids();
1025 for (int i = 0; i<nb; i++) {
1026 ssgEntity *e = b->getKid(i);
1027 if (e->isAKindOf(ssgTypeLeaf())) {
1028 ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
1029 s->enable( GL_ALPHA_TEST );
1030 s->setAlphaClamp( clamp );
1031 } else if (e->isAKindOf(ssgTypeBranch())) {
1032 setAlphaClampToBranch( (ssgBranch*)e, clamp );
1039 ////////////////////////////////////////////////////////////////////////
1040 // Implementation of SGFlashAnimation
1041 ////////////////////////////////////////////////////////////////////////
1042 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
1043 : SGAnimation( props, new SGFlash )
1046 axis[0] = props->getFloatValue("axis/x", 0);
1047 axis[1] = props->getFloatValue("axis/y", 0);
1048 axis[2] = props->getFloatValue("axis/z", 1);
1049 ((SGFlash *)_branch)->setAxis( axis );
1052 center[0] = props->getFloatValue("center/x-m", 0);
1053 center[1] = props->getFloatValue("center/y-m", 0);
1054 center[2] = props->getFloatValue("center/z-m", 0);
1055 ((SGFlash *)_branch)->setCenter( center );
1057 float offset = props->getFloatValue("offset", 0.0);
1058 float factor = props->getFloatValue("factor", 1.0);
1059 float power = props->getFloatValue("power", 1.0);
1060 bool two_sides = props->getBoolValue("two-sides", false);
1061 ((SGFlash *)_branch)->setParameters( power, factor, offset, two_sides );
1063 float v_min = props->getFloatValue("min", 0.0);
1064 float v_max = props->getFloatValue("max", 1.0);
1065 ((SGFlash *)_branch)->setClampValues( v_min, v_max );
1068 SGFlashAnimation::~SGFlashAnimation()
1072 // end of animation.cxx