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 <string.h> // for strcmp()
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>
19 #include "animation.hxx"
20 #include "custtrans.hxx"
21 #include "personality.hxx"
24 ////////////////////////////////////////////////////////////////////////
25 // Static utility functions.
26 ////////////////////////////////////////////////////////////////////////
29 * Set up the transform matrix for a spin or rotation.
32 set_rotation (sgMat4 &matrix, double position_deg,
33 sgVec3 ¢er, sgVec3 &axis)
35 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
37 float s = (float) sin ( temp_angle ) ;
38 float c = (float) cos ( temp_angle ) ;
39 float t = SG_ONE - c ;
41 // axis was normalized at load time
42 // hint to the compiler to put these into FP registers
47 matrix[0][0] = t * x * x + c ;
48 matrix[0][1] = t * y * x - s * z ;
49 matrix[0][2] = t * z * x + s * y ;
50 matrix[0][3] = SG_ZERO;
52 matrix[1][0] = t * x * y + s * z ;
53 matrix[1][1] = t * y * y + c ;
54 matrix[1][2] = t * z * y - s * x ;
55 matrix[1][3] = SG_ZERO;
57 matrix[2][0] = t * x * z - s * y ;
58 matrix[2][1] = t * y * z + s * x ;
59 matrix[2][2] = t * z * z + c ;
60 matrix[2][3] = SG_ZERO;
62 // hint to the compiler to put these into FP registers
67 matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0];
68 matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1];
69 matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2];
70 matrix[3][3] = SG_ONE;
74 * Set up the transform matrix for a translation.
77 set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
80 sgScaleVec3(xyz, axis, position_m);
81 sgMakeTransMat4(matrix, xyz);
85 * Set up the transform matrix for a scale operation.
88 set_scale (sgMat4 &matrix, double x, double y, double z)
90 sgMakeIdentMat4( matrix );
97 * Recursively process all kids to change the alpha values
100 change_alpha( ssgBase *_branch, float _blend )
104 for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
105 change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
107 if ( !_branch->isAKindOf(ssgTypeLeaf())
108 && !_branch->isAKindOf(ssgTypeVtxTable())
109 && !_branch->isAKindOf(ssgTypeVTable()) )
112 int num_colors = ((ssgLeaf *)_branch)->getNumColours();
113 // unsigned int select_ = (_blend == 1.0) ? false : true;
115 for (i = 0; i < num_colors; i++)
117 // ((ssgSelector *)_branch)->select( select_ );
118 float *color = ((ssgLeaf *)_branch)->getColour(i);
124 * Modify property value by step and scroll settings in texture translations
127 apply_mods(double property, double step, double scroll)
132 double scrollval = 0.0;
134 // calculate scroll amount (for odometer like movement)
135 double remainder = step - fmod(fabs(property), step);
136 if (remainder < scroll) {
137 scrollval = (scroll - remainder) / scroll * step;
140 // apply stepping of input value
142 modprop = ((floor(property/step) * step) + scrollval);
144 modprop = ((ceil(property/step) * step) + scrollval);
153 * Read an interpolation table from properties.
155 static SGInterpTable *
156 read_interpolation_table (SGPropertyNode_ptr props)
158 SGPropertyNode_ptr table_node = props->getNode("interpolation");
159 if (table_node != 0) {
160 SGInterpTable * table = new SGInterpTable();
161 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
162 for (unsigned int i = 0; i < entries.size(); i++)
163 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
164 entries[i]->getDoubleValue("dep", 0.0));
173 ////////////////////////////////////////////////////////////////////////
174 // Implementation of SGAnimation
175 ////////////////////////////////////////////////////////////////////////
177 // Initialize the static data member
178 double SGAnimation::sim_time_sec = 0.0;
179 SGPersonalityBranch *SGAnimation::current_object = 0;
181 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
185 _branch->setName(props->getStringValue("name", 0));
186 if ( props->getBoolValue( "enable-hot", true ) ) {
187 _branch->setTraversalMaskBits( SSGTRAV_HOT );
189 _branch->clrTraversalMaskBits( SSGTRAV_HOT );
193 SGAnimation::~SGAnimation ()
203 SGAnimation::update()
209 SGAnimation::restore()
215 ////////////////////////////////////////////////////////////////////////
216 // Implementation of SGNullAnimation
217 ////////////////////////////////////////////////////////////////////////
219 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
220 : SGAnimation(props, new ssgBranch)
224 SGNullAnimation::~SGNullAnimation ()
230 ////////////////////////////////////////////////////////////////////////
231 // Implementation of SGRangeAnimation
232 ////////////////////////////////////////////////////////////////////////
234 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
235 SGPropertyNode_ptr props)
236 : SGAnimation(props, new ssgRangeSelector),
237 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
240 SGPropertyNode_ptr node = props->getChild("condition");
242 _condition = sgReadCondition(prop_root, node);
246 node = props->getChild( "min-factor" );
248 _min_factor = props->getFloatValue("min-factor", 1.0);
250 node = props->getChild( "max-factor" );
252 _max_factor = props->getFloatValue("max-factor", 1.0);
254 node = props->getChild( "min-property" );
256 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
257 ranges[0] = _min_prop->getFloatValue() * _min_factor;
259 _min = props->getFloatValue("min-m", 0);
260 ranges[0] = _min * _min_factor;
262 node = props->getChild( "max-property" );
264 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
265 ranges[1] = _max_prop->getFloatValue() * _max_factor;
267 _max = props->getFloatValue("max-m", 0);
268 ranges[1] = _max * _max_factor;
270 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
273 SGRangeAnimation::~SGRangeAnimation ()
278 SGRangeAnimation::update()
281 if ( _condition == 0 || _condition->test() ) {
282 if (_min_prop != 0) {
283 ranges[0] = _min_prop->getFloatValue() * _min_factor;
285 ranges[0] = _min * _min_factor;
287 if (_max_prop != 0) {
288 ranges[1] = _max_prop->getFloatValue() * _max_factor;
290 ranges[1] = _max * _max_factor;
294 ranges[1] = 1000000000.f;
296 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
302 ////////////////////////////////////////////////////////////////////////
303 // Implementation of SGBillboardAnimation
304 ////////////////////////////////////////////////////////////////////////
306 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
307 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
311 SGBillboardAnimation::~SGBillboardAnimation ()
317 ////////////////////////////////////////////////////////////////////////
318 // Implementation of SGSelectAnimation
319 ////////////////////////////////////////////////////////////////////////
321 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
322 SGPropertyNode_ptr props )
323 : SGAnimation(props, new ssgSelector),
326 SGPropertyNode_ptr node = props->getChild("condition");
328 _condition = sgReadCondition(prop_root, node);
331 SGSelectAnimation::~SGSelectAnimation ()
337 SGSelectAnimation::update()
339 if (_condition != 0 && _condition->test())
340 ((ssgSelector *)_branch)->select(0xffff);
342 ((ssgSelector *)_branch)->select(0x0000);
348 ////////////////////////////////////////////////////////////////////////
349 // Implementation of SGSpinAnimation
350 ////////////////////////////////////////////////////////////////////////
352 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
353 SGPropertyNode_ptr props,
354 double sim_time_sec )
355 : SGAnimation(props, new ssgTransform),
356 _use_personality( props->getBoolValue("use-personality",false) ),
357 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
358 _last_time_sec( sim_time_sec ),
361 SGPropertyNode_ptr node = props->getChild("condition");
363 _condition = sgReadCondition(prop_root, node);
368 if (props->hasValue("axis/x1-m")) {
369 double x1,y1,z1,x2,y2,z2;
370 x1 = props->getFloatValue("axis/x1-m");
371 y1 = props->getFloatValue("axis/y1-m");
372 z1 = props->getFloatValue("axis/z1-m");
373 x2 = props->getFloatValue("axis/x2-m");
374 y2 = props->getFloatValue("axis/y2-m");
375 z2 = props->getFloatValue("axis/z2-m");
376 _center[0] = (x1+x2)/2;
377 _center[1]= (y1+y2)/2;
378 _center[2] = (z1+z2)/2;
379 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
380 _axis[0] = (x2-x1)/vector_length;
381 _axis[1] = (y2-y1)/vector_length;
382 _axis[2] = (z2-z1)/vector_length;
384 _axis[0] = props->getFloatValue("axis/x", 0);
385 _axis[1] = props->getFloatValue("axis/y", 0);
386 _axis[2] = props->getFloatValue("axis/z", 0);
388 if (props->hasValue("center/x-m")) {
389 _center[0] = props->getFloatValue("center/x-m", 0);
390 _center[1] = props->getFloatValue("center/y-m", 0);
391 _center[2] = props->getFloatValue("center/z-m", 0);
393 sgNormalizeVec3(_axis);
395 //_factor(props->getDoubleValue("factor", 1.0)),
399 SGPropertyNode_ptr factor_n = props->getNode( "factor" );
400 if ( factor_n != 0 ) {
401 SGPropertyNode_ptr rand_n = factor_n->getNode( "random" );
403 _factor_min = rand_n->getDoubleValue( "min", 0.0 );
404 _factor_max = rand_n->getDoubleValue( "max", 1.0 );
405 _factor = _factor_min + sg_random() * ( _factor_max - _factor_min );
407 _factor = _factor_min = _factor_max = props->getDoubleValue("factor", 1.0);
410 //_position_deg(props->getDoubleValue("starting-position-deg", 0)),
412 _position_deg_min = 0.0;
413 _position_deg_max = 0.0;
414 SGPropertyNode_ptr position_deg_n = props->getNode( "starting-position-deg" );
415 if ( position_deg_n != 0 ) {
416 SGPropertyNode_ptr rand_n = position_deg_n->getNode( "random" );
418 _position_deg_min = rand_n->getDoubleValue( "min", 0.0 );
419 _position_deg_max = rand_n->getDoubleValue( "max", 1.0 );
420 _position_deg = _position_deg_min + sg_random() * ( _position_deg_max - _position_deg_min );
422 _position_deg = _position_deg_min = _position_deg_max =
423 props->getDoubleValue("starting-position-deg", 1.0);
428 SGSpinAnimation::~SGSpinAnimation ()
433 SGSpinAnimation::update()
435 if ( _condition == 0 || _condition->test() ) {
438 if ( _use_personality ) {
439 SGPersonalityBranch *key = current_object;
440 if ( !key->getIntValue( this, INIT_SPIN ) ) {
441 double v = _factor_min + sg_random() * ( _factor_max - _factor_min );
442 key->setDoubleValue( v, this, FACTOR_SPIN );
444 key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC_SPIN );
445 key->setIntValue( 1, this, INIT_SPIN );
447 v = _position_deg_min + sg_random() * ( _position_deg_max - _position_deg_min );
448 key->setDoubleValue( v, this, POSITION_DEG_SPIN );
451 _factor = key->getDoubleValue( this, FACTOR_SPIN );
452 _position_deg = key->getDoubleValue( this, POSITION_DEG_SPIN );
453 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_SPIN );
454 dt = sim_time_sec - _last_time_sec;
455 _last_time_sec = sim_time_sec;
456 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_SPIN );
458 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
459 _position_deg += (dt * velocity_rpms * 360);
460 while (_position_deg < 0)
461 _position_deg += 360.0;
462 while (_position_deg >= 360.0)
463 _position_deg -= 360.0;
464 key->setDoubleValue( _position_deg, this, POSITION_DEG_SPIN );
466 dt = sim_time_sec - _last_time_sec;
467 _last_time_sec = sim_time_sec;
469 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
470 _position_deg += (dt * velocity_rpms * 360);
471 while (_position_deg < 0)
472 _position_deg += 360.0;
473 while (_position_deg >= 360.0)
474 _position_deg -= 360.0;
477 set_rotation(_matrix, _position_deg, _center, _axis);
478 ((ssgTransform *)_branch)->setTransform(_matrix);
485 ////////////////////////////////////////////////////////////////////////
486 // Implementation of SGTimedAnimation
487 ////////////////////////////////////////////////////////////////////////
489 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
490 : SGAnimation(props, new ssgSelector),
491 _use_personality( props->getBoolValue("use-personality",false) ),
492 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
493 _last_time_sec( sim_time_sec ),
494 _total_duration_sec( 0 ),
498 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
499 size_t nb = nodes.size();
500 for ( size_t i = 0; i < nb; i++ ) {
501 size_t ind = nodes[ i ]->getIndex();
502 while ( ind >= _branch_duration_specs.size() ) {
503 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
505 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
507 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
509 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
510 rNode->getDoubleValue( "max", 1.0 ) );
515 SGTimedAnimation::~SGTimedAnimation ()
520 SGTimedAnimation::init()
522 if ( !_use_personality ) {
523 for ( int i = 0; i < getBranch()->getNumKids(); i++ ) {
525 if ( i < (int)_branch_duration_specs.size() ) {
526 DurationSpec &sp = _branch_duration_specs[ i ];
527 v = sp._min + sg_random() * ( sp._max - sp._min );
531 _branch_duration_sec.push_back( v );
532 _total_duration_sec += v;
534 // Sanity check : total duration shouldn't equal zero
535 if ( _total_duration_sec < 0.01 ) {
536 _total_duration_sec = 0.01;
539 ((ssgSelector *)getBranch())->selectStep(_step);
543 SGTimedAnimation::update()
545 if ( _use_personality ) {
546 SGPersonalityBranch *key = current_object;
547 if ( !key->getIntValue( this, INIT_TIMED ) ) {
550 for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
551 DurationSpec &sp = _branch_duration_specs[ i ];
552 double v = sp._min + sg_random() * ( sp._max - sp._min );
553 key->setDoubleValue( v, this, BRANCH_DURATION_SEC_TIMED, i );
558 // Sanity check : total duration shouldn't equal zero
559 if ( total < 0.01 ) {
562 offset *= sg_random();
563 key->setDoubleValue( sim_time_sec - offset, this, LAST_TIME_SEC_TIMED );
564 key->setDoubleValue( total, this, TOTAL_DURATION_SEC_TIMED );
565 key->setIntValue( 0, this, STEP_TIMED );
566 key->setIntValue( 1, this, INIT_TIMED );
569 _step = key->getIntValue( this, STEP_TIMED );
570 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_TIMED );
571 _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC_TIMED );
572 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
573 _last_time_sec += _total_duration_sec;
575 double duration = _duration_sec;
576 if ( _step < (int)_branch_duration_specs.size() ) {
577 duration = key->getDoubleValue( this, BRANCH_DURATION_SEC_TIMED, _step );
579 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
580 _last_time_sec += duration;
582 if ( _step >= getBranch()->getNumKids() )
585 ((ssgSelector *)getBranch())->selectStep( _step );
586 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_TIMED );
587 key->setIntValue( _step, this, STEP_TIMED );
589 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
590 _last_time_sec += _total_duration_sec;
592 double duration = _duration_sec;
593 if ( _step < (int)_branch_duration_sec.size() ) {
594 duration = _branch_duration_sec[ _step ];
596 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
597 _last_time_sec += duration;
599 if ( _step >= getBranch()->getNumKids() )
601 ((ssgSelector *)getBranch())->selectStep( _step );
609 ////////////////////////////////////////////////////////////////////////
610 // Implementation of SGRotateAnimation
611 ////////////////////////////////////////////////////////////////////////
613 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
614 SGPropertyNode_ptr props )
615 : SGAnimation(props, new ssgTransform),
616 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
617 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
618 _factor(props->getDoubleValue("factor", 1.0)),
619 _table(read_interpolation_table(props)),
620 _has_min(props->hasValue("min-deg")),
621 _min_deg(props->getDoubleValue("min-deg")),
622 _has_max(props->hasValue("max-deg")),
623 _max_deg(props->getDoubleValue("max-deg")),
624 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
627 SGPropertyNode_ptr node = props->getChild("condition");
629 _condition = sgReadCondition(prop_root, node);
634 if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
635 _axis[0] = props->getFloatValue("axis/x", 0);
636 _axis[1] = props->getFloatValue("axis/y", 0);
637 _axis[2] = props->getFloatValue("axis/z", 0);
639 double x1,y1,z1,x2,y2,z2;
640 x1 = props->getFloatValue("axis/x1-m", 0);
641 y1 = props->getFloatValue("axis/y1-m", 0);
642 z1 = props->getFloatValue("axis/z1-m", 0);
643 x2 = props->getFloatValue("axis/x2-m", 0);
644 y2 = props->getFloatValue("axis/y2-m", 0);
645 z2 = props->getFloatValue("axis/z2-m", 0);
646 _center[0] = (x1+x2)/2;
647 _center[1]= (y1+y2)/2;
648 _center[2] = (z1+z2)/2;
649 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
650 _axis[0] = (x2-x1)/vector_length;
651 _axis[1] = (y2-y1)/vector_length;
652 _axis[2] = (z2-z1)/vector_length;
654 if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
655 || props->hasValue("center/z-m")) {
656 _center[0] = props->getFloatValue("center/x-m", 0);
657 _center[1] = props->getFloatValue("center/y-m", 0);
658 _center[2] = props->getFloatValue("center/z-m", 0);
660 sgNormalizeVec3(_axis);
663 SGRotateAnimation::~SGRotateAnimation ()
669 SGRotateAnimation::update()
671 if (_condition == 0 || _condition->test()) {
673 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
674 if (_has_min && _position_deg < _min_deg)
675 _position_deg = _min_deg;
676 if (_has_max && _position_deg > _max_deg)
677 _position_deg = _max_deg;
679 _position_deg = _table->interpolate(_prop->getDoubleValue());
681 set_rotation(_matrix, _position_deg, _center, _axis);
682 ((ssgTransform *)_branch)->setTransform(_matrix);
688 ////////////////////////////////////////////////////////////////////////
689 // Implementation of SGBlendAnimation
690 ////////////////////////////////////////////////////////////////////////
692 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
693 SGPropertyNode_ptr props )
694 : SGAnimation(props, new ssgTransform),
695 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
696 _table(read_interpolation_table(props)),
698 _offset(props->getDoubleValue("offset", 0.0)),
699 _factor(props->getDoubleValue("factor", 1.0)),
700 _has_min(props->hasValue("min")),
701 _min(props->getDoubleValue("min", 0.0)),
702 _has_max(props->hasValue("max")),
703 _max(props->getDoubleValue("max", 1.0))
707 SGBlendAnimation::~SGBlendAnimation ()
713 SGBlendAnimation::update()
718 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
720 if (_has_min && (_blend < _min))
722 if (_has_max && (_blend > _max))
725 _blend = _table->interpolate(_prop->getDoubleValue());
728 if (_blend != _prev_value) {
729 _prev_value = _blend;
730 change_alpha( _branch, _blend );
737 ////////////////////////////////////////////////////////////////////////
738 // Implementation of SGTranslateAnimation
739 ////////////////////////////////////////////////////////////////////////
741 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
742 SGPropertyNode_ptr props )
743 : SGAnimation(props, new ssgTransform),
744 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
745 _offset_m(props->getDoubleValue("offset-m", 0.0)),
746 _factor(props->getDoubleValue("factor", 1.0)),
747 _table(read_interpolation_table(props)),
748 _has_min(props->hasValue("min-m")),
749 _min_m(props->getDoubleValue("min-m")),
750 _has_max(props->hasValue("max-m")),
751 _max_m(props->getDoubleValue("max-m")),
752 _position_m(props->getDoubleValue("starting-position-m", 0)),
755 SGPropertyNode_ptr node = props->getChild("condition");
757 _condition = sgReadCondition(prop_root, node);
759 _axis[0] = props->getFloatValue("axis/x", 0);
760 _axis[1] = props->getFloatValue("axis/y", 0);
761 _axis[2] = props->getFloatValue("axis/z", 0);
762 sgNormalizeVec3(_axis);
765 SGTranslateAnimation::~SGTranslateAnimation ()
771 SGTranslateAnimation::update()
773 if (_condition == 0 || _condition->test()) {
775 _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
776 if (_has_min && _position_m < _min_m)
777 _position_m = _min_m;
778 if (_has_max && _position_m > _max_m)
779 _position_m = _max_m;
781 _position_m = _table->interpolate(_prop->getDoubleValue());
783 set_translation(_matrix, _position_m, _axis);
784 ((ssgTransform *)_branch)->setTransform(_matrix);
791 ////////////////////////////////////////////////////////////////////////
792 // Implementation of SGScaleAnimation
793 ////////////////////////////////////////////////////////////////////////
795 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
796 SGPropertyNode_ptr props )
797 : SGAnimation(props, new ssgTransform),
798 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
799 _x_factor(props->getDoubleValue("x-factor", 1.0)),
800 _y_factor(props->getDoubleValue("y-factor", 1.0)),
801 _z_factor(props->getDoubleValue("z-factor", 1.0)),
802 _x_offset(props->getDoubleValue("x-offset", 1.0)),
803 _y_offset(props->getDoubleValue("y-offset", 1.0)),
804 _z_offset(props->getDoubleValue("z-offset", 1.0)),
805 _table(read_interpolation_table(props)),
806 _has_min_x(props->hasValue("x-min")),
807 _has_min_y(props->hasValue("y-min")),
808 _has_min_z(props->hasValue("z-min")),
809 _min_x(props->getDoubleValue("x-min")),
810 _min_y(props->getDoubleValue("y-min")),
811 _min_z(props->getDoubleValue("z-min")),
812 _has_max_x(props->hasValue("x-max")),
813 _has_max_y(props->hasValue("y-max")),
814 _has_max_z(props->hasValue("z-max")),
815 _max_x(props->getDoubleValue("x-max")),
816 _max_y(props->getDoubleValue("y-max")),
817 _max_z(props->getDoubleValue("z-max"))
821 SGScaleAnimation::~SGScaleAnimation ()
827 SGScaleAnimation::update()
830 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
831 if (_has_min_x && _x_scale < _min_x)
833 if (_has_max_x && _x_scale > _max_x)
836 _x_scale = _table->interpolate(_prop->getDoubleValue());
840 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
841 if (_has_min_y && _y_scale < _min_y)
843 if (_has_max_y && _y_scale > _max_y)
846 _y_scale = _table->interpolate(_prop->getDoubleValue());
850 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
851 if (_has_min_z && _z_scale < _min_z)
853 if (_has_max_z && _z_scale > _max_z)
856 _z_scale = _table->interpolate(_prop->getDoubleValue());
859 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
860 ((ssgTransform *)_branch)->setTransform(_matrix);
865 ////////////////////////////////////////////////////////////////////////
866 // Implementation of SGTexRotateAnimation
867 ////////////////////////////////////////////////////////////////////////
869 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
870 SGPropertyNode_ptr props )
871 : SGAnimation(props, new ssgTexTrans),
872 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
873 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
874 _factor(props->getDoubleValue("factor", 1.0)),
875 _table(read_interpolation_table(props)),
876 _has_min(props->hasValue("min-deg")),
877 _min_deg(props->getDoubleValue("min-deg")),
878 _has_max(props->hasValue("max-deg")),
879 _max_deg(props->getDoubleValue("max-deg")),
880 _position_deg(props->getDoubleValue("starting-position-deg", 0))
882 _center[0] = props->getFloatValue("center/x", 0);
883 _center[1] = props->getFloatValue("center/y", 0);
884 _center[2] = props->getFloatValue("center/z", 0);
885 _axis[0] = props->getFloatValue("axis/x", 0);
886 _axis[1] = props->getFloatValue("axis/y", 0);
887 _axis[2] = props->getFloatValue("axis/z", 0);
888 sgNormalizeVec3(_axis);
891 SGTexRotateAnimation::~SGTexRotateAnimation ()
897 SGTexRotateAnimation::update()
900 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
901 if (_has_min && _position_deg < _min_deg)
902 _position_deg = _min_deg;
903 if (_has_max && _position_deg > _max_deg)
904 _position_deg = _max_deg;
906 _position_deg = _table->interpolate(_prop->getDoubleValue());
908 set_rotation(_matrix, _position_deg, _center, _axis);
909 ((ssgTexTrans *)_branch)->setTransform(_matrix);
914 ////////////////////////////////////////////////////////////////////////
915 // Implementation of SGTexTranslateAnimation
916 ////////////////////////////////////////////////////////////////////////
918 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
919 SGPropertyNode_ptr props )
920 : SGAnimation(props, new ssgTexTrans),
921 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
922 _offset(props->getDoubleValue("offset", 0.0)),
923 _factor(props->getDoubleValue("factor", 1.0)),
924 _step(props->getDoubleValue("step",0.0)),
925 _scroll(props->getDoubleValue("scroll",0.0)),
926 _table(read_interpolation_table(props)),
927 _has_min(props->hasValue("min")),
928 _min(props->getDoubleValue("min")),
929 _has_max(props->hasValue("max")),
930 _max(props->getDoubleValue("max")),
931 _position(props->getDoubleValue("starting-position", 0))
933 _axis[0] = props->getFloatValue("axis/x", 0);
934 _axis[1] = props->getFloatValue("axis/y", 0);
935 _axis[2] = props->getFloatValue("axis/z", 0);
936 sgNormalizeVec3(_axis);
939 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
945 SGTexTranslateAnimation::update()
948 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
949 if (_has_min && _position < _min)
951 if (_has_max && _position > _max)
954 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
956 set_translation(_matrix, _position, _axis);
957 ((ssgTexTrans *)_branch)->setTransform(_matrix);
962 ////////////////////////////////////////////////////////////////////////
963 // Implementation of SGTexMultipleAnimation
964 ////////////////////////////////////////////////////////////////////////
966 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
967 SGPropertyNode_ptr props )
968 : SGAnimation(props, new ssgTexTrans),
969 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
973 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
974 _transform = new TexTransform [transform_nodes.size()];
976 for (i = 0; i < transform_nodes.size(); i++) {
977 SGPropertyNode_ptr transform_props = transform_nodes[i];
979 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
981 // transform is a translation
982 _transform[i].subtype = 0;
984 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
986 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
987 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
988 _transform[i].step = transform_props->getDoubleValue("step",0.0);
989 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
990 _transform[i].table = read_interpolation_table(transform_props);
991 _transform[i].has_min = transform_props->hasValue("min");
992 _transform[i].min = transform_props->getDoubleValue("min");
993 _transform[i].has_max = transform_props->hasValue("max");
994 _transform[i].max = transform_props->getDoubleValue("max");
995 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
997 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
998 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
999 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
1000 sgNormalizeVec3(_transform[i].axis);
1002 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
1004 // transform is a rotation
1005 _transform[i].subtype = 1;
1007 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
1008 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
1009 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
1010 _transform[i].table = read_interpolation_table(transform_props);
1011 _transform[i].has_min = transform_props->hasValue("min-deg");
1012 _transform[i].min = transform_props->getDoubleValue("min-deg");
1013 _transform[i].has_max = transform_props->hasValue("max-deg");
1014 _transform[i].max = transform_props->getDoubleValue("max-deg");
1015 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
1017 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
1018 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
1019 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
1020 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
1021 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
1022 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
1023 sgNormalizeVec3(_transform[i].axis);
1029 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
1031 delete [] _transform;
1035 SGTexMultipleAnimation::update()
1039 sgMakeIdentMat4(tmatrix);
1040 for (i = 0; i < _num_transforms; i++) {
1042 if(_transform[i].subtype == 0) {
1044 // subtype 0 is translation
1045 if (_transform[i].table == 0) {
1046 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
1047 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1048 _transform[i].position = _transform[i].min;
1049 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1050 _transform[i].position = _transform[i].max;
1052 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
1054 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
1055 sgPreMultMat4(tmatrix, _transform[i].matrix);
1057 } else if (_transform[i].subtype == 1) {
1059 // subtype 1 is rotation
1061 if (_transform[i].table == 0) {
1062 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
1063 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
1064 _transform[i].position = _transform[i].min;
1065 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
1066 _transform[i].position = _transform[i].max;
1068 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
1070 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
1071 sgPreMultMat4(tmatrix, _transform[i].matrix);
1074 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
1080 ////////////////////////////////////////////////////////////////////////
1081 // Implementation of SGAlphaTestAnimation
1082 ////////////////////////////////////////////////////////////////////////
1084 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
1085 : SGAnimation(props, new ssgBranch)
1087 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
1090 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
1094 void SGAlphaTestAnimation::init()
1096 setAlphaClampToBranch(_branch,_alpha_clamp);
1099 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
1101 int nb = b->getNumKids();
1102 for (int i = 0; i<nb; i++) {
1103 ssgEntity *e = b->getKid(i);
1104 if (e->isAKindOf(ssgTypeLeaf())) {
1105 ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
1106 s->enable( GL_ALPHA_TEST );
1107 s->setAlphaClamp( clamp );
1108 } else if (e->isAKindOf(ssgTypeBranch())) {
1109 setAlphaClampToBranch( (ssgBranch*)e, clamp );
1116 ////////////////////////////////////////////////////////////////////////
1117 // Implementation of SGMaterialAnimation
1118 ////////////////////////////////////////////////////////////////////////
1120 SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
1121 SGPropertyNode_ptr props, const SGPath &texture_path)
1122 : SGAnimation(props, new ssgBranch),
1123 _prop_root(prop_root),
1125 _texture_base(texture_path),
1126 _cached_material(0),
1127 _cloned_material(0),
1130 _global(props->getBoolValue("global", false))
1132 SGPropertyNode_ptr n;
1133 n = props->getChild("condition");
1134 _condition = n ? sgReadCondition(_prop_root, n) : 0;
1135 n = props->getChild("property-base");
1137 _prop_base = n->getStringValue();
1138 if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
1142 initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
1143 initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
1144 initColorGroup(props->getChild("emission"), &_emis, EMISSION);
1145 initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
1147 _shi = props->getFloatValue("shininess", -1.0);
1149 _update |= SHININESS;
1151 SGPropertyNode_ptr group = props->getChild("transparency");
1153 _trans.value = group->getFloatValue("alpha", -1.0);
1154 _trans.factor = group->getFloatValue("factor", 1.0);
1155 _trans.offset = group->getFloatValue("offset", 0.0);
1156 _trans.min = group->getFloatValue("min", 0.0);
1157 if (_trans.min < 0.0)
1159 _trans.max = group->getFloatValue("max", 1.0);
1160 if (_trans.max > 1.0)
1163 _update |= TRANSPARENCY;
1165 n = group->getChild("alpha-prop");
1166 _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1167 n = group->getChild("factor-prop");
1168 _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1169 n = group->getChild("offset-prop");
1170 _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1172 _read |= TRANSPARENCY;
1175 _thresh = props->getFloatValue("threshold", -1.0);
1177 _update |= THRESHOLD;
1179 string _texture_str = props->getStringValue("texture", "");
1180 if (!_texture_str.empty()) {
1181 _texture = _texture_base;
1182 _texture.append(_texture_str);
1186 n = props->getChild("shininess-prop");
1187 _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1188 n = props->getChild("threshold-prop");
1189 _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1190 n = props->getChild("texture-prop");
1191 _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1194 void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
1199 col->red = group->getFloatValue("red", -1.0);
1200 col->green = group->getFloatValue("green", -1.0);
1201 col->blue = group->getFloatValue("blue", -1.0);
1202 col->factor = group->getFloatValue("factor", 1.0);
1203 col->offset = group->getFloatValue("offset", 0.0);
1208 n = group->getChild("red-prop");
1209 col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1210 n = group->getChild("green-prop");
1211 col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1212 n = group->getChild("blue-prop");
1213 col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1214 n = group->getChild("factor-prop");
1215 col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1216 n = group->getChild("offset-prop");
1217 col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
1222 void SGMaterialAnimation::init()
1225 cloneMaterials(_branch);
1228 int SGMaterialAnimation::update()
1230 if (_condition && !_condition->test())
1233 if (_read & DIFFUSE)
1234 updateColorGroup(&_diff, DIFFUSE);
1235 if (_read & AMBIENT)
1236 updateColorGroup(&_amb, AMBIENT);
1237 if (_read & EMISSION)
1238 updateColorGroup(&_emis, EMISSION);
1239 if (_read & SPECULAR)
1240 updateColorGroup(&_spec, SPECULAR);
1245 _shi = _shi_prop->getFloatValue();
1247 _update |= SHININESS;
1249 if (_read & TRANSPARENCY) {
1250 PropSpec tmp = _trans;
1251 if (_trans.value_prop)
1252 _trans.value = _trans.value_prop->getFloatValue();
1253 if (_trans.factor_prop)
1254 _trans.factor = _trans.factor_prop->getFloatValue();
1255 if (_trans.offset_prop)
1256 _trans.offset = _trans.offset_prop->getFloatValue();
1258 _update |= TRANSPARENCY;
1262 _thresh = _thresh_prop->getFloatValue();
1264 _update |= THRESHOLD;
1267 string t = _tex_prop->getStringValue();
1268 if (!t.empty() && t != _texture_str) {
1270 _texture = _texture_base;
1276 setMaterialBranch(_branch);
1282 void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
1284 ColorSpec tmp = *col;
1286 col->red = col->red_prop->getFloatValue();
1287 if (col->green_prop)
1288 col->green = col->green_prop->getFloatValue();
1290 col->blue = col->blue_prop->getFloatValue();
1291 if (col->factor_prop)
1292 col->factor = col->factor_prop->getFloatValue();
1293 if (col->offset_prop)
1294 col->offset = col->offset_prop->getFloatValue();
1299 void SGMaterialAnimation::cloneMaterials(ssgBranch *b)
1301 for (int i = 0; i < b->getNumKids(); i++)
1302 cloneMaterials((ssgBranch *)b->getKid(i));
1304 if (!b->isAKindOf(ssgTypeLeaf()) || !((ssgLeaf *)b)->hasState())
1307 ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
1308 if (!_cached_material || _cached_material != s) {
1309 _cached_material = s;
1310 _cloned_material = (ssgSimpleState *)s->clone(SSG_CLONE_STATE);
1312 ((ssgLeaf *)b)->setState(_cloned_material);
1315 void SGMaterialAnimation::setMaterialBranch(ssgBranch *b)
1317 for (int i = 0; i < b->getNumKids(); i++)
1318 setMaterialBranch((ssgBranch *)b->getKid(i));
1320 if (!b->isAKindOf(ssgTypeLeaf()) || !((ssgLeaf *)b)->hasState())
1323 ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
1325 if (_update & DIFFUSE) {
1326 float *v = _diff.rgba();
1327 SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
1328 s->setColourMaterial(GL_DIFFUSE);
1329 s->enable(GL_COLOR_MATERIAL);
1330 s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], alpha);
1331 s->disable(GL_COLOR_MATERIAL);
1333 if (_update & AMBIENT) {
1334 s->setColourMaterial(GL_AMBIENT);
1335 s->enable(GL_COLOR_MATERIAL);
1336 s->setMaterial(GL_AMBIENT, _amb.rgba());
1337 s->disable(GL_COLOR_MATERIAL);
1339 if (_update & EMISSION)
1340 s->setMaterial(GL_EMISSION, _emis.rgba());
1341 if (_update & SPECULAR)
1342 s->setMaterial(GL_SPECULAR, _spec.rgba());
1343 if (_update & SHININESS)
1344 s->setShininess(clamp(_shi, 0.0, 128.0));
1345 if (_update & TRANSPARENCY) {
1346 SGfloat *v = s->getMaterial(GL_DIFFUSE);
1347 float trans = _trans.value * _trans.factor + _trans.offset;
1348 trans = trans < _trans.min ? _trans.min : trans > _trans.max ? _trans.max : trans;
1349 s->setMaterial(GL_DIFFUSE, v[0], v[1], v[2], trans);
1351 if (_update & THRESHOLD)
1352 s->setAlphaClamp(clamp(_thresh));
1353 if (_update & TEXTURE)
1354 s->setTexture(_texture.c_str());
1355 if (_update & (TEXTURE|TRANSPARENCY)) {
1356 SGfloat alpha = s->getMaterial(GL_DIFFUSE)[3];
1357 ssgTexture *tex = s->getTexture();
1358 if ((tex && tex->hasAlpha()) || alpha < 0.999) {
1359 s->setColourMaterial(GL_DIFFUSE);
1360 s->enable(GL_COLOR_MATERIAL);
1361 s->enable(GL_BLEND);
1362 s->enable(GL_ALPHA_TEST);
1363 s->setTranslucent();
1364 s->disable(GL_COLOR_MATERIAL);
1366 s->disable(GL_BLEND);
1367 s->disable(GL_ALPHA_TEST);
1376 ////////////////////////////////////////////////////////////////////////
1377 // Implementation of SGFlashAnimation
1378 ////////////////////////////////////////////////////////////////////////
1379 SGFlashAnimation::SGFlashAnimation(SGPropertyNode_ptr props)
1380 : SGAnimation( props, new SGCustomTransform )
1382 _axis[0] = props->getFloatValue("axis/x", 0);
1383 _axis[1] = props->getFloatValue("axis/y", 0);
1384 _axis[2] = props->getFloatValue("axis/z", 1);
1386 _center[0] = props->getFloatValue("center/x-m", 0);
1387 _center[1] = props->getFloatValue("center/y-m", 0);
1388 _center[2] = props->getFloatValue("center/z-m", 0);
1390 _offset = props->getFloatValue("offset", 0.0);
1391 _factor = props->getFloatValue("factor", 1.0);
1392 _power = props->getFloatValue("power", 1.0);
1393 _two_sides = props->getBoolValue("two-sides", false);
1395 _min_v = props->getFloatValue("min", 0.0);
1396 _max_v = props->getFloatValue("max", 1.0);
1398 ((SGCustomTransform *)_branch)->setTransCallback( &SGFlashAnimation::flashCallback, this );
1401 SGFlashAnimation::~SGFlashAnimation()
1405 void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d )
1407 ((SGFlashAnimation *)d)->flashCallback( r, f, m );
1410 void SGFlashAnimation::flashCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
1412 sgVec3 transformed_axis;
1413 sgXformVec3( transformed_axis, _axis, m );
1414 sgNormalizeVec3( transformed_axis );
1417 sgFullXformPnt3( view, _center, m );
1418 sgNormalizeVec3( view );
1420 float cos_angle = -sgScalarProductVec3( transformed_axis, view );
1421 float scale_factor = 0.f;
1422 if ( _two_sides && cos_angle < 0 )
1423 scale_factor = _factor * (float)pow( -cos_angle, _power ) + _offset;
1424 else if ( cos_angle > 0 )
1425 scale_factor = _factor * (float)pow( cos_angle, _power ) + _offset;
1427 if ( scale_factor < _min_v )
1428 scale_factor = _min_v;
1429 if ( scale_factor > _max_v )
1430 scale_factor = _max_v;
1433 sgMakeIdentMat4( transform );
1434 transform[0][0] = scale_factor;
1435 transform[1][1] = scale_factor;
1436 transform[2][2] = scale_factor;
1437 transform[3][0] = _center[0] * ( 1 - scale_factor );
1438 transform[3][1] = _center[1] * ( 1 - scale_factor );
1439 transform[3][2] = _center[2] * ( 1 - scale_factor );
1442 sgPreMultMat4( r, transform );
1447 ////////////////////////////////////////////////////////////////////////
1448 // Implementation of SGDistScaleAnimation
1449 ////////////////////////////////////////////////////////////////////////
1450 SGDistScaleAnimation::SGDistScaleAnimation(SGPropertyNode_ptr props)
1451 : SGAnimation( props, new SGCustomTransform ),
1452 _factor(props->getFloatValue("factor", 1.0)),
1453 _offset(props->getFloatValue("offset", 0.0)),
1454 _min_v(props->getFloatValue("min", 0.0)),
1455 _max_v(props->getFloatValue("max", 1.0)),
1456 _has_min(props->hasValue("min")),
1457 _has_max(props->hasValue("max")),
1458 _table(read_interpolation_table(props))
1460 _center[0] = props->getFloatValue("center/x-m", 0);
1461 _center[1] = props->getFloatValue("center/y-m", 0);
1462 _center[2] = props->getFloatValue("center/z-m", 0);
1464 ((SGCustomTransform *)_branch)->setTransCallback( &SGDistScaleAnimation::distScaleCallback, this );
1467 SGDistScaleAnimation::~SGDistScaleAnimation()
1471 void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m, void *d )
1473 ((SGDistScaleAnimation *)d)->distScaleCallback( r, f, m );
1476 void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
1479 sgFullXformPnt3( view, _center, m );
1481 float scale_factor = sgLengthVec3( view );
1483 scale_factor = _factor * scale_factor + _offset;
1484 if ( _has_min && scale_factor < _min_v )
1485 scale_factor = _min_v;
1486 if ( _has_max && scale_factor > _max_v )
1487 scale_factor = _max_v;
1489 scale_factor = _table->interpolate( scale_factor );
1493 sgMakeIdentMat4( transform );
1494 transform[0][0] = scale_factor;
1495 transform[1][1] = scale_factor;
1496 transform[2][2] = scale_factor;
1497 transform[3][0] = _center[0] * ( 1 - scale_factor );
1498 transform[3][1] = _center[1] * ( 1 - scale_factor );
1499 transform[3][2] = _center[2] * ( 1 - scale_factor );
1502 sgPreMultMat4( r, transform );
1505 ////////////////////////////////////////////////////////////////////////
1506 // Implementation of SGShadowAnimation
1507 ////////////////////////////////////////////////////////////////////////
1509 SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
1510 SGPropertyNode_ptr props )
1511 : SGAnimation(props, new ssgBranch),
1513 _condition_value(true)
1516 SGPropertyNode_ptr node = props->getChild("condition");
1518 _condition = sgReadCondition(prop_root, node);
1519 _condition_value = false;
1523 SGShadowAnimation::~SGShadowAnimation ()
1529 SGShadowAnimation::update()
1532 _condition_value = _condition->test();
1536 bool SGShadowAnimation::get_condition_value(void) {
1537 return _condition_value;
1540 // end of animation.cxx