]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/animation.cxx
6ced085855e3ac2b8e603a84640803792d6300e2
[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 #include "flash.hxx"
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 ( !_branch->isAKindOf(ssgTypeLeaf())
106        && !_branch->isAKindOf(ssgTypeVtxTable())
107        && !_branch->isAKindOf(ssgTypeVTable()) )
108     return;
109
110   int num_colors = ((ssgLeaf *)_branch)->getNumColours();
111 // unsigned int select_ = (_blend == 1.0) ? false : true;
112
113   for (i = 0; i < num_colors; i++)
114   {
115 //    ((ssgSelector *)_branch)->select( select_ );
116     float *color =  ((ssgLeaf *)_branch)->getColour(i);
117     color[3] = _blend;
118   }
119 }
120
121 /**
122  * Modify property value by step and scroll settings in texture translations
123  */
124 static double
125 apply_mods(double property, double step, double scroll)
126 {
127
128   double modprop;
129   if(step > 0) {
130     double scrollval = 0.0;
131     if(scroll > 0) {
132       // calculate scroll amount (for odometer like movement)
133       double remainder  =  step - fmod(fabs(property), step);
134       if (remainder < scroll) {
135         scrollval = (scroll - remainder) / scroll * step;
136       }
137     }
138   // apply stepping of input value
139   if(property > 0) 
140      modprop = ((floor(property/step) * step) + scrollval);
141   else
142      modprop = ((ceil(property/step) * step) + scrollval);
143   } else {
144      modprop = property;
145   }
146   return modprop;
147
148 }
149
150 /**
151  * Read an interpolation table from properties.
152  */
153 static SGInterpTable *
154 read_interpolation_table (SGPropertyNode_ptr props)
155 {
156   SGPropertyNode_ptr table_node = props->getNode("interpolation");
157   if (table_node != 0) {
158     SGInterpTable * table = new SGInterpTable();
159     vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
160     for (unsigned int i = 0; i < entries.size(); i++)
161       table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
162                       entries[i]->getDoubleValue("dep", 0.0));
163     return table;
164   } else {
165     return 0;
166   }
167 }
168
169
170 \f
171 ////////////////////////////////////////////////////////////////////////
172 // Implementation of SGAnimation
173 ////////////////////////////////////////////////////////////////////////
174
175 // Initialize the static data member
176 double SGAnimation::sim_time_sec = 0.0;
177
178 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
179     : _branch(branch)
180 {
181     _branch->setName(props->getStringValue("name", 0));
182 }
183
184 SGAnimation::~SGAnimation ()
185 {
186 }
187
188 void
189 SGAnimation::init ()
190 {
191 }
192
193 int
194 SGAnimation::update()
195 {
196     return 1;
197 }
198
199 void
200 SGAnimation::restore()
201 {
202 }
203
204
205 \f
206 ////////////////////////////////////////////////////////////////////////
207 // Implementation of SGNullAnimation
208 ////////////////////////////////////////////////////////////////////////
209
210 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
211   : SGAnimation(props, new ssgBranch)
212 {
213 }
214
215 SGNullAnimation::~SGNullAnimation ()
216 {
217 }
218
219
220 \f
221 ////////////////////////////////////////////////////////////////////////
222 // Implementation of SGRangeAnimation
223 ////////////////////////////////////////////////////////////////////////
224
225 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
226                                     SGPropertyNode_ptr props)
227   : SGAnimation(props, new ssgRangeSelector),
228     _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0)
229
230 {
231     float ranges[2];
232
233     SGPropertyNode_ptr node = props->getChild( "min-factor" );
234     if (node != 0) {
235        _min_factor = props->getFloatValue("min-factor", 1.0);
236     }
237     node = props->getChild( "max-factor" );
238     if (node != 0) {
239        _max_factor = props->getFloatValue("max-factor", 1.0);
240     }
241     node = props->getChild( "min-property" );
242     if (node != 0) {
243        _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
244        ranges[0] = _min_prop->getFloatValue() * _min_factor;
245     } else {
246        _min = props->getFloatValue("min-m", 0);
247        ranges[0] = _min * _min_factor;
248     }
249     node = props->getChild( "max-property" );
250     if (node != 0) {
251        _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
252        ranges[1] = _max_prop->getFloatValue() * _max_factor;
253     } else {
254        _max = props->getFloatValue("max-m", 0);
255        ranges[1] = _max * _max_factor;
256     }
257     ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
258 }
259
260 SGRangeAnimation::~SGRangeAnimation ()
261 {
262 }
263
264 int
265 SGRangeAnimation::update()
266 {
267     float ranges[2];
268     bool upd = false;
269     if (_min_prop != 0) {
270        ranges[0] = _min_prop->getFloatValue() * _min_factor;
271        upd = true;
272     } else {
273        ranges[0] = _min * _min_factor;
274     }
275     if (_max_prop != 0) {
276        ranges[1] = _max_prop->getFloatValue() * _max_factor;
277        upd = true;
278     } else {
279        ranges[1] = _max * _max_factor;
280     }
281     if (upd) {
282        ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
283     }
284   return 1;
285 }
286
287
288 \f
289 ////////////////////////////////////////////////////////////////////////
290 // Implementation of SGBillboardAnimation
291 ////////////////////////////////////////////////////////////////////////
292
293 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
294     : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
295 {
296 }
297
298 SGBillboardAnimation::~SGBillboardAnimation ()
299 {
300 }
301
302
303 \f
304 ////////////////////////////////////////////////////////////////////////
305 // Implementation of SGSelectAnimation
306 ////////////////////////////////////////////////////////////////////////
307
308 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
309                                   SGPropertyNode_ptr props )
310   : SGAnimation(props, new ssgSelector),
311     _condition(0)
312 {
313   SGPropertyNode_ptr node = props->getChild("condition");
314   if (node != 0)
315     _condition = sgReadCondition(prop_root, node);
316 }
317
318 SGSelectAnimation::~SGSelectAnimation ()
319 {
320   delete _condition;
321 }
322
323 int
324 SGSelectAnimation::update()
325 {
326   if (_condition != 0 && _condition->test()) 
327       ((ssgSelector *)_branch)->select(0xffff);
328   else
329       ((ssgSelector *)_branch)->select(0x0000);
330   return 1;
331 }
332
333
334 \f
335 ////////////////////////////////////////////////////////////////////////
336 // Implementation of SGSpinAnimation
337 ////////////////////////////////////////////////////////////////////////
338
339 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
340                               SGPropertyNode_ptr props,
341                               double sim_time_sec )
342   : SGAnimation(props, new ssgTransform),
343     _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
344     _factor(props->getDoubleValue("factor", 1.0)),
345     _position_deg(props->getDoubleValue("starting-position-deg", 0)),
346     _last_time_sec( sim_time_sec )
347 {
348     _center[0] = 0;
349     _center[1] = 0;
350     _center[2] = 0;
351     if (props->hasValue("axis/x1-m")) {
352         double x1,y1,z1,x2,y2,z2;
353         x1 = props->getFloatValue("axis/x1-m");
354         y1 = props->getFloatValue("axis/y1-m");
355         z1 = props->getFloatValue("axis/z1-m");
356         x2 = props->getFloatValue("axis/x2-m");
357         y2 = props->getFloatValue("axis/y2-m");
358         z2 = props->getFloatValue("axis/z2-m");
359         _center[0] = (x1+x2)/2;
360         _center[1]= (y1+y2)/2;
361         _center[2] = (z1+z2)/2;
362         float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
363         _axis[0] = (x2-x1)/vector_length;
364         _axis[1] = (y2-y1)/vector_length;
365         _axis[2] = (z2-z1)/vector_length;
366     } else {
367        _axis[0] = props->getFloatValue("axis/x", 0);
368        _axis[1] = props->getFloatValue("axis/y", 0);
369        _axis[2] = props->getFloatValue("axis/z", 0);
370     }
371     if (props->hasValue("center/x-m")) {
372        _center[0] = props->getFloatValue("center/x-m", 0);
373        _center[1] = props->getFloatValue("center/y-m", 0);
374        _center[2] = props->getFloatValue("center/z-m", 0);
375     }
376     sgNormalizeVec3(_axis);
377 }
378
379 SGSpinAnimation::~SGSpinAnimation ()
380 {
381 }
382
383 int
384 SGSpinAnimation::update()
385 {
386   double dt = sim_time_sec - _last_time_sec;
387   _last_time_sec = sim_time_sec;
388
389   float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
390   _position_deg += (dt * velocity_rpms * 360);
391   while (_position_deg < 0)
392     _position_deg += 360.0;
393   while (_position_deg >= 360.0)
394     _position_deg -= 360.0;
395   set_rotation(_matrix, _position_deg, _center, _axis);
396   ((ssgTransform *)_branch)->setTransform(_matrix);
397   return 1;
398 }
399
400
401 \f
402 ////////////////////////////////////////////////////////////////////////
403 // Implementation of SGTimedAnimation
404 ////////////////////////////////////////////////////////////////////////
405
406 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
407   : SGAnimation(props, new ssgSelector),
408     _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
409     _last_time_sec(0),
410     _step(-1)
411 {
412 }
413
414 SGTimedAnimation::~SGTimedAnimation ()
415 {
416 }
417
418 int
419 SGTimedAnimation::update()
420 {
421     if ((sim_time_sec - _last_time_sec) >= _duration_sec) {
422         _last_time_sec = sim_time_sec;
423         _step++;
424         if (_step >= getBranch()->getNumKids())
425             _step = 0;
426         ((ssgSelector *)getBranch())->selectStep(_step);
427     }
428   return 1;
429 }
430
431
432 \f
433 ////////////////////////////////////////////////////////////////////////
434 // Implementation of SGRotateAnimation
435 ////////////////////////////////////////////////////////////////////////
436
437 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
438                                   SGPropertyNode_ptr props )
439     : SGAnimation(props, new ssgTransform),
440       _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
441       _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
442       _factor(props->getDoubleValue("factor", 1.0)),
443       _table(read_interpolation_table(props)),
444       _has_min(props->hasValue("min-deg")),
445       _min_deg(props->getDoubleValue("min-deg")),
446       _has_max(props->hasValue("max-deg")),
447       _max_deg(props->getDoubleValue("max-deg")),
448       _position_deg(props->getDoubleValue("starting-position-deg", 0))
449 {
450     _center[0] = 0;
451     _center[1] = 0;
452     _center[2] = 0;
453     if (props->hasValue("axis/x1-m")) {
454         double x1,y1,z1,x2,y2,z2;
455         x1 = props->getFloatValue("axis/x1-m");
456         y1 = props->getFloatValue("axis/y1-m");
457         z1 = props->getFloatValue("axis/z1-m");
458         x2 = props->getFloatValue("axis/x2-m");
459         y2 = props->getFloatValue("axis/y2-m");
460         z2 = props->getFloatValue("axis/z2-m");
461         _center[0] = (x1+x2)/2;
462         _center[1]= (y1+y2)/2;
463         _center[2] = (z1+z2)/2;
464         float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
465         _axis[0] = (x2-x1)/vector_length;
466         _axis[1] = (y2-y1)/vector_length;
467         _axis[2] = (z2-z1)/vector_length;
468     } else {
469        _axis[0] = props->getFloatValue("axis/x", 0);
470        _axis[1] = props->getFloatValue("axis/y", 0);
471        _axis[2] = props->getFloatValue("axis/z", 0);
472     }
473     if (props->hasValue("center/x-m")) {
474        _center[0] = props->getFloatValue("center/x-m", 0);
475        _center[1] = props->getFloatValue("center/y-m", 0);
476        _center[2] = props->getFloatValue("center/z-m", 0);
477     }
478     sgNormalizeVec3(_axis);
479 }
480
481 SGRotateAnimation::~SGRotateAnimation ()
482 {
483   delete _table;
484 }
485
486 int
487 SGRotateAnimation::update()
488 {
489   if (_table == 0) {
490    _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
491    if (_has_min && _position_deg < _min_deg)
492      _position_deg = _min_deg;
493    if (_has_max && _position_deg > _max_deg)
494      _position_deg = _max_deg;
495   } else {
496     _position_deg = _table->interpolate(_prop->getDoubleValue());
497   }
498   set_rotation(_matrix, _position_deg, _center, _axis);
499   ((ssgTransform *)_branch)->setTransform(_matrix);
500   return 1;
501 }
502
503 \f
504 ////////////////////////////////////////////////////////////////////////
505 // Implementation of SGBlendAnimation
506 ////////////////////////////////////////////////////////////////////////
507
508 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
509                                         SGPropertyNode_ptr props )
510   : SGAnimation(props, new ssgTransform),
511     _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
512     _table(read_interpolation_table(props)),
513     _prev_value(1.0),
514     _offset(props->getDoubleValue("offset", 0.0)),
515     _factor(props->getDoubleValue("factor", 1.0)),
516     _has_min(props->hasValue("min")),
517     _min(props->getDoubleValue("min", 0.0)),
518     _has_max(props->hasValue("max")),
519     _max(props->getDoubleValue("max", 1.0))
520 {
521 }
522
523 SGBlendAnimation::~SGBlendAnimation ()
524 {
525     delete _table;
526 }
527
528 int
529 SGBlendAnimation::update()
530 {
531   double _blend;
532
533   if (_table == 0) {
534     _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
535
536     if (_has_min && (_blend < _min))
537       _blend = _min;
538     if (_has_max && (_blend > _max))
539       _blend = _max;
540   } else {
541     _blend = _table->interpolate(_prop->getDoubleValue());
542   }
543
544   if (_blend != _prev_value) {
545     _prev_value = _blend;
546     change_alpha( _branch, _blend );
547   }
548   return 1;
549 }
550
551
552 \f
553 ////////////////////////////////////////////////////////////////////////
554 // Implementation of SGTranslateAnimation
555 ////////////////////////////////////////////////////////////////////////
556
557 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
558                                         SGPropertyNode_ptr props )
559   : SGAnimation(props, new ssgTransform),
560       _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
561     _offset_m(props->getDoubleValue("offset-m", 0.0)),
562     _factor(props->getDoubleValue("factor", 1.0)),
563     _table(read_interpolation_table(props)),
564     _has_min(props->hasValue("min-m")),
565     _min_m(props->getDoubleValue("min-m")),
566     _has_max(props->hasValue("max-m")),
567     _max_m(props->getDoubleValue("max-m")),
568     _position_m(props->getDoubleValue("starting-position-m", 0))
569 {
570   _axis[0] = props->getFloatValue("axis/x", 0);
571   _axis[1] = props->getFloatValue("axis/y", 0);
572   _axis[2] = props->getFloatValue("axis/z", 0);
573   sgNormalizeVec3(_axis);
574 }
575
576 SGTranslateAnimation::~SGTranslateAnimation ()
577 {
578   delete _table;
579 }
580
581 int
582 SGTranslateAnimation::update()
583 {
584   if (_table == 0) {
585     _position_m = (_prop->getDoubleValue() + _offset_m) * _factor;
586     if (_has_min && _position_m < _min_m)
587       _position_m = _min_m;
588     if (_has_max && _position_m > _max_m)
589       _position_m = _max_m;
590   } else {
591     _position_m = _table->interpolate(_prop->getDoubleValue());
592   }
593   set_translation(_matrix, _position_m, _axis);
594   ((ssgTransform *)_branch)->setTransform(_matrix);
595   return 1;
596 }
597
598
599 \f
600 ////////////////////////////////////////////////////////////////////////
601 // Implementation of SGScaleAnimation
602 ////////////////////////////////////////////////////////////////////////
603
604 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
605                                         SGPropertyNode_ptr props )
606   : SGAnimation(props, new ssgTransform),
607       _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
608     _x_factor(props->getDoubleValue("x-factor", 1.0)),
609     _y_factor(props->getDoubleValue("y-factor", 1.0)),
610     _z_factor(props->getDoubleValue("z-factor", 1.0)),
611     _x_offset(props->getDoubleValue("x-offset", 1.0)),
612     _y_offset(props->getDoubleValue("y-offset", 1.0)),
613     _z_offset(props->getDoubleValue("z-offset", 1.0)),
614     _table(read_interpolation_table(props)),
615     _has_min_x(props->hasValue("x-min")),
616     _has_min_y(props->hasValue("y-min")),
617     _has_min_z(props->hasValue("z-min")),
618     _min_x(props->getDoubleValue("x-min")),
619     _min_y(props->getDoubleValue("y-min")),
620     _min_z(props->getDoubleValue("z-min")),
621     _has_max_x(props->hasValue("x-max")),
622     _has_max_y(props->hasValue("y-max")),
623     _has_max_z(props->hasValue("z-max")),
624     _max_x(props->getDoubleValue("x-max")),
625     _max_y(props->getDoubleValue("y-max")),
626     _max_z(props->getDoubleValue("z-max"))
627 {
628 }
629
630 SGScaleAnimation::~SGScaleAnimation ()
631 {
632   delete _table;
633 }
634
635 int
636 SGScaleAnimation::update()
637 {
638   if (_table == 0) {
639       _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
640     if (_has_min_x && _x_scale < _min_x)
641       _x_scale = _min_x;
642     if (_has_max_x && _x_scale > _max_x)
643       _x_scale = _max_x;
644   } else {
645     _x_scale = _table->interpolate(_prop->getDoubleValue());
646   }
647
648   if (_table == 0) {
649     _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
650     if (_has_min_y && _y_scale < _min_y)
651       _y_scale = _min_y;
652     if (_has_max_y && _y_scale > _max_y)
653       _y_scale = _max_y;
654   } else {
655     _y_scale = _table->interpolate(_prop->getDoubleValue());
656   }
657
658   if (_table == 0) {
659     _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
660     if (_has_min_z && _z_scale < _min_z)
661       _z_scale = _min_z;
662     if (_has_max_z && _z_scale > _max_z)
663       _z_scale = _max_z;
664   } else {
665     _z_scale = _table->interpolate(_prop->getDoubleValue());
666   }
667
668   set_scale(_matrix, _x_scale, _y_scale, _z_scale );
669   ((ssgTransform *)_branch)->setTransform(_matrix);
670   return 1;
671 }
672
673
674 ////////////////////////////////////////////////////////////////////////
675 // Implementation of SGTexRotateAnimation
676 ////////////////////////////////////////////////////////////////////////
677
678 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
679                                   SGPropertyNode_ptr props )
680     : SGAnimation(props, new ssgTexTrans),
681       _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
682       _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
683       _factor(props->getDoubleValue("factor", 1.0)),
684       _table(read_interpolation_table(props)),
685       _has_min(props->hasValue("min-deg")),
686       _min_deg(props->getDoubleValue("min-deg")),
687       _has_max(props->hasValue("max-deg")),
688       _max_deg(props->getDoubleValue("max-deg")),
689       _position_deg(props->getDoubleValue("starting-position-deg", 0))
690 {
691   _center[0] = props->getFloatValue("center/x", 0);
692   _center[1] = props->getFloatValue("center/y", 0);
693   _center[2] = props->getFloatValue("center/z", 0);
694   _axis[0] = props->getFloatValue("axis/x", 0);
695   _axis[1] = props->getFloatValue("axis/y", 0);
696   _axis[2] = props->getFloatValue("axis/z", 0);
697   sgNormalizeVec3(_axis);
698 }
699
700 SGTexRotateAnimation::~SGTexRotateAnimation ()
701 {
702   delete _table;
703 }
704
705 int
706 SGTexRotateAnimation::update()
707 {
708   if (_table == 0) {
709    _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
710    if (_has_min && _position_deg < _min_deg)
711      _position_deg = _min_deg;
712    if (_has_max && _position_deg > _max_deg)
713      _position_deg = _max_deg;
714   } else {
715     _position_deg = _table->interpolate(_prop->getDoubleValue());
716   }
717   set_rotation(_matrix, _position_deg, _center, _axis);
718   ((ssgTexTrans *)_branch)->setTransform(_matrix);
719   return 1;
720 }
721
722
723 ////////////////////////////////////////////////////////////////////////
724 // Implementation of SGTexTranslateAnimation
725 ////////////////////////////////////////////////////////////////////////
726
727 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
728                                         SGPropertyNode_ptr props )
729   : SGAnimation(props, new ssgTexTrans),
730       _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
731     _offset(props->getDoubleValue("offset", 0.0)),
732     _factor(props->getDoubleValue("factor", 1.0)),
733     _step(props->getDoubleValue("step",0.0)),
734     _scroll(props->getDoubleValue("scroll",0.0)),
735     _table(read_interpolation_table(props)),
736     _has_min(props->hasValue("min")),
737     _min(props->getDoubleValue("min")),
738     _has_max(props->hasValue("max")),
739     _max(props->getDoubleValue("max")),
740     _position(props->getDoubleValue("starting-position", 0))
741 {
742   _axis[0] = props->getFloatValue("axis/x", 0);
743   _axis[1] = props->getFloatValue("axis/y", 0);
744   _axis[2] = props->getFloatValue("axis/z", 0);
745   sgNormalizeVec3(_axis);
746 }
747
748 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
749 {
750   delete _table;
751 }
752
753 int
754 SGTexTranslateAnimation::update()
755 {
756   if (_table == 0) {
757     _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
758     if (_has_min && _position < _min)
759       _position = _min;
760     if (_has_max && _position > _max)
761       _position = _max;
762   } else {
763     _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
764   }
765   set_translation(_matrix, _position, _axis);
766   ((ssgTexTrans *)_branch)->setTransform(_matrix);
767   return 1;
768 }
769
770
771 ////////////////////////////////////////////////////////////////////////
772 // Implementation of SGTexMultipleAnimation
773 ////////////////////////////////////////////////////////////////////////
774
775 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
776                                         SGPropertyNode_ptr props )
777   : SGAnimation(props, new ssgTexTrans),
778       _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
779 {
780   unsigned int i;
781   // Load animations
782   vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
783   _transform = new TexTransform [transform_nodes.size()];
784   _num_transforms = 0;
785   for (i = 0; i < transform_nodes.size(); i++) {
786     SGPropertyNode_ptr transform_props = transform_nodes[i];
787
788     if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
789
790       // transform is a translation
791       _transform[i].subtype = 0;
792
793       _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
794
795       _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
796       _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
797       _transform[i].step = transform_props->getDoubleValue("step",0.0);
798       _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
799       _transform[i].table = read_interpolation_table(transform_props);
800       _transform[i].has_min = transform_props->hasValue("min");
801       _transform[i].min = transform_props->getDoubleValue("min");
802       _transform[i].has_max = transform_props->hasValue("max");
803       _transform[i].max = transform_props->getDoubleValue("max");
804       _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
805
806       _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
807       _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
808       _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
809       sgNormalizeVec3(_transform[i].axis);
810       _num_transforms++;
811     } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
812
813       // transform is a rotation
814       _transform[i].subtype = 1;
815
816       _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
817       _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
818       _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
819       _transform[i].table = read_interpolation_table(transform_props);
820       _transform[i].has_min = transform_props->hasValue("min-deg");
821       _transform[i].min = transform_props->getDoubleValue("min-deg");
822       _transform[i].has_max = transform_props->hasValue("max-deg");
823       _transform[i].max = transform_props->getDoubleValue("max-deg");
824       _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
825
826       _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
827       _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
828       _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
829       _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
830       _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
831       _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
832       sgNormalizeVec3(_transform[i].axis);
833       _num_transforms++;
834     }
835   }
836 }
837
838 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
839 {
840   // delete _table;
841   delete _transform;
842 }
843
844 int
845 SGTexMultipleAnimation::update()
846 {
847   int i;
848   sgMat4 tmatrix;
849   sgMakeIdentMat4(tmatrix);
850   for (i = 0; i < _num_transforms; i++) {
851
852     if(_transform[i].subtype == 0) {
853
854       // subtype 0 is translation
855       if (_transform[i].table == 0) {
856         _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
857         if (_transform[i].has_min && _transform[i].position < _transform[i].min)
858           _transform[i].position = _transform[i].min;
859         if (_transform[i].has_max && _transform[i].position > _transform[i].max)
860           _transform[i].position = _transform[i].max;
861       } else {
862          _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
863       }
864       set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
865       sgPreMultMat4(tmatrix, _transform[i].matrix);
866
867     } else if (_transform[i].subtype == 1) {
868
869       // subtype 1 is rotation
870
871       if (_transform[i].table == 0) {
872         _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
873         if (_transform[i].has_min && _transform[i].position < _transform[i].min)
874          _transform[i].position = _transform[i].min;
875        if (_transform[i].has_max && _transform[i].position > _transform[i].max)
876          _transform[i].position = _transform[i].max;
877      } else {
878         _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
879       }
880       set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
881       sgPreMultMat4(tmatrix, _transform[i].matrix);
882     }
883   }
884   ((ssgTexTrans *)_branch)->setTransform(tmatrix);
885   return 1;
886 }
887
888
889 \f
890 ////////////////////////////////////////////////////////////////////////
891 // Implementation of SGAlphaTestAnimation
892 ////////////////////////////////////////////////////////////////////////
893
894 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
895   : SGAnimation(props, new ssgBranch)
896 {
897   _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
898 }
899
900 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
901 {
902 }
903
904 void SGAlphaTestAnimation::init()
905 {
906   setAlphaClampToBranch(_branch,_alpha_clamp);
907 }
908
909 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
910 {
911   int nb = b->getNumKids();
912   for (int i = 0; i<nb; i++) {
913     ssgEntity *e = b->getKid(i);
914     if (e->isAKindOf(ssgTypeLeaf())) {
915       ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
916       s->enable( GL_ALPHA_TEST );
917       s->setAlphaClamp( clamp );
918     } else if (e->isAKindOf(ssgTypeBranch())) {
919       setAlphaClampToBranch( (ssgBranch*)e, clamp );
920     }
921   }
922 }
923
924
925 \f
926 ////////////////////////////////////////////////////////////////////////
927 // Implementation of SGFlashAnimation
928 ////////////////////////////////////////////////////////////////////////
929 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
930   : SGAnimation( props, new SGFlash )
931 {
932   sgVec3 axis;
933   axis[0] = props->getFloatValue("axis/x", 0);
934   axis[1] = props->getFloatValue("axis/y", 0);
935   axis[2] = props->getFloatValue("axis/z", 1);
936   ((SGFlash *)_branch)->setAxis( axis );
937
938   sgVec3 center;
939   center[0] = props->getFloatValue("center/x-m", 0);
940   center[1] = props->getFloatValue("center/y-m", 0);
941   center[2] = props->getFloatValue("center/z-m", 0);
942   ((SGFlash *)_branch)->setCenter( center );
943
944   float offset = props->getFloatValue("offset", 0.0);
945   float factor = props->getFloatValue("factor", 1.0);
946   float power = props->getFloatValue("power", 1.0);
947   bool two_sides = props->getBoolValue("two-sides", false);
948   ((SGFlash *)_branch)->setParameters( power, factor, offset, two_sides );
949
950   float v_min = props->getFloatValue("min", 0.0);
951   float v_max = props->getFloatValue("max", 1.0);
952   ((SGFlash *)_branch)->setClampValues( v_min, v_max );
953 }
954
955 SGFlashAnimation::~SGFlashAnimation()
956 {
957 }
958
959 // end of animation.cxx