24 TypeHandle CLerpNodePathInterval::_type_handle;
51 CLerpInterval::BlendType blend_type,
52 bool bake_in_start,
bool fluid,
63 _flags |= F_bake_in_start;
78 check_stopped(get_class_type(),
"priv_initialize");
92 check_stopped(get_class_type(),
"priv_instant");
107 check_started(get_class_type(),
"priv_step");
109 double d = compute_delta(t);
114 if ((_flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale | F_end_shear)) != 0) {
133 if ((_flags & F_end_pos) != 0) {
134 if ((_flags & F_start_pos) != 0) {
137 }
else if ((_flags & F_bake_in_start) != 0) {
144 pos = transform->get_pos();
148 if ((_flags & F_end_hpr) != 0) {
149 if ((_flags & F_start_hpr) != 0) {
152 }
else if ((_flags & F_start_quat) != 0) {
153 _start_hpr = _start_quat.get_hpr();
154 _flags |= F_start_hpr;
157 }
else if ((_flags & F_bake_in_start) != 0) {
162 hpr = transform->get_hpr();
166 if ((_flags & F_end_quat) != 0) {
167 if ((_flags & F_slerp_setup) == 0) {
168 if ((_flags & F_start_quat) != 0) {
171 }
else if ((_flags & F_start_hpr) != 0) {
172 _start_quat.set_hpr(_start_hpr);
173 _flags |= F_start_quat;
176 }
else if ((_flags & F_bake_in_start) != 0) {
181 if (_prev_d == 1.0) {
182 _start_quat = _end_quat;
184 LQuaternion prev_value = transform->get_norm_quat();
185 _start_quat = (prev_value - _prev_d * _end_quat) / (1.0 - _prev_d);
191 _flags &= ~F_slerp_setup;
194 nassertv(_slerp !=
nullptr);
195 (this->*_slerp)(quat, d);
197 if ((_flags & F_end_scale) != 0) {
198 if ((_flags & F_start_scale) != 0) {
199 lerp_value(scale, d, _start_scale, _end_scale);
201 }
else if ((_flags & F_bake_in_start) != 0) {
203 lerp_value(scale, d, _start_scale, _end_scale);
206 scale = transform->get_scale();
210 if ((_flags & F_end_shear) != 0) {
211 if ((_flags & F_start_shear) != 0) {
212 lerp_value(shear, d, _start_shear, _end_shear);
214 }
else if ((_flags & F_bake_in_start) != 0) {
216 lerp_value(shear, d, _start_shear, _end_shear);
219 shear = transform->get_shear();
228 unsigned int transform_flags = _flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale);
229 switch (transform_flags) {
237 _node.set_pos(_other, pos);
265 case F_end_hpr | F_end_scale:
273 case F_end_quat | F_end_scale:
281 case F_end_pos | F_end_hpr:
289 case F_end_pos | F_end_quat:
297 case F_end_pos | F_end_scale:
298 if (transform->quat_given()) {
313 case F_end_pos | F_end_hpr | F_end_scale:
314 if ((_flags & F_end_shear) != 0) {
331 case F_end_pos | F_end_quat | F_end_scale:
332 if ((_flags & F_end_shear) != 0) {
352 <<
"Internal error in CLerpNodePathInterval::priv_step().\n";
354 if ((_flags & F_end_shear) != 0) {
356 if (transform_flags == (F_end_pos | F_end_hpr | F_end_scale) ||
357 transform_flags == (F_end_pos | F_end_quat | F_end_scale)) {
370 if ((_flags & F_fluid) != 0) {
374 _node.set_prev_transform(prev_transform);
377 if ((_flags & (F_end_color | F_end_color_scale | F_end_tex_offset | F_end_tex_rotate | F_end_tex_scale)) != 0) {
396 if ((_flags & F_end_color) != 0) {
399 if ((_flags & F_start_color) != 0) {
400 lerp_value(color, d, _start_color, _end_color);
404 color.set(1.0f, 1.0f, 1.0f, 1.0f);
406 state->get_attrib(ColorAttrib::get_class_type());
407 if (attrib !=
nullptr) {
417 state = state->add_attrib(ColorAttrib::make_flat(color), _override);
420 if ((_flags & F_end_color_scale) != 0) {
421 LVecBase4 color_scale;
423 if ((_flags & F_start_color_scale) != 0) {
424 lerp_value(color_scale, d, _start_color_scale, _end_color_scale);
428 color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
430 state->get_attrib(ColorScaleAttrib::get_class_type());
431 if (attrib !=
nullptr) {
439 state = state->add_attrib(ColorScaleAttrib::make(color_scale), _override);
442 if ((_flags & (F_end_tex_offset | F_end_tex_rotate | F_end_tex_scale)) != 0) {
447 state->get_attrib(TexMatrixAttrib::get_class_type());
449 if (attrib !=
nullptr) {
451 transform = tma->get_transform(_texture_stage);
456 if ((_flags & F_end_tex_offset) != 0) {
457 LVecBase2 tex_offset;
459 if ((_flags & F_start_tex_offset) != 0) {
460 lerp_value(tex_offset, d, _start_tex_offset, _end_tex_offset);
462 tex_offset = transform->get_pos2d();
467 transform = transform->set_pos2d(tex_offset);
470 if ((_flags & F_end_tex_rotate) != 0) {
471 PN_stdfloat tex_rotate;
473 if ((_flags & F_start_tex_rotate) != 0) {
474 lerp_value(tex_rotate, d, _start_tex_rotate, _end_tex_rotate);
476 tex_rotate = transform->get_rotate2d();
481 transform = transform->set_rotate2d(tex_rotate);
484 if ((_flags & F_end_tex_scale) != 0) {
487 if ((_flags & F_start_tex_scale) != 0) {
488 lerp_value(tex_scale, d, _start_tex_scale, _end_tex_scale);
490 tex_scale = transform->get_scale2d();
495 transform = transform->set_scale2d(tex_scale);
499 state = state->set_attrib(tma->add_stage(_texture_stage, transform, _override));
520 check_stopped(get_class_type(),
"priv_reverse_initialize");
535 check_stopped(get_class_type(),
"priv_reverse_initialize");
546 void CLerpNodePathInterval::
547 output(std::ostream &out)
const {
550 if ((_flags & F_end_pos) != 0) {
552 if ((_flags & F_start_pos) != 0) {
553 out <<
" from " << _start_pos;
555 out <<
" to " << _end_pos;
558 if ((_flags & F_end_hpr) != 0) {
560 if ((_flags & F_start_hpr) != 0) {
561 out <<
" from " << _start_hpr;
563 out <<
" to " << _end_hpr;
566 if ((_flags & F_end_quat) != 0) {
568 if ((_flags & F_start_quat) != 0) {
569 out <<
" from " << _start_quat;
571 out <<
" to " << _end_quat;
574 if ((_flags & F_end_scale) != 0) {
576 if ((_flags & F_start_scale) != 0) {
577 out <<
" from " << _start_scale;
579 out <<
" to " << _end_scale;
582 if ((_flags & F_end_shear) != 0) {
584 if ((_flags & F_start_shear) != 0) {
585 out <<
" from " << _start_shear;
587 out <<
" to " << _end_shear;
590 if ((_flags & F_end_color) != 0) {
592 if ((_flags & F_start_color) != 0) {
593 out <<
" from " << _start_color;
595 out <<
" to " << _end_color;
598 if ((_flags & F_end_color_scale) != 0) {
599 out <<
" color_scale";
600 if ((_flags & F_start_color_scale) != 0) {
601 out <<
" from " << _start_color_scale;
603 out <<
" to " << _end_color_scale;
614 void CLerpNodePathInterval::
616 if (_start_quat.dot(_end_quat) < 0.0f) {
618 _start_quat = -_start_quat;
621 _slerp_angle = _start_quat.angle_rad(_end_quat);
623 if (_slerp_angle < 0.1f) {
628 _slerp = &CLerpNodePathInterval::slerp_angle_0;
630 }
else if (_slerp_angle > 3.14) {
638 _slerp_c = (_start_quat + _end_quat);
639 _slerp_c.normalize();
640 _slerp_angle = _end_quat.angle_rad(_slerp_c);
641 _slerp_denom = csin(_slerp_angle);
643 _slerp = &CLerpNodePathInterval::slerp_angle_180;
647 _slerp_denom = csin(_slerp_angle);
648 _slerp = &CLerpNodePathInterval::slerp_basic;
651 nassertv(_slerp_denom != 0.0f);
652 _flags |= F_slerp_setup;
660 void CLerpNodePathInterval::
661 slerp_basic(LQuaternion &result, PN_stdfloat t)
const {
662 nassertv(_slerp_denom != 0.0f);
663 PN_stdfloat ti = 1.0f - t;
664 PN_stdfloat ta = t * _slerp_angle;
665 PN_stdfloat tia = ti * _slerp_angle;
667 if (interval_cat.is_spam()) {
669 <<
"slerp_basic, (t = " << t <<
"), angle = " << _slerp_angle <<
"\n"
670 <<
"_start_quat = " << _start_quat <<
", _end_quat = "
671 << _end_quat <<
", denom = " << _slerp_denom <<
"\n";
674 result = (csin(tia) * _start_quat + csin(ta) * _end_quat) / _slerp_denom;
675 nassertv(!result.is_nan());
682 void CLerpNodePathInterval::
683 slerp_angle_0(LQuaternion &result, PN_stdfloat t)
const {
684 nassertv(_slerp_denom != 0.0f);
685 PN_stdfloat ti = 1.0f - t;
686 PN_stdfloat ta = t * _slerp_angle;
687 PN_stdfloat tia = ti * _slerp_angle;
689 if (interval_cat.is_spam()) {
691 <<
"slerp_angle_0, (t = " << t <<
"), angle = " << _slerp_angle
692 <<
"\n_start_quat = " << _start_quat <<
", _end_quat = "
693 << _end_quat <<
", denom = " << _slerp_denom <<
"\n";
697 nassertv(!result.is_nan());
706 void CLerpNodePathInterval::
707 slerp_angle_180(LQuaternion &result, PN_stdfloat t)
const {
708 nassertv(_slerp_denom != 0.0f);
714 PN_stdfloat ti = 1.0f - t;
715 PN_stdfloat ta = t * _slerp_angle;
716 PN_stdfloat tia = ti * _slerp_angle;
718 if (interval_cat.is_spam()) {
720 <<
"slerp_angle_180, first half (t = " << t <<
"), angle = "
721 << _slerp_angle <<
"\n_start_quat = " << _start_quat
722 <<
", _slerp_c = " << _slerp_c <<
", denom = "
723 << _slerp_denom <<
"\n";
726 result = (csin(tia) * _start_quat + csin(ta) * _slerp_c) / _slerp_denom;
732 PN_stdfloat ti = 1.0f - t;
733 PN_stdfloat ta = t * _slerp_angle;
734 PN_stdfloat tia = ti * _slerp_angle;
736 if (interval_cat.is_spam()) {
738 <<
"slerp_angle_180, second half (t = " << t <<
"), angle = "
739 << _slerp_angle <<
"\n_slerp_c = " << _slerp_c
740 <<
", _end_quat = " << _end_quat <<
", denom = "
741 << _slerp_denom <<
"\n";
744 result = (csin(tia) * _slerp_c + csin(ta) * _end_quat) / _slerp_denom;
747 nassertv(!result.is_nan());