00001
00002
00003
00004
00005
00006 #ifdef HAVE_CONFIG_H
00007 # include <simgear_config.h>
00008 #endif
00009
00010 #include <string.h>
00011 #include <math.h>
00012
00013 #include <plib/sg.h>
00014 #include <plib/ssg.h>
00015 #include <plib/ul.h>
00016
00017 #include <simgear/math/interpolater.hxx>
00018 #include <simgear/props/condition.hxx>
00019 #include <simgear/props/props.hxx>
00020 #include <simgear/math/sg_random.h>
00021
00022 #include "animation.hxx"
00023 #include "custtrans.hxx"
00024 #include "personality.hxx"
00025
00026
00028
00030
00034 static void
00035 set_rotation (sgMat4 &matrix, double position_deg,
00036 sgVec3 ¢er, sgVec3 &axis)
00037 {
00038 float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ;
00039
00040 float s = (float) sin ( temp_angle ) ;
00041 float c = (float) cos ( temp_angle ) ;
00042 float t = SG_ONE - c ;
00043
00044
00045
00046 float x = axis[0];
00047 float y = axis[1];
00048 float z = axis[2];
00049
00050 matrix[0][0] = t * x * x + c ;
00051 matrix[0][1] = t * y * x - s * z ;
00052 matrix[0][2] = t * z * x + s * y ;
00053 matrix[0][3] = SG_ZERO;
00054
00055 matrix[1][0] = t * x * y + s * z ;
00056 matrix[1][1] = t * y * y + c ;
00057 matrix[1][2] = t * z * y - s * x ;
00058 matrix[1][3] = SG_ZERO;
00059
00060 matrix[2][0] = t * x * z - s * y ;
00061 matrix[2][1] = t * y * z + s * x ;
00062 matrix[2][2] = t * z * z + c ;
00063 matrix[2][3] = SG_ZERO;
00064
00065
00066 x = center[0];
00067 y = center[1];
00068 z = center[2];
00069
00070 matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0];
00071 matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1];
00072 matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2];
00073 matrix[3][3] = SG_ONE;
00074 }
00075
00079 static void
00080 set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis)
00081 {
00082 sgVec3 xyz;
00083 sgScaleVec3(xyz, axis, position_m);
00084 sgMakeTransMat4(matrix, xyz);
00085 }
00086
00090 static void
00091 set_scale (sgMat4 &matrix, double x, double y, double z)
00092 {
00093 sgMakeIdentMat4( matrix );
00094 matrix[0][0] = x;
00095 matrix[1][1] = y;
00096 matrix[2][2] = z;
00097 }
00098
00102 static void
00103 change_alpha( ssgBase *_branch, float _blend )
00104 {
00105 int i;
00106
00107 for (i = 0; i < ((ssgBranch *)_branch)->getNumKids(); i++)
00108 change_alpha( ((ssgBranch *)_branch)->getKid(i), _blend );
00109
00110 if ( !_branch->isAKindOf(ssgTypeLeaf())
00111 && !_branch->isAKindOf(ssgTypeVtxTable())
00112 && !_branch->isAKindOf(ssgTypeVTable()) )
00113 return;
00114
00115 int num_colors = ((ssgLeaf *)_branch)->getNumColours();
00116
00117
00118 for (i = 0; i < num_colors; i++)
00119 {
00120
00121 float *color = ((ssgLeaf *)_branch)->getColour(i);
00122 color[3] = _blend;
00123 }
00124 }
00125
00129 static double
00130 apply_mods(double property, double step, double scroll)
00131 {
00132
00133 double modprop;
00134 if(step > 0) {
00135 double scrollval = 0.0;
00136 if(scroll > 0) {
00137
00138 double remainder = step - fmod(fabs(property), step);
00139 if (remainder < scroll) {
00140 scrollval = (scroll - remainder) / scroll * step;
00141 }
00142 }
00143
00144 if(property > 0)
00145 modprop = ((floor(property/step) * step) + scrollval);
00146 else
00147 modprop = ((ceil(property/step) * step) + scrollval);
00148 } else {
00149 modprop = property;
00150 }
00151 return modprop;
00152
00153 }
00154
00158 static SGInterpTable *
00159 read_interpolation_table (SGPropertyNode_ptr props)
00160 {
00161 SGPropertyNode_ptr table_node = props->getNode("interpolation");
00162 if (table_node != 0) {
00163 SGInterpTable * table = new SGInterpTable();
00164 vector<SGPropertyNode_ptr> entries = table_node->getChildren("entry");
00165 for (unsigned int i = 0; i < entries.size(); i++)
00166 table->addEntry(entries[i]->getDoubleValue("ind", 0.0),
00167 entries[i]->getDoubleValue("dep", 0.0));
00168 return table;
00169 } else {
00170 return 0;
00171 }
00172 }
00173
00174
00175
00177
00179
00180
00181 double SGAnimation::sim_time_sec = 0.0;
00182 SGPersonalityBranch *SGAnimation::current_object = 0;
00183
00184 SGAnimation::SGAnimation (SGPropertyNode_ptr props, ssgBranch * branch)
00185 : _branch(branch),
00186 animation_type(0)
00187 {
00188 _branch->setName(props->getStringValue("name", 0));
00189 if ( props->getBoolValue( "enable-hot", true ) ) {
00190 _branch->setTraversalMaskBits( SSGTRAV_HOT );
00191 } else {
00192 _branch->clrTraversalMaskBits( SSGTRAV_HOT );
00193 }
00194 }
00195
00196 SGAnimation::~SGAnimation ()
00197 {
00198 }
00199
00200 void
00201 SGAnimation::init ()
00202 {
00203 }
00204
00205 int
00206 SGAnimation::update()
00207 {
00208 return 1;
00209 }
00210
00211 void
00212 SGAnimation::restore()
00213 {
00214 }
00215
00216
00217
00219
00221
00222 SGNullAnimation::SGNullAnimation (SGPropertyNode_ptr props)
00223 : SGAnimation(props, new ssgBranch)
00224 {
00225 }
00226
00227 SGNullAnimation::~SGNullAnimation ()
00228 {
00229 }
00230
00231
00232
00234
00236
00237 SGRangeAnimation::SGRangeAnimation (SGPropertyNode *prop_root,
00238 SGPropertyNode_ptr props)
00239 : SGAnimation(props, new ssgRangeSelector),
00240 _min(0.0), _max(0.0), _min_factor(1.0), _max_factor(1.0),
00241 _condition(0)
00242 {
00243 SGPropertyNode_ptr node = props->getChild("condition");
00244 if (node != 0)
00245 _condition = sgReadCondition(prop_root, node);
00246
00247 float ranges[2];
00248
00249 node = props->getChild( "min-factor" );
00250 if (node != 0) {
00251 _min_factor = props->getFloatValue("min-factor", 1.0);
00252 }
00253 node = props->getChild( "max-factor" );
00254 if (node != 0) {
00255 _max_factor = props->getFloatValue("max-factor", 1.0);
00256 }
00257 node = props->getChild( "min-property" );
00258 if (node != 0) {
00259 _min_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
00260 ranges[0] = _min_prop->getFloatValue() * _min_factor;
00261 } else {
00262 _min = props->getFloatValue("min-m", 0);
00263 ranges[0] = _min * _min_factor;
00264 }
00265 node = props->getChild( "max-property" );
00266 if (node != 0) {
00267 _max_prop = (SGPropertyNode *)prop_root->getNode(node->getStringValue(), true);
00268 ranges[1] = _max_prop->getFloatValue() * _max_factor;
00269 } else {
00270 _max = props->getFloatValue("max-m", 0);
00271 ranges[1] = _max * _max_factor;
00272 }
00273 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
00274 }
00275
00276 SGRangeAnimation::~SGRangeAnimation ()
00277 {
00278 delete _condition;
00279 }
00280
00281 int
00282 SGRangeAnimation::update()
00283 {
00284 float ranges[2];
00285 if ( _condition == 0 || _condition->test() ) {
00286 if (_min_prop != 0) {
00287 ranges[0] = _min_prop->getFloatValue() * _min_factor;
00288 } else {
00289 ranges[0] = _min * _min_factor;
00290 }
00291 if (_max_prop != 0) {
00292 ranges[1] = _max_prop->getFloatValue() * _max_factor;
00293 } else {
00294 ranges[1] = _max * _max_factor;
00295 }
00296 } else {
00297 ranges[0] = 0.f;
00298 ranges[1] = 1000000000.f;
00299 }
00300 ((ssgRangeSelector *)_branch)->setRanges(ranges, 2);
00301 return 2;
00302 }
00303
00304
00305
00307
00309
00310 SGBillboardAnimation::SGBillboardAnimation (SGPropertyNode_ptr props)
00311 : SGAnimation(props, new ssgCutout(props->getBoolValue("spherical", true)))
00312 {
00313 }
00314
00315 SGBillboardAnimation::~SGBillboardAnimation ()
00316 {
00317 }
00318
00319
00320
00322
00324
00325 SGSelectAnimation::SGSelectAnimation( SGPropertyNode *prop_root,
00326 SGPropertyNode_ptr props )
00327 : SGAnimation(props, new ssgSelector),
00328 _condition(0)
00329 {
00330 SGPropertyNode_ptr node = props->getChild("condition");
00331 if (node != 0)
00332 _condition = sgReadCondition(prop_root, node);
00333 }
00334
00335 SGSelectAnimation::~SGSelectAnimation ()
00336 {
00337 delete _condition;
00338 }
00339
00340 int
00341 SGSelectAnimation::update()
00342 {
00343 if (_condition != 0 && _condition->test())
00344 ((ssgSelector *)_branch)->select(0xffff);
00345 else
00346 ((ssgSelector *)_branch)->select(0x0000);
00347 return 2;
00348 }
00349
00350
00351
00353
00355
00356 SGSpinAnimation::SGSpinAnimation( SGPropertyNode *prop_root,
00357 SGPropertyNode_ptr props,
00358 double sim_time_sec )
00359 : SGAnimation(props, new ssgTransform),
00360 _use_personality( props->getBoolValue("use-personality",false) ),
00361 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
00362 _last_time_sec( sim_time_sec ),
00363 _condition(0),
00364 _factor( props, "factor", 1.0 ),
00365 _position_deg( props, "starting-position-deg", 0.0 )
00366 {
00367 SGPropertyNode_ptr node = props->getChild("condition");
00368 if (node != 0)
00369 _condition = sgReadCondition(prop_root, node);
00370
00371 _center[0] = 0;
00372 _center[1] = 0;
00373 _center[2] = 0;
00374 if (props->hasValue("axis/x1-m")) {
00375 double x1,y1,z1,x2,y2,z2;
00376 x1 = props->getFloatValue("axis/x1-m");
00377 y1 = props->getFloatValue("axis/y1-m");
00378 z1 = props->getFloatValue("axis/z1-m");
00379 x2 = props->getFloatValue("axis/x2-m");
00380 y2 = props->getFloatValue("axis/y2-m");
00381 z2 = props->getFloatValue("axis/z2-m");
00382 _center[0] = (x1+x2)/2;
00383 _center[1]= (y1+y2)/2;
00384 _center[2] = (z1+z2)/2;
00385 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
00386 _axis[0] = (x2-x1)/vector_length;
00387 _axis[1] = (y2-y1)/vector_length;
00388 _axis[2] = (z2-z1)/vector_length;
00389 } else {
00390 _axis[0] = props->getFloatValue("axis/x", 0);
00391 _axis[1] = props->getFloatValue("axis/y", 0);
00392 _axis[2] = props->getFloatValue("axis/z", 0);
00393 }
00394 if (props->hasValue("center/x-m")) {
00395 _center[0] = props->getFloatValue("center/x-m", 0);
00396 _center[1] = props->getFloatValue("center/y-m", 0);
00397 _center[2] = props->getFloatValue("center/z-m", 0);
00398 }
00399 sgNormalizeVec3(_axis);
00400 }
00401
00402 SGSpinAnimation::~SGSpinAnimation ()
00403 {
00404 delete _condition;
00405 }
00406
00407 int
00408 SGSpinAnimation::update()
00409 {
00410 if ( _condition == 0 || _condition->test() ) {
00411 double dt;
00412 float velocity_rpms;
00413 if ( _use_personality && current_object ) {
00414 SGPersonalityBranch *key = current_object;
00415 if ( !key->getIntValue( this, INIT_SPIN ) ) {
00416 key->setDoubleValue( _factor.shuffle(), this, FACTOR_SPIN );
00417 key->setDoubleValue( _position_deg.shuffle(), this, POSITION_DEG_SPIN );
00418
00419 key->setDoubleValue( sim_time_sec, this, LAST_TIME_SEC_SPIN );
00420 key->setIntValue( 1, this, INIT_SPIN );
00421 }
00422
00423 _factor = key->getDoubleValue( this, FACTOR_SPIN );
00424 _position_deg = key->getDoubleValue( this, POSITION_DEG_SPIN );
00425 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_SPIN );
00426 dt = sim_time_sec - _last_time_sec;
00427 _last_time_sec = sim_time_sec;
00428 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_SPIN );
00429
00430 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
00431 _position_deg += (dt * velocity_rpms * 360);
00432 while (_position_deg < 0)
00433 _position_deg += 360.0;
00434 while (_position_deg >= 360.0)
00435 _position_deg -= 360.0;
00436 key->setDoubleValue( _position_deg, this, POSITION_DEG_SPIN );
00437 } else {
00438 dt = sim_time_sec - _last_time_sec;
00439 _last_time_sec = sim_time_sec;
00440
00441 velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0);
00442 _position_deg += (dt * velocity_rpms * 360);
00443 while (_position_deg < 0)
00444 _position_deg += 360.0;
00445 while (_position_deg >= 360.0)
00446 _position_deg -= 360.0;
00447 }
00448
00449 set_rotation(_matrix, _position_deg, _center, _axis);
00450 ((ssgTransform *)_branch)->setTransform(_matrix);
00451 }
00452 return 1;
00453 }
00454
00455
00456
00458
00460
00461 SGTimedAnimation::SGTimedAnimation (SGPropertyNode_ptr props)
00462 : SGAnimation(props, new ssgSelector),
00463 _use_personality( props->getBoolValue("use-personality",false) ),
00464 _duration_sec(props->getDoubleValue("duration-sec", 1.0)),
00465 _last_time_sec( sim_time_sec ),
00466 _total_duration_sec( 0 ),
00467 _step( 0 )
00468
00469 {
00470 vector<SGPropertyNode_ptr> nodes = props->getChildren( "branch-duration-sec" );
00471 size_t nb = nodes.size();
00472 for ( size_t i = 0; i < nb; i++ ) {
00473 size_t ind = nodes[ i ]->getIndex();
00474 while ( ind >= _branch_duration_specs.size() ) {
00475 _branch_duration_specs.push_back( DurationSpec( _duration_sec ) );
00476 }
00477 SGPropertyNode_ptr rNode = nodes[ i ]->getChild("random");
00478 if ( rNode == 0 ) {
00479 _branch_duration_specs[ ind ] = DurationSpec( nodes[ i ]->getDoubleValue() );
00480 } else {
00481 _branch_duration_specs[ ind ] = DurationSpec( rNode->getDoubleValue( "min", 0.0 ),
00482 rNode->getDoubleValue( "max", 1.0 ) );
00483 }
00484 }
00485 }
00486
00487 SGTimedAnimation::~SGTimedAnimation ()
00488 {
00489 }
00490
00491 void
00492 SGTimedAnimation::init()
00493 {
00494 if ( !_use_personality ) {
00495 for ( int i = 0; i < getBranch()->getNumKids(); i++ ) {
00496 double v;
00497 if ( i < (int)_branch_duration_specs.size() ) {
00498 DurationSpec &sp = _branch_duration_specs[ i ];
00499 v = sp._min + sg_random() * ( sp._max - sp._min );
00500 } else {
00501 v = _duration_sec;
00502 }
00503 _branch_duration_sec.push_back( v );
00504 _total_duration_sec += v;
00505 }
00506
00507 if ( _total_duration_sec < 0.01 ) {
00508 _total_duration_sec = 0.01;
00509 }
00510 }
00511 ((ssgSelector *)getBranch())->selectStep(_step);
00512 }
00513
00514 int
00515 SGTimedAnimation::update()
00516 {
00517 if ( _use_personality && current_object ) {
00518 SGPersonalityBranch *key = current_object;
00519 if ( !key->getIntValue( this, INIT_TIMED ) ) {
00520 double total = 0;
00521 double offset = 1.0;
00522 for ( size_t i = 0; i < _branch_duration_specs.size(); i++ ) {
00523 DurationSpec &sp = _branch_duration_specs[ i ];
00524 double v = sp._min + sg_random() * ( sp._max - sp._min );
00525 key->setDoubleValue( v, this, BRANCH_DURATION_SEC_TIMED, i );
00526 if ( i == 0 )
00527 offset = v;
00528 total += v;
00529 }
00530
00531 if ( total < 0.01 ) {
00532 total = 0.01;
00533 }
00534 offset *= sg_random();
00535 key->setDoubleValue( sim_time_sec - offset, this, LAST_TIME_SEC_TIMED );
00536 key->setDoubleValue( total, this, TOTAL_DURATION_SEC_TIMED );
00537 key->setIntValue( 0, this, STEP_TIMED );
00538 key->setIntValue( 1, this, INIT_TIMED );
00539 }
00540
00541 _step = key->getIntValue( this, STEP_TIMED );
00542 _last_time_sec = key->getDoubleValue( this, LAST_TIME_SEC_TIMED );
00543 _total_duration_sec = key->getDoubleValue( this, TOTAL_DURATION_SEC_TIMED );
00544 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
00545 _last_time_sec += _total_duration_sec;
00546 }
00547 double duration = _duration_sec;
00548 if ( _step < (int)_branch_duration_specs.size() ) {
00549 duration = key->getDoubleValue( this, BRANCH_DURATION_SEC_TIMED, _step );
00550 }
00551 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
00552 _last_time_sec += duration;
00553 _step += 1;
00554 if ( _step >= getBranch()->getNumKids() )
00555 _step = 0;
00556 }
00557 ((ssgSelector *)getBranch())->selectStep( _step );
00558 key->setDoubleValue( _last_time_sec, this, LAST_TIME_SEC_TIMED );
00559 key->setIntValue( _step, this, STEP_TIMED );
00560 } else {
00561 while ( ( sim_time_sec - _last_time_sec ) >= _total_duration_sec ) {
00562 _last_time_sec += _total_duration_sec;
00563 }
00564 double duration = _duration_sec;
00565 if ( _step < (int)_branch_duration_sec.size() ) {
00566 duration = _branch_duration_sec[ _step ];
00567 }
00568 if ( ( sim_time_sec - _last_time_sec ) >= duration ) {
00569 _last_time_sec += duration;
00570 _step += 1;
00571 if ( _step >= getBranch()->getNumKids() )
00572 _step = 0;
00573 ((ssgSelector *)getBranch())->selectStep( _step );
00574 }
00575 }
00576 return 1;
00577 }
00578
00579
00580
00582
00584
00585 SGRotateAnimation::SGRotateAnimation( SGPropertyNode *prop_root,
00586 SGPropertyNode_ptr props )
00587 : SGAnimation(props, new ssgTransform),
00588 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
00589 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
00590 _factor(props->getDoubleValue("factor", 1.0)),
00591 _table(read_interpolation_table(props)),
00592 _has_min(props->hasValue("min-deg")),
00593 _min_deg(props->getDoubleValue("min-deg")),
00594 _has_max(props->hasValue("max-deg")),
00595 _max_deg(props->getDoubleValue("max-deg")),
00596 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
00597 _condition(0)
00598 {
00599 SGPropertyNode_ptr node = props->getChild("condition");
00600 if (node != 0)
00601 _condition = sgReadCondition(prop_root, node);
00602
00603 _center[0] = 0;
00604 _center[1] = 0;
00605 _center[2] = 0;
00606 if (props->hasValue("axis/x") || props->hasValue("axis/y") || props->hasValue("axis/z")) {
00607 _axis[0] = props->getFloatValue("axis/x", 0);
00608 _axis[1] = props->getFloatValue("axis/y", 0);
00609 _axis[2] = props->getFloatValue("axis/z", 0);
00610 } else {
00611 double x1,y1,z1,x2,y2,z2;
00612 x1 = props->getFloatValue("axis/x1-m", 0);
00613 y1 = props->getFloatValue("axis/y1-m", 0);
00614 z1 = props->getFloatValue("axis/z1-m", 0);
00615 x2 = props->getFloatValue("axis/x2-m", 0);
00616 y2 = props->getFloatValue("axis/y2-m", 0);
00617 z2 = props->getFloatValue("axis/z2-m", 0);
00618 _center[0] = (x1+x2)/2;
00619 _center[1]= (y1+y2)/2;
00620 _center[2] = (z1+z2)/2;
00621 float vector_length = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
00622 _axis[0] = (x2-x1)/vector_length;
00623 _axis[1] = (y2-y1)/vector_length;
00624 _axis[2] = (z2-z1)/vector_length;
00625 }
00626 if (props->hasValue("center/x-m") || props->hasValue("center/y-m")
00627 || props->hasValue("center/z-m")) {
00628 _center[0] = props->getFloatValue("center/x-m", 0);
00629 _center[1] = props->getFloatValue("center/y-m", 0);
00630 _center[2] = props->getFloatValue("center/z-m", 0);
00631 }
00632 sgNormalizeVec3(_axis);
00633 }
00634
00635 SGRotateAnimation::~SGRotateAnimation ()
00636 {
00637 delete _table;
00638 delete _condition;
00639 }
00640
00641 int
00642 SGRotateAnimation::update()
00643 {
00644 if (_condition == 0 || _condition->test()) {
00645 if (_table == 0) {
00646 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
00647 if (_has_min && _position_deg < _min_deg)
00648 _position_deg = _min_deg;
00649 if (_has_max && _position_deg > _max_deg)
00650 _position_deg = _max_deg;
00651 } else {
00652 _position_deg = _table->interpolate(_prop->getDoubleValue());
00653 }
00654 set_rotation(_matrix, _position_deg, _center, _axis);
00655 ((ssgTransform *)_branch)->setTransform(_matrix);
00656 }
00657 return 2;
00658 }
00659
00660
00662
00664
00665 SGBlendAnimation::SGBlendAnimation( SGPropertyNode *prop_root,
00666 SGPropertyNode_ptr props )
00667 : SGAnimation(props, new ssgTransform),
00668 _use_personality( props->getBoolValue("use-personality",false) ),
00669 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
00670 _table(read_interpolation_table(props)),
00671 _prev_value(1.0),
00672 _offset(props,"offset",0.0),
00673 _factor(props,"factor",1.0),
00674 _has_min(props->hasValue("min")),
00675 _min(props->getDoubleValue("min", 0.0)),
00676 _has_max(props->hasValue("max")),
00677 _max(props->getDoubleValue("max", 1.0))
00678 {
00679 }
00680
00681 SGBlendAnimation::~SGBlendAnimation ()
00682 {
00683 delete _table;
00684 }
00685
00686 int
00687 SGBlendAnimation::update()
00688 {
00689 double _blend;
00690
00691 if ( _use_personality && current_object ) {
00692 SGPersonalityBranch *key = current_object;
00693 if ( !key->getIntValue( this, INIT_BLEND ) ) {
00694 key->setDoubleValue( _factor.shuffle(), this, FACTOR_BLEND );
00695 key->setDoubleValue( _offset.shuffle(), this, OFFSET_BLEND );
00696
00697 key->setIntValue( 1, this, INIT_BLEND );
00698 }
00699
00700 _factor = key->getDoubleValue( this, FACTOR_BLEND );
00701 _offset = key->getDoubleValue( this, OFFSET_BLEND );
00702 }
00703
00704 if (_table == 0) {
00705 _blend = 1.0 - (_prop->getDoubleValue() * _factor + _offset);
00706
00707 if (_has_min && (_blend < _min))
00708 _blend = _min;
00709 if (_has_max && (_blend > _max))
00710 _blend = _max;
00711 } else {
00712 _blend = _table->interpolate(_prop->getDoubleValue());
00713 }
00714
00715 if (_blend != _prev_value) {
00716 _prev_value = _blend;
00717 change_alpha( _branch, _blend );
00718 }
00719 return 1;
00720 }
00721
00722
00723
00725
00727
00728 SGTranslateAnimation::SGTranslateAnimation( SGPropertyNode *prop_root,
00729 SGPropertyNode_ptr props )
00730 : SGAnimation(props, new ssgTransform),
00731 _use_personality( props->getBoolValue("use-personality",false) ),
00732 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
00733 _table(read_interpolation_table(props)),
00734 _has_min(props->hasValue("min-m")),
00735 _min_m(props->getDoubleValue("min-m")),
00736 _has_max(props->hasValue("max-m")),
00737 _max_m(props->getDoubleValue("max-m")),
00738 _position_m(props->getDoubleValue("starting-position-m", 0)),
00739 _condition(0),
00740 _factor( props, "factor", 1.0 ),
00741 _offset_m( props, "offset-m", 0.0 )
00742 {
00743 SGPropertyNode_ptr node = props->getChild("condition");
00744 if (node != 0)
00745 _condition = sgReadCondition(prop_root, node);
00746
00747 _axis[0] = props->getFloatValue("axis/x", 0);
00748 _axis[1] = props->getFloatValue("axis/y", 0);
00749 _axis[2] = props->getFloatValue("axis/z", 0);
00750 sgNormalizeVec3(_axis);
00751 }
00752
00753 SGTranslateAnimation::~SGTranslateAnimation ()
00754 {
00755 delete _table;
00756 delete _condition;
00757 }
00758
00759 int
00760 SGTranslateAnimation::update()
00761 {
00762 if (_condition == 0 || _condition->test()) {
00763 if ( _use_personality && current_object ) {
00764 SGPersonalityBranch *key = current_object;
00765 if ( !key->getIntValue( this, INIT_TRANSLATE ) ) {
00766 key->setDoubleValue( _factor.shuffle(), this, FACTOR_TRANSLATE );
00767 key->setDoubleValue( _offset_m.shuffle(), this, OFFSET_TRANSLATE );
00768 }
00769
00770 _factor = key->getDoubleValue( this, FACTOR_TRANSLATE );
00771 _offset_m = key->getDoubleValue( this, OFFSET_TRANSLATE );
00772
00773 key->setIntValue( 1, this, INIT_TRANSLATE );
00774 }
00775
00776 if (_table == 0) {
00777 _position_m = (_prop->getDoubleValue() * _factor) + _offset_m;
00778 if (_has_min && _position_m < _min_m)
00779 _position_m = _min_m;
00780 if (_has_max && _position_m > _max_m)
00781 _position_m = _max_m;
00782 } else {
00783 _position_m = _table->interpolate(_prop->getDoubleValue());
00784 }
00785
00786 set_translation(_matrix, _position_m, _axis);
00787 ((ssgTransform *)_branch)->setTransform(_matrix);
00788 }
00789 return 2;
00790 }
00791
00792
00793
00795
00797
00798 SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root,
00799 SGPropertyNode_ptr props )
00800 : SGAnimation(props, new ssgTransform),
00801 _use_personality( props->getBoolValue("use-personality",false) ),
00802 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
00803 _x_factor(props,"x-factor",1.0),
00804 _y_factor(props,"y-factor",1.0),
00805 _z_factor(props,"z-factor",1.0),
00806 _x_offset(props,"x-offset",0.0),
00807 _y_offset(props,"y-offset",0.0),
00808 _z_offset(props,"z-offset",0.0),
00809 _table(read_interpolation_table(props)),
00810 _has_min_x(props->hasValue("x-min")),
00811 _has_min_y(props->hasValue("y-min")),
00812 _has_min_z(props->hasValue("z-min")),
00813 _min_x(props->getDoubleValue("x-min")),
00814 _min_y(props->getDoubleValue("y-min")),
00815 _min_z(props->getDoubleValue("z-min")),
00816 _has_max_x(props->hasValue("x-max")),
00817 _has_max_y(props->hasValue("y-max")),
00818 _has_max_z(props->hasValue("z-max")),
00819 _max_x(props->getDoubleValue("x-max")),
00820 _max_y(props->getDoubleValue("y-max")),
00821 _max_z(props->getDoubleValue("z-max"))
00822 {
00823 }
00824
00825 SGScaleAnimation::~SGScaleAnimation ()
00826 {
00827 delete _table;
00828 }
00829
00830 int
00831 SGScaleAnimation::update()
00832 {
00833 if ( _use_personality && current_object ) {
00834 SGPersonalityBranch *key = current_object;
00835 if ( !key->getIntValue( this, INIT_SCALE ) ) {
00836 key->setDoubleValue( _x_factor.shuffle(), this, X_FACTOR_SCALE );
00837 key->setDoubleValue( _x_offset.shuffle(), this, X_OFFSET_SCALE );
00838 key->setDoubleValue( _y_factor.shuffle(), this, Y_FACTOR_SCALE );
00839 key->setDoubleValue( _y_offset.shuffle(), this, Y_OFFSET_SCALE );
00840 key->setDoubleValue( _z_factor.shuffle(), this, Z_FACTOR_SCALE );
00841 key->setDoubleValue( _z_offset.shuffle(), this, Z_OFFSET_SCALE );
00842
00843 key->setIntValue( 1, this, INIT_SCALE );
00844 }
00845
00846 _x_factor = key->getDoubleValue( this, X_FACTOR_SCALE );
00847 _x_offset = key->getDoubleValue( this, X_OFFSET_SCALE );
00848 _y_factor = key->getDoubleValue( this, Y_FACTOR_SCALE );
00849 _y_offset = key->getDoubleValue( this, Y_OFFSET_SCALE );
00850 _z_factor = key->getDoubleValue( this, Z_FACTOR_SCALE );
00851 _z_offset = key->getDoubleValue( this, Z_OFFSET_SCALE );
00852 }
00853
00854 if (_table == 0) {
00855 _x_scale = _prop->getDoubleValue() * _x_factor + _x_offset;
00856 if (_has_min_x && _x_scale < _min_x)
00857 _x_scale = _min_x;
00858 if (_has_max_x && _x_scale > _max_x)
00859 _x_scale = _max_x;
00860 } else {
00861 _x_scale = _table->interpolate(_prop->getDoubleValue());
00862 }
00863
00864 if (_table == 0) {
00865 _y_scale = _prop->getDoubleValue() * _y_factor + _y_offset;
00866 if (_has_min_y && _y_scale < _min_y)
00867 _y_scale = _min_y;
00868 if (_has_max_y && _y_scale > _max_y)
00869 _y_scale = _max_y;
00870 } else {
00871 _y_scale = _table->interpolate(_prop->getDoubleValue());
00872 }
00873
00874 if (_table == 0) {
00875 _z_scale = _prop->getDoubleValue() * _z_factor + _z_offset;
00876 if (_has_min_z && _z_scale < _min_z)
00877 _z_scale = _min_z;
00878 if (_has_max_z && _z_scale > _max_z)
00879 _z_scale = _max_z;
00880 } else {
00881 _z_scale = _table->interpolate(_prop->getDoubleValue());
00882 }
00883
00884 set_scale(_matrix, _x_scale, _y_scale, _z_scale );
00885 ((ssgTransform *)_branch)->setTransform(_matrix);
00886 return 2;
00887 }
00888
00889
00891
00893
00894 SGTexRotateAnimation::SGTexRotateAnimation( SGPropertyNode *prop_root,
00895 SGPropertyNode_ptr props )
00896 : SGAnimation(props, new ssgTexTrans),
00897 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
00898 _offset_deg(props->getDoubleValue("offset-deg", 0.0)),
00899 _factor(props->getDoubleValue("factor", 1.0)),
00900 _table(read_interpolation_table(props)),
00901 _has_min(props->hasValue("min-deg")),
00902 _min_deg(props->getDoubleValue("min-deg")),
00903 _has_max(props->hasValue("max-deg")),
00904 _max_deg(props->getDoubleValue("max-deg")),
00905 _position_deg(props->getDoubleValue("starting-position-deg", 0)),
00906 _condition(0)
00907 {
00908 SGPropertyNode *node = props->getChild("condition");
00909 if (node != 0)
00910 _condition = sgReadCondition(prop_root, node);
00911
00912 _center[0] = props->getFloatValue("center/x", 0);
00913 _center[1] = props->getFloatValue("center/y", 0);
00914 _center[2] = props->getFloatValue("center/z", 0);
00915 _axis[0] = props->getFloatValue("axis/x", 0);
00916 _axis[1] = props->getFloatValue("axis/y", 0);
00917 _axis[2] = props->getFloatValue("axis/z", 0);
00918 sgNormalizeVec3(_axis);
00919 }
00920
00921 SGTexRotateAnimation::~SGTexRotateAnimation ()
00922 {
00923 delete _table;
00924 delete _condition;
00925 }
00926
00927 int
00928 SGTexRotateAnimation::update()
00929 {
00930 if (_condition && !_condition->test())
00931 return 1;
00932
00933 if (_table == 0) {
00934 _position_deg = _prop->getDoubleValue() * _factor + _offset_deg;
00935 if (_has_min && _position_deg < _min_deg)
00936 _position_deg = _min_deg;
00937 if (_has_max && _position_deg > _max_deg)
00938 _position_deg = _max_deg;
00939 } else {
00940 _position_deg = _table->interpolate(_prop->getDoubleValue());
00941 }
00942 set_rotation(_matrix, _position_deg, _center, _axis);
00943 ((ssgTexTrans *)_branch)->setTransform(_matrix);
00944 return 2;
00945 }
00946
00947
00949
00951
00952 SGTexTranslateAnimation::SGTexTranslateAnimation( SGPropertyNode *prop_root,
00953 SGPropertyNode_ptr props )
00954 : SGAnimation(props, new ssgTexTrans),
00955 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)),
00956 _offset(props->getDoubleValue("offset", 0.0)),
00957 _factor(props->getDoubleValue("factor", 1.0)),
00958 _step(props->getDoubleValue("step",0.0)),
00959 _scroll(props->getDoubleValue("scroll",0.0)),
00960 _table(read_interpolation_table(props)),
00961 _has_min(props->hasValue("min")),
00962 _min(props->getDoubleValue("min")),
00963 _has_max(props->hasValue("max")),
00964 _max(props->getDoubleValue("max")),
00965 _position(props->getDoubleValue("starting-position", 0)),
00966 _condition(0)
00967 {
00968 SGPropertyNode *node = props->getChild("condition");
00969 if (node != 0)
00970 _condition = sgReadCondition(prop_root, node);
00971
00972 _axis[0] = props->getFloatValue("axis/x", 0);
00973 _axis[1] = props->getFloatValue("axis/y", 0);
00974 _axis[2] = props->getFloatValue("axis/z", 0);
00975 sgNormalizeVec3(_axis);
00976 }
00977
00978 SGTexTranslateAnimation::~SGTexTranslateAnimation ()
00979 {
00980 delete _table;
00981 delete _condition;
00982 }
00983
00984 int
00985 SGTexTranslateAnimation::update()
00986 {
00987 if (_condition && !_condition->test())
00988 return 1;
00989
00990 if (_table == 0) {
00991 _position = (apply_mods(_prop->getDoubleValue(), _step, _scroll) + _offset) * _factor;
00992 if (_has_min && _position < _min)
00993 _position = _min;
00994 if (_has_max && _position > _max)
00995 _position = _max;
00996 } else {
00997 _position = _table->interpolate(apply_mods(_prop->getDoubleValue(), _step, _scroll));
00998 }
00999 set_translation(_matrix, _position, _axis);
01000 ((ssgTexTrans *)_branch)->setTransform(_matrix);
01001 return 2;
01002 }
01003
01004
01006
01008
01009 SGTexMultipleAnimation::SGTexMultipleAnimation( SGPropertyNode *prop_root,
01010 SGPropertyNode_ptr props )
01011 : SGAnimation(props, new ssgTexTrans),
01012 _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true))
01013 {
01014 unsigned int i;
01015
01016 vector<SGPropertyNode_ptr> transform_nodes = props->getChildren("transform");
01017 _transform = new TexTransform [transform_nodes.size()];
01018 _num_transforms = 0;
01019 for (i = 0; i < transform_nodes.size(); i++) {
01020 SGPropertyNode_ptr transform_props = transform_nodes[i];
01021
01022 if (!strcmp("textranslate",transform_props->getStringValue("subtype", 0))) {
01023
01024
01025 _transform[i].subtype = 0;
01026
01027 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
01028
01029 _transform[i].offset = transform_props->getDoubleValue("offset", 0.0);
01030 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
01031 _transform[i].step = transform_props->getDoubleValue("step",0.0);
01032 _transform[i].scroll = transform_props->getDoubleValue("scroll",0.0);
01033 _transform[i].table = read_interpolation_table(transform_props);
01034 _transform[i].has_min = transform_props->hasValue("min");
01035 _transform[i].min = transform_props->getDoubleValue("min");
01036 _transform[i].has_max = transform_props->hasValue("max");
01037 _transform[i].max = transform_props->getDoubleValue("max");
01038 _transform[i].position = transform_props->getDoubleValue("starting-position", 0);
01039
01040 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
01041 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
01042 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
01043 sgNormalizeVec3(_transform[i].axis);
01044 _num_transforms++;
01045 } else if (!strcmp("texrotate",transform_nodes[i]->getStringValue("subtype", 0))) {
01046
01047
01048 _transform[i].subtype = 1;
01049
01050 _transform[i].prop = (SGPropertyNode *)prop_root->getNode(transform_props->getStringValue("property", "/null"), true);
01051 _transform[i].offset = transform_props->getDoubleValue("offset-deg", 0.0);
01052 _transform[i].factor = transform_props->getDoubleValue("factor", 1.0);
01053 _transform[i].table = read_interpolation_table(transform_props);
01054 _transform[i].has_min = transform_props->hasValue("min-deg");
01055 _transform[i].min = transform_props->getDoubleValue("min-deg");
01056 _transform[i].has_max = transform_props->hasValue("max-deg");
01057 _transform[i].max = transform_props->getDoubleValue("max-deg");
01058 _transform[i].position = transform_props->getDoubleValue("starting-position-deg", 0);
01059
01060 _transform[i].center[0] = transform_props->getFloatValue("center/x", 0);
01061 _transform[i].center[1] = transform_props->getFloatValue("center/y", 0);
01062 _transform[i].center[2] = transform_props->getFloatValue("center/z", 0);
01063 _transform[i].axis[0] = transform_props->getFloatValue("axis/x", 0);
01064 _transform[i].axis[1] = transform_props->getFloatValue("axis/y", 0);
01065 _transform[i].axis[2] = transform_props->getFloatValue("axis/z", 0);
01066 sgNormalizeVec3(_transform[i].axis);
01067 _num_transforms++;
01068 }
01069 }
01070 }
01071
01072 SGTexMultipleAnimation::~SGTexMultipleAnimation ()
01073 {
01074 delete [] _transform;
01075 }
01076
01077 int
01078 SGTexMultipleAnimation::update()
01079 {
01080 int i;
01081 sgMat4 tmatrix;
01082 sgMakeIdentMat4(tmatrix);
01083 for (i = 0; i < _num_transforms; i++) {
01084
01085 if(_transform[i].subtype == 0) {
01086
01087
01088 if (_transform[i].table == 0) {
01089 _transform[i].position = (apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll) + _transform[i].offset) * _transform[i].factor;
01090 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
01091 _transform[i].position = _transform[i].min;
01092 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
01093 _transform[i].position = _transform[i].max;
01094 } else {
01095 _transform[i].position = _transform[i].table->interpolate(apply_mods(_transform[i].prop->getDoubleValue(), _transform[i].step,_transform[i].scroll));
01096 }
01097 set_translation(_transform[i].matrix, _transform[i].position, _transform[i].axis);
01098 sgPreMultMat4(tmatrix, _transform[i].matrix);
01099
01100 } else if (_transform[i].subtype == 1) {
01101
01102
01103
01104 if (_transform[i].table == 0) {
01105 _transform[i].position = _transform[i].prop->getDoubleValue() * _transform[i].factor + _transform[i].offset;
01106 if (_transform[i].has_min && _transform[i].position < _transform[i].min)
01107 _transform[i].position = _transform[i].min;
01108 if (_transform[i].has_max && _transform[i].position > _transform[i].max)
01109 _transform[i].position = _transform[i].max;
01110 } else {
01111 _transform[i].position = _transform[i].table->interpolate(_transform[i].prop->getDoubleValue());
01112 }
01113 set_rotation(_transform[i].matrix, _transform[i].position, _transform[i].center, _transform[i].axis);
01114 sgPreMultMat4(tmatrix, _transform[i].matrix);
01115 }
01116 }
01117 ((ssgTexTrans *)_branch)->setTransform(tmatrix);
01118 return 2;
01119 }
01120
01121
01122
01124
01126
01127 SGAlphaTestAnimation::SGAlphaTestAnimation(SGPropertyNode_ptr props)
01128 : SGAnimation(props, new ssgBranch)
01129 {
01130 _alpha_clamp = props->getFloatValue("alpha-factor", 0.0);
01131 }
01132
01133 SGAlphaTestAnimation::~SGAlphaTestAnimation ()
01134 {
01135 }
01136
01137 void SGAlphaTestAnimation::init()
01138 {
01139 setAlphaClampToBranch(_branch,_alpha_clamp);
01140 }
01141
01142 void SGAlphaTestAnimation::setAlphaClampToBranch(ssgBranch *b, float clamp)
01143 {
01144 int nb = b->getNumKids();
01145 for (int i = 0; i<nb; i++) {
01146 ssgEntity *e = b->getKid(i);
01147 if (e->isAKindOf(ssgTypeLeaf())) {
01148 ssgSimpleState*s = (ssgSimpleState*)((ssgLeaf*)e)->getState();
01149 s->enable( GL_ALPHA_TEST );
01150 s->setAlphaClamp( clamp );
01151 } else if (e->isAKindOf(ssgTypeBranch())) {
01152 setAlphaClampToBranch( (ssgBranch*)e, clamp );
01153 }
01154 }
01155 }
01156
01157
01158
01160
01162
01163 SGMaterialAnimation::SGMaterialAnimation( SGPropertyNode *prop_root,
01164 SGPropertyNode_ptr props, const SGPath &texture_path)
01165 : SGAnimation(props, new ssgBranch),
01166 _last_condition(false),
01167 _prop_root(prop_root),
01168 _prop_base(""),
01169 _texture_base(texture_path),
01170 _cached_material(0),
01171 _cloned_material(0),
01172 _read(0),
01173 _update(0),
01174 _global(props->getBoolValue("global", false))
01175 {
01176 SGPropertyNode_ptr n;
01177 n = props->getChild("condition");
01178 _condition = n ? sgReadCondition(_prop_root, n) : 0;
01179 n = props->getChild("property-base");
01180 if (n) {
01181 _prop_base = n->getStringValue();
01182 if (!_prop_base.empty() && _prop_base.end()[-1] != '/')
01183 _prop_base += '/';
01184 }
01185
01186 initColorGroup(props->getChild("diffuse"), &_diff, DIFFUSE);
01187 initColorGroup(props->getChild("ambient"), &_amb, AMBIENT);
01188 initColorGroup(props->getChild("emission"), &_emis, EMISSION);
01189 initColorGroup(props->getChild("specular"), &_spec, SPECULAR);
01190
01191 _shi = props->getFloatValue("shininess", -1.0);
01192 if (_shi >= 0.0)
01193 _update |= SHININESS;
01194
01195 SGPropertyNode_ptr group = props->getChild("transparency");
01196 if (group) {
01197 _trans.value = group->getFloatValue("alpha", -1.0);
01198 _trans.factor = group->getFloatValue("factor", 1.0);
01199 _trans.offset = group->getFloatValue("offset", 0.0);
01200 _trans.min = group->getFloatValue("min", 0.0);
01201 if (_trans.min < 0.0)
01202 _trans.min = 0.0;
01203 _trans.max = group->getFloatValue("max", 1.0);
01204 if (_trans.max > 1.0)
01205 _trans.max = 1.0;
01206 if (_trans.dirty())
01207 _update |= TRANSPARENCY;
01208
01209 n = group->getChild("alpha-prop");
01210 _trans.value_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01211 n = group->getChild("factor-prop");
01212 _trans.factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01213 n = group->getChild("offset-prop");
01214 _trans.offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01215 if (_trans.live())
01216 _read |= TRANSPARENCY;
01217 }
01218
01219 _thresh = props->getFloatValue("threshold", -1.0);
01220 if (_thresh >= 0.0)
01221 _update |= THRESHOLD;
01222
01223 string _texture_str = props->getStringValue("texture", "");
01224 if (!_texture_str.empty()) {
01225 _texture = _texture_base;
01226 _texture.append(_texture_str);
01227 _update |= TEXTURE;
01228 }
01229
01230 n = props->getChild("shininess-prop");
01231 _shi_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01232 n = props->getChild("threshold-prop");
01233 _thresh_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01234 n = props->getChild("texture-prop");
01235 _tex_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01236
01237 _static_update = _update;
01238 }
01239
01240 SGMaterialAnimation::~SGMaterialAnimation()
01241 {
01242 delete _condition;
01243 }
01244
01245
01246 void SGMaterialAnimation::initColorGroup(SGPropertyNode_ptr group, ColorSpec *col, int flag)
01247 {
01248 if (!group)
01249 return;
01250
01251 col->red = group->getFloatValue("red", -1.0);
01252 col->green = group->getFloatValue("green", -1.0);
01253 col->blue = group->getFloatValue("blue", -1.0);
01254 col->factor = group->getFloatValue("factor", 1.0);
01255 col->offset = group->getFloatValue("offset", 0.0);
01256 if (col->dirty())
01257 _update |= flag;
01258
01259 SGPropertyNode *n;
01260 n = group->getChild("red-prop");
01261 col->red_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01262 n = group->getChild("green-prop");
01263 col->green_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01264 n = group->getChild("blue-prop");
01265 col->blue_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01266 n = group->getChild("factor-prop");
01267 col->factor_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01268 n = group->getChild("offset-prop");
01269 col->offset_prop = n ? _prop_root->getNode(path(n->getStringValue()), true) : 0;
01270 if (col->live())
01271 _read |= flag;
01272 }
01273
01274 void SGMaterialAnimation::init()
01275 {
01276 if (!_global)
01277 cloneMaterials(_branch);
01278 }
01279
01280 int SGMaterialAnimation::update()
01281 {
01282 if (_condition) {
01283 bool cond = _condition->test();
01284 if (cond && !_last_condition)
01285 _update |= _static_update;
01286
01287 _last_condition = cond;
01288 if (!cond)
01289 return 2;
01290 }
01291
01292 if (_read & DIFFUSE)
01293 updateColorGroup(&_diff, DIFFUSE);
01294 if (_read & AMBIENT)
01295 updateColorGroup(&_amb, AMBIENT);
01296 if (_read & EMISSION)
01297 updateColorGroup(&_emis, EMISSION);
01298 if (_read & SPECULAR)
01299 updateColorGroup(&_spec, SPECULAR);
01300
01301 float f;
01302 if (_shi_prop) {
01303 f = _shi;
01304 _shi = _shi_prop->getFloatValue();
01305 if (_shi != f)
01306 _update |= SHININESS;
01307 }
01308 if (_read & TRANSPARENCY) {
01309 PropSpec tmp = _trans;
01310 if (_trans.value_prop)
01311 _trans.value = _trans.value_prop->getFloatValue();
01312 if (_trans.factor_prop)
01313 _trans.factor = _trans.factor_prop->getFloatValue();
01314 if (_trans.offset_prop)
01315 _trans.offset = _trans.offset_prop->getFloatValue();
01316 if (_trans != tmp)
01317 _update |= TRANSPARENCY;
01318 }
01319 if (_thresh_prop) {
01320 f = _thresh;
01321 _thresh = _thresh_prop->getFloatValue();
01322 if (_thresh != f)
01323 _update |= THRESHOLD;
01324 }
01325 if (_tex_prop) {
01326 string t = _tex_prop->getStringValue();
01327 if (!t.empty() && t != _texture_str) {
01328 _texture_str = t;
01329 _texture = _texture_base;
01330 _texture.append(t);
01331 _update |= TEXTURE;
01332 }
01333 }
01334 if (_update) {
01335 setMaterialBranch(_branch);
01336 _update = 0;
01337 }
01338 return 2;
01339 }
01340
01341 void SGMaterialAnimation::updateColorGroup(ColorSpec *col, int flag)
01342 {
01343 ColorSpec tmp = *col;
01344 if (col->red_prop)
01345 col->red = col->red_prop->getFloatValue();
01346 if (col->green_prop)
01347 col->green = col->green_prop->getFloatValue();
01348 if (col->blue_prop)
01349 col->blue = col->blue_prop->getFloatValue();
01350 if (col->factor_prop)
01351 col->factor = col->factor_prop->getFloatValue();
01352 if (col->offset_prop)
01353 col->offset = col->offset_prop->getFloatValue();
01354 if (*col != tmp)
01355 _update |= flag;
01356 }
01357
01358 void SGMaterialAnimation::cloneMaterials(ssgBranch *b)
01359 {
01360 for (int i = 0; i < b->getNumKids(); i++)
01361 cloneMaterials((ssgBranch *)b->getKid(i));
01362
01363 if (!b->isAKindOf(ssgTypeLeaf()) || !((ssgLeaf *)b)->hasState())
01364 return;
01365
01366 ssgSimpleState *s = (ssgSimpleState *)((ssgLeaf *)b)->getState();
01367 if (!_cached_material || _cached_material != s) {
01368 _cached_material = s;
01369 _cloned_material = (ssgSimpleState *)s->clone(SSG_CLONE_STATE);
01370 }
01371 ((ssgLeaf *)b)->setState(_cloned_material)