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