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 ( strcmp("ssgLeaf", _branch->getTypeName()) &&
106 strcmp("ssgVtxTable", _branch->getTypeName()) &&
107 strcmp("ssgVTable", _branch->getTypeName()) )
110 int num_colors = ((ssgLeaf *)_branch)->getNumColours();
112 for (i = 0; i < num_colors; i++)
114 float *color = ((ssgLeaf *)_branch)->getColour(i);
120 * Modify property value by step and scroll settings in texture translations
123 apply_mods(double property, double step, double scroll)
128 double scrollval = 0.0;
130 // calculate scroll amount (for odometer like movement)
131 double remainder = step - fmod(fabs(property), step);
132 if (remainder < scroll) {
133 scrollval = (scroll - remainder) / scroll * step;
136 // apply stepping of input value
138 modprop = ((floor(property/step) * step) + scrollval);
140 modprop = ((ceil(property/step) * step) + scrollval);
149 * Read an interpolation table from properties.
151 static SGInterpTable *
152 read_interpolation_table (SGPropertyNode_ptr props)
154 SGPropertyNode_ptr table_node = props->getNode("interpolation");
155 if (table_node != 0) {
156 SGInterpTable * table = new SGInterpTable();
157 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
158 for (unsigned int i = 0; i < entries.size(); i++)
159 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
160 entries[i]->getDoubleValue("dep", 0.0));
169 ////////////////////////////////////////////////////////////////////////
170 // Implementation of SGAnimation
171 ////////////////////////////////////////////////////////////////////////
173 // Initialize the static data member
174 double SGAnimation::sim_time_sec = 0.0;
176 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
179 _branch->setName(props->getStringValue("name", 0));
182 SGAnimation::~SGAnimation ()
192 SGAnimation::update()
198 ////////////////////////////////////////////////////////////////////////
199 // Implementation of SGNullAnimation
200 ////////////////////////////////////////////////////////////////////////
202 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
203 : SGAnimation(props, new ssgBranch)
207 SGNullAnimation::~SGNullAnimation ()
213 ////////////////////////////////////////////////////////////////////////
214 // Implementation of SGRangeAnimation
215 ////////////////////////////////////////////////////////////////////////
217 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
218 SGPropertyNode_ptr props)
219 : SGAnimation(props, new ssgRangeSelector),
224 SGPropertyNode_ptr node = props->getChild( "min-property" );
226 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
227 ranges[0] = _min_prop->getFloatValue();
229 ranges[0] = _min = props->getFloatValue("min-m", 0);
231 node = props->getChild( "max-property" );
233 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
234 ranges[1] = _max_prop->getFloatValue();
236 ranges[1] = _max = props->getFloatValue("max-m", 0);
238 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
241 SGRangeAnimation::~SGRangeAnimation ()
246 SGRangeAnimation::update()
250 if (_min_prop != 0) {
251 ranges[0] = _min_prop->getFloatValue();
256 if (_max_prop != 0) {
257 ranges[1] = _max_prop->getFloatValue();
263 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
268 ////////////////////////////////////////////////////////////////////////
269 // Implementation of SGBillboardAnimation
270 ////////////////////////////////////////////////////////////////////////
272 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
273 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
277 SGBillboardAnimation::~SGBillboardAnimation ()
283 ////////////////////////////////////////////////////////////////////////
284 // Implementation of SGSelectAnimation
285 ////////////////////////////////////////////////////////////////////////
287 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
288 SGPropertyNode_ptr props )
289 : SGAnimation(props, new ssgSelector),
292 SGPropertyNode_ptr node = props->getChild("condition");
294 _condition = sgReadCondition(prop_root, node);
297 SGSelectAnimation::~SGSelectAnimation ()
303 SGSelectAnimation::update()
305 if (_condition != 0 && _condition->test())
306 ((ssgSelector *)_branch)->select(0xffff);
308 ((ssgSelector *)_branch)->select(0x0000);
313 ////////////////////////////////////////////////////////////////////////
314 // Implementation of SGSpinAnimation
315 ////////////////////////////////////////////////////////////////////////
317 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
318 SGPropertyNode_ptr props,
319 double sim_time_sec )
320 : SGAnimation(props, new ssgTransform),
321 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
322 _factor(props->getDoubleValue("factor", 1.0)),
323 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
324 _last_time_sec( sim_time_sec )
329 if (props->hasValue("axis/x1-m")) {
330 double x1,y1,z1,x2,y2,z2;
331 x1 = props->getFloatValue("axis/x1-m");
332 y1 = props->getFloatValue("axis/y1-m");
333 z1 = props->getFloatValue("axis/z1-m");
334 x2 = props->getFloatValue("axis/x2-m");
335 y2 = props->getFloatValue("axis/y2-m");
336 z2 = props->getFloatValue("axis/z2-m");
337 _center[0] = (x1+x2)/2;
338 _center[1]= (y1+y2)/2;
339 _center[2] = (z1+z2)/2;
340 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
341 _axis[0] = (x2-x1)/vector_length;
342 _axis[1] = (y2-y1)/vector_length;
343 _axis[2] = (z2-z1)/vector_length;
345 _axis[0] = props->getFloatValue("axis/x", 0);
346 _axis[1] = props->getFloatValue("axis/y", 0);
347 _axis[2] = props->getFloatValue("axis/z", 0);
349 if (props->hasValue("center/x-m")) {
350 _center[0] = props->getFloatValue("center/x-m", 0);
351 _center[1] = props->getFloatValue("center/y-m", 0);
352 _center[2] = props->getFloatValue("center/z-m", 0);
354 sgNormalizeVec3(_axis);
357 SGSpinAnimation::~SGSpinAnimation ()
362 SGSpinAnimation::update()
364 double dt = sim_time_sec - _last_time_sec;
365 _last_time_sec = sim_time_sec;
367 float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
368 _position_deg += (dt * velocity_rpms * 360);
369 while (_position_deg < 0)
370 _position_deg += 360.0;
371 while (_position_deg >= 360.0)
372 _position_deg -= 360.0;
373 set_rotation(_matrix, _position_deg, _center, _axis);
374 ((ssgTransform *)_branch)->setTransform(_matrix);
379 ////////////////////////////////////////////////////////////////////////
380 // Implementation of SGTimedAnimation
381 ////////////////////////////////////////////////////////////////////////
383 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
384 : SGAnimation(props, new ssgSelector),
385 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
391 SGTimedAnimation::~SGTimedAnimation ()
396 SGTimedAnimation::update()
398 if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
399 _last_time_sec = sim_time_sec;
401 if (_step >= getBranch()->getNumKids())
403 ((ssgSelector *)getBranch())->selectStep(_step);
409 ////////////////////////////////////////////////////////////////////////
410 // Implementation of SGRotateAnimation
411 ////////////////////////////////////////////////////////////////////////
413 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
414 SGPropertyNode_ptr props )
415 : SGAnimation(props, new ssgTransform),
416 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
417 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
418 _factor(props->getDoubleValue("factor", 1.0)),
419 _table(read_interpolation_table(props)),
420 _has_min(props->hasValue("min-deg")),
421 _min_deg(props->getDoubleValue("min-deg")),
422 _has_max(props->hasValue("max-deg")),
423 _max_deg(props->getDoubleValue("max-deg")),
424 _position_deg(props->getDoubleValue("starting-position-deg", 0))
429 if (props->hasValue("axis/x1-m")) {
430 double x1,y1,z1,x2,y2,z2;
431 x1 = props->getFloatValue("axis/x1-m");
432 y1 = props->getFloatValue("axis/y1-m");
433 z1 = props->getFloatValue("axis/z1-m");
434 x2 = props->getFloatValue("axis/x2-m");
435 y2 = props->getFloatValue("axis/y2-m");
436 z2 = props->getFloatValue("axis/z2-m");
437 _center[0] = (x1+x2)/2;
438 _center[1]= (y1+y2)/2;
439 _center[2] = (z1+z2)/2;
440 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
441 _axis[0] = (x2-x1)/vector_length;
442 _axis[1] = (y2-y1)/vector_length;
443 _axis[2] = (z2-z1)/vector_length;
445 _axis[0] = props->getFloatValue("axis/x", 0);
446 _axis[1] = props->getFloatValue("axis/y", 0);
447 _axis[2] = props->getFloatValue("axis/z", 0);
449 if (props->hasValue("center/x-m")) {
450 _center[0] = props->getFloatValue("center/x-m", 0);
451 _center[1] = props->getFloatValue("center/y-m", 0);
452 _center[2] = props->getFloatValue("center/z-m", 0);
454 sgNormalizeVec3(_axis);
457 SGRotateAnimation::~SGRotateAnimation ()
463 SGRotateAnimation::update()
466 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
467 if (_has_min && _position_deg < _min_deg)
468 _position_deg = _min_deg;
469 if (_has_max && _position_deg > _max_deg)
470 _position_deg = _max_deg;
472 _position_deg = _table->interpolate(_prop->getDoubleValue());
474 set_rotation(_matrix, _position_deg, _center, _axis);
475 ((ssgTransform *)_branch)->setTransform(_matrix);
479 ////////////////////////////////////////////////////////////////////////
480 // Implementation of SGBlendAnimation
481 ////////////////////////////////////////////////////////////////////////
483 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
484 SGPropertyNode_ptr props )
485 : SGAnimation(props, new ssgTransform),
486 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
487 _offset(props->getDoubleValue("offset", 0.0)),
488 _factor(props->getDoubleValue("factor", 1.0)),
489 _table(read_interpolation_table(props)),
490 _has_min(props->hasValue("min")),
491 _min(props->getDoubleValue("min", 0.0)),
492 _has_max(props->hasValue("max")),
493 _max(props->getDoubleValue("max", 1.0)),
498 SGBlendAnimation::~SGBlendAnimation ()
504 SGBlendAnimation::update()
509 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
511 if (_has_min && (_blend < _min))
513 if (_has_max && (_blend > _max))
516 _blend = _table->interpolate(_prop->getDoubleValue());
519 if (_blend != _prev_value) {
520 _prev_value = _blend;
521 change_alpha( _branch, _blend );
527 ////////////////////////////////////////////////////////////////////////
528 // Implementation of SGTranslateAnimation
529 ////////////////////////////////////////////////////////////////////////
531 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
532 SGPropertyNode_ptr props )
533 : SGAnimation(props, new ssgTransform),
534 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
535 _offset_m(props->getDoubleValue("offset-m", 0.0)),
536 _factor(props->getDoubleValue("factor", 1.0)),
537 _table(read_interpolation_table(props)),
538 _has_min(props->hasValue("min-m")),
539 _min_m(props->getDoubleValue("min-m")),
540 _has_max(props->hasValue("max-m")),
541 _max_m(props->getDoubleValue("max-m")),
542 _position_m(props->getDoubleValue("starting-position-m", 0))
544 _axis[0] = props->getFloatValue("axis/x", 0);
545 _axis[1] = props->getFloatValue("axis/y", 0);
546 _axis[2] = props->getFloatValue("axis/z", 0);
547 sgNormalizeVec3(_axis);
550 SGTranslateAnimation::~SGTranslateAnimation ()
556 SGTranslateAnimation::update()
559 _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
560 if (_has_min && _position_m < _min_m)
561 _position_m = _min_m;
562 if (_has_max && _position_m > _max_m)
563 _position_m = _max_m;
565 _position_m = _table->interpolate(_prop->getDoubleValue());
567 set_translation(_matrix, _position_m, _axis);
568 ((ssgTransform *)_branch)->setTransform(_matrix);
573 ////////////////////////////////////////////////////////////////////////
574 // Implementation of SGScaleAnimation
575 ////////////////////////////////////////////////////////////////////////
577 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
578 SGPropertyNode_ptr props )
579 : SGAnimation(props, new ssgTransform),
580 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
581 _x_factor(props->getDoubleValue("x-factor", 1.0)),
582 _y_factor(props->getDoubleValue("y-factor", 1.0)),
583 _z_factor(props->getDoubleValue("z-factor", 1.0)),
584 _x_offset(props->getDoubleValue("x-offset", 1.0)),
585 _y_offset(props->getDoubleValue("y-offset", 1.0)),
586 _z_offset(props->getDoubleValue("z-offset", 1.0)),
587 _table(read_interpolation_table(props)),
588 _has_min_x(props->hasValue("x-min")),
589 _has_min_y(props->hasValue("y-min")),
590 _has_min_z(props->hasValue("z-min")),
591 _min_x(props->getDoubleValue("x-min")),
592 _min_y(props->getDoubleValue("y-min")),
593 _min_z(props->getDoubleValue("z-min")),
594 _has_max_x(props->hasValue("x-max")),
595 _has_max_y(props->hasValue("y-max")),
596 _has_max_z(props->hasValue("z-max")),
597 _max_x(props->getDoubleValue("x-max")),
598 _max_y(props->getDoubleValue("y-max")),
599 _max_z(props->getDoubleValue("z-max"))
603 SGScaleAnimation::~SGScaleAnimation ()
609 SGScaleAnimation::update()
612 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
613 if (_has_min_x && _x_scale < _min_x)
615 if (_has_max_x && _x_scale > _max_x)
618 _x_scale = _table->interpolate(_prop->getDoubleValue());
622 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
623 if (_has_min_y && _y_scale < _min_y)
625 if (_has_max_y && _y_scale > _max_y)
628 _y_scale = _table->interpolate(_prop->getDoubleValue());
632 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
633 if (_has_min_z && _z_scale < _min_z)
635 if (_has_max_z && _z_scale > _max_z)
638 _z_scale = _table->interpolate(_prop->getDoubleValue());
641 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
642 ((ssgTransform *)_branch)->setTransform(_matrix);
646 ////////////////////////////////////////////////////////////////////////
647 // Implementation of SGTexRotateAnimation
648 ////////////////////////////////////////////////////////////////////////
650 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
651 SGPropertyNode_ptr props )
652 : SGAnimation(props, new ssgTexTrans),
653 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
654 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
655 _factor(props->getDoubleValue("factor", 1.0)),
656 _table(read_interpolation_table(props)),
657 _has_min(props->hasValue("min-deg")),
658 _min_deg(props->getDoubleValue("min-deg")),
659 _has_max(props->hasValue("max-deg")),
660 _max_deg(props->getDoubleValue("max-deg")),
661 _position_deg(props->getDoubleValue("starting-position-deg", 0))
663 _center[0] = props->getFloatValue("center/x", 0);
664 _center[1] = props->getFloatValue("center/y", 0);
665 _center[2] = props->getFloatValue("center/z", 0);
666 _axis[0] = props->getFloatValue("axis/x", 0);
667 _axis[1] = props->getFloatValue("axis/y", 0);
668 _axis[2] = props->getFloatValue("axis/z", 0);
669 sgNormalizeVec3(_axis);
672 SGTexRotateAnimation::~SGTexRotateAnimation ()
678 SGTexRotateAnimation::update()
681 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
682 if (_has_min && _position_deg < _min_deg)
683 _position_deg = _min_deg;
684 if (_has_max && _position_deg > _max_deg)
685 _position_deg = _max_deg;
687 _position_deg = _table->interpolate(_prop->getDoubleValue());
689 set_rotation(_matrix, _position_deg, _center, _axis);
690 ((ssgTexTrans *)_branch)->setTransform(_matrix);
694 ////////////////////////////////////////////////////////////////////////
695 // Implementation of SGTexTranslateAnimation
696 ////////////////////////////////////////////////////////////////////////
698 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
699 SGPropertyNode_ptr props )
700 : SGAnimation(props, new ssgTexTrans),
701 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
702 _offset(props->getDoubleValue("offset", 0.0)),
703 _factor(props->getDoubleValue("factor", 1.0)),
704 _step(props->getDoubleValue("step",0.0)),
705 _scroll(props->getDoubleValue("scroll",0.0)),
706 _table(read_interpolation_table(props)),
707 _has_min(props->hasValue("min")),
708 _min(props->getDoubleValue("min")),
709 _has_max(props->hasValue("max")),
710 _max(props->getDoubleValue("max")),
711 _position(props->getDoubleValue("starting-position", 0))
713 _axis[0] = props->getFloatValue("axis/x", 0);
714 _axis[1] = props->getFloatValue("axis/y", 0);
715 _axis[2] = props->getFloatValue("axis/z", 0);
716 sgNormalizeVec3(_axis);
719 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
725 SGTexTranslateAnimation::update()
728 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
729 if (_has_min && _position < _min)
731 if (_has_max && _position > _max)
734 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
736 set_translation(_matrix, _position, _axis);
737 ((ssgTexTrans *)_branch)->setTransform(_matrix);
741 ////////////////////////////////////////////////////////////////////////
742 // Implementation of SGTexMultipleAnimation
743 ////////////////////////////////////////////////////////////////////////
745 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
746 SGPropertyNode_ptr props )
747 : SGAnimation(props, new ssgTexTrans),
748 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
752 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
753 _transform = new TexTransform [transform_nodes.size()];
755 for (i = 0; i < transform_nodes.size(); i++) {
756 SGPropertyNode_ptr transform_props = transform_nodes[i];
758 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
760 // transform is a translation
761 _transform[i].subtype = 0;
763 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
765 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
766 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
767 _transform[i].step = transform_props->getDoubleValue("step",0.0);
768 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
769 _transform[i].table = read_interpolation_table(transform_props);
770 _transform[i].has_min = transform_props->hasValue("min");
771 _transform[i].min = transform_props->getDoubleValue("min");
772 _transform[i].has_max = transform_props->hasValue("max");
773 _transform[i].max = transform_props->getDoubleValue("max");
774 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
776 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
777 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
778 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
779 sgNormalizeVec3(_transform[i].axis);
781 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
783 // transform is a rotation
784 _transform[i].subtype = 1;
786 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
787 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
788 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
789 _transform[i].table = read_interpolation_table(transform_props);
790 _transform[i].has_min = transform_props->hasValue("min-deg");
791 _transform[i].min = transform_props->getDoubleValue("min-deg");
792 _transform[i].has_max = transform_props->hasValue("max-deg");
793 _transform[i].max = transform_props->getDoubleValue("max-deg");
794 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
796 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
797 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
798 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
799 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
800 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
801 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
802 sgNormalizeVec3(_transform[i].axis);
808 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
815 SGTexMultipleAnimation::update()
819 sgMakeIdentMat4(tmatrix);
820 for (i = 0; i < _num_transforms; i++) {
822 if(_transform[i].subtype == 0) {
824 // subtype 0 is translation
825 if (_transform[i].table == 0) {
826 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
827 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
828 _transform[i].position = _transform[i].min;
829 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
830 _transform[i].position = _transform[i].max;
832 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
834 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
835 sgPreMultMat4(tmatrix, _transform[i].matrix);
837 } else if (_transform[i].subtype == 1) {
839 // subtype 1 is rotation
841 if (_transform[i].table == 0) {
842 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
843 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
844 _transform[i].position = _transform[i].min;
845 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
846 _transform[i].position = _transform[i].max;
848 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
850 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
851 sgPreMultMat4(tmatrix, _transform[i].matrix);
854 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
857 // end of animation.cxx