]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/animation.cxx
8988c3399767214327accdc88dc3e3f681ea1566
[simgear.git] / simgear / scene / model / animation.cxx
1 // animation.cxx - classes to manage model animation.
2 // Written by David Megginson, started 2002.
3 //
4 // This file is in the Public Domain, and comes with no warranty.
5
6
7 #include <string.h>             // for strcmp()
8 #include <math.h>
9
10 #include <plib/sg.h>
11 #include <plib/ssg.h>
12 #include <plib/ul.h>
13
14 #include <simgear/math/interpolater.hxx>
15 #include <simgear/props/condition.hxx>
16 #include <simgear/props/props.hxx>
17
18 #include "animation.hxx"
19
20
21 \f
22 ////////////////////////////////////////////////////////////////////////
23 // Static utility functions.
24 ////////////////////////////////////////////////////////////////////////
25
26 /**
27  * Set up the transform matrix for a spin or rotation.
28  */
29 static void
30 set_rotation (sgMat4 &matrix, double position_deg,
31               sgVec3 &center, sgVec3 &axis)
32 {
33  float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
34  
35  float s = (float) sin ( temp_angle ) ;
36  float c = (float) cos ( temp_angle ) ;
37  float t = SG_ONE - c ;
38
39  // axis was normalized at load time 
40  // hint to the compiler to put these into FP registers
41  float x = axis[0];
42  float y = axis[1];
43  float z = axis[2];
44
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;
49  
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;
54  
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;
59
60   // hint to the compiler to put these into FP registers
61  x = center[0];
62  y = center[1];
63  z = center[2];
64  
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;
69 }
70
71 /**
72  * Set up the transform matrix for a translation.
73  */
74 static void
75 set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
76 {
77   sgVec3 xyz;
78   sgScaleVec3(xyz, axis, position_m);
79   sgMakeTransMat4(matrix, xyz);
80 }
81
82 /**
83  * Set up the transform matrix for a scale operation.
84  */
85 static void
86 set_scale (sgMat4 &matrix, double x, double y, double z)
87 {
88   sgMakeIdentMat4( matrix );
89   matrix[0][0] = x;
90   matrix[1][1] = y;
91   matrix[2][2] = z;
92 }
93
94 /**
95  * Recursively process all kids to change the alpha values
96  */
97 static void
98 change_alpha( ssgBase *_branch, float _blend )
99 {
100   int i;
101
102   for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
103     change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
104
105   if ( strcmp("ssgLeaf", _branch->getTypeName()) &&
106        strcmp("ssgVtxTable", _branch->getTypeName()) &&
107        strcmp("ssgVTable", _branch->getTypeName()) )
108     return;
109
110   int num_colors = ((ssgLeaf *)_branch)->getNumColours();
111
112   for (i = 0; i < num_colors; i++)
113   {
114     float *color =  ((ssgLeaf *)_branch)->getColour(i);
115     color[3] = _blend;
116   }
117 }
118
119 /**
120  * Modify property value by step and scroll settings in texture translations
121  */
122 static double
123 apply_mods(double property, double step, double scroll)
124 {
125
126   double modprop;
127   if(step > 0) {
128     double scrollval = 0.0;
129     if(scroll > 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;
134       }
135     }
136   // apply stepping of input value
137   if(property > 0) 
138      modprop = ((floor(property/step) * step) + scrollval);
139   else
140      modprop = ((ceil(property/step) * step) + scrollval);
141   } else {
142      modprop = property;
143   }
144   return modprop;
145
146 }
147
148 /**
149  * Read an interpolation table from properties.
150  */
151 static SGInterpTable *
152 read_interpolation_table (SGPropertyNode_ptr props)
153 {
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));
161     return table;
162   } else {
163     return 0;
164   }
165 }
166
167
168 \f
169 ////////////////////////////////////////////////////////////////////////
170 // Implementation of SGAnimation
171 ////////////////////////////////////////////////////////////////////////
172
173 // Initialize the static data member
174 double SGAnimation::sim_time_sec = 0.0;
175
176 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
177     : _branch(branch)
178 {
179     _branch->setName(props->getStringValue("name", 0));
180 }
181
182 SGAnimation::~SGAnimation ()
183 {
184 }
185
186 void
187 SGAnimation::init ()
188 {
189 }
190
191 void
192 SGAnimation::update()
193 {
194 }
195
196
197 \f
198 ////////////////////////////////////////////////////////////////////////
199 // Implementation of SGNullAnimation
200 ////////////////////////////////////////////////////////////////////////
201
202 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
203   : SGAnimation(props, new ssgBranch)
204 {
205 }
206
207 SGNullAnimation::~SGNullAnimation ()
208 {
209 }
210
211
212 \f
213 ////////////////////////////////////////////////////////////////////////
214 // Implementation of SGRangeAnimation
215 ////////////////////////////////////////////////////////////////////////
216
217 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
218                                     SGPropertyNode_ptr props)
219   : SGAnimation(props, new ssgRangeSelector),
220     _min(0.0), _max(0.0)
221 {
222     float ranges[2];
223
224     SGPropertyNode_ptr node = props->getChild( "min-property" );
225     if (node != 0) {
226        _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
227        ranges[0] = _min_prop->getFloatValue();
228     } else {
229        ranges[0] = _min = props->getFloatValue("min-m", 0);
230     }
231     node = props->getChild( "max-property" );
232     if (node != 0) {
233        _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
234        ranges[1] = _max_prop->getFloatValue();
235     } else {
236        ranges[1] = _max = props->getFloatValue("max-m", 0);
237     }
238     ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
239 }
240
241 SGRangeAnimation::~SGRangeAnimation ()
242 {
243 }
244
245 void
246 SGRangeAnimation::update()
247 {
248     float ranges[2];
249     bool upd = false;
250     if (_min_prop != 0) {
251        ranges[0] = _min_prop->getFloatValue();
252        upd = true;
253     } else {
254        ranges[0] = _min;
255     }
256     if (_max_prop != 0) {
257        ranges[1] = _max_prop->getFloatValue();
258        upd = true;
259     } else {
260        ranges[1] = _max;
261     }
262     if (upd)
263        ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
264 }
265
266
267 \f
268 ////////////////////////////////////////////////////////////////////////
269 // Implementation of SGBillboardAnimation
270 ////////////////////////////////////////////////////////////////////////
271
272 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
273     : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
274 {
275 }
276
277 SGBillboardAnimation::~SGBillboardAnimation ()
278 {
279 }
280
281
282 \f
283 ////////////////////////////////////////////////////////////////////////
284 // Implementation of SGSelectAnimation
285 ////////////////////////////////////////////////////////////////////////
286
287 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
288                                   SGPropertyNode_ptr props )
289   : SGAnimation(props, new ssgSelector),
290     _condition(0)
291 {
292   SGPropertyNode_ptr node = props->getChild("condition");
293   if (node != 0)
294     _condition = sgReadCondition(prop_root, node);
295 }
296
297 SGSelectAnimation::~SGSelectAnimation ()
298 {
299   delete _condition;
300 }
301
302 void
303 SGSelectAnimation::update()
304 {
305   if (_condition != 0 && _condition->test()) 
306       ((ssgSelector *)_branch)->select(0xffff);
307   else
308       ((ssgSelector *)_branch)->select(0x0000);
309 }
310
311
312 \f
313 ////////////////////////////////////////////////////////////////////////
314 // Implementation of SGSpinAnimation
315 ////////////////////////////////////////////////////////////////////////
316
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 )
325 {
326     _center[0] = 0;
327     _center[1] = 0;
328     _center[2] = 0;
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;
344     } else {
345        _axis[0] = props->getFloatValue("axis/x", 0);
346        _axis[1] = props->getFloatValue("axis/y", 0);
347        _axis[2] = props->getFloatValue("axis/z", 0);
348     }
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);
353     }
354     sgNormalizeVec3(_axis);
355 }
356
357 SGSpinAnimation::~SGSpinAnimation ()
358 {
359 }
360
361 void
362 SGSpinAnimation::update()
363 {
364   double dt = sim_time_sec - _last_time_sec;
365   _last_time_sec = sim_time_sec;
366
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);
375 }
376
377
378 \f
379 ////////////////////////////////////////////////////////////////////////
380 // Implementation of SGTimedAnimation
381 ////////////////////////////////////////////////////////////////////////
382
383 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
384   : SGAnimation(props, new ssgSelector),
385     _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
386     _last_time_sec(0),
387     _step(-1)
388 {
389 }
390
391 SGTimedAnimation::~SGTimedAnimation ()
392 {
393 }
394
395 void
396 SGTimedAnimation::update()
397 {
398     if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
399         _last_time_sec = sim_time_sec;
400         _step++;
401         if (_step >= getBranch()->getNumKids())
402             _step = 0;
403         ((ssgSelector *)getBranch())->selectStep(_step);
404     }
405 }
406
407
408 \f
409 ////////////////////////////////////////////////////////////////////////
410 // Implementation of SGRotateAnimation
411 ////////////////////////////////////////////////////////////////////////
412
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))
425 {
426     _center[0] = 0;
427     _center[1] = 0;
428     _center[2] = 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;
444     } else {
445        _axis[0] = props->getFloatValue("axis/x", 0);
446        _axis[1] = props->getFloatValue("axis/y", 0);
447        _axis[2] = props->getFloatValue("axis/z", 0);
448     }
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);
453     }
454     sgNormalizeVec3(_axis);
455 }
456
457 SGRotateAnimation::~SGRotateAnimation ()
458 {
459   delete _table;
460 }
461
462 void
463 SGRotateAnimation::update()
464 {
465   if (_table == 0) {
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;
471   } else {
472     _position_deg = _table->interpolate(_prop->getDoubleValue());
473   }
474   set_rotation(_matrix, _position_deg, _center, _axis);
475   ((ssgTransform *)_branch)->setTransform(_matrix);
476 }
477
478 \f
479 ////////////////////////////////////////////////////////////////////////
480 // Implementation of SGBlendAnimation
481 ////////////////////////////////////////////////////////////////////////
482
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)),
494     _prev_value(1.0)
495 {
496 }
497
498 SGBlendAnimation::~SGBlendAnimation ()
499 {
500     delete _table;
501 }
502
503 void
504 SGBlendAnimation::update()
505 {
506   double _blend;
507
508   if (_table == 0) {
509     _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
510
511     if (_has_min && (_blend < _min))
512       _blend = _min;
513     if (_has_max && (_blend > _max))
514       _blend = _max;
515   } else {
516     _blend = _table->interpolate(_prop->getDoubleValue());
517   }
518
519   if (_blend != _prev_value) {
520     _prev_value = _blend;
521     change_alpha( _branch, _blend );
522   }
523 }
524
525
526 \f
527 ////////////////////////////////////////////////////////////////////////
528 // Implementation of SGTranslateAnimation
529 ////////////////////////////////////////////////////////////////////////
530
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))
543 {
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);
548 }
549
550 SGTranslateAnimation::~SGTranslateAnimation ()
551 {
552   delete _table;
553 }
554
555 void
556 SGTranslateAnimation::update()
557 {
558   if (_table == 0) {
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;
564   } else {
565     _position_m = _table->interpolate(_prop->getDoubleValue());
566   }
567   set_translation(_matrix, _position_m, _axis);
568   ((ssgTransform *)_branch)->setTransform(_matrix);
569 }
570
571
572 \f
573 ////////////////////////////////////////////////////////////////////////
574 // Implementation of SGScaleAnimation
575 ////////////////////////////////////////////////////////////////////////
576
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"))
600 {
601 }
602
603 SGScaleAnimation::~SGScaleAnimation ()
604 {
605   delete _table;
606 }
607
608 void
609 SGScaleAnimation::update()
610 {
611   if (_table == 0) {
612       _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
613     if (_has_min_x && _x_scale < _min_x)
614       _x_scale = _min_x;
615     if (_has_max_x && _x_scale > _max_x)
616       _x_scale = _max_x;
617   } else {
618     _x_scale = _table->interpolate(_prop->getDoubleValue());
619   }
620
621   if (_table == 0) {
622     _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
623     if (_has_min_y && _y_scale < _min_y)
624       _y_scale = _min_y;
625     if (_has_max_y && _y_scale > _max_y)
626       _y_scale = _max_y;
627   } else {
628     _y_scale = _table->interpolate(_prop->getDoubleValue());
629   }
630
631   if (_table == 0) {
632     _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
633     if (_has_min_z && _z_scale < _min_z)
634       _z_scale = _min_z;
635     if (_has_max_z && _z_scale > _max_z)
636       _z_scale = _max_z;
637   } else {
638     _z_scale = _table->interpolate(_prop->getDoubleValue());
639   }
640
641   set_scale(_matrix, _x_scale, _y_scale, _z_scale );
642   ((ssgTransform *)_branch)->setTransform(_matrix);
643 }
644
645
646 ////////////////////////////////////////////////////////////////////////
647 // Implementation of SGTexRotateAnimation
648 ////////////////////////////////////////////////////////////////////////
649
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))
662 {
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);
670 }
671
672 SGTexRotateAnimation::~SGTexRotateAnimation ()
673 {
674   delete _table;
675 }
676
677 void
678 SGTexRotateAnimation::update()
679 {
680   if (_table == 0) {
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;
686   } else {
687     _position_deg = _table->interpolate(_prop->getDoubleValue());
688   }
689   set_rotation(_matrix, _position_deg, _center, _axis);
690   ((ssgTexTrans *)_branch)->setTransform(_matrix);
691 }
692
693
694 ////////////////////////////////////////////////////////////////////////
695 // Implementation of SGTexTranslateAnimation
696 ////////////////////////////////////////////////////////////////////////
697
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))
712 {
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);
717 }
718
719 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
720 {
721   delete _table;
722 }
723
724 void
725 SGTexTranslateAnimation::update()
726 {
727   if (_table == 0) {
728     _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
729     if (_has_min && _position < _min)
730       _position = _min;
731     if (_has_max && _position > _max)
732       _position = _max;
733   } else {
734     _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
735   }
736   set_translation(_matrix, _position, _axis);
737   ((ssgTexTrans *)_branch)->setTransform(_matrix);
738 }
739
740
741 ////////////////////////////////////////////////////////////////////////
742 // Implementation of SGTexMultipleAnimation
743 ////////////////////////////////////////////////////////////////////////
744
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))
749 {
750   unsigned int i;
751   // Load animations
752   vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
753   _transform = new TexTransform [transform_nodes.size()];
754   _num_transforms = 0;
755   for (i = 0; i < transform_nodes.size(); i++) {
756     SGPropertyNode_ptr transform_props = transform_nodes[i];
757
758     if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
759
760       // transform is a translation
761       _transform[i].subtype = 0;
762
763       _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
764
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);
775
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);
780       _num_transforms++;
781     } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
782
783       // transform is a rotation
784       _transform[i].subtype = 1;
785
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);
795
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);
803       _num_transforms++;
804     }
805   }
806 }
807
808 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
809 {
810   // delete _table;
811   delete _transform;
812 }
813
814 void
815 SGTexMultipleAnimation::update()
816 {
817   int i;
818   sgMat4 tmatrix;
819   sgMakeIdentMat4(tmatrix);
820   for (i = 0; i < _num_transforms; i++) {
821
822     if(_transform[i].subtype == 0) {
823
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;
831       } else {
832          _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
833       }
834       set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
835       sgPreMultMat4(tmatrix, _transform[i].matrix);
836
837     } else if (_transform[i].subtype == 1) {
838
839       // subtype 1 is rotation
840
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;
847      } else {
848         _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
849       }
850       set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
851       sgPreMultMat4(tmatrix, _transform[i].matrix);
852     }
853   }
854   ((ssgTexTrans *)_branch)->setTransform(tmatrix);
855 }
856
857 // end of animation.cxx