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_ptr props)
218 : SGAnimation(props, new ssgRangeSelector)
220 float ranges[] = { props->getFloatValue("min-m", 0),
221 props->getFloatValue("max-m", 5000) };
222 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
226 SGRangeAnimation::~SGRangeAnimation ()
232 ////////////////////////////////////////////////////////////////////////
233 // Implementation of SGBillboardAnimation
234 ////////////////////////////////////////////////////////////////////////
236 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
237 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
241 SGBillboardAnimation::~SGBillboardAnimation ()
247 ////////////////////////////////////////////////////////////////////////
248 // Implementation of SGSelectAnimation
249 ////////////////////////////////////////////////////////////////////////
251 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
252 SGPropertyNode_ptr props )
253 : SGAnimation(props, new ssgSelector),
256 SGPropertyNode_ptr node = props->getChild("condition");
258 _condition = sgReadCondition(prop_root, node);
261 SGSelectAnimation::~SGSelectAnimation ()
267 SGSelectAnimation::update()
269 if (_condition != 0 && _condition->test())
270 ((ssgSelector *)_branch)->select(0xffff);
272 ((ssgSelector *)_branch)->select(0x0000);
277 ////////////////////////////////////////////////////////////////////////
278 // Implementation of SGSpinAnimation
279 ////////////////////////////////////////////////////////////////////////
281 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
282 SGPropertyNode_ptr props,
283 double sim_time_sec )
284 : SGAnimation(props, new ssgTransform),
285 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
286 _factor(props->getDoubleValue("factor", 1.0)),
287 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
288 _last_time_sec( sim_time_sec )
293 if (props->hasValue("axis/x1-m")) {
294 double x1,y1,z1,x2,y2,z2;
295 x1 = props->getFloatValue("axis/x1-m");
296 y1 = props->getFloatValue("axis/y1-m");
297 z1 = props->getFloatValue("axis/z1-m");
298 x2 = props->getFloatValue("axis/x2-m");
299 y2 = props->getFloatValue("axis/y2-m");
300 z2 = props->getFloatValue("axis/z2-m");
301 _center[0] = (x1+x2)/2;
302 _center[1]= (y1+y2)/2;
303 _center[2] = (z1+z2)/2;
304 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
305 _axis[0] = (x2-x1)/vector_length;
306 _axis[1] = (y2-y1)/vector_length;
307 _axis[2] = (z2-z1)/vector_length;
309 _axis[0] = props->getFloatValue("axis/x", 0);
310 _axis[1] = props->getFloatValue("axis/y", 0);
311 _axis[2] = props->getFloatValue("axis/z", 0);
313 if (props->hasValue("center/x-m")) {
314 _center[0] = props->getFloatValue("center/x-m", 0);
315 _center[1] = props->getFloatValue("center/y-m", 0);
316 _center[2] = props->getFloatValue("center/z-m", 0);
318 sgNormalizeVec3(_axis);
321 SGSpinAnimation::~SGSpinAnimation ()
326 SGSpinAnimation::update()
328 double dt = sim_time_sec - _last_time_sec;
329 _last_time_sec = sim_time_sec;
331 float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
332 _position_deg += (dt * velocity_rpms * 360);
333 while (_position_deg < 0)
334 _position_deg += 360.0;
335 while (_position_deg >= 360.0)
336 _position_deg -= 360.0;
337 set_rotation(_matrix, _position_deg, _center, _axis);
338 ((ssgTransform *)_branch)->setTransform(_matrix);
343 ////////////////////////////////////////////////////////////////////////
344 // Implementation of SGTimedAnimation
345 ////////////////////////////////////////////////////////////////////////
347 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
348 : SGAnimation(props, new ssgSelector),
349 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
355 SGTimedAnimation::~SGTimedAnimation ()
360 SGTimedAnimation::update()
362 if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
363 _last_time_sec = sim_time_sec;
365 if (_step >= getBranch()->getNumKids())
367 ((ssgSelector *)getBranch())->selectStep(_step);
373 ////////////////////////////////////////////////////////////////////////
374 // Implementation of SGRotateAnimation
375 ////////////////////////////////////////////////////////////////////////
377 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
378 SGPropertyNode_ptr props )
379 : SGAnimation(props, new ssgTransform),
380 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
381 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
382 _factor(props->getDoubleValue("factor", 1.0)),
383 _table(read_interpolation_table(props)),
384 _has_min(props->hasValue("min-deg")),
385 _min_deg(props->getDoubleValue("min-deg")),
386 _has_max(props->hasValue("max-deg")),
387 _max_deg(props->getDoubleValue("max-deg")),
388 _position_deg(props->getDoubleValue("starting-position-deg", 0))
393 if (props->hasValue("axis/x1-m")) {
394 double x1,y1,z1,x2,y2,z2;
395 x1 = props->getFloatValue("axis/x1-m");
396 y1 = props->getFloatValue("axis/y1-m");
397 z1 = props->getFloatValue("axis/z1-m");
398 x2 = props->getFloatValue("axis/x2-m");
399 y2 = props->getFloatValue("axis/y2-m");
400 z2 = props->getFloatValue("axis/z2-m");
401 _center[0] = (x1+x2)/2;
402 _center[1]= (y1+y2)/2;
403 _center[2] = (z1+z2)/2;
404 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
405 _axis[0] = (x2-x1)/vector_length;
406 _axis[1] = (y2-y1)/vector_length;
407 _axis[2] = (z2-z1)/vector_length;
409 _axis[0] = props->getFloatValue("axis/x", 0);
410 _axis[1] = props->getFloatValue("axis/y", 0);
411 _axis[2] = props->getFloatValue("axis/z", 0);
413 if (props->hasValue("center/x-m")) {
414 _center[0] = props->getFloatValue("center/x-m", 0);
415 _center[1] = props->getFloatValue("center/y-m", 0);
416 _center[2] = props->getFloatValue("center/z-m", 0);
418 sgNormalizeVec3(_axis);
421 SGRotateAnimation::~SGRotateAnimation ()
427 SGRotateAnimation::update()
430 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
431 if (_has_min && _position_deg < _min_deg)
432 _position_deg = _min_deg;
433 if (_has_max && _position_deg > _max_deg)
434 _position_deg = _max_deg;
436 _position_deg = _table->interpolate(_prop->getDoubleValue());
438 set_rotation(_matrix, _position_deg, _center, _axis);
439 ((ssgTransform *)_branch)->setTransform(_matrix);
443 ////////////////////////////////////////////////////////////////////////
444 // Implementation of SGBlendAnimation
445 ////////////////////////////////////////////////////////////////////////
447 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
448 SGPropertyNode_ptr props )
449 : SGAnimation(props, new ssgTransform),
450 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
451 _offset(props->getDoubleValue("offset", 0.0)),
452 _factor(props->getDoubleValue("factor", 1.0)),
453 _table(read_interpolation_table(props)),
454 _has_min(props->hasValue("min")),
455 _min(props->getDoubleValue("min", 0.0)),
456 _has_max(props->hasValue("max")),
457 _max(props->getDoubleValue("max", 1.0)),
462 SGBlendAnimation::~SGBlendAnimation ()
468 SGBlendAnimation::update()
473 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
475 if (_has_min && (_blend < _min))
477 if (_has_max && (_blend > _max))
480 _blend = _table->interpolate(_prop->getDoubleValue());
483 if (_blend != _prev_value) {
484 _prev_value = _blend;
485 change_alpha( _branch, _blend );
491 ////////////////////////////////////////////////////////////////////////
492 // Implementation of SGTranslateAnimation
493 ////////////////////////////////////////////////////////////////////////
495 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
496 SGPropertyNode_ptr props )
497 : SGAnimation(props, new ssgTransform),
498 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
499 _offset_m(props->getDoubleValue("offset-m", 0.0)),
500 _factor(props->getDoubleValue("factor", 1.0)),
501 _table(read_interpolation_table(props)),
502 _has_min(props->hasValue("min-m")),
503 _min_m(props->getDoubleValue("min-m")),
504 _has_max(props->hasValue("max-m")),
505 _max_m(props->getDoubleValue("max-m")),
506 _position_m(props->getDoubleValue("starting-position-m", 0))
508 _axis[0] = props->getFloatValue("axis/x", 0);
509 _axis[1] = props->getFloatValue("axis/y", 0);
510 _axis[2] = props->getFloatValue("axis/z", 0);
511 sgNormalizeVec3(_axis);
514 SGTranslateAnimation::~SGTranslateAnimation ()
520 SGTranslateAnimation::update()
523 _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
524 if (_has_min && _position_m < _min_m)
525 _position_m = _min_m;
526 if (_has_max && _position_m > _max_m)
527 _position_m = _max_m;
529 _position_m = _table->interpolate(_prop->getDoubleValue());
531 set_translation(_matrix, _position_m, _axis);
532 ((ssgTransform *)_branch)->setTransform(_matrix);
537 ////////////////////////////////////////////////////////////////////////
538 // Implementation of SGScaleAnimation
539 ////////////////////////////////////////////////////////////////////////
541 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
542 SGPropertyNode_ptr props )
543 : SGAnimation(props, new ssgTransform),
544 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
545 _x_factor(props->getDoubleValue("x-factor", 1.0)),
546 _y_factor(props->getDoubleValue("y-factor", 1.0)),
547 _z_factor(props->getDoubleValue("z-factor", 1.0)),
548 _x_offset(props->getDoubleValue("x-offset", 1.0)),
549 _y_offset(props->getDoubleValue("y-offset", 1.0)),
550 _z_offset(props->getDoubleValue("z-offset", 1.0)),
551 _table(read_interpolation_table(props)),
552 _has_min_x(props->hasValue("x-min")),
553 _has_min_y(props->hasValue("y-min")),
554 _has_min_z(props->hasValue("z-min")),
555 _min_x(props->getDoubleValue("x-min")),
556 _min_y(props->getDoubleValue("y-min")),
557 _min_z(props->getDoubleValue("z-min")),
558 _has_max_x(props->hasValue("x-max")),
559 _has_max_y(props->hasValue("y-max")),
560 _has_max_z(props->hasValue("z-max")),
561 _max_x(props->getDoubleValue("x-max")),
562 _max_y(props->getDoubleValue("y-max")),
563 _max_z(props->getDoubleValue("z-max"))
567 SGScaleAnimation::~SGScaleAnimation ()
573 SGScaleAnimation::update()
576 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
577 if (_has_min_x && _x_scale < _min_x)
579 if (_has_max_x && _x_scale > _max_x)
582 _x_scale = _table->interpolate(_prop->getDoubleValue());
586 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
587 if (_has_min_y && _y_scale < _min_y)
589 if (_has_max_y && _y_scale > _max_y)
592 _y_scale = _table->interpolate(_prop->getDoubleValue());
596 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
597 if (_has_min_z && _z_scale < _min_z)
599 if (_has_max_z && _z_scale > _max_z)
602 _z_scale = _table->interpolate(_prop->getDoubleValue());
605 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
606 ((ssgTransform *)_branch)->setTransform(_matrix);
610 ////////////////////////////////////////////////////////////////////////
611 // Implementation of SGTexRotateAnimation
612 ////////////////////////////////////////////////////////////////////////
614 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
615 SGPropertyNode_ptr props )
616 : SGAnimation(props, new ssgTexTrans),
617 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
618 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
619 _factor(props->getDoubleValue("factor", 1.0)),
620 _table(read_interpolation_table(props)),
621 _has_min(props->hasValue("min-deg")),
622 _min_deg(props->getDoubleValue("min-deg")),
623 _has_max(props->hasValue("max-deg")),
624 _max_deg(props->getDoubleValue("max-deg")),
625 _position_deg(props->getDoubleValue("starting-position-deg", 0))
627 _center[0] = props->getFloatValue("center/x", 0);
628 _center[1] = props->getFloatValue("center/y", 0);
629 _center[2] = props->getFloatValue("center/z", 0);
630 _axis[0] = props->getFloatValue("axis/x", 0);
631 _axis[1] = props->getFloatValue("axis/y", 0);
632 _axis[2] = props->getFloatValue("axis/z", 0);
633 sgNormalizeVec3(_axis);
636 SGTexRotateAnimation::~SGTexRotateAnimation ()
642 SGTexRotateAnimation::update()
645 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
646 if (_has_min && _position_deg < _min_deg)
647 _position_deg = _min_deg;
648 if (_has_max && _position_deg > _max_deg)
649 _position_deg = _max_deg;
651 _position_deg = _table->interpolate(_prop->getDoubleValue());
653 set_rotation(_matrix, _position_deg, _center, _axis);
654 ((ssgTexTrans *)_branch)->setTransform(_matrix);
658 ////////////////////////////////////////////////////////////////////////
659 // Implementation of SGTexTranslateAnimation
660 ////////////////////////////////////////////////////////////////////////
662 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
663 SGPropertyNode_ptr props )
664 : SGAnimation(props, new ssgTexTrans),
665 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
666 _offset(props->getDoubleValue("offset", 0.0)),
667 _factor(props->getDoubleValue("factor", 1.0)),
668 _step(props->getDoubleValue("step",0.0)),
669 _scroll(props->getDoubleValue("scroll",0.0)),
670 _table(read_interpolation_table(props)),
671 _has_min(props->hasValue("min")),
672 _min(props->getDoubleValue("min")),
673 _has_max(props->hasValue("max")),
674 _max(props->getDoubleValue("max")),
675 _position(props->getDoubleValue("starting-position", 0))
677 _axis[0] = props->getFloatValue("axis/x", 0);
678 _axis[1] = props->getFloatValue("axis/y", 0);
679 _axis[2] = props->getFloatValue("axis/z", 0);
680 sgNormalizeVec3(_axis);
683 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
689 SGTexTranslateAnimation::update()
692 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
693 if (_has_min && _position < _min)
695 if (_has_max && _position > _max)
698 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
700 set_translation(_matrix, _position, _axis);
701 ((ssgTexTrans *)_branch)->setTransform(_matrix);
705 ////////////////////////////////////////////////////////////////////////
706 // Implementation of SGTexMultipleAnimation
707 ////////////////////////////////////////////////////////////////////////
709 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
710 SGPropertyNode_ptr props )
711 : SGAnimation(props, new ssgTexTrans),
712 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
716 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
717 _transform = new TexTransform [transform_nodes.size()];
719 for (i = 0; i < transform_nodes.size(); i++) {
720 SGPropertyNode_ptr transform_props = transform_nodes[i];
722 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
724 // transform is a translation
725 _transform[i].subtype = 0;
727 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
729 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
730 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
731 _transform[i].step = transform_props->getDoubleValue("step",0.0);
732 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
733 _transform[i].table = read_interpolation_table(transform_props);
734 _transform[i].has_min = transform_props->hasValue("min");
735 _transform[i].min = transform_props->getDoubleValue("min");
736 _transform[i].has_max = transform_props->hasValue("max");
737 _transform[i].max = transform_props->getDoubleValue("max");
738 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
740 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
741 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
742 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
743 sgNormalizeVec3(_transform[i].axis);
745 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
747 // transform is a rotation
748 _transform[i].subtype = 1;
750 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
751 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
752 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
753 _transform[i].table = read_interpolation_table(transform_props);
754 _transform[i].has_min = transform_props->hasValue("min-deg");
755 _transform[i].min = transform_props->getDoubleValue("min-deg");
756 _transform[i].has_max = transform_props->hasValue("max-deg");
757 _transform[i].max = transform_props->getDoubleValue("max-deg");
758 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
760 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
761 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
762 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
763 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
764 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
765 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
766 sgNormalizeVec3(_transform[i].axis);
772 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
779 SGTexMultipleAnimation::update()
783 sgMakeIdentMat4(tmatrix);
784 for (i = 0; i < _num_transforms; i++) {
786 if(_transform[i].subtype == 0) {
788 // subtype 0 is translation
789 if (_transform[i].table == 0) {
790 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
791 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
792 _transform[i].position = _transform[i].min;
793 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
794 _transform[i].position = _transform[i].max;
796 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
798 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
799 sgPreMultMat4(tmatrix, _transform[i].matrix);
801 } else if (_transform[i].subtype == 1) {
803 // subtype 1 is rotation
805 if (_transform[i].table == 0) {
806 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
807 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
808 _transform[i].position = _transform[i].min;
809 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
810 _transform[i].position = _transform[i].max;
812 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
814 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
815 sgPreMultMat4(tmatrix, _transform[i].matrix);
818 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
821 // end of animation.cxx