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();
112 if ( _blend == 1.0 ) { // fully translucent.
113 for (i = 0; i < num_colors; i++)
114 ((ssgSelector *)_branch)->select(0x0000); // deselect item.
116 for (i = 0; i < num_colors; i++)
118 ((ssgSelector *)_branch)->select(0xffff);
119 float *color = ((ssgLeaf *)_branch)->getColour(i);
126 * Modify property value by step and scroll settings in texture translations
129 apply_mods(double property, double step, double scroll)
134 double scrollval = 0.0;
136 // calculate scroll amount (for odometer like movement)
137 double remainder = step - fmod(fabs(property), step);
138 if (remainder < scroll) {
139 scrollval = (scroll - remainder) / scroll * step;
142 // apply stepping of input value
144 modprop = ((floor(property/step) * step) + scrollval);
146 modprop = ((ceil(property/step) * step) + scrollval);
155 * Read an interpolation table from properties.
157 static SGInterpTable *
158 read_interpolation_table (SGPropertyNode_ptr props)
160 SGPropertyNode_ptr table_node = props->getNode("interpolation");
161 if (table_node != 0) {
162 SGInterpTable * table = new SGInterpTable();
163 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
164 for (unsigned int i = 0; i < entries.size(); i++)
165 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
166 entries[i]->getDoubleValue("dep", 0.0));
175 ////////////////////////////////////////////////////////////////////////
176 // Implementation of SGAnimation
177 ////////////////////////////////////////////////////////////////////////
179 // Initialize the static data member
180 double SGAnimation::sim_time_sec = 0.0;
182 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
185 _branch->setName(props->getStringValue("name", 0));
188 SGAnimation::~SGAnimation ()
198 SGAnimation::update()
204 ////////////////////////////////////////////////////////////////////////
205 // Implementation of SGNullAnimation
206 ////////////////////////////////////////////////////////////////////////
208 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
209 : SGAnimation(props, new ssgBranch)
213 SGNullAnimation::~SGNullAnimation ()
219 ////////////////////////////////////////////////////////////////////////
220 // Implementation of SGRangeAnimation
221 ////////////////////////////////////////////////////////////////////////
223 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
224 SGPropertyNode_ptr props)
225 : SGAnimation(props, new ssgRangeSelector),
226 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0)
231 SGPropertyNode_ptr node = props->getChild( "min-factor" );
233 _min_factor = props->getFloatValue("min-factor", 1.0);
235 node = props->getChild( "max-factor" );
237 _max_factor = props->getFloatValue("max-factor", 1.0);
239 node = props->getChild( "min-property" );
241 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
242 ranges[0] = _min_prop->getFloatValue() * _min_factor;
244 _min = props->getFloatValue("min-m", 0);
245 ranges[0] = _min * _min_factor;
247 node = props->getChild( "max-property" );
249 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
250 ranges[1] = _max_prop->getFloatValue() * _max_factor;
252 _max = props->getFloatValue("max-m", 0);
253 ranges[1] = _max * _max_factor;
255 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
258 SGRangeAnimation::~SGRangeAnimation ()
263 SGRangeAnimation::update()
267 if (_min_prop != 0) {
268 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;
277 ranges[1] = _max * _max_factor;
280 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
286 ////////////////////////////////////////////////////////////////////////
287 // Implementation of SGBillboardAnimation
288 ////////////////////////////////////////////////////////////////////////
290 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
291 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
295 SGBillboardAnimation::~SGBillboardAnimation ()
301 ////////////////////////////////////////////////////////////////////////
302 // Implementation of SGSelectAnimation
303 ////////////////////////////////////////////////////////////////////////
305 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
306 SGPropertyNode_ptr props )
307 : SGAnimation(props, new ssgSelector),
310 SGPropertyNode_ptr node = props->getChild("condition");
312 _condition = sgReadCondition(prop_root, node);
315 SGSelectAnimation::~SGSelectAnimation ()
321 SGSelectAnimation::update()
323 if (_condition != 0 && _condition->test())
324 ((ssgSelector *)_branch)->select(0xffff);
326 ((ssgSelector *)_branch)->select(0x0000);
331 ////////////////////////////////////////////////////////////////////////
332 // Implementation of SGSpinAnimation
333 ////////////////////////////////////////////////////////////////////////
335 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
336 SGPropertyNode_ptr props,
337 double sim_time_sec )
338 : SGAnimation(props, new ssgTransform),
339 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
340 _factor(props->getDoubleValue("factor", 1.0)),
341 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
342 _last_time_sec( sim_time_sec )
347 if (props->hasValue("axis/x1-m")) {
348 double x1,y1,z1,x2,y2,z2;
349 x1 = props->getFloatValue("axis/x1-m");
350 y1 = props->getFloatValue("axis/y1-m");
351 z1 = props->getFloatValue("axis/z1-m");
352 x2 = props->getFloatValue("axis/x2-m");
353 y2 = props->getFloatValue("axis/y2-m");
354 z2 = props->getFloatValue("axis/z2-m");
355 _center[0] = (x1+x2)/2;
356 _center[1]= (y1+y2)/2;
357 _center[2] = (z1+z2)/2;
358 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
359 _axis[0] = (x2-x1)/vector_length;
360 _axis[1] = (y2-y1)/vector_length;
361 _axis[2] = (z2-z1)/vector_length;
363 _axis[0] = props->getFloatValue("axis/x", 0);
364 _axis[1] = props->getFloatValue("axis/y", 0);
365 _axis[2] = props->getFloatValue("axis/z", 0);
367 if (props->hasValue("center/x-m")) {
368 _center[0] = props->getFloatValue("center/x-m", 0);
369 _center[1] = props->getFloatValue("center/y-m", 0);
370 _center[2] = props->getFloatValue("center/z-m", 0);
372 sgNormalizeVec3(_axis);
375 SGSpinAnimation::~SGSpinAnimation ()
380 SGSpinAnimation::update()
382 double dt = sim_time_sec - _last_time_sec;
383 _last_time_sec = sim_time_sec;
385 float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
386 _position_deg += (dt * velocity_rpms * 360);
387 while (_position_deg < 0)
388 _position_deg += 360.0;
389 while (_position_deg >= 360.0)
390 _position_deg -= 360.0;
391 set_rotation(_matrix, _position_deg, _center, _axis);
392 ((ssgTransform *)_branch)->setTransform(_matrix);
397 ////////////////////////////////////////////////////////////////////////
398 // Implementation of SGTimedAnimation
399 ////////////////////////////////////////////////////////////////////////
401 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
402 : SGAnimation(props, new ssgSelector),
403 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
409 SGTimedAnimation::~SGTimedAnimation ()
414 SGTimedAnimation::update()
416 if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
417 _last_time_sec = sim_time_sec;
419 if (_step >= getBranch()->getNumKids())
421 ((ssgSelector *)getBranch())->selectStep(_step);
427 ////////////////////////////////////////////////////////////////////////
428 // Implementation of SGRotateAnimation
429 ////////////////////////////////////////////////////////////////////////
431 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
432 SGPropertyNode_ptr props )
433 : SGAnimation(props, new ssgTransform),
434 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
435 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
436 _factor(props->getDoubleValue("factor", 1.0)),
437 _table(read_interpolation_table(props)),
438 _has_min(props->hasValue("min-deg")),
439 _min_deg(props->getDoubleValue("min-deg")),
440 _has_max(props->hasValue("max-deg")),
441 _max_deg(props->getDoubleValue("max-deg")),
442 _position_deg(props->getDoubleValue("starting-position-deg", 0))
447 if (props->hasValue("axis/x1-m")) {
448 double x1,y1,z1,x2,y2,z2;
449 x1 = props->getFloatValue("axis/x1-m");
450 y1 = props->getFloatValue("axis/y1-m");
451 z1 = props->getFloatValue("axis/z1-m");
452 x2 = props->getFloatValue("axis/x2-m");
453 y2 = props->getFloatValue("axis/y2-m");
454 z2 = props->getFloatValue("axis/z2-m");
455 _center[0] = (x1+x2)/2;
456 _center[1]= (y1+y2)/2;
457 _center[2] = (z1+z2)/2;
458 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
459 _axis[0] = (x2-x1)/vector_length;
460 _axis[1] = (y2-y1)/vector_length;
461 _axis[2] = (z2-z1)/vector_length;
463 _axis[0] = props->getFloatValue("axis/x", 0);
464 _axis[1] = props->getFloatValue("axis/y", 0);
465 _axis[2] = props->getFloatValue("axis/z", 0);
467 if (props->hasValue("center/x-m")) {
468 _center[0] = props->getFloatValue("center/x-m", 0);
469 _center[1] = props->getFloatValue("center/y-m", 0);
470 _center[2] = props->getFloatValue("center/z-m", 0);
472 sgNormalizeVec3(_axis);
475 SGRotateAnimation::~SGRotateAnimation ()
481 SGRotateAnimation::update()
484 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
485 if (_has_min && _position_deg < _min_deg)
486 _position_deg = _min_deg;
487 if (_has_max && _position_deg > _max_deg)
488 _position_deg = _max_deg;
490 _position_deg = _table->interpolate(_prop->getDoubleValue());
492 set_rotation(_matrix, _position_deg, _center, _axis);
493 ((ssgTransform *)_branch)->setTransform(_matrix);
497 ////////////////////////////////////////////////////////////////////////
498 // Implementation of SGBlendAnimation
499 ////////////////////////////////////////////////////////////////////////
501 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
502 SGPropertyNode_ptr props )
503 : SGAnimation(props, new ssgTransform),
504 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
505 _offset(props->getDoubleValue("offset", 0.0)),
506 _factor(props->getDoubleValue("factor", 1.0)),
507 _table(read_interpolation_table(props)),
508 _has_min(props->hasValue("min")),
509 _min(props->getDoubleValue("min", 0.0)),
510 _has_max(props->hasValue("max")),
511 _max(props->getDoubleValue("max", 1.0)),
516 SGBlendAnimation::~SGBlendAnimation ()
522 SGBlendAnimation::update()
527 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
529 if (_has_min && (_blend < _min))
531 if (_has_max && (_blend > _max))
534 _blend = _table->interpolate(_prop->getDoubleValue());
537 if (_blend != _prev_value) {
538 _prev_value = _blend;
539 change_alpha( _branch, _blend );
545 ////////////////////////////////////////////////////////////////////////
546 // Implementation of SGTranslateAnimation
547 ////////////////////////////////////////////////////////////////////////
549 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
550 SGPropertyNode_ptr props )
551 : SGAnimation(props, new ssgTransform),
552 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
553 _offset_m(props->getDoubleValue("offset-m", 0.0)),
554 _factor(props->getDoubleValue("factor", 1.0)),
555 _table(read_interpolation_table(props)),
556 _has_min(props->hasValue("min-m")),
557 _min_m(props->getDoubleValue("min-m")),
558 _has_max(props->hasValue("max-m")),
559 _max_m(props->getDoubleValue("max-m")),
560 _position_m(props->getDoubleValue("starting-position-m", 0))
562 _axis[0] = props->getFloatValue("axis/x", 0);
563 _axis[1] = props->getFloatValue("axis/y", 0);
564 _axis[2] = props->getFloatValue("axis/z", 0);
565 sgNormalizeVec3(_axis);
568 SGTranslateAnimation::~SGTranslateAnimation ()
574 SGTranslateAnimation::update()
577 _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
578 if (_has_min && _position_m < _min_m)
579 _position_m = _min_m;
580 if (_has_max && _position_m > _max_m)
581 _position_m = _max_m;
583 _position_m = _table->interpolate(_prop->getDoubleValue());
585 set_translation(_matrix, _position_m, _axis);
586 ((ssgTransform *)_branch)->setTransform(_matrix);
591 ////////////////////////////////////////////////////////////////////////
592 // Implementation of SGScaleAnimation
593 ////////////////////////////////////////////////////////////////////////
595 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
596 SGPropertyNode_ptr props )
597 : SGAnimation(props, new ssgTransform),
598 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
599 _x_factor(props->getDoubleValue("x-factor", 1.0)),
600 _y_factor(props->getDoubleValue("y-factor", 1.0)),
601 _z_factor(props->getDoubleValue("z-factor", 1.0)),
602 _x_offset(props->getDoubleValue("x-offset", 1.0)),
603 _y_offset(props->getDoubleValue("y-offset", 1.0)),
604 _z_offset(props->getDoubleValue("z-offset", 1.0)),
605 _table(read_interpolation_table(props)),
606 _has_min_x(props->hasValue("x-min")),
607 _has_min_y(props->hasValue("y-min")),
608 _has_min_z(props->hasValue("z-min")),
609 _min_x(props->getDoubleValue("x-min")),
610 _min_y(props->getDoubleValue("y-min")),
611 _min_z(props->getDoubleValue("z-min")),
612 _has_max_x(props->hasValue("x-max")),
613 _has_max_y(props->hasValue("y-max")),
614 _has_max_z(props->hasValue("z-max")),
615 _max_x(props->getDoubleValue("x-max")),
616 _max_y(props->getDoubleValue("y-max")),
617 _max_z(props->getDoubleValue("z-max"))
621 SGScaleAnimation::~SGScaleAnimation ()
627 SGScaleAnimation::update()
630 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
631 if (_has_min_x && _x_scale < _min_x)
633 if (_has_max_x && _x_scale > _max_x)
636 _x_scale = _table->interpolate(_prop->getDoubleValue());
640 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
641 if (_has_min_y && _y_scale < _min_y)
643 if (_has_max_y && _y_scale > _max_y)
646 _y_scale = _table->interpolate(_prop->getDoubleValue());
650 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
651 if (_has_min_z && _z_scale < _min_z)
653 if (_has_max_z && _z_scale > _max_z)
656 _z_scale = _table->interpolate(_prop->getDoubleValue());
659 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
660 ((ssgTransform *)_branch)->setTransform(_matrix);
664 ////////////////////////////////////////////////////////////////////////
665 // Implementation of SGTexRotateAnimation
666 ////////////////////////////////////////////////////////////////////////
668 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
669 SGPropertyNode_ptr props )
670 : SGAnimation(props, new ssgTexTrans),
671 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
672 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
673 _factor(props->getDoubleValue("factor", 1.0)),
674 _table(read_interpolation_table(props)),
675 _has_min(props->hasValue("min-deg")),
676 _min_deg(props->getDoubleValue("min-deg")),
677 _has_max(props->hasValue("max-deg")),
678 _max_deg(props->getDoubleValue("max-deg")),
679 _position_deg(props->getDoubleValue("starting-position-deg", 0))
681 _center[0] = props->getFloatValue("center/x", 0);
682 _center[1] = props->getFloatValue("center/y", 0);
683 _center[2] = props->getFloatValue("center/z", 0);
684 _axis[0] = props->getFloatValue("axis/x", 0);
685 _axis[1] = props->getFloatValue("axis/y", 0);
686 _axis[2] = props->getFloatValue("axis/z", 0);
687 sgNormalizeVec3(_axis);
690 SGTexRotateAnimation::~SGTexRotateAnimation ()
696 SGTexRotateAnimation::update()
699 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
700 if (_has_min && _position_deg < _min_deg)
701 _position_deg = _min_deg;
702 if (_has_max && _position_deg > _max_deg)
703 _position_deg = _max_deg;
705 _position_deg = _table->interpolate(_prop->getDoubleValue());
707 set_rotation(_matrix, _position_deg, _center, _axis);
708 ((ssgTexTrans *)_branch)->setTransform(_matrix);
712 ////////////////////////////////////////////////////////////////////////
713 // Implementation of SGTexTranslateAnimation
714 ////////////////////////////////////////////////////////////////////////
716 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
717 SGPropertyNode_ptr props )
718 : SGAnimation(props, new ssgTexTrans),
719 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
720 _offset(props->getDoubleValue("offset", 0.0)),
721 _factor(props->getDoubleValue("factor", 1.0)),
722 _step(props->getDoubleValue("step",0.0)),
723 _scroll(props->getDoubleValue("scroll",0.0)),
724 _table(read_interpolation_table(props)),
725 _has_min(props->hasValue("min")),
726 _min(props->getDoubleValue("min")),
727 _has_max(props->hasValue("max")),
728 _max(props->getDoubleValue("max")),
729 _position(props->getDoubleValue("starting-position", 0))
731 _axis[0] = props->getFloatValue("axis/x", 0);
732 _axis[1] = props->getFloatValue("axis/y", 0);
733 _axis[2] = props->getFloatValue("axis/z", 0);
734 sgNormalizeVec3(_axis);
737 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
743 SGTexTranslateAnimation::update()
746 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
747 if (_has_min && _position < _min)
749 if (_has_max && _position > _max)
752 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
754 set_translation(_matrix, _position, _axis);
755 ((ssgTexTrans *)_branch)->setTransform(_matrix);
759 ////////////////////////////////////////////////////////////////////////
760 // Implementation of SGTexMultipleAnimation
761 ////////////////////////////////////////////////////////////////////////
763 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
764 SGPropertyNode_ptr props )
765 : SGAnimation(props, new ssgTexTrans),
766 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
770 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
771 _transform = new TexTransform [transform_nodes.size()];
773 for (i = 0; i < transform_nodes.size(); i++) {
774 SGPropertyNode_ptr transform_props = transform_nodes[i];
776 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
778 // transform is a translation
779 _transform[i].subtype = 0;
781 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
783 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
784 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
785 _transform[i].step = transform_props->getDoubleValue("step",0.0);
786 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
787 _transform[i].table = read_interpolation_table(transform_props);
788 _transform[i].has_min = transform_props->hasValue("min");
789 _transform[i].min = transform_props->getDoubleValue("min");
790 _transform[i].has_max = transform_props->hasValue("max");
791 _transform[i].max = transform_props->getDoubleValue("max");
792 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
794 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
795 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
796 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
797 sgNormalizeVec3(_transform[i].axis);
799 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
801 // transform is a rotation
802 _transform[i].subtype = 1;
804 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
805 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
806 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
807 _transform[i].table = read_interpolation_table(transform_props);
808 _transform[i].has_min = transform_props->hasValue("min-deg");
809 _transform[i].min = transform_props->getDoubleValue("min-deg");
810 _transform[i].has_max = transform_props->hasValue("max-deg");
811 _transform[i].max = transform_props->getDoubleValue("max-deg");
812 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
814 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
815 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
816 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
817 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
818 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
819 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
820 sgNormalizeVec3(_transform[i].axis);
826 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
833 SGTexMultipleAnimation::update()
837 sgMakeIdentMat4(tmatrix);
838 for (i = 0; i < _num_transforms; i++) {
840 if(_transform[i].subtype == 0) {
842 // subtype 0 is translation
843 if (_transform[i].table == 0) {
844 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
845 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
846 _transform[i].position = _transform[i].min;
847 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
848 _transform[i].position = _transform[i].max;
850 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
852 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
853 sgPreMultMat4(tmatrix, _transform[i].matrix);
855 } else if (_transform[i].subtype == 1) {
857 // subtype 1 is rotation
859 if (_transform[i].table == 0) {
860 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
861 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
862 _transform[i].position = _transform[i].min;
863 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
864 _transform[i].position = _transform[i].max;
866 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
868 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
869 sgPreMultMat4(tmatrix, _transform[i].matrix);
872 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
877 ////////////////////////////////////////////////////////////////////////
878 // Implementation of SGAlphaTestAnimation
879 ////////////////////////////////////////////////////////////////////////
881 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
882 : SGAnimation(props, new ssgBranch)
884 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
887 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
891 void SGAlphaTestAnimation::init()
893 setAlphaClampToBranch(_branch,_alpha_clamp);
896 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
898 int nb = b->getNumKids();
899 for (int i = 0; i<nb; i++) {
900 ssgEntity *e = b->getKid(i);
901 if (e->isAKindOf(ssgTypeLeaf())) {
902 ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
903 s->enable( GL_ALPHA_TEST );
904 s->setAlphaClamp( clamp );
905 } else if (e->isAKindOf(ssgTypeBranch())) {
906 setAlphaClampToBranch( (ssgBranch*)e, clamp );
911 // end of animation.cxx