1 // animation.cxx - classes to manage model animation.
2 // Written by David Megginson, started 2002.
4 // This file is in the Public Domain, and comes with no warranty.
7 # include <simgear_config.h>
10 #include <string.h> // for strcmp()
17 #include <simgear/math/interpolater.hxx>
18 #include <simgear/props/condition.hxx>
19 #include <simgear/props/props.hxx>
20 #include <simgear/math/sg_random.h>
22 #include "animation.hxx"
23 #include "custtrans.hxx"
24 #include "personality.hxx"
27 ////////////////////////////////////////////////////////////////////////
28 // Static utility functions.
29 ////////////////////////////////////////////////////////////////////////
32 * Set up the transform matrix for a spin or rotation.
35 set_rotation (sgMat4 &matrix, double position_deg,
36 sgVec3 ¢er, sgVec3 &axis)
38 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
40 float s = (float) sin ( temp_angle ) ;
41 float c = (float) cos ( temp_angle ) ;
42 float t = SG_ONE - c ;
44 // axis was normalized at load time
45 // hint to the compiler to put these into FP registers
50 matrix[0][0] = t * x * x + c ;
51 matrix[0][1] = t * y * x - s * z ;
52 matrix[0][2] = t * z * x + s * y ;
53 matrix[0][3] = SG_ZERO;
55 matrix[1][0] = t * x * y + s * z ;
56 matrix[1][1] = t * y * y + c ;
57 matrix[1][2] = t * z * y - s * x ;
58 matrix[1][3] = SG_ZERO;
60 matrix[2][0] = t * x * z - s * y ;
61 matrix[2][1] = t * y * z + s * x ;
62 matrix[2][2] = t * z * z + c ;
63 matrix[2][3] = SG_ZERO;
65 // hint to the compiler to put these into FP registers
70 matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0];
71 matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1];
72 matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2];
73 matrix[3][3] = SG_ONE;
77 * Set up the transform matrix for a translation.
80 set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
83 sgScaleVec3(xyz, axis, position_m);
84 sgMakeTransMat4(matrix, xyz);
88 * Set up the transform matrix for a scale operation.
91 set_scale (sgMat4 &matrix, double x, double y, double z)
93 sgMakeIdentMat4( matrix );
100 * Recursively process all kids to change the alpha values
103 change_alpha( ssgBase *_branch, float _blend )
107 for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
108 change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
110 if ( !_branch->isAKindOf(ssgTypeLeaf())
111 && !_branch->isAKindOf(ssgTypeVtxTable())
112 && !_branch->isAKindOf(ssgTypeVTable()) )
115 int num_colors = ((ssgLeaf *)_branch)->getNumColours();
116 // unsigned int select_ = (_blend == 1.0) ? false : true;
118 for (i = 0; i < num_colors; i++)
120 // ((ssgSelector *)_branch)->select( select_ );
121 float *color = ((ssgLeaf *)_branch)->getColour(i);
127 * Modify property value by step and scroll settings in texture translations
130 apply_mods(double property, double step, double scroll)
135 double scrollval = 0.0;
137 // calculate scroll amount (for odometer like movement)
138 double remainder = step - fmod(fabs(property), step);
139 if (remainder < scroll) {
140 scrollval = (scroll - remainder) / scroll * step;
143 // apply stepping of input value
145 modprop = ((floor(property/step) * step) + scrollval);
147 modprop = ((ceil(property/step) * step) + scrollval);
156 * Read an interpolation table from properties.
158 static SGInterpTable *
159 read_interpolation_table (SGPropertyNode_ptr props)
161 SGPropertyNode_ptr table_node = props->getNode("interpolation");
162 if (table_node != 0) {
163 SGInterpTable * table = new SGInterpTable();
164 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
165 for (unsigned int i = 0; i < entries.size(); i++)
166 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
167 entries[i]->getDoubleValue("dep", 0.0));
176 ////////////////////////////////////////////////////////////////////////
177 // Implementation of SGAnimation
178 ////////////////////////////////////////////////////////////////////////
180 // Initialize the static data member
181 double SGAnimation::sim_time_sec = 0.0;
182 SGPersonalityBranch *SGAnimation::current_object = 0;
184 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
188 _branch->setName(props->getStringValue("name", 0));
189 if ( props->getBoolValue( "enable-hot", true ) ) {
190 _branch->setTraversalMaskBits( SSGTRAV_HOT );
192 _branch->clrTraversalMaskBits( SSGTRAV_HOT );
196 SGAnimation::~SGAnimation ()
206 SGAnimation::update()
212 SGAnimation::restore()
218 ////////////////////////////////////////////////////////////////////////
219 // Implementation of SGNullAnimation
220 ////////////////////////////////////////////////////////////////////////
222 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
223 : SGAnimation(props, new ssgBranch)
227 SGNullAnimation::~SGNullAnimation ()
233 ////////////////////////////////////////////////////////////////////////
234 // Implementation of SGRangeAnimation
235 ////////////////////////////////////////////////////////////////////////
237 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
238 SGPropertyNode_ptr props)
239 : SGAnimation(props, new ssgRangeSelector),
240 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
243 SGPropertyNode_ptr node = props->getChild("condition");
245 _condition = sgReadCondition(prop_root, node);
249 node = props->getChild( "min-factor" );
251 _min_factor = props->getFloatValue("min-factor", 1.0);
253 node = props->getChild( "max-factor" );
255 _max_factor = props->getFloatValue("max-factor", 1.0);
257 node = props->getChild( "min-property" );
259 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
260 ranges[0] = _min_prop->getFloatValue() * _min_factor;
262 _min = props->getFloatValue("min-m", 0);
263 ranges[0] = _min * _min_factor;
265 node = props->getChild( "max-property" );
267 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
268 ranges[1] = _max_prop->getFloatValue() * _max_factor;
270 _max = props->getFloatValue("max-m", 0);
271 ranges[1] = _max * _max_factor;
273 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
276 SGRangeAnimation::~SGRangeAnimation ()
281 SGRangeAnimation::update()
284 if ( _condition == 0 || _condition->test() ) {
285 if (_min_prop != 0) {
286 ranges[0] = _min_prop->getFloatValue() * _min_factor;
288 ranges[0] = _min * _min_factor;
290 if (_max_prop != 0) {
291 ranges[1] = _max_prop->getFloatValue() * _max_factor;
293 ranges[1] = _max * _max_factor;
297 ranges[1] = 1000000000.f;
299 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
305 ////////////////////////////////////////////////////////////////////////
306 // Implementation of SGBillboardAnimation
307 ////////////////////////////////////////////////////////////////////////
309 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
310 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
314 SGBillboardAnimation::~SGBillboardAnimation ()
320 ////////////////////////////////////////////////////////////////////////
321 // Implementation of SGSelectAnimation
322 ////////////////////////////////////////////////////////////////////////
324 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
325 SGPropertyNode_ptr props )
326 : SGAnimation(props, new ssgSelector),
329 SGPropertyNode_ptr node = props->getChild("condition");
331 _condition = sgReadCondition(prop_root, node);
334 SGSelectAnimation::~SGSelectAnimation ()
340 SGSelectAnimation::update()
342 if (_condition != 0 && _condition->test())
343 ((ssgSelector *)_branch)->select(0xffff);
345 ((ssgSelector *)_branch)->select(0x0000);
351 ////////////////////////////////////////////////////////////////////////
352 // Implementation of SGSpinAnimation
353 ////////////////////////////////////////////////////////////////////////
355 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
356 SGPropertyNode_ptr props,
357 double sim_time_sec )
358 : SGAnimation(props, new ssgTransform),
359 _use_personality( props->getBoolValue("use-personality",false) ),
360 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
361 _last_time_sec( sim_time_sec ),
364 SGPropertyNode_ptr node = props->getChild("condition");
366 _condition = sgReadCondition(prop_root, node);
371 if (props->hasValue("axis/x1-m")) {
372 double x1,y1,z1,x2,y2,z2;
373 x1 = props->getFloatValue("axis/x1-m");
374 y1 = props->getFloatValue("axis/y1-m");
375 z1 = props->getFloatValue("axis/z1-m");
376 x2 = props->getFloatValue("axis/x2-m");
377 y2 = props->getFloatValue("axis/y2-m");
378 z2 = props->getFloatValue("axis/z2-m");
379 _center[0] = (x1+x2)/2;
380 _center[1]= (y1+y2)/2;
381 _center[2] = (z1+z2)/2;
382 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
383 _axis[0] = (x2-x1)/vector_length;
384 _axis[1] = (y2-y1)/vector_length;
385 _axis[2] = (z2-z1)/vector_length;
387 _axis[0] = props->getFloatValue("axis/x", 0);
388 _axis[1] = props->getFloatValue("axis/y", 0);
389 _axis[2] = props->getFloatValue("axis/z", 0);
391 if (props->hasValue("center/x-m")) {
392 _center[0] = props->getFloatValue("center/x-m", 0);
393 _center[1] = props->getFloatValue("center/y-m", 0);
394 _center[2] = props->getFloatValue("center/z-m", 0);
396 sgNormalizeVec3(_axis);
398 //_factor(props->getDoubleValue("factor", 1.0)),
402 SGPropertyNode_ptr factor_n = props->getNode( "factor" );
403 if ( factor_n != 0 ) {
404 SGPropertyNode_ptr rand_n = factor_n->getNode( "random" );
406 _factor_min = rand_n->getDoubleValue( "min", 0.0 );
407 _factor_max = rand_n->getDoubleValue( "max", 1.0 );
408 _factor = _factor_min + sg_random() * ( _factor_max - _factor_min );
410 _factor = _factor_min = _factor_max = props->getDoubleValue("factor", 1.0);
413 //_position_deg(props->getDoubleValue("starting-position-deg", 0)),
415 _position_deg_min = 0.0;
416 _position_deg_max = 0.0;
417 SGPropertyNode_ptr position_deg_n = props->getNode( "starting-position-deg" );
418 if ( position_deg_n != 0 ) {
419 SGPropertyNode_ptr rand_n = position_deg_n->getNode( "random" );
421 _position_deg_min = rand_n->getDoubleValue( "min", 0.0 );
422 _position_deg_max = rand_n->getDoubleValue( "max", 1.0 );
423 _position_deg = _position_deg_min + sg_random() * ( _position_deg_max - _position_deg_min );
425 _position_deg = _position_deg_min = _position_deg_max =
426 props->getDoubleValue("starting-position-deg", 1.0);
431 SGSpinAnimation::~SGSpinAnimation ()
436 SGSpinAnimation::update()
438 if ( _condition == 0 || _condition->test() ) {
441 if ( _use_personality ) {
442 SGPersonalityBranch *key = current_object;
443 if ( !key->getIntValue( this, INIT_SPIN ) ) {
444 double v = _factor_min + sg_random() * ( _factor_max - _factor_min );
445 key->setDoubleValue( v, this, FACTOR_SPIN );
447 key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC_SPIN );
448 key->setIntValue( 1, this, INIT_SPIN );
450 v = _position_deg_min + sg_random() * ( _position_deg_max - _position_deg_min );
451 key->setDoubleValue( v, this, POSITION_DEG_SPIN );
454 _factor = key->getDoubleValue( this, FACTOR_SPIN );
455 _position_deg = key->getDoubleValue( this, POSITION_DEG_SPIN );
456 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_SPIN );
457 dt = sim_time_sec - _last_time_sec;
458 _last_time_sec = sim_time_sec;
459 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_SPIN );
461 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
462 _position_deg += (dt * velocity_rpms * 360);
463 while (_position_deg < 0)
464 _position_deg += 360.0;
465 while (_position_deg >= 360.0)
466 _position_deg -= 360.0;
467 key->setDoubleValue( _position_deg, this, POSITION_DEG_SPIN );
469 dt = sim_time_sec - _last_time_sec;
470 _last_time_sec = sim_time_sec;
472 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
473 _position_deg += (dt * velocity_rpms * 360);
474 while (_position_deg < 0)
475 _position_deg += 360.0;
476 while (_position_deg >= 360.0)
477 _position_deg -= 360.0;
480 set_rotation(_matrix, _position_deg, _center, _axis);
481 ((ssgTransform *)_branch)->setTransform(_matrix);
488 ////////////////////////////////////////////////////////////////////////
489 // Implementation of SGTimedAnimation
490 ////////////////////////////////////////////////////////////////////////
492 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
493 : SGAnimation(props, new ssgSelector),
494 _use_personality( props->getBoolValue("use-personality",false) ),
495 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
496 _last_time_sec( sim_time_sec ),
497 _total_duration_sec( 0 ),
501 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
502 size_t nb = nodes.size();
503 for ( size_t i = 0; i < nb; i++ ) {
504 size_t ind = nodes[ i ]->getIndex();
505 while ( ind >= _branch_duration_specs.size() ) {
506 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
508 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
510 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
512 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
513 rNode->getDoubleValue( "max", 1.0 ) );
518 SGTimedAnimation::~SGTimedAnimation ()
523 SGTimedAnimation::init()
525 if ( !_use_personality ) {
526 for ( int i = 0; i < getBranch()->getNumKids(); i++ ) {
528 if ( i < (int)_branch_duration_specs.size() ) {
529 DurationSpec &sp = _branch_duration_specs[ i ];
530 v = sp._min + sg_random() * ( sp._max - sp._min );
534 _branch_duration_sec.push_back( v );
535 _total_duration_sec += v;
537 // Sanity check : total duration shouldn't equal zero
538 if ( _total_duration_sec < 0.01 ) {
539 _total_duration_sec = 0.01;
542 ((ssgSelector *)getBranch())->selectStep(_step);
546 SGTimedAnimation::update()
548 if ( _use_personality ) {
549 SGPersonalityBranch *key = current_object;
550 if ( !key->getIntValue( this, INIT_TIMED ) ) {
553 for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
554 DurationSpec &sp = _branch_duration_specs[ i ];
555 double v = sp._min + sg_random() * ( sp._max - sp._min );
556 key->setDoubleValue( v, this, BRANCH_DURATION_SEC_TIMED, i );
561 // Sanity check : total duration shouldn't equal zero
562 if ( total < 0.01 ) {
565 offset *= sg_random();
566 key->setDoubleValue( sim_time_sec - offset, this, LAST_TIME_SEC_TIMED );
567 key->setDoubleValue( total, this, TOTAL_DURATION_SEC_TIMED );
568 key->setIntValue( 0, this, STEP_TIMED );
569 key->setIntValue( 1, this, INIT_TIMED );
572 _step = key->getIntValue( this, STEP_TIMED );
573 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_TIMED );
574 _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC_TIMED );
575 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
576 _last_time_sec += _total_duration_sec;
578 double duration = _duration_sec;
579 if ( _step < (int)_branch_duration_specs.size() ) {
580 duration = key->getDoubleValue( this, BRANCH_DURATION_SEC_TIMED, _step );
582 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
583 _last_time_sec += duration;
585 if ( _step >= getBranch()->getNumKids() )
588 ((ssgSelector *)getBranch())->selectStep( _step );
589 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_TIMED );
590 key->setIntValue( _step, this, STEP_TIMED );
592 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
593 _last_time_sec += _total_duration_sec;
595 double duration = _duration_sec;
596 if ( _step < (int)_branch_duration_sec.size() ) {
597 duration = _branch_duration_sec[ _step ];
599 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
600 _last_time_sec += duration;
602 if ( _step >= getBranch()->getNumKids() )
604 ((ssgSelector *)getBranch())->selectStep( _step );
612 ////////////////////////////////////////////////////////////////////////
613 // Implementation of SGRotateAnimation
614 ////////////////////////////////////////////////////////////////////////
616 SGRotateAnimation::SGRotateAnimation( 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_deg(props->getDoubleValue("offset-deg", 0.0)),
621 _factor(props->getDoubleValue("factor", 1.0)),
622 _table(read_interpolation_table(props)),
623 _has_min(props->hasValue("min-deg")),
624 _min_deg(props->getDoubleValue("min-deg")),
625 _has_max(props->hasValue("max-deg")),
626 _max_deg(props->getDoubleValue("max-deg")),
627 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
630 SGPropertyNode_ptr node = props->getChild("condition");
632 _condition = sgReadCondition(prop_root, node);
637 if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
638 _axis[0] = props->getFloatValue("axis/x", 0);
639 _axis[1] = props->getFloatValue("axis/y", 0);
640 _axis[2] = props->getFloatValue("axis/z", 0);
642 double x1,y1,z1,x2,y2,z2;
643 x1 = props->getFloatValue("axis/x1-m", 0);
644 y1 = props->getFloatValue("axis/y1-m", 0);
645 z1 = props->getFloatValue("axis/z1-m", 0);
646 x2 = props->getFloatValue("axis/x2-m", 0);
647 y2 = props->getFloatValue("axis/y2-m", 0);
648 z2 = props->getFloatValue("axis/z2-m", 0);
649 _center[0] = (x1+x2)/2;
650 _center[1]= (y1+y2)/2;
651 _center[2] = (z1+z2)/2;
652 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
653 _axis[0] = (x2-x1)/vector_length;
654 _axis[1] = (y2-y1)/vector_length;
655 _axis[2] = (z2-z1)/vector_length;
657 if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
658 || props->hasValue("center/z-m")) {
659 _center[0] = props->getFloatValue("center/x-m", 0);
660 _center[1] = props->getFloatValue("center/y-m", 0);
661 _center[2] = props->getFloatValue("center/z-m", 0);
663 sgNormalizeVec3(_axis);
666 SGRotateAnimation::~SGRotateAnimation ()
672 SGRotateAnimation::update()
674 if (_condition == 0 || _condition->test()) {
676 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
677 if (_has_min && _position_deg < _min_deg)
678 _position_deg = _min_deg;
679 if (_has_max && _position_deg > _max_deg)
680 _position_deg = _max_deg;
682 _position_deg = _table->interpolate(_prop->getDoubleValue());
684 set_rotation(_matrix, _position_deg, _center, _axis);
685 ((ssgTransform *)_branch)->setTransform(_matrix);
691 ////////////////////////////////////////////////////////////////////////
692 // Implementation of SGBlendAnimation
693 ////////////////////////////////////////////////////////////////////////
695 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
696 SGPropertyNode_ptr props )
697 : SGAnimation(props, new ssgTransform),
698 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
699 _table(read_interpolation_table(props)),
701 _offset(props->getDoubleValue("offset", 0.0)),
702 _factor(props->getDoubleValue("factor", 1.0)),
703 _has_min(props->hasValue("min")),
704 _min(props->getDoubleValue("min", 0.0)),
705 _has_max(props->hasValue("max")),
706 _max(props->getDoubleValue("max", 1.0))
710 SGBlendAnimation::~SGBlendAnimation ()
716 SGBlendAnimation::update()
721 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
723 if (_has_min && (_blend < _min))
725 if (_has_max && (_blend > _max))
728 _blend = _table->interpolate(_prop->getDoubleValue());
731 if (_blend != _prev_value) {
732 _prev_value = _blend;
733 change_alpha( _branch, _blend );
740 ////////////////////////////////////////////////////////////////////////
741 // Implementation of SGTranslateAnimation
742 ////////////////////////////////////////////////////////////////////////
744 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
745 SGPropertyNode_ptr props )
746 : SGAnimation(props, new ssgTransform),
747 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
748 _offset_m(props->getDoubleValue("offset-m", 0.0)),
749 _factor(props->getDoubleValue("factor", 1.0)),
750 _table(read_interpolation_table(props)),
751 _has_min(props->hasValue("min-m")),
752 _min_m(props->getDoubleValue("min-m")),
753 _has_max(props->hasValue("max-m")),
754 _max_m(props->getDoubleValue("max-m")),
755 _position_m(props->getDoubleValue("starting-position-m", 0)),
758 SGPropertyNode_ptr node = props->getChild("condition");
760 _condition = sgReadCondition(prop_root, node);
762 _axis[0] = props->getFloatValue("axis/x", 0);
763 _axis[1] = props->getFloatValue("axis/y", 0);
764 _axis[2] = props->getFloatValue("axis/z", 0);
765 sgNormalizeVec3(_axis);
768 SGTranslateAnimation::~SGTranslateAnimation ()
774 SGTranslateAnimation::update()
776 if (_condition == 0 || _condition->test()) {
778 _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
779 if (_has_min && _position_m < _min_m)
780 _position_m = _min_m;
781 if (_has_max && _position_m > _max_m)
782 _position_m = _max_m;
784 _position_m = _table->interpolate(_prop->getDoubleValue());
786 set_translation(_matrix, _position_m, _axis);
787 ((ssgTransform *)_branch)->setTransform(_matrix);
794 ////////////////////////////////////////////////////////////////////////
795 // Implementation of SGScaleAnimation
796 ////////////////////////////////////////////////////////////////////////
798 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
799 SGPropertyNode_ptr props )
800 : SGAnimation(props, new ssgTransform),
801 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
802 _x_factor(props->getDoubleValue("x-factor", 1.0)),
803 _y_factor(props->getDoubleValue("y-factor", 1.0)),
804 _z_factor(props->getDoubleValue("z-factor", 1.0)),
805 _x_offset(props->getDoubleValue("x-offset", 1.0)),
806 _y_offset(props->getDoubleValue("y-offset", 1.0)),
807 _z_offset(props->getDoubleValue("z-offset", 1.0)),
808 _table(read_interpolation_table(props)),
809 _has_min_x(props->hasValue("x-min")),
810 _has_min_y(props->hasValue("y-min")),
811 _has_min_z(props->hasValue("z-min")),
812 _min_x(props->getDoubleValue("x-min")),
813 _min_y(props->getDoubleValue("y-min")),
814 _min_z(props->getDoubleValue("z-min")),
815 _has_max_x(props->hasValue("x-max")),
816 _has_max_y(props->hasValue("y-max")),
817 _has_max_z(props->hasValue("z-max")),
818 _max_x(props->getDoubleValue("x-max")),
819 _max_y(props->getDoubleValue("y-max")),
820 _max_z(props->getDoubleValue("z-max"))
824 SGScaleAnimation::~SGScaleAnimation ()
830 SGScaleAnimation::update()
833 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
834 if (_has_min_x && _x_scale < _min_x)
836 if (_has_max_x && _x_scale > _max_x)
839 _x_scale = _table->interpolate(_prop->getDoubleValue());
843 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
844 if (_has_min_y && _y_scale < _min_y)
846 if (_has_max_y && _y_scale > _max_y)
849 _y_scale = _table->interpolate(_prop->getDoubleValue());
853 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
854 if (_has_min_z && _z_scale < _min_z)
856 if (_has_max_z && _z_scale > _max_z)
859 _z_scale = _table->interpolate(_prop->getDoubleValue());
862 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
863 ((ssgTransform *)_branch)->setTransform(_matrix);
868 ////////////////////////////////////////////////////////////////////////
869 // Implementation of SGTexRotateAnimation
870 ////////////////////////////////////////////////////////////////////////
872 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
873 SGPropertyNode_ptr props )
874 : SGAnimation(props, new ssgTexTrans),
875 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
876 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
877 _factor(props->getDoubleValue("factor", 1.0)),
878 _table(read_interpolation_table(props)),
879 _has_min(props->hasValue("min-deg")),
880 _min_deg(props->getDoubleValue("min-deg")),
881 _has_max(props->hasValue("max-deg")),
882 _max_deg(props->getDoubleValue("max-deg")),
883 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
886 SGPropertyNode *node = props->getChild("condition");
888 _condition = sgReadCondition(prop_root, node);
890 _center[0] = props->getFloatValue("center/x", 0);
891 _center[1] = props->getFloatValue("center/y", 0);
892 _center[2] = props->getFloatValue("center/z", 0);
893 _axis[0] = props->getFloatValue("axis/x", 0);
894 _axis[1] = props->getFloatValue("axis/y", 0);
895 _axis[2] = props->getFloatValue("axis/z", 0);
896 sgNormalizeVec3(_axis);
899 SGTexRotateAnimation::~SGTexRotateAnimation ()
905 SGTexRotateAnimation::update()
907 if (_condition && !_condition->test())
911 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
912 if (_has_min && _position_deg < _min_deg)
913 _position_deg = _min_deg;
914 if (_has_max && _position_deg > _max_deg)
915 _position_deg = _max_deg;
917 _position_deg = _table->interpolate(_prop->getDoubleValue());
919 set_rotation(_matrix, _position_deg, _center, _axis);
920 ((ssgTexTrans *)_branch)->setTransform(_matrix);
925 ////////////////////////////////////////////////////////////////////////
926 // Implementation of SGTexTranslateAnimation
927 ////////////////////////////////////////////////////////////////////////
929 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
930 SGPropertyNode_ptr props )
931 : SGAnimation(props, new ssgTexTrans),
932 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
933 _offset(props->getDoubleValue("offset", 0.0)),
934 _factor(props->getDoubleValue("factor", 1.0)),
935 _step(props->getDoubleValue("step",0.0)),
936 _scroll(props->getDoubleValue("scroll",0.0)),
937 _table(read_interpolation_table(props)),
938 _has_min(props->hasValue("min")),
939 _min(props->getDoubleValue("min")),
940 _has_max(props->hasValue("max")),
941 _max(props->getDoubleValue("max")),
942 _position(props->getDoubleValue("starting-position", 0)),
945 SGPropertyNode *node = props->getChild("condition");
947 _condition = sgReadCondition(prop_root, node);
949 _axis[0] = props->getFloatValue("axis/x", 0);
950 _axis[1] = props->getFloatValue("axis/y", 0);
951 _axis[2] = props->getFloatValue("axis/z", 0);
952 sgNormalizeVec3(_axis);
955 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
961 SGTexTranslateAnimation::update()
963 if (_condition && !_condition->test())
967 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
968 if (_has_min && _position < _min)
970 if (_has_max && _position > _max)
973 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
975 set_translation(_matrix, _position, _axis);
976 ((ssgTexTrans *)_branch)->setTransform(_matrix);
981 ////////////////////////////////////////////////////////////////////////
982 // Implementation of SGTexMultipleAnimation
983 ////////////////////////////////////////////////////////////////////////
985 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
986 SGPropertyNode_ptr props )
987 : SGAnimation(props, new ssgTexTrans),
988 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
992 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
993 _transform = new TexTransform [transform_nodes.size()];
995 for (i = 0; i < transform_nodes.size(); i++) {
996 SGPropertyNode_ptr transform_props = transform_nodes[i];
998 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
1000 // transform is a translation
1001 _transform[i].subtype = 0;
1003 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
1005 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
1006 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
1007 _transform[i].step = transform_props->getDoubleValue("step",0.0);
1008 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
1009 _transform[i].table = read_interpolation_table(transform_props);
1010 _transform[i].has_min = transform_props->hasValue("min");
1011 _transform[i].min = transform_props->getDoubleValue("min");
1012 _transform[i].has_max = transform_props->hasValue("max");
1013 _transform[i].max = transform_props->getDoubleValue("max");
1014 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
1016 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
1017 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
1018 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
1019 sgNormalizeVec3(_transform[i].axis);
1021 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
1023 // transform is a rotation
1024 _transform[i].subtype = 1;
1026 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
1027 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
1028 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
1029 _transform[i].table = read_interpolation_table(transform_props);
1030 _transform[i].has_min = transform_props->hasValue("min-deg");
1031 _transform[i].min = transform_props->getDoubleValue("min-deg");
1032 _transform[i].has_max = transform_props->hasValue("max-deg");
1033 _transform[i].max = transform_props->getDoubleValue("max-deg");
1034 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
1036 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
1037 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
1038 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
1039 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
1040 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
1041 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
1042 sgNormalizeVec3(_transform[i].axis);
1048 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
1050 delete [] _transform;
1054 SGTexMultipleAnimation::update()
1058 sgMakeIdentMat4(tmatrix);
1059 for (i = 0; i < _num_transforms; i++) {
1061 if(_transform[i].subtype == 0) {
1063 // subtype 0 is translation
1064 if (_transform[i].table == 0) {
1065 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
1066 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1067 _transform[i].position = _transform[i].min;
1068 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1069 _transform[i].position = _transform[i].max;
1071 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
1073 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
1074 sgPreMultMat4(tmatrix, _transform[i].matrix);
1076 } else if (_transform[i].subtype == 1) {
1078 // subtype 1 is rotation
1080 if (_transform[i].table == 0) {
1081 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
1082 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1083 _transform[i].position = _transform[i].min;
1084 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1085 _transform[i].position = _transform[i].max;
1087 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
1089 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
1090 sgPreMultMat4(tmatrix, _transform[i].matrix);
1093 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
1099 ////////////////////////////////////////////////////////////////////////
1100 // Implementation of SGAlphaTestAnimation
1101 ////////////////////////////////////////////////////////////////////////
1103 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
1104 : SGAnimation(props, new ssgBranch)
1106 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
1109 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
1113 void SGAlphaTestAnimation::init()
1115 setAlphaClampToBranch(_branch,_alpha_clamp);
1118 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
1120 int nb = b->getNumKids();
1121 for (int i = 0; i<nb; i++) {
1122 ssgEntity *e = b->getKid(i);
1123 if (e->isAKindOf(ssgTypeLeaf())) {
1124 ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
1125 s->enable( GL_ALPHA_TEST );
1126 s->setAlphaClamp( clamp );
1127 } else if (e->isAKindOf(ssgTypeBranch())) {
1128 setAlphaClampToBranch( (ssgBranch*)e, clamp );
1135 ////////////////////////////////////////////////////////////////////////
1136 // Implementation of SGMaterialAnimation
1137 ////////////////////////////////////////////////////////////////////////
1139 SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
1140 SGPropertyNode_ptr props, const SGPath &texture_path)
1141 : SGAnimation(props, new ssgBranch),
1142 _last_condition(false),
1143 _prop_root(prop_root),
1145 _texture_base(texture_path),
1146 _cached_material(0),
1147 _cloned_material(0),
1150 _global(props->getBoolValue("global", false))
1152 SGPropertyNode_ptr n;
1153 n = props->getChild("condition");
1154 _condition = n ? sgReadCondition(_prop_root, n) : 0;
1155 n = props->getChild("property-base");
1157 _prop_base = n->getStringValue();
1158 if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
1162 initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
1163 initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
1164 initColorGroup(props->getChild("emission"), &_emis, EMISSION);
1165 initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
1167 _shi = props->getFloatValue("shininess", -1.0);
1169 _update |= SHININESS;
1171 SGPropertyNode_ptr group = props->getChild("transparency");
1173 _trans.value = group->getFloatValue("alpha", -1.0);
1174 _trans.factor = group->getFloatValue("factor", 1.0);
1175 _trans.offset = group->getFloatValue("offset", 0.0);
1176 _trans.min = group->getFloatValue("min", 0.0);
1177 if (_trans.min < 0.0)
1179 _trans.max = group->getFloatValue("max", 1.0);
1180 if (_trans.max > 1.0)
1183 _update |= TRANSPARENCY;
1185 n = group->getChild("alpha-prop");
1186 _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1187 n = group->getChild("factor-prop");
1188 _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1189 n = group->getChild("offset-prop");
1190 _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1192 _read |= TRANSPARENCY;
1195 _thresh = props->getFloatValue("threshold", -1.0);
1197 _update |= THRESHOLD;
1199 string _texture_str = props->getStringValue("texture", "");
1200 if (!_texture_str.empty()) {
1201 _texture = _texture_base;
1202 _texture.append(_texture_str);
1206 n = props->getChild("shininess-prop");
1207 _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1208 n = props->getChild("threshold-prop");
1209 _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1210 n = props->getChild("texture-prop");
1211 _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1213 _static_update = _update;
1216 void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
1221 col->red = group->getFloatValue("red", -1.0);
1222 col->green = group->getFloatValue("green", -1.0);
1223 col->blue = group->getFloatValue("blue", -1.0);
1224 col->factor = group->getFloatValue("factor", 1.0);
1225 col->offset = group->getFloatValue("offset", 0.0);
1230 n = group->getChild("red-prop");
1231 col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1232 n = group->getChild("green-prop");
1233 col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1234 n = group->getChild("blue-prop");
1235 col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1236 n = group->getChild("factor-prop");
1237 col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1238 n = group->getChild("offset-prop");
1239 col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1244 void SGMaterialAnimation::init()
1247 cloneMaterials(_branch);
1250 int SGMaterialAnimation::update()
1253 bool cond = _condition->test();
1254 if (cond && !_last_condition)
1255 _update |= _static_update;
1257 _last_condition = cond;
1262 if (_read & DIFFUSE)
1263 updateColorGroup(&_diff, DIFFUSE);
1264 if (_read & AMBIENT)
1265 updateColorGroup(&_amb, AMBIENT);
1266 if (_read & EMISSION)
1267 updateColorGroup(&_emis, EMISSION);
1268 if (_read & SPECULAR)
1269 updateColorGroup(&_spec, SPECULAR);
1274 _shi = _shi_prop->getFloatValue();
1276 _update |= SHININESS;
1278 if (_read & TRANSPARENCY) {
1279 PropSpec tmp = _trans;
1280 if (_trans.value_prop)
1281 _trans.value = _trans.value_prop->getFloatValue();
1282 if (_trans.factor_prop)
1283 _trans.factor = _trans.factor_prop->getFloatValue();
1284 if (_trans.offset_prop)
1285 _trans.offset = _trans.offset_prop->getFloatValue();
1287 _update |= TRANSPARENCY;
1291 _thresh = _thresh_prop->getFloatValue();
1293 _update |= THRESHOLD;
1296 string t = _tex_prop->getStringValue();
1297 if (!t.empty() && t != _texture_str) {
1299 _texture = _texture_base;
1305 setMaterialBranch(_branch);
1311 void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
1313 ColorSpec tmp = *col;
1315 col->red = col->red_prop->getFloatValue();
1316 if (col->green_prop)
1317 col->green = col->green_prop->getFloatValue();
1319 col->blue = col->blue_prop->getFloatValue();
1320 if (col->factor_prop)
1321 col->factor = col->factor_prop->getFloatValue();
1322 if (col->offset_prop)
1323 col->offset = col->offset_prop->getFloatValue();
1328 void SGMaterialAnimation::cloneMaterials(ssgBranch *b)
1330 for (int i = 0; i < b->getNumKids(); i++)
1331 cloneMaterials((ssgBranch *)b->getKid(i));
1333 if (!b->isAKindOf(ssgTypeLeaf()) || !((ssgLeaf *)b)->hasState())
1336 ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
1337 if (!_cached_material || _cached_material != s) {
1338 _cached_material = s;
1339 _cloned_material = (ssgSimpleState *)s->clone(SSG_CLONE_STATE);
1341 ((ssgLeaf *)b)->setState(_cloned_material);
1344 void SGMaterialAnimation::setMaterialBranch(ssgBranch *b)
1346 for (int i = 0; i < b->getNumKids(); i++)
1347 setMaterialBranch((ssgBranch *)b->getKid(i));
1349 if (!b->isAKindOf(ssgTypeLeaf()) || !((ssgLeaf *)b)->hasState())
1352 ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
1354 if (_update & DIFFUSE) {
1355 float *v = _diff.rgba();
1356 SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
1357 s->setColourMaterial(GL_DIFFUSE);
1358 s->enable(GL_COLOR_MATERIAL);
1359 s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], alpha);
1360 s->disable(GL_COLOR_MATERIAL);
1362 if (_update & AMBIENT) {
1363 s->setColourMaterial(GL_AMBIENT);
1364 s->enable(GL_COLOR_MATERIAL);
1365 s->setMaterial(GL_AMBIENT, _amb.rgba());
1366 s->disable(GL_COLOR_MATERIAL);
1368 if (_update & EMISSION)
1369 s->setMaterial(GL_EMISSION, _emis.rgba());
1370 if (_update & SPECULAR)
1371 s->setMaterial(GL_SPECULAR, _spec.rgba());
1372 if (_update & SHININESS)
1373 s->setShininess(clamp(_shi, 0.0, 128.0));
1374 if (_update & TRANSPARENCY) {
1375 SGfloat *v = s->getMaterial(GL_DIFFUSE);
1376 float trans = _trans.value * _trans.factor + _trans.offset;
1377 trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
1378 s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], trans);
1380 if (_update & THRESHOLD)
1381 s->setAlphaClamp(clamp(_thresh));
1382 if (_update & TEXTURE)
1383 s->setTexture(_texture.c_str());
1384 if (_update & (TEXTURE|TRANSPARENCY)) {
1385 SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
1386 ssgTexture *tex = s->getTexture();
1387 if ((tex && tex->hasAlpha()) || alpha < 0.999) {
1388 s->setColourMaterial(GL_DIFFUSE);
1389 s->enable(GL_COLOR_MATERIAL);
1390 s->enable(GL_BLEND);
1391 s->enable(GL_ALPHA_TEST);
1392 s->setTranslucent();
1393 s->disable(GL_COLOR_MATERIAL);
1395 s->disable(GL_BLEND);
1396 s->disable(GL_ALPHA_TEST);
1405 ////////////////////////////////////////////////////////////////////////
1406 // Implementation of SGFlashAnimation
1407 ////////////////////////////////////////////////////////////////////////
1408 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
1409 : SGAnimation( props, new SGCustomTransform )
1411 _axis[0] = props->getFloatValue("axis/x", 0);
1412 _axis[1] = props->getFloatValue("axis/y", 0);
1413 _axis[2] = props->getFloatValue("axis/z", 1);
1415 _center[0] = props->getFloatValue("center/x-m", 0);
1416 _center[1] = props->getFloatValue("center/y-m", 0);
1417 _center[2] = props->getFloatValue("center/z-m", 0);
1419 _offset = props->getFloatValue("offset", 0.0);
1420 _factor = props->getFloatValue("factor", 1.0);
1421 _power = props->getFloatValue("power", 1.0);
1422 _two_sides = props->getBoolValue("two-sides", false);
1424 _min_v = props->getFloatValue("min", 0.0);
1425 _max_v = props->getFloatValue("max", 1.0);
1427 ((SGCustomTransform *)_branch)->setTransCallback( &SGFlashAnimation::flashCallback, this );
1430 SGFlashAnimation::~SGFlashAnimation()
1434 void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d )
1436 ((SGFlashAnimation *)d)->flashCallback( r, f, m );
1439 void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
1441 sgVec3 transformed_axis;
1442 sgXformVec3( transformed_axis, _axis, m );
1443 sgNormalizeVec3( transformed_axis );
1446 sgFullXformPnt3( view, _center, m );
1447 sgNormalizeVec3( view );
1449 float cos_angle = -sgScalarProductVec3( transformed_axis, view );
1450 float scale_factor = 0.f;
1451 if ( _two_sides && cos_angle < 0 )
1452 scale_factor = _factor * (float)pow( -cos_angle, _power ) + _offset;
1453 else if ( cos_angle > 0 )
1454 scale_factor = _factor * (float)pow( cos_angle, _power ) + _offset;
1456 if ( scale_factor < _min_v )
1457 scale_factor = _min_v;
1458 if ( scale_factor > _max_v )
1459 scale_factor = _max_v;
1462 sgMakeIdentMat4( transform );
1463 transform[0][0] = scale_factor;
1464 transform[1][1] = scale_factor;
1465 transform[2][2] = scale_factor;
1466 transform[3][0] = _center[0] * ( 1 - scale_factor );
1467 transform[3][1] = _center[1] * ( 1 - scale_factor );
1468 transform[3][2] = _center[2] * ( 1 - scale_factor );
1471 sgPreMultMat4( r, transform );
1476 ////////////////////////////////////////////////////////////////////////
1477 // Implementation of SGDistScaleAnimation
1478 ////////////////////////////////////////////////////////////////////////
1479 SGDistScaleAnimation::SGDistScaleAnimation(SGPropertyNode_ptr props)
1480 : SGAnimation( props, new SGCustomTransform ),
1481 _factor(props->getFloatValue("factor", 1.0)),
1482 _offset(props->getFloatValue("offset", 0.0)),
1483 _min_v(props->getFloatValue("min", 0.0)),
1484 _max_v(props->getFloatValue("max", 1.0)),
1485 _has_min(props->hasValue("min")),
1486 _has_max(props->hasValue("max")),
1487 _table(read_interpolation_table(props))
1489 _center[0] = props->getFloatValue("center/x-m", 0);
1490 _center[1] = props->getFloatValue("center/y-m", 0);
1491 _center[2] = props->getFloatValue("center/z-m", 0);
1493 ((SGCustomTransform *)_branch)->setTransCallback( &SGDistScaleAnimation::distScaleCallback, this );
1496 SGDistScaleAnimation::~SGDistScaleAnimation()
1500 void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d )
1502 ((SGDistScaleAnimation *)d)->distScaleCallback( r, f, m );
1505 void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
1508 sgFullXformPnt3( view, _center, m );
1510 float scale_factor = sgLengthVec3( view );
1512 scale_factor = _factor * scale_factor + _offset;
1513 if ( _has_min && scale_factor < _min_v )
1514 scale_factor = _min_v;
1515 if ( _has_max && scale_factor > _max_v )
1516 scale_factor = _max_v;
1518 scale_factor = _table->interpolate( scale_factor );
1522 sgMakeIdentMat4( transform );
1523 transform[0][0] = scale_factor;
1524 transform[1][1] = scale_factor;
1525 transform[2][2] = scale_factor;
1526 transform[3][0] = _center[0] * ( 1 - scale_factor );
1527 transform[3][1] = _center[1] * ( 1 - scale_factor );
1528 transform[3][2] = _center[2] * ( 1 - scale_factor );
1531 sgPreMultMat4( r, transform );
1534 ////////////////////////////////////////////////////////////////////////
1535 // Implementation of SGShadowAnimation
1536 ////////////////////////////////////////////////////////////////////////
1538 SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
1539 SGPropertyNode_ptr props )
1540 : SGAnimation(props, new ssgBranch),
1542 _condition_value(true)
1545 SGPropertyNode_ptr node = props->getChild("condition");
1547 _condition = sgReadCondition(prop_root, node);
1548 _condition_value = false;
1552 SGShadowAnimation::~SGShadowAnimation ()
1558 SGShadowAnimation::update()
1561 _condition_value = _condition->test();
1565 bool SGShadowAnimation::get_condition_value(void) {
1566 return _condition_value;
1569 // end of animation.cxx