00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "cLerpNodePathInterval.h"
00016 #include "lerp_helpers.h"
00017 #include "transformState.h"
00018 #include "renderState.h"
00019 #include "colorAttrib.h"
00020 #include "colorScaleAttrib.h"
00021 #include "texMatrixAttrib.h"
00022 #include "dcast.h"
00023 #include "config_interval.h"
00024
00025 TypeHandle CLerpNodePathInterval::_type_handle;
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 CLerpNodePathInterval::
00059 CLerpNodePathInterval(const string &name, double duration,
00060 CLerpInterval::BlendType blend_type,
00061 bool bake_in_start, bool fluid,
00062 const NodePath &node, const NodePath &other) :
00063 CLerpInterval(name, duration, blend_type),
00064 _node(node),
00065 _other(other),
00066 _flags(0),
00067 _texture_stage(TextureStage::get_default()),
00068 _override(0),
00069 _slerp(NULL)
00070 {
00071 if (bake_in_start) {
00072 _flags |= F_bake_in_start;
00073 }
00074 if (fluid) {
00075 _flags |= F_fluid;
00076 }
00077 _prev_d = 0.0;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 void CLerpNodePathInterval::
00089 priv_initialize(double t) {
00090 check_stopped(get_class_type(), "priv_initialize");
00091 recompute();
00092 _prev_d = 0.0;
00093 _state = S_started;
00094 priv_step(t);
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 void CLerpNodePathInterval::
00106 priv_instant() {
00107 check_stopped(get_class_type(), "priv_instant");
00108 recompute();
00109 _prev_d = 0.0;
00110 _state = S_started;
00111 priv_step(get_duration());
00112 _state = S_final;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122 void CLerpNodePathInterval::
00123 priv_step(double t) {
00124 check_started(get_class_type(), "priv_step");
00125 _state = S_started;
00126 double d = compute_delta(t);
00127
00128
00129 CPT(TransformState) prev_transform = _node.get_prev_transform();
00130
00131 if ((_flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale | F_end_shear)) != 0) {
00132
00133 CPT(TransformState) transform;
00134
00135 if (_other.is_empty()) {
00136
00137 transform = _node.get_transform();
00138 } else {
00139
00140
00141 transform = _node.get_transform(_other);
00142 }
00143
00144 LPoint3 pos;
00145 LVecBase3 hpr;
00146 LQuaternion quat;
00147 LVecBase3 scale;
00148 LVecBase3 shear;
00149
00150 if ((_flags & F_end_pos) != 0) {
00151 if ((_flags & F_start_pos) != 0) {
00152 lerp_value(pos, d, _start_pos, _end_pos);
00153
00154 } else if ((_flags & F_bake_in_start) != 0) {
00155
00156 set_start_pos(transform->get_pos());
00157 lerp_value(pos, d, _start_pos, _end_pos);
00158
00159 } else {
00160
00161 pos = transform->get_pos();
00162 lerp_value_from_prev(pos, d, _prev_d, pos, _end_pos);
00163 }
00164 }
00165 if ((_flags & F_end_hpr) != 0) {
00166 if ((_flags & F_start_hpr) != 0) {
00167 lerp_value(hpr, d, _start_hpr, _end_hpr);
00168
00169 } else if ((_flags & F_start_quat) != 0) {
00170 _start_hpr = _start_quat.get_hpr();
00171 _flags |= F_start_hpr;
00172 lerp_value(hpr, d, _start_hpr, _end_hpr);
00173
00174 } else if ((_flags & F_bake_in_start) != 0) {
00175 set_start_hpr(transform->get_hpr());
00176 lerp_value(hpr, d, _start_hpr, _end_hpr);
00177
00178 } else {
00179 hpr = transform->get_hpr();
00180 lerp_value_from_prev(hpr, d, _prev_d, hpr, _end_hpr);
00181 }
00182 }
00183 if ((_flags & F_end_quat) != 0) {
00184 if ((_flags & F_slerp_setup) == 0) {
00185 if ((_flags & F_start_quat) != 0) {
00186 setup_slerp();
00187
00188 } else if ((_flags & F_start_hpr) != 0) {
00189 _start_quat.set_hpr(_start_hpr);
00190 _flags |= F_start_quat;
00191 setup_slerp();
00192
00193 } else if ((_flags & F_bake_in_start) != 0) {
00194 set_start_quat(transform->get_quat());
00195 setup_slerp();
00196
00197 } else {
00198 if (_prev_d == 1.0) {
00199 _start_quat = _end_quat;
00200 } else {
00201 LQuaternion prev_value = transform->get_quat();
00202 _start_quat = (prev_value - _prev_d * _end_quat) / (1.0 - _prev_d);
00203 }
00204 setup_slerp();
00205
00206
00207
00208 _flags &= ~F_slerp_setup;
00209 }
00210 }
00211 nassertv(_slerp != NULL);
00212 (this->*_slerp)(quat, d);
00213 }
00214 if ((_flags & F_end_scale) != 0) {
00215 if ((_flags & F_start_scale) != 0) {
00216 lerp_value(scale, d, _start_scale, _end_scale);
00217
00218 } else if ((_flags & F_bake_in_start) != 0) {
00219 set_start_scale(transform->get_scale());
00220 lerp_value(scale, d, _start_scale, _end_scale);
00221
00222 } else {
00223 scale = transform->get_scale();
00224 lerp_value_from_prev(scale, d, _prev_d, scale, _end_scale);
00225 }
00226 }
00227 if ((_flags & F_end_shear) != 0) {
00228 if ((_flags & F_start_shear) != 0) {
00229 lerp_value(shear, d, _start_shear, _end_shear);
00230
00231 } else if ((_flags & F_bake_in_start) != 0) {
00232 set_start_shear(transform->get_shear());
00233 lerp_value(shear, d, _start_shear, _end_shear);
00234
00235 } else {
00236 shear = transform->get_shear();
00237 lerp_value_from_prev(shear, d, _prev_d, shear, _end_shear);
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246 unsigned int transform_flags = _flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale);
00247 switch (transform_flags) {
00248 case 0:
00249 break;
00250
00251 case F_end_pos:
00252 if (_other.is_empty()) {
00253 _node.set_pos(pos);
00254 } else {
00255 _node.set_pos(_other, pos);
00256 }
00257 break;
00258
00259 case F_end_hpr:
00260 if (_other.is_empty()) {
00261 _node.set_hpr(hpr);
00262 } else {
00263 _node.set_hpr(_other, hpr);
00264 }
00265 break;
00266
00267 case F_end_quat:
00268 if (_other.is_empty()) {
00269 _node.set_quat(quat);
00270 } else {
00271 _node.set_quat(_other, quat);
00272 }
00273 break;
00274
00275 case F_end_scale:
00276 if (_other.is_empty()) {
00277 _node.set_scale(scale);
00278 } else {
00279 _node.set_scale(_other, scale);
00280 }
00281 break;
00282
00283 case F_end_hpr | F_end_scale:
00284 if (_other.is_empty()) {
00285 _node.set_hpr_scale(hpr, scale);
00286 } else {
00287 _node.set_hpr_scale(hpr, scale);
00288 }
00289 break;
00290
00291 case F_end_quat | F_end_scale:
00292 if (_other.is_empty()) {
00293 _node.set_quat_scale(quat, scale);
00294 } else {
00295 _node.set_quat_scale(quat, scale);
00296 }
00297 break;
00298
00299 case F_end_pos | F_end_hpr:
00300 if (_other.is_empty()) {
00301 _node.set_pos_hpr(pos, hpr);
00302 } else {
00303 _node.set_pos_hpr(_other, pos, hpr);
00304 }
00305 break;
00306
00307 case F_end_pos | F_end_quat:
00308 if (_other.is_empty()) {
00309 _node.set_pos_quat(pos, quat);
00310 } else {
00311 _node.set_pos_quat(_other, pos, quat);
00312 }
00313 break;
00314
00315 case F_end_pos | F_end_scale:
00316 if (transform->quat_given()) {
00317 if (_other.is_empty()) {
00318 _node.set_pos_quat_scale(pos, transform->get_quat(), scale);
00319 } else {
00320 _node.set_pos_quat_scale(_other, pos, transform->get_quat(), scale);
00321 }
00322 } else {
00323 if (_other.is_empty()) {
00324 _node.set_pos_hpr_scale(pos, transform->get_hpr(), scale);
00325 } else {
00326 _node.set_pos_hpr_scale(_other, pos, transform->get_hpr(), scale);
00327 }
00328 }
00329 break;
00330
00331 case F_end_pos | F_end_hpr | F_end_scale:
00332 if ((_flags & F_end_shear) != 0) {
00333
00334 if (_other.is_empty()) {
00335 _node.set_pos_hpr_scale_shear(pos, hpr, scale, shear);
00336 } else {
00337 _node.set_pos_hpr_scale_shear(_other, pos, hpr, scale, shear);
00338 }
00339 } else {
00340
00341 if (_other.is_empty()) {
00342 _node.set_pos_hpr_scale(pos, hpr, scale);
00343 } else {
00344 _node.set_pos_hpr_scale(_other, pos, hpr, scale);
00345 }
00346 }
00347 break;
00348
00349 case F_end_pos | F_end_quat | F_end_scale:
00350 if ((_flags & F_end_shear) != 0) {
00351
00352 if (_other.is_empty()) {
00353 _node.set_pos_quat_scale_shear(pos, quat, scale, shear);
00354 } else {
00355 _node.set_pos_quat_scale_shear(_other, pos, quat, scale, shear);
00356 }
00357 } else {
00358
00359 if (_other.is_empty()) {
00360 _node.set_pos_quat_scale(pos, quat, scale);
00361 } else {
00362 _node.set_pos_quat_scale(_other, pos, quat, scale);
00363 }
00364 }
00365 break;
00366
00367 default:
00368
00369 interval_cat.error()
00370 << "Internal error in CLerpNodePathInterval::priv_step().\n";
00371 }
00372 if ((_flags & F_end_shear) != 0) {
00373
00374 if (transform_flags == (F_end_pos | F_end_hpr | F_end_scale) ||
00375 transform_flags == (F_end_pos | F_end_quat | F_end_scale)) {
00376
00377
00378 } else {
00379 if (_other.is_empty()) {
00380 _node.set_shear(shear);
00381 } else {
00382 _node.set_shear(_other, shear);
00383 }
00384 }
00385 }
00386 }
00387
00388 if ((_flags & F_fluid) != 0) {
00389
00390
00391
00392 _node.set_prev_transform(prev_transform);
00393 }
00394
00395 if ((_flags & (F_end_color | F_end_color_scale | F_end_tex_offset | F_end_tex_rotate | F_end_tex_scale)) != 0) {
00396
00397 CPT(RenderState) state;
00398
00399 if (_other.is_empty()) {
00400
00401
00402 state = _node.get_state();
00403 } else {
00404
00405
00406
00407 state = _node.get_state(_other);
00408 }
00409
00410
00411
00412
00413
00414 if ((_flags & F_end_color) != 0) {
00415 LColor color;
00416
00417 if ((_flags & F_start_color) != 0) {
00418 lerp_value(color, d, _start_color, _end_color);
00419
00420 } else {
00421
00422 color.set(1.0f, 1.0f, 1.0f, 1.0f);
00423 const RenderAttrib *attrib =
00424 state->get_attrib(ColorAttrib::get_class_type());
00425 if (attrib != (const RenderAttrib *)NULL) {
00426 const ColorAttrib *ca = DCAST(ColorAttrib, attrib);
00427 if (ca->get_color_type() == ColorAttrib::T_flat) {
00428 color = ca->get_color();
00429 }
00430 }
00431
00432 lerp_value_from_prev(color, d, _prev_d, color, _end_color);
00433 }
00434
00435 state = state->add_attrib(ColorAttrib::make_flat(color), _override);
00436 }
00437
00438 if ((_flags & F_end_color_scale) != 0) {
00439 LVecBase4 color_scale;
00440
00441 if ((_flags & F_start_color_scale) != 0) {
00442 lerp_value(color_scale, d, _start_color_scale, _end_color_scale);
00443
00444 } else {
00445
00446 color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
00447 const RenderAttrib *attrib =
00448 state->get_attrib(ColorScaleAttrib::get_class_type());
00449 if (attrib != (const RenderAttrib *)NULL) {
00450 const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
00451 color_scale = csa->get_scale();
00452 }
00453
00454 lerp_value_from_prev(color_scale, d, _prev_d, color_scale, _end_color_scale);
00455 }
00456
00457 state = state->add_attrib(ColorScaleAttrib::make(color_scale), _override);
00458 }
00459
00460 if ((_flags & (F_end_tex_offset | F_end_tex_rotate | F_end_tex_scale)) != 0) {
00461
00462 CPT(TransformState) transform = TransformState::make_identity();
00463
00464 const RenderAttrib *attrib =
00465 state->get_attrib(TexMatrixAttrib::get_class_type());
00466 CPT(TexMatrixAttrib) tma;
00467 if (attrib != (const TexMatrixAttrib *)NULL) {
00468 tma = DCAST(TexMatrixAttrib, attrib);
00469 transform = tma->get_transform(_texture_stage);
00470 } else {
00471 tma = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
00472 }
00473
00474 if ((_flags & F_end_tex_offset) != 0) {
00475 LVecBase2 tex_offset;
00476
00477 if ((_flags & F_start_tex_offset) != 0) {
00478 lerp_value(tex_offset, d, _start_tex_offset, _end_tex_offset);
00479 } else {
00480 tex_offset = transform->get_pos2d();
00481 lerp_value_from_prev(tex_offset, d, _prev_d, tex_offset,
00482 _end_tex_offset);
00483 }
00484
00485 transform = transform->set_pos2d(tex_offset);
00486 }
00487
00488 if ((_flags & F_end_tex_rotate) != 0) {
00489 PN_stdfloat tex_rotate;
00490
00491 if ((_flags & F_start_tex_rotate) != 0) {
00492 lerp_value(tex_rotate, d, _start_tex_rotate, _end_tex_rotate);
00493 } else {
00494 tex_rotate = transform->get_rotate2d();
00495 lerp_value_from_prev(tex_rotate, d, _prev_d, tex_rotate,
00496 _end_tex_rotate);
00497 }
00498
00499 transform = transform->set_rotate2d(tex_rotate);
00500 }
00501
00502 if ((_flags & F_end_tex_scale) != 0) {
00503 LVecBase2 tex_scale;
00504
00505 if ((_flags & F_start_tex_scale) != 0) {
00506 lerp_value(tex_scale, d, _start_tex_scale, _end_tex_scale);
00507 } else {
00508 tex_scale = transform->get_scale2d();
00509 lerp_value_from_prev(tex_scale, d, _prev_d, tex_scale,
00510 _end_tex_scale);
00511 }
00512
00513 transform = transform->set_scale2d(tex_scale);
00514 }
00515
00516
00517 state = state->set_attrib(tma->add_stage(_texture_stage, transform, _override));
00518 }
00519
00520
00521
00522 if (_other.is_empty()) {
00523 _node.set_state(state);
00524 } else {
00525 _node.set_state(_other, state);
00526 }
00527 } _prev_d = d;
00528 _curr_t = t;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 void CLerpNodePathInterval::
00540 priv_reverse_initialize(double t) {
00541 check_stopped(get_class_type(), "priv_reverse_initialize");
00542 recompute();
00543 _state = S_started;
00544 _prev_d = 1.0;
00545 priv_step(t);
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 void CLerpNodePathInterval::
00558 priv_reverse_instant() {
00559 check_stopped(get_class_type(), "priv_reverse_initialize");
00560 recompute();
00561 _state = S_started;
00562 _prev_d = 1.0;
00563 priv_step(0.0);
00564 _state = S_initial;
00565 }
00566
00567
00568
00569
00570
00571
00572 void CLerpNodePathInterval::
00573 output(ostream &out) const {
00574 out << get_name() << ":";
00575
00576 if ((_flags & F_end_pos) != 0) {
00577 out << " pos";
00578 if ((_flags & F_start_pos) != 0) {
00579 out << " from " << _start_pos;
00580 }
00581 out << " to " << _end_pos;
00582 }
00583
00584 if ((_flags & F_end_hpr) != 0) {
00585 out << " hpr";
00586 if ((_flags & F_start_hpr) != 0) {
00587 out << " from " << _start_hpr;
00588 }
00589 out << " to " << _end_hpr;
00590 }
00591
00592 if ((_flags & F_end_quat) != 0) {
00593 out << " quat";
00594 if ((_flags & F_start_quat) != 0) {
00595 out << " from " << _start_quat;
00596 }
00597 out << " to " << _end_quat;
00598 }
00599
00600 if ((_flags & F_end_scale) != 0) {
00601 out << " scale";
00602 if ((_flags & F_start_scale) != 0) {
00603 out << " from " << _start_scale;
00604 }
00605 out << " to " << _end_scale;
00606 }
00607
00608 if ((_flags & F_end_shear) != 0) {
00609 out << " shear";
00610 if ((_flags & F_start_shear) != 0) {
00611 out << " from " << _start_shear;
00612 }
00613 out << " to " << _end_shear;
00614 }
00615
00616 if ((_flags & F_end_color) != 0) {
00617 out << " color";
00618 if ((_flags & F_start_color) != 0) {
00619 out << " from " << _start_color;
00620 }
00621 out << " to " << _end_color;
00622 }
00623
00624 if ((_flags & F_end_color_scale) != 0) {
00625 out << " color_scale";
00626 if ((_flags & F_start_color_scale) != 0) {
00627 out << " from " << _start_color_scale;
00628 }
00629 out << " to " << _end_color_scale;
00630 }
00631
00632 out << " dur " << get_duration();
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 void CLerpNodePathInterval::
00644 setup_slerp() {
00645 if (_start_quat.dot(_end_quat) < 0.0f) {
00646
00647 _start_quat = -_start_quat;
00648 }
00649
00650 _slerp_angle = _start_quat.angle_rad(_end_quat);
00651
00652 if (_slerp_angle < 0.1f) {
00653
00654
00655
00656 _slerp_denom = csin_over_x(_slerp_angle);
00657 _slerp = &CLerpNodePathInterval::slerp_angle_0;
00658
00659 } else if (_slerp_angle > 3.14) {
00660
00661
00662
00663
00664
00665
00666
00667
00668 _slerp_c = (_start_quat + _end_quat);
00669 _slerp_c.normalize();
00670 _slerp_angle = _end_quat.angle_rad(_slerp_c);
00671 _slerp_denom = csin(_slerp_angle);
00672
00673 _slerp = &CLerpNodePathInterval::slerp_angle_180;
00674
00675 } else {
00676
00677
00678 _slerp_denom = csin(_slerp_angle);
00679 _slerp = &CLerpNodePathInterval::slerp_basic;
00680 }
00681
00682 nassertv(_slerp_denom != 0.0f);
00683 _flags |= F_slerp_setup;
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693 void CLerpNodePathInterval::
00694 slerp_basic(LQuaternion &result, PN_stdfloat t) const {
00695 nassertv(_slerp_denom != 0.0f);
00696 PN_stdfloat ti = 1.0f - t;
00697 PN_stdfloat ta = t * _slerp_angle;
00698 PN_stdfloat tia = ti * _slerp_angle;
00699
00700 if (interval_cat.is_spam()) {
00701 interval_cat.spam()
00702 << "slerp_basic, (t = " << t << "), angle = " << _slerp_angle << "\n"
00703 << "_start_quat = " << _start_quat << ", _end_quat = "
00704 << _end_quat << ", denom = " << _slerp_denom << "\n";
00705 }
00706
00707 result = (csin(tia) * _start_quat + csin(ta) * _end_quat) / _slerp_denom;
00708 nassertv(!result.is_nan());
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718 void CLerpNodePathInterval::
00719 slerp_angle_0(LQuaternion &result, PN_stdfloat t) const {
00720 nassertv(_slerp_denom != 0.0f);
00721 PN_stdfloat ti = 1.0f - t;
00722 PN_stdfloat ta = t * _slerp_angle;
00723 PN_stdfloat tia = ti * _slerp_angle;
00724
00725 if (interval_cat.is_spam()) {
00726 interval_cat.spam()
00727 << "slerp_angle_0, (t = " << t << "), angle = " << _slerp_angle
00728 << "\n_start_quat = " << _start_quat << ", _end_quat = "
00729 << _end_quat << ", denom = " << _slerp_denom << "\n";
00730 }
00731
00732 result = (csin_over_x(tia) * ti * _start_quat + csin_over_x(ta) * t * _end_quat) / _slerp_denom;
00733 nassertv(!result.is_nan());
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 void CLerpNodePathInterval::
00745 slerp_angle_180(LQuaternion &result, PN_stdfloat t) const {
00746 nassertv(_slerp_denom != 0.0f);
00747 if (t < 0.5) {
00748
00749
00750 t *= 2.0f;
00751
00752 PN_stdfloat ti = 1.0f - t;
00753 PN_stdfloat ta = t * _slerp_angle;
00754 PN_stdfloat tia = ti * _slerp_angle;
00755
00756 if (interval_cat.is_spam()) {
00757 interval_cat.spam()
00758 << "slerp_angle_180, first half (t = " << t << "), angle = "
00759 << _slerp_angle << "\n_start_quat = " << _start_quat
00760 << ", _slerp_c = " << _slerp_c << ", denom = "
00761 << _slerp_denom << "\n";
00762 }
00763
00764 result = (csin(tia) * _start_quat + csin(ta) * _slerp_c) / _slerp_denom;
00765
00766 } else {
00767
00768 t = t * 2.0f - 1.0f;
00769
00770 PN_stdfloat ti = 1.0f - t;
00771 PN_stdfloat ta = t * _slerp_angle;
00772 PN_stdfloat tia = ti * _slerp_angle;
00773
00774 if (interval_cat.is_spam()) {
00775 interval_cat.spam()
00776 << "slerp_angle_180, second half (t = " << t << "), angle = "
00777 << _slerp_angle << "\n_slerp_c = " << _slerp_c
00778 << ", _end_quat = " << _end_quat << ", denom = "
00779 << _slerp_denom << "\n";
00780 }
00781
00782 result = (csin(tia) * _slerp_c + csin(ta) * _end_quat) / _slerp_denom;
00783 }
00784
00785 nassertv(!result.is_nan());
00786 }