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"
23 ////////////////////////////////////////////////////////////////////////
24 // Static utility functions.
25 ////////////////////////////////////////////////////////////////////////
28 * Set up the transform matrix for a spin or rotation.
31 set_rotation (sgMat4 &matrix, double position_deg,
32 sgVec3 ¢er, sgVec3 &axis)
34 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
36 float s = (float) sin ( temp_angle ) ;
37 float c = (float) cos ( temp_angle ) ;
38 float t = SG_ONE - c ;
40 // axis was normalized at load time
41 // hint to the compiler to put these into FP registers
46 matrix[0][0] = t * x * x + c ;
47 matrix[0][1] = t * y * x - s * z ;
48 matrix[0][2] = t * z * x + s * y ;
49 matrix[0][3] = SG_ZERO;
51 matrix[1][0] = t * x * y + s * z ;
52 matrix[1][1] = t * y * y + c ;
53 matrix[1][2] = t * z * y - s * x ;
54 matrix[1][3] = SG_ZERO;
56 matrix[2][0] = t * x * z - s * y ;
57 matrix[2][1] = t * y * z + s * x ;
58 matrix[2][2] = t * z * z + c ;
59 matrix[2][3] = SG_ZERO;
61 // hint to the compiler to put these into FP registers
66 matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0];
67 matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1];
68 matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2];
69 matrix[3][3] = SG_ONE;
73 * Set up the transform matrix for a translation.
76 set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
79 sgScaleVec3(xyz, axis, position_m);
80 sgMakeTransMat4(matrix, xyz);
84 * Set up the transform matrix for a scale operation.
87 set_scale (sgMat4 &matrix, double x, double y, double z)
89 sgMakeIdentMat4( matrix );
96 * Recursively process all kids to change the alpha values
99 change_alpha( ssgBase *_branch, float _blend )
103 for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
104 change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
106 if ( !_branch->isAKindOf(ssgTypeLeaf())
107 && !_branch->isAKindOf(ssgTypeVtxTable())
108 && !_branch->isAKindOf(ssgTypeVTable()) )
111 int num_colors = ((ssgLeaf *)_branch)->getNumColours();
112 // unsigned int select_ = (_blend == 1.0) ? false : true;
114 for (i = 0; i < num_colors; i++)
116 // ((ssgSelector *)_branch)->select( select_ );
117 float *color = ((ssgLeaf *)_branch)->getColour(i);
123 * Modify property value by step and scroll settings in texture translations
126 apply_mods(double property, double step, double scroll)
131 double scrollval = 0.0;
133 // calculate scroll amount (for odometer like movement)
134 double remainder = step - fmod(fabs(property), step);
135 if (remainder < scroll) {
136 scrollval = (scroll - remainder) / scroll * step;
139 // apply stepping of input value
141 modprop = ((floor(property/step) * step) + scrollval);
143 modprop = ((ceil(property/step) * step) + scrollval);
152 * Read an interpolation table from properties.
154 static SGInterpTable *
155 read_interpolation_table (SGPropertyNode_ptr props)
157 SGPropertyNode_ptr table_node = props->getNode("interpolation");
158 if (table_node != 0) {
159 SGInterpTable * table = new SGInterpTable();
160 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
161 for (unsigned int i = 0; i < entries.size(); i++)
162 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
163 entries[i]->getDoubleValue("dep", 0.0));
172 ////////////////////////////////////////////////////////////////////////
173 // Implementation of SGAnimation
174 ////////////////////////////////////////////////////////////////////////
176 // Initialize the static data member
177 double SGAnimation::sim_time_sec = 0.0;
178 ssgBranch *SGAnimation::current_object = 0;
180 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
183 _branch->setName(props->getStringValue("name", 0));
186 SGAnimation::~SGAnimation ()
196 SGAnimation::update()
202 SGAnimation::restore()
208 ////////////////////////////////////////////////////////////////////////
209 // Implementation of SGNullAnimation
210 ////////////////////////////////////////////////////////////////////////
212 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
213 : SGAnimation(props, new ssgBranch)
217 SGNullAnimation::~SGNullAnimation ()
223 ////////////////////////////////////////////////////////////////////////
224 // Implementation of SGRangeAnimation
225 ////////////////////////////////////////////////////////////////////////
227 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
228 SGPropertyNode_ptr props)
229 : SGAnimation(props, new ssgRangeSelector),
230 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
233 SGPropertyNode_ptr node = props->getChild("condition");
235 _condition = sgReadCondition(prop_root, node);
239 node = props->getChild( "min-factor" );
241 _min_factor = props->getFloatValue("min-factor", 1.0);
243 node = props->getChild( "max-factor" );
245 _max_factor = props->getFloatValue("max-factor", 1.0);
247 node = props->getChild( "min-property" );
249 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
250 ranges[0] = _min_prop->getFloatValue() * _min_factor;
252 _min = props->getFloatValue("min-m", 0);
253 ranges[0] = _min * _min_factor;
255 node = props->getChild( "max-property" );
257 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
258 ranges[1] = _max_prop->getFloatValue() * _max_factor;
260 _max = props->getFloatValue("max-m", 0);
261 ranges[1] = _max * _max_factor;
263 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
266 SGRangeAnimation::~SGRangeAnimation ()
271 SGRangeAnimation::update()
274 if ( _condition == 0 || _condition->test() ) {
275 if (_min_prop != 0) {
276 ranges[0] = _min_prop->getFloatValue() * _min_factor;
278 ranges[0] = _min * _min_factor;
280 if (_max_prop != 0) {
281 ranges[1] = _max_prop->getFloatValue() * _max_factor;
283 ranges[1] = _max * _max_factor;
287 ranges[1] = 1000000000.f;
289 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
295 ////////////////////////////////////////////////////////////////////////
296 // Implementation of SGBillboardAnimation
297 ////////////////////////////////////////////////////////////////////////
299 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
300 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
304 SGBillboardAnimation::~SGBillboardAnimation ()
310 ////////////////////////////////////////////////////////////////////////
311 // Implementation of SGSelectAnimation
312 ////////////////////////////////////////////////////////////////////////
314 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
315 SGPropertyNode_ptr props )
316 : SGAnimation(props, new ssgSelector),
319 SGPropertyNode_ptr node = props->getChild("condition");
321 _condition = sgReadCondition(prop_root, node);
324 SGSelectAnimation::~SGSelectAnimation ()
330 SGSelectAnimation::update()
332 if (_condition != 0 && _condition->test())
333 ((ssgSelector *)_branch)->select(0xffff);
335 ((ssgSelector *)_branch)->select(0x0000);
341 ////////////////////////////////////////////////////////////////////////
342 // Implementation of SGSpinAnimation
343 ////////////////////////////////////////////////////////////////////////
345 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
346 SGPropertyNode_ptr props,
347 double sim_time_sec )
348 : SGAnimation(props, new ssgTransform),
349 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
350 _factor(props->getDoubleValue("factor", 1.0)),
351 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
352 _last_time_sec( sim_time_sec ),
355 SGPropertyNode_ptr node = props->getChild("condition");
357 _condition = sgReadCondition(prop_root, node);
362 if (props->hasValue("axis/x1-m")) {
363 double x1,y1,z1,x2,y2,z2;
364 x1 = props->getFloatValue("axis/x1-m");
365 y1 = props->getFloatValue("axis/y1-m");
366 z1 = props->getFloatValue("axis/z1-m");
367 x2 = props->getFloatValue("axis/x2-m");
368 y2 = props->getFloatValue("axis/y2-m");
369 z2 = props->getFloatValue("axis/z2-m");
370 _center[0] = (x1+x2)/2;
371 _center[1]= (y1+y2)/2;
372 _center[2] = (z1+z2)/2;
373 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
374 _axis[0] = (x2-x1)/vector_length;
375 _axis[1] = (y2-y1)/vector_length;
376 _axis[2] = (z2-z1)/vector_length;
378 _axis[0] = props->getFloatValue("axis/x", 0);
379 _axis[1] = props->getFloatValue("axis/y", 0);
380 _axis[2] = props->getFloatValue("axis/z", 0);
382 if (props->hasValue("center/x-m")) {
383 _center[0] = props->getFloatValue("center/x-m", 0);
384 _center[1] = props->getFloatValue("center/y-m", 0);
385 _center[2] = props->getFloatValue("center/z-m", 0);
387 sgNormalizeVec3(_axis);
390 SGSpinAnimation::~SGSpinAnimation ()
395 SGSpinAnimation::update()
397 if ( _condition == 0 || _condition->test() ) {
398 double dt = sim_time_sec - _last_time_sec;
399 _last_time_sec = sim_time_sec;
401 float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
402 _position_deg += (dt * velocity_rpms * 360);
403 while (_position_deg < 0)
404 _position_deg += 360.0;
405 while (_position_deg >= 360.0)
406 _position_deg -= 360.0;
407 set_rotation(_matrix, _position_deg, _center, _axis);
408 ((ssgTransform *)_branch)->setTransform(_matrix);
415 ////////////////////////////////////////////////////////////////////////
416 // Implementation of SGTimedAnimation
417 ////////////////////////////////////////////////////////////////////////
419 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
420 : SGAnimation(props, new ssgSelector),
421 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
423 _use_personality( props->getBoolValue("use-personality",false) )
425 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
426 size_t nb = nodes.size();
427 for ( size_t i = 0; i < nb; i++ ) {
428 size_t ind = nodes[ i ]->getIndex();
429 while ( ind >= _branch_duration_specs.size() ) {
430 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
432 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
434 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
436 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
437 rNode->getDoubleValue( "max", 1.0 ) );
440 ((ssgSelector *)getBranch())->selectStep(_step);
443 SGTimedAnimation::~SGTimedAnimation ()
448 SGTimedAnimation::update()
450 ssgBranch *key = ( _use_personality ? current_object : 0 );
451 PersonalityMap::iterator it = _branch_duration_sec.find( key );
452 if ( it == _branch_duration_sec.end() ) {
453 vector<double> durations;
455 for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
456 DurationSpec &sp = _branch_duration_specs[ i ];
457 double v = sp._min + sg_random() * ( sp._max - sp._min );
458 durations.push_back( v );
461 it = _branch_duration_sec.insert( PersonalityMap::value_type( key, durations ) ).first;
462 _last_time_sec[ key ] = sim_time_sec;
463 _total_duration_sec[ key ] = total;
466 while ( ( sim_time_sec - _last_time_sec[ key ] ) >= _total_duration_sec[ key ] ) {
467 _last_time_sec[ key ] += _total_duration_sec[ key ];
469 double duration = _duration_sec;
470 if ( _step < (int)it->second.size() ) {
471 duration = it->second[ _step ];
473 if ( ( sim_time_sec - _last_time_sec[ key ] ) >= duration ) {
474 _last_time_sec[ key ] += duration;
476 if ( _step >= getBranch()->getNumKids() )
478 ((ssgSelector *)getBranch())->selectStep( _step );
485 ////////////////////////////////////////////////////////////////////////
486 // Implementation of SGRotateAnimation
487 ////////////////////////////////////////////////////////////////////////
489 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
490 SGPropertyNode_ptr props )
491 : SGAnimation(props, new ssgTransform),
492 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
493 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
494 _factor(props->getDoubleValue("factor", 1.0)),
495 _table(read_interpolation_table(props)),
496 _has_min(props->hasValue("min-deg")),
497 _min_deg(props->getDoubleValue("min-deg")),
498 _has_max(props->hasValue("max-deg")),
499 _max_deg(props->getDoubleValue("max-deg")),
500 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
503 SGPropertyNode_ptr node = props->getChild("condition");
505 _condition = sgReadCondition(prop_root, node);
510 if (props->hasValue("axis/x1-m")) {
511 double x1,y1,z1,x2,y2,z2;
512 x1 = props->getFloatValue("axis/x1-m");
513 y1 = props->getFloatValue("axis/y1-m");
514 z1 = props->getFloatValue("axis/z1-m");
515 x2 = props->getFloatValue("axis/x2-m");
516 y2 = props->getFloatValue("axis/y2-m");
517 z2 = props->getFloatValue("axis/z2-m");
518 _center[0] = (x1+x2)/2;
519 _center[1]= (y1+y2)/2;
520 _center[2] = (z1+z2)/2;
521 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
522 _axis[0] = (x2-x1)/vector_length;
523 _axis[1] = (y2-y1)/vector_length;
524 _axis[2] = (z2-z1)/vector_length;
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 if (props->hasValue("center/x-m")) {
531 _center[0] = props->getFloatValue("center/x-m", 0);
532 _center[1] = props->getFloatValue("center/y-m", 0);
533 _center[2] = props->getFloatValue("center/z-m", 0);
535 sgNormalizeVec3(_axis);
538 SGRotateAnimation::~SGRotateAnimation ()
544 SGRotateAnimation::update()
546 if (_condition == 0 || _condition->test()) {
548 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
549 if (_has_min && _position_deg < _min_deg)
550 _position_deg = _min_deg;
551 if (_has_max && _position_deg > _max_deg)
552 _position_deg = _max_deg;
554 _position_deg = _table->interpolate(_prop->getDoubleValue());
556 set_rotation(_matrix, _position_deg, _center, _axis);
557 ((ssgTransform *)_branch)->setTransform(_matrix);
563 ////////////////////////////////////////////////////////////////////////
564 // Implementation of SGBlendAnimation
565 ////////////////////////////////////////////////////////////////////////
567 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
568 SGPropertyNode_ptr props )
569 : SGAnimation(props, new ssgTransform),
570 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
571 _table(read_interpolation_table(props)),
573 _offset(props->getDoubleValue("offset", 0.0)),
574 _factor(props->getDoubleValue("factor", 1.0)),
575 _has_min(props->hasValue("min")),
576 _min(props->getDoubleValue("min", 0.0)),
577 _has_max(props->hasValue("max")),
578 _max(props->getDoubleValue("max", 1.0))
582 SGBlendAnimation::~SGBlendAnimation ()
588 SGBlendAnimation::update()
593 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
595 if (_has_min && (_blend < _min))
597 if (_has_max && (_blend > _max))
600 _blend = _table->interpolate(_prop->getDoubleValue());
603 if (_blend != _prev_value) {
604 _prev_value = _blend;
605 change_alpha( _branch, _blend );
612 ////////////////////////////////////////////////////////////////////////
613 // Implementation of SGTranslateAnimation
614 ////////////////////////////////////////////////////////////////////////
616 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
617 SGPropertyNode_ptr props )
618 : SGAnimation(props, new ssgTransform),
619 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
620 _offset_m(props->getDoubleValue("offset-m", 0.0)),
621 _factor(props->getDoubleValue("factor", 1.0)),
622 _table(read_interpolation_table(props)),
623 _has_min(props->hasValue("min-m")),
624 _min_m(props->getDoubleValue("min-m")),
625 _has_max(props->hasValue("max-m")),
626 _max_m(props->getDoubleValue("max-m")),
627 _position_m(props->getDoubleValue("starting-position-m", 0)),
630 SGPropertyNode_ptr node = props->getChild("condition");
632 _condition = sgReadCondition(prop_root, node);
634 _axis[0] = props->getFloatValue("axis/x", 0);
635 _axis[1] = props->getFloatValue("axis/y", 0);
636 _axis[2] = props->getFloatValue("axis/z", 0);
637 sgNormalizeVec3(_axis);
640 SGTranslateAnimation::~SGTranslateAnimation ()
646 SGTranslateAnimation::update()
648 if (_condition == 0 || _condition->test()) {
650 _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
651 if (_has_min && _position_m < _min_m)
652 _position_m = _min_m;
653 if (_has_max && _position_m > _max_m)
654 _position_m = _max_m;
656 _position_m = _table->interpolate(_prop->getDoubleValue());
658 set_translation(_matrix, _position_m, _axis);
659 ((ssgTransform *)_branch)->setTransform(_matrix);
666 ////////////////////////////////////////////////////////////////////////
667 // Implementation of SGScaleAnimation
668 ////////////////////////////////////////////////////////////////////////
670 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
671 SGPropertyNode_ptr props )
672 : SGAnimation(props, new ssgTransform),
673 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
674 _x_factor(props->getDoubleValue("x-factor", 1.0)),
675 _y_factor(props->getDoubleValue("y-factor", 1.0)),
676 _z_factor(props->getDoubleValue("z-factor", 1.0)),
677 _x_offset(props->getDoubleValue("x-offset", 1.0)),
678 _y_offset(props->getDoubleValue("y-offset", 1.0)),
679 _z_offset(props->getDoubleValue("z-offset", 1.0)),
680 _table(read_interpolation_table(props)),
681 _has_min_x(props->hasValue("x-min")),
682 _has_min_y(props->hasValue("y-min")),
683 _has_min_z(props->hasValue("z-min")),
684 _min_x(props->getDoubleValue("x-min")),
685 _min_y(props->getDoubleValue("y-min")),
686 _min_z(props->getDoubleValue("z-min")),
687 _has_max_x(props->hasValue("x-max")),
688 _has_max_y(props->hasValue("y-max")),
689 _has_max_z(props->hasValue("z-max")),
690 _max_x(props->getDoubleValue("x-max")),
691 _max_y(props->getDoubleValue("y-max")),
692 _max_z(props->getDoubleValue("z-max"))
696 SGScaleAnimation::~SGScaleAnimation ()
702 SGScaleAnimation::update()
705 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
706 if (_has_min_x && _x_scale < _min_x)
708 if (_has_max_x && _x_scale > _max_x)
711 _x_scale = _table->interpolate(_prop->getDoubleValue());
715 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
716 if (_has_min_y && _y_scale < _min_y)
718 if (_has_max_y && _y_scale > _max_y)
721 _y_scale = _table->interpolate(_prop->getDoubleValue());
725 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
726 if (_has_min_z && _z_scale < _min_z)
728 if (_has_max_z && _z_scale > _max_z)
731 _z_scale = _table->interpolate(_prop->getDoubleValue());
734 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
735 ((ssgTransform *)_branch)->setTransform(_matrix);
740 ////////////////////////////////////////////////////////////////////////
741 // Implementation of SGTexRotateAnimation
742 ////////////////////////////////////////////////////////////////////////
744 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
745 SGPropertyNode_ptr props )
746 : SGAnimation(props, new ssgTexTrans),
747 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
748 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
749 _factor(props->getDoubleValue("factor", 1.0)),
750 _table(read_interpolation_table(props)),
751 _has_min(props->hasValue("min-deg")),
752 _min_deg(props->getDoubleValue("min-deg")),
753 _has_max(props->hasValue("max-deg")),
754 _max_deg(props->getDoubleValue("max-deg")),
755 _position_deg(props->getDoubleValue("starting-position-deg", 0))
757 _center[0] = props->getFloatValue("center/x", 0);
758 _center[1] = props->getFloatValue("center/y", 0);
759 _center[2] = props->getFloatValue("center/z", 0);
760 _axis[0] = props->getFloatValue("axis/x", 0);
761 _axis[1] = props->getFloatValue("axis/y", 0);
762 _axis[2] = props->getFloatValue("axis/z", 0);
763 sgNormalizeVec3(_axis);
766 SGTexRotateAnimation::~SGTexRotateAnimation ()
772 SGTexRotateAnimation::update()
775 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
776 if (_has_min && _position_deg < _min_deg)
777 _position_deg = _min_deg;
778 if (_has_max && _position_deg > _max_deg)
779 _position_deg = _max_deg;
781 _position_deg = _table->interpolate(_prop->getDoubleValue());
783 set_rotation(_matrix, _position_deg, _center, _axis);
784 ((ssgTexTrans *)_branch)->setTransform(_matrix);
789 ////////////////////////////////////////////////////////////////////////
790 // Implementation of SGTexTranslateAnimation
791 ////////////////////////////////////////////////////////////////////////
793 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
794 SGPropertyNode_ptr props )
795 : SGAnimation(props, new ssgTexTrans),
796 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
797 _offset(props->getDoubleValue("offset", 0.0)),
798 _factor(props->getDoubleValue("factor", 1.0)),
799 _step(props->getDoubleValue("step",0.0)),
800 _scroll(props->getDoubleValue("scroll",0.0)),
801 _table(read_interpolation_table(props)),
802 _has_min(props->hasValue("min")),
803 _min(props->getDoubleValue("min")),
804 _has_max(props->hasValue("max")),
805 _max(props->getDoubleValue("max")),
806 _position(props->getDoubleValue("starting-position", 0))
808 _axis[0] = props->getFloatValue("axis/x", 0);
809 _axis[1] = props->getFloatValue("axis/y", 0);
810 _axis[2] = props->getFloatValue("axis/z", 0);
811 sgNormalizeVec3(_axis);
814 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
820 SGTexTranslateAnimation::update()
823 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
824 if (_has_min && _position < _min)
826 if (_has_max && _position > _max)
829 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
831 set_translation(_matrix, _position, _axis);
832 ((ssgTexTrans *)_branch)->setTransform(_matrix);
837 ////////////////////////////////////////////////////////////////////////
838 // Implementation of SGTexMultipleAnimation
839 ////////////////////////////////////////////////////////////////////////
841 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
842 SGPropertyNode_ptr props )
843 : SGAnimation(props, new ssgTexTrans),
844 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
848 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
849 _transform = new TexTransform [transform_nodes.size()];
851 for (i = 0; i < transform_nodes.size(); i++) {
852 SGPropertyNode_ptr transform_props = transform_nodes[i];
854 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
856 // transform is a translation
857 _transform[i].subtype = 0;
859 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
861 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
862 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
863 _transform[i].step = transform_props->getDoubleValue("step",0.0);
864 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
865 _transform[i].table = read_interpolation_table(transform_props);
866 _transform[i].has_min = transform_props->hasValue("min");
867 _transform[i].min = transform_props->getDoubleValue("min");
868 _transform[i].has_max = transform_props->hasValue("max");
869 _transform[i].max = transform_props->getDoubleValue("max");
870 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
872 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
873 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
874 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
875 sgNormalizeVec3(_transform[i].axis);
877 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
879 // transform is a rotation
880 _transform[i].subtype = 1;
882 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
883 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
884 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
885 _transform[i].table = read_interpolation_table(transform_props);
886 _transform[i].has_min = transform_props->hasValue("min-deg");
887 _transform[i].min = transform_props->getDoubleValue("min-deg");
888 _transform[i].has_max = transform_props->hasValue("max-deg");
889 _transform[i].max = transform_props->getDoubleValue("max-deg");
890 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
892 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
893 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
894 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
895 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
896 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
897 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
898 sgNormalizeVec3(_transform[i].axis);
904 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
911 SGTexMultipleAnimation::update()
915 sgMakeIdentMat4(tmatrix);
916 for (i = 0; i < _num_transforms; i++) {
918 if(_transform[i].subtype == 0) {
920 // subtype 0 is translation
921 if (_transform[i].table == 0) {
922 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
923 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
924 _transform[i].position = _transform[i].min;
925 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
926 _transform[i].position = _transform[i].max;
928 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
930 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
931 sgPreMultMat4(tmatrix, _transform[i].matrix);
933 } else if (_transform[i].subtype == 1) {
935 // subtype 1 is rotation
937 if (_transform[i].table == 0) {
938 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
939 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
940 _transform[i].position = _transform[i].min;
941 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
942 _transform[i].position = _transform[i].max;
944 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
946 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
947 sgPreMultMat4(tmatrix, _transform[i].matrix);
950 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
956 ////////////////////////////////////////////////////////////////////////
957 // Implementation of SGAlphaTestAnimation
958 ////////////////////////////////////////////////////////////////////////
960 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
961 : SGAnimation(props, new ssgBranch)
963 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
966 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
970 void SGAlphaTestAnimation::init()
972 setAlphaClampToBranch(_branch,_alpha_clamp);
975 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
977 int nb = b->getNumKids();
978 for (int i = 0; i<nb; i++) {
979 ssgEntity *e = b->getKid(i);
980 if (e->isAKindOf(ssgTypeLeaf())) {
981 ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
982 s->enable( GL_ALPHA_TEST );
983 s->setAlphaClamp( clamp );
984 } else if (e->isAKindOf(ssgTypeBranch())) {
985 setAlphaClampToBranch( (ssgBranch*)e, clamp );
992 ////////////////////////////////////////////////////////////////////////
993 // Implementation of SGFlashAnimation
994 ////////////////////////////////////////////////////////////////////////
995 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
996 : SGAnimation( props, new SGFlash )
999 axis[0] = props->getFloatValue("axis/x", 0);
1000 axis[1] = props->getFloatValue("axis/y", 0);
1001 axis[2] = props->getFloatValue("axis/z", 1);
1002 ((SGFlash *)_branch)->setAxis( axis );
1005 center[0] = props->getFloatValue("center/x-m", 0);
1006 center[1] = props->getFloatValue("center/y-m", 0);
1007 center[2] = props->getFloatValue("center/z-m", 0);
1008 ((SGFlash *)_branch)->setCenter( center );
1010 float offset = props->getFloatValue("offset", 0.0);
1011 float factor = props->getFloatValue("factor", 1.0);
1012 float power = props->getFloatValue("power", 1.0);
1013 bool two_sides = props->getBoolValue("two-sides", false);
1014 ((SGFlash *)_branch)->setParameters( power, factor, offset, two_sides );
1016 float v_min = props->getFloatValue("min", 0.0);
1017 float v_max = props->getFloatValue("max", 1.0);
1018 ((SGFlash *)_branch)->setClampValues( v_min, v_max );
1021 SGFlashAnimation::~SGFlashAnimation()
1025 // end of animation.cxx