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>
18 #include "animation.hxx"
22 ////////////////////////////////////////////////////////////////////////
23 // Static utility functions.
24 ////////////////////////////////////////////////////////////////////////
27 * Set up the transform matrix for a spin or rotation.
30 set_rotation (sgMat4 &matrix, double position_deg,
31 sgVec3 ¢er, sgVec3 &axis)
33 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
35 float s = (float) sin ( temp_angle ) ;
36 float c = (float) cos ( temp_angle ) ;
37 float t = SG_ONE - c ;
39 // axis was normalized at load time
40 // hint to the compiler to put these into FP registers
45 matrix[0][0] = t * x * x + c ;
46 matrix[0][1] = t * y * x - s * z ;
47 matrix[0][2] = t * z * x + s * y ;
48 matrix[0][3] = SG_ZERO;
50 matrix[1][0] = t * x * y + s * z ;
51 matrix[1][1] = t * y * y + c ;
52 matrix[1][2] = t * z * y - s * x ;
53 matrix[1][3] = SG_ZERO;
55 matrix[2][0] = t * x * z - s * y ;
56 matrix[2][1] = t * y * z + s * x ;
57 matrix[2][2] = t * z * z + c ;
58 matrix[2][3] = SG_ZERO;
60 // hint to the compiler to put these into FP registers
65 matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0];
66 matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1];
67 matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2];
68 matrix[3][3] = SG_ONE;
72 * Set up the transform matrix for a translation.
75 set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
78 sgScaleVec3(xyz, axis, position_m);
79 sgMakeTransMat4(matrix, xyz);
83 * Set up the transform matrix for a scale operation.
86 set_scale (sgMat4 &matrix, double x, double y, double z)
88 sgMakeIdentMat4( matrix );
95 * Recursively process all kids to change the alpha values
98 change_alpha( ssgBase *_branch, float _blend )
102 for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
103 change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
105 if ( !_branch->isAKindOf(ssgTypeLeaf())
106 && !_branch->isAKindOf(ssgTypeVtxTable())
107 && !_branch->isAKindOf(ssgTypeVTable()) )
110 int num_colors = ((ssgLeaf *)_branch)->getNumColours();
111 // unsigned int select_ = (_blend == 1.0) ? false : true;
113 for (i = 0; i < num_colors; i++)
115 // ((ssgSelector *)_branch)->select( select_ );
116 float *color = ((ssgLeaf *)_branch)->getColour(i);
122 * Modify property value by step and scroll settings in texture translations
125 apply_mods(double property, double step, double scroll)
130 double scrollval = 0.0;
132 // calculate scroll amount (for odometer like movement)
133 double remainder = step - fmod(fabs(property), step);
134 if (remainder < scroll) {
135 scrollval = (scroll - remainder) / scroll * step;
138 // apply stepping of input value
140 modprop = ((floor(property/step) * step) + scrollval);
142 modprop = ((ceil(property/step) * step) + scrollval);
151 * Read an interpolation table from properties.
153 static SGInterpTable *
154 read_interpolation_table (SGPropertyNode_ptr props)
156 SGPropertyNode_ptr table_node = props->getNode("interpolation");
157 if (table_node != 0) {
158 SGInterpTable * table = new SGInterpTable();
159 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
160 for (unsigned int i = 0; i < entries.size(); i++)
161 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
162 entries[i]->getDoubleValue("dep", 0.0));
171 ////////////////////////////////////////////////////////////////////////
172 // Implementation of SGAnimation
173 ////////////////////////////////////////////////////////////////////////
175 // Initialize the static data member
176 double SGAnimation::sim_time_sec = 0.0;
178 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
181 _branch->setName(props->getStringValue("name", 0));
184 SGAnimation::~SGAnimation ()
194 SGAnimation::update()
200 SGAnimation::restore()
206 ////////////////////////////////////////////////////////////////////////
207 // Implementation of SGNullAnimation
208 ////////////////////////////////////////////////////////////////////////
210 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
211 : SGAnimation(props, new ssgBranch)
215 SGNullAnimation::~SGNullAnimation ()
221 ////////////////////////////////////////////////////////////////////////
222 // Implementation of SGRangeAnimation
223 ////////////////////////////////////////////////////////////////////////
225 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
226 SGPropertyNode_ptr props)
227 : SGAnimation(props, new ssgRangeSelector),
228 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0)
233 SGPropertyNode_ptr node = props->getChild( "min-factor" );
235 _min_factor = props->getFloatValue("min-factor", 1.0);
237 node = props->getChild( "max-factor" );
239 _max_factor = props->getFloatValue("max-factor", 1.0);
241 node = props->getChild( "min-property" );
243 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
244 ranges[0] = _min_prop->getFloatValue() * _min_factor;
246 _min = props->getFloatValue("min-m", 0);
247 ranges[0] = _min * _min_factor;
249 node = props->getChild( "max-property" );
251 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
252 ranges[1] = _max_prop->getFloatValue() * _max_factor;
254 _max = props->getFloatValue("max-m", 0);
255 ranges[1] = _max * _max_factor;
257 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
260 SGRangeAnimation::~SGRangeAnimation ()
265 SGRangeAnimation::update()
269 if (_min_prop != 0) {
270 ranges[0] = _min_prop->getFloatValue() * _min_factor;
273 ranges[0] = _min * _min_factor;
275 if (_max_prop != 0) {
276 ranges[1] = _max_prop->getFloatValue() * _max_factor;
279 ranges[1] = _max * _max_factor;
282 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
289 ////////////////////////////////////////////////////////////////////////
290 // Implementation of SGBillboardAnimation
291 ////////////////////////////////////////////////////////////////////////
293 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
294 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
298 SGBillboardAnimation::~SGBillboardAnimation ()
304 ////////////////////////////////////////////////////////////////////////
305 // Implementation of SGSelectAnimation
306 ////////////////////////////////////////////////////////////////////////
308 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
309 SGPropertyNode_ptr props )
310 : SGAnimation(props, new ssgSelector),
313 SGPropertyNode_ptr node = props->getChild("condition");
315 _condition = sgReadCondition(prop_root, node);
318 SGSelectAnimation::~SGSelectAnimation ()
324 SGSelectAnimation::update()
326 if (_condition != 0 && _condition->test())
327 ((ssgSelector *)_branch)->select(0xffff);
329 ((ssgSelector *)_branch)->select(0x0000);
335 ////////////////////////////////////////////////////////////////////////
336 // Implementation of SGSpinAnimation
337 ////////////////////////////////////////////////////////////////////////
339 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
340 SGPropertyNode_ptr props,
341 double sim_time_sec )
342 : SGAnimation(props, new ssgTransform),
343 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
344 _factor(props->getDoubleValue("factor", 1.0)),
345 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
346 _last_time_sec( sim_time_sec )
351 if (props->hasValue("axis/x1-m")) {
352 double x1,y1,z1,x2,y2,z2;
353 x1 = props->getFloatValue("axis/x1-m");
354 y1 = props->getFloatValue("axis/y1-m");
355 z1 = props->getFloatValue("axis/z1-m");
356 x2 = props->getFloatValue("axis/x2-m");
357 y2 = props->getFloatValue("axis/y2-m");
358 z2 = props->getFloatValue("axis/z2-m");
359 _center[0] = (x1+x2)/2;
360 _center[1]= (y1+y2)/2;
361 _center[2] = (z1+z2)/2;
362 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
363 _axis[0] = (x2-x1)/vector_length;
364 _axis[1] = (y2-y1)/vector_length;
365 _axis[2] = (z2-z1)/vector_length;
367 _axis[0] = props->getFloatValue("axis/x", 0);
368 _axis[1] = props->getFloatValue("axis/y", 0);
369 _axis[2] = props->getFloatValue("axis/z", 0);
371 if (props->hasValue("center/x-m")) {
372 _center[0] = props->getFloatValue("center/x-m", 0);
373 _center[1] = props->getFloatValue("center/y-m", 0);
374 _center[2] = props->getFloatValue("center/z-m", 0);
376 sgNormalizeVec3(_axis);
379 SGSpinAnimation::~SGSpinAnimation ()
384 SGSpinAnimation::update()
386 double dt = sim_time_sec - _last_time_sec;
387 _last_time_sec = sim_time_sec;
389 float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
390 _position_deg += (dt * velocity_rpms * 360);
391 while (_position_deg < 0)
392 _position_deg += 360.0;
393 while (_position_deg >= 360.0)
394 _position_deg -= 360.0;
395 set_rotation(_matrix, _position_deg, _center, _axis);
396 ((ssgTransform *)_branch)->setTransform(_matrix);
402 ////////////////////////////////////////////////////////////////////////
403 // Implementation of SGTimedAnimation
404 ////////////////////////////////////////////////////////////////////////
406 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
407 : SGAnimation(props, new ssgSelector),
408 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
414 SGTimedAnimation::~SGTimedAnimation ()
419 SGTimedAnimation::update()
421 if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
422 _last_time_sec = sim_time_sec;
424 if (_step >= getBranch()->getNumKids())
426 ((ssgSelector *)getBranch())->selectStep(_step);
433 ////////////////////////////////////////////////////////////////////////
434 // Implementation of SGRotateAnimation
435 ////////////////////////////////////////////////////////////////////////
437 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
438 SGPropertyNode_ptr props )
439 : SGAnimation(props, new ssgTransform),
440 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
441 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
442 _factor(props->getDoubleValue("factor", 1.0)),
443 _table(read_interpolation_table(props)),
444 _has_min(props->hasValue("min-deg")),
445 _min_deg(props->getDoubleValue("min-deg")),
446 _has_max(props->hasValue("max-deg")),
447 _max_deg(props->getDoubleValue("max-deg")),
448 _position_deg(props->getDoubleValue("starting-position-deg", 0))
453 if (props->hasValue("axis/x1-m")) {
454 double x1,y1,z1,x2,y2,z2;
455 x1 = props->getFloatValue("axis/x1-m");
456 y1 = props->getFloatValue("axis/y1-m");
457 z1 = props->getFloatValue("axis/z1-m");
458 x2 = props->getFloatValue("axis/x2-m");
459 y2 = props->getFloatValue("axis/y2-m");
460 z2 = props->getFloatValue("axis/z2-m");
461 _center[0] = (x1+x2)/2;
462 _center[1]= (y1+y2)/2;
463 _center[2] = (z1+z2)/2;
464 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
465 _axis[0] = (x2-x1)/vector_length;
466 _axis[1] = (y2-y1)/vector_length;
467 _axis[2] = (z2-z1)/vector_length;
469 _axis[0] = props->getFloatValue("axis/x", 0);
470 _axis[1] = props->getFloatValue("axis/y", 0);
471 _axis[2] = props->getFloatValue("axis/z", 0);
473 if (props->hasValue("center/x-m")) {
474 _center[0] = props->getFloatValue("center/x-m", 0);
475 _center[1] = props->getFloatValue("center/y-m", 0);
476 _center[2] = props->getFloatValue("center/z-m", 0);
478 sgNormalizeVec3(_axis);
481 SGRotateAnimation::~SGRotateAnimation ()
487 SGRotateAnimation::update()
490 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
491 if (_has_min && _position_deg < _min_deg)
492 _position_deg = _min_deg;
493 if (_has_max && _position_deg > _max_deg)
494 _position_deg = _max_deg;
496 _position_deg = _table->interpolate(_prop->getDoubleValue());
498 set_rotation(_matrix, _position_deg, _center, _axis);
499 ((ssgTransform *)_branch)->setTransform(_matrix);
504 ////////////////////////////////////////////////////////////////////////
505 // Implementation of SGBlendAnimation
506 ////////////////////////////////////////////////////////////////////////
508 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
509 SGPropertyNode_ptr props )
510 : SGAnimation(props, new ssgTransform),
511 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
512 _table(read_interpolation_table(props)),
514 _offset(props->getDoubleValue("offset", 0.0)),
515 _factor(props->getDoubleValue("factor", 1.0)),
516 _has_min(props->hasValue("min")),
517 _min(props->getDoubleValue("min", 0.0)),
518 _has_max(props->hasValue("max")),
519 _max(props->getDoubleValue("max", 1.0))
523 SGBlendAnimation::~SGBlendAnimation ()
529 SGBlendAnimation::update()
534 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
536 if (_has_min && (_blend < _min))
538 if (_has_max && (_blend > _max))
541 _blend = _table->interpolate(_prop->getDoubleValue());
544 if (_blend != _prev_value) {
545 _prev_value = _blend;
546 change_alpha( _branch, _blend );
553 ////////////////////////////////////////////////////////////////////////
554 // Implementation of SGTranslateAnimation
555 ////////////////////////////////////////////////////////////////////////
557 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
558 SGPropertyNode_ptr props )
559 : SGAnimation(props, new ssgTransform),
560 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
561 _offset_m(props->getDoubleValue("offset-m", 0.0)),
562 _factor(props->getDoubleValue("factor", 1.0)),
563 _table(read_interpolation_table(props)),
564 _has_min(props->hasValue("min-m")),
565 _min_m(props->getDoubleValue("min-m")),
566 _has_max(props->hasValue("max-m")),
567 _max_m(props->getDoubleValue("max-m")),
568 _position_m(props->getDoubleValue("starting-position-m", 0))
570 _axis[0] = props->getFloatValue("axis/x", 0);
571 _axis[1] = props->getFloatValue("axis/y", 0);
572 _axis[2] = props->getFloatValue("axis/z", 0);
573 sgNormalizeVec3(_axis);
576 SGTranslateAnimation::~SGTranslateAnimation ()
582 SGTranslateAnimation::update()
585 _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
586 if (_has_min && _position_m < _min_m)
587 _position_m = _min_m;
588 if (_has_max && _position_m > _max_m)
589 _position_m = _max_m;
591 _position_m = _table->interpolate(_prop->getDoubleValue());
593 set_translation(_matrix, _position_m, _axis);
594 ((ssgTransform *)_branch)->setTransform(_matrix);
600 ////////////////////////////////////////////////////////////////////////
601 // Implementation of SGScaleAnimation
602 ////////////////////////////////////////////////////////////////////////
604 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
605 SGPropertyNode_ptr props )
606 : SGAnimation(props, new ssgTransform),
607 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
608 _x_factor(props->getDoubleValue("x-factor", 1.0)),
609 _y_factor(props->getDoubleValue("y-factor", 1.0)),
610 _z_factor(props->getDoubleValue("z-factor", 1.0)),
611 _x_offset(props->getDoubleValue("x-offset", 1.0)),
612 _y_offset(props->getDoubleValue("y-offset", 1.0)),
613 _z_offset(props->getDoubleValue("z-offset", 1.0)),
614 _table(read_interpolation_table(props)),
615 _has_min_x(props->hasValue("x-min")),
616 _has_min_y(props->hasValue("y-min")),
617 _has_min_z(props->hasValue("z-min")),
618 _min_x(props->getDoubleValue("x-min")),
619 _min_y(props->getDoubleValue("y-min")),
620 _min_z(props->getDoubleValue("z-min")),
621 _has_max_x(props->hasValue("x-max")),
622 _has_max_y(props->hasValue("y-max")),
623 _has_max_z(props->hasValue("z-max")),
624 _max_x(props->getDoubleValue("x-max")),
625 _max_y(props->getDoubleValue("y-max")),
626 _max_z(props->getDoubleValue("z-max"))
630 SGScaleAnimation::~SGScaleAnimation ()
636 SGScaleAnimation::update()
639 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
640 if (_has_min_x && _x_scale < _min_x)
642 if (_has_max_x && _x_scale > _max_x)
645 _x_scale = _table->interpolate(_prop->getDoubleValue());
649 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
650 if (_has_min_y && _y_scale < _min_y)
652 if (_has_max_y && _y_scale > _max_y)
655 _y_scale = _table->interpolate(_prop->getDoubleValue());
659 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
660 if (_has_min_z && _z_scale < _min_z)
662 if (_has_max_z && _z_scale > _max_z)
665 _z_scale = _table->interpolate(_prop->getDoubleValue());
668 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
669 ((ssgTransform *)_branch)->setTransform(_matrix);
674 ////////////////////////////////////////////////////////////////////////
675 // Implementation of SGTexRotateAnimation
676 ////////////////////////////////////////////////////////////////////////
678 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
679 SGPropertyNode_ptr props )
680 : SGAnimation(props, new ssgTexTrans),
681 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
682 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
683 _factor(props->getDoubleValue("factor", 1.0)),
684 _table(read_interpolation_table(props)),
685 _has_min(props->hasValue("min-deg")),
686 _min_deg(props->getDoubleValue("min-deg")),
687 _has_max(props->hasValue("max-deg")),
688 _max_deg(props->getDoubleValue("max-deg")),
689 _position_deg(props->getDoubleValue("starting-position-deg", 0))
691 _center[0] = props->getFloatValue("center/x", 0);
692 _center[1] = props->getFloatValue("center/y", 0);
693 _center[2] = props->getFloatValue("center/z", 0);
694 _axis[0] = props->getFloatValue("axis/x", 0);
695 _axis[1] = props->getFloatValue("axis/y", 0);
696 _axis[2] = props->getFloatValue("axis/z", 0);
697 sgNormalizeVec3(_axis);
700 SGTexRotateAnimation::~SGTexRotateAnimation ()
706 SGTexRotateAnimation::update()
709 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
710 if (_has_min && _position_deg < _min_deg)
711 _position_deg = _min_deg;
712 if (_has_max && _position_deg > _max_deg)
713 _position_deg = _max_deg;
715 _position_deg = _table->interpolate(_prop->getDoubleValue());
717 set_rotation(_matrix, _position_deg, _center, _axis);
718 ((ssgTexTrans *)_branch)->setTransform(_matrix);
723 ////////////////////////////////////////////////////////////////////////
724 // Implementation of SGTexTranslateAnimation
725 ////////////////////////////////////////////////////////////////////////
727 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
728 SGPropertyNode_ptr props )
729 : SGAnimation(props, new ssgTexTrans),
730 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
731 _offset(props->getDoubleValue("offset", 0.0)),
732 _factor(props->getDoubleValue("factor", 1.0)),
733 _step(props->getDoubleValue("step",0.0)),
734 _scroll(props->getDoubleValue("scroll",0.0)),
735 _table(read_interpolation_table(props)),
736 _has_min(props->hasValue("min")),
737 _min(props->getDoubleValue("min")),
738 _has_max(props->hasValue("max")),
739 _max(props->getDoubleValue("max")),
740 _position(props->getDoubleValue("starting-position", 0))
742 _axis[0] = props->getFloatValue("axis/x", 0);
743 _axis[1] = props->getFloatValue("axis/y", 0);
744 _axis[2] = props->getFloatValue("axis/z", 0);
745 sgNormalizeVec3(_axis);
748 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
754 SGTexTranslateAnimation::update()
757 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
758 if (_has_min && _position < _min)
760 if (_has_max && _position > _max)
763 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
765 set_translation(_matrix, _position, _axis);
766 ((ssgTexTrans *)_branch)->setTransform(_matrix);
771 ////////////////////////////////////////////////////////////////////////
772 // Implementation of SGTexMultipleAnimation
773 ////////////////////////////////////////////////////////////////////////
775 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
776 SGPropertyNode_ptr props )
777 : SGAnimation(props, new ssgTexTrans),
778 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
782 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
783 _transform = new TexTransform [transform_nodes.size()];
785 for (i = 0; i < transform_nodes.size(); i++) {
786 SGPropertyNode_ptr transform_props = transform_nodes[i];
788 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
790 // transform is a translation
791 _transform[i].subtype = 0;
793 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
795 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
796 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
797 _transform[i].step = transform_props->getDoubleValue("step",0.0);
798 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
799 _transform[i].table = read_interpolation_table(transform_props);
800 _transform[i].has_min = transform_props->hasValue("min");
801 _transform[i].min = transform_props->getDoubleValue("min");
802 _transform[i].has_max = transform_props->hasValue("max");
803 _transform[i].max = transform_props->getDoubleValue("max");
804 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
806 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
807 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
808 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
809 sgNormalizeVec3(_transform[i].axis);
811 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
813 // transform is a rotation
814 _transform[i].subtype = 1;
816 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
817 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
818 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
819 _transform[i].table = read_interpolation_table(transform_props);
820 _transform[i].has_min = transform_props->hasValue("min-deg");
821 _transform[i].min = transform_props->getDoubleValue("min-deg");
822 _transform[i].has_max = transform_props->hasValue("max-deg");
823 _transform[i].max = transform_props->getDoubleValue("max-deg");
824 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
826 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
827 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
828 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
829 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
830 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
831 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
832 sgNormalizeVec3(_transform[i].axis);
838 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
845 SGTexMultipleAnimation::update()
849 sgMakeIdentMat4(tmatrix);
850 for (i = 0; i < _num_transforms; i++) {
852 if(_transform[i].subtype == 0) {
854 // subtype 0 is translation
855 if (_transform[i].table == 0) {
856 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
857 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
858 _transform[i].position = _transform[i].min;
859 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
860 _transform[i].position = _transform[i].max;
862 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
864 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
865 sgPreMultMat4(tmatrix, _transform[i].matrix);
867 } else if (_transform[i].subtype == 1) {
869 // subtype 1 is rotation
871 if (_transform[i].table == 0) {
872 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
873 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
874 _transform[i].position = _transform[i].min;
875 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
876 _transform[i].position = _transform[i].max;
878 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
880 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
881 sgPreMultMat4(tmatrix, _transform[i].matrix);
884 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
890 ////////////////////////////////////////////////////////////////////////
891 // Implementation of SGAlphaTestAnimation
892 ////////////////////////////////////////////////////////////////////////
894 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
895 : SGAnimation(props, new ssgBranch)
897 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
900 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
904 void SGAlphaTestAnimation::init()
906 setAlphaClampToBranch(_branch,_alpha_clamp);
909 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
911 int nb = b->getNumKids();
912 for (int i = 0; i<nb; i++) {
913 ssgEntity *e = b->getKid(i);
914 if (e->isAKindOf(ssgTypeLeaf())) {
915 ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
916 s->enable( GL_ALPHA_TEST );
917 s->setAlphaClamp( clamp );
918 } else if (e->isAKindOf(ssgTypeBranch())) {
919 setAlphaClampToBranch( (ssgBranch*)e, clamp );
926 ////////////////////////////////////////////////////////////////////////
927 // Implementation of SGFlashAnimation
928 ////////////////////////////////////////////////////////////////////////
929 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
930 : SGAnimation( props, new SGFlash )
933 axis[0] = props->getFloatValue("axis/x", 0);
934 axis[1] = props->getFloatValue("axis/y", 0);
935 axis[2] = props->getFloatValue("axis/z", 1);
936 ((SGFlash *)_branch)->setAxis( axis );
939 center[0] = props->getFloatValue("center/x-m", 0);
940 center[1] = props->getFloatValue("center/y-m", 0);
941 center[2] = props->getFloatValue("center/z-m", 0);
942 ((SGFlash *)_branch)->setCenter( center );
944 float offset = props->getFloatValue("offset", 0.0);
945 float factor = props->getFloatValue("factor", 1.0);
946 float power = props->getFloatValue("power", 1.0);
947 bool two_sides = props->getBoolValue("two-sides", false);
948 ((SGFlash *)_branch)->setParameters( power, factor, offset, two_sides );
950 float v_min = props->getFloatValue("min", 0.0);
951 float v_max = props->getFloatValue("max", 1.0);
952 ((SGFlash *)_branch)->setClampValues( v_min, v_max );
955 SGFlashAnimation::~SGFlashAnimation()
959 // end of animation.cxx