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