15 #include "cLerpNodePathInterval.h"
16 #include "lerp_helpers.h"
17 #include "transformState.h"
18 #include "renderState.h"
19 #include "colorAttrib.h"
20 #include "colorScaleAttrib.h"
21 #include "texMatrixAttrib.h"
23 #include "config_interval.h"
25 TypeHandle CLerpNodePathInterval::_type_handle;
60 CLerpInterval::BlendType blend_type,
61 bool bake_in_start,
bool fluid,
72 _flags |= F_bake_in_start;
90 check_stopped(get_class_type(),
"priv_initialize");
107 check_stopped(get_class_type(),
"priv_instant");
124 check_started(get_class_type(),
"priv_step");
126 double d = compute_delta(t);
131 if ((_flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale | F_end_shear)) != 0) {
133 CPT(TransformState) transform;
150 if ((_flags & F_end_pos) != 0) {
151 if ((_flags & F_start_pos) != 0) {
152 lerp_value(pos, d, _start_pos, _end_pos);
154 }
else if ((_flags & F_bake_in_start) != 0) {
157 lerp_value(pos, d, _start_pos, _end_pos);
161 pos = transform->get_pos();
162 lerp_value_from_prev(pos, d, _prev_d, pos, _end_pos);
165 if ((_flags & F_end_hpr) != 0) {
166 if ((_flags & F_start_hpr) != 0) {
167 lerp_value(hpr, d, _start_hpr, _end_hpr);
169 }
else if ((_flags & F_start_quat) != 0) {
170 _start_hpr = _start_quat.
get_hpr();
171 _flags |= F_start_hpr;
172 lerp_value(hpr, d, _start_hpr, _end_hpr);
174 }
else if ((_flags & F_bake_in_start) != 0) {
176 lerp_value(hpr, d, _start_hpr, _end_hpr);
179 hpr = transform->get_hpr();
180 lerp_value_from_prev(hpr, d, _prev_d, hpr, _end_hpr);
183 if ((_flags & F_end_quat) != 0) {
184 if ((_flags & F_slerp_setup) == 0) {
185 if ((_flags & F_start_quat) != 0) {
188 }
else if ((_flags & F_start_hpr) != 0) {
189 _start_quat.
set_hpr(_start_hpr);
190 _flags |= F_start_quat;
193 }
else if ((_flags & F_bake_in_start) != 0) {
198 if (_prev_d == 1.0) {
199 _start_quat = _end_quat;
202 _start_quat = (prev_value - _prev_d * _end_quat) / (1.0 - _prev_d);
208 _flags &= ~F_slerp_setup;
211 nassertv(_slerp != NULL);
212 (this->*_slerp)(quat, d);
214 if ((_flags & F_end_scale) != 0) {
215 if ((_flags & F_start_scale) != 0) {
216 lerp_value(scale, d, _start_scale, _end_scale);
218 }
else if ((_flags & F_bake_in_start) != 0) {
220 lerp_value(scale, d, _start_scale, _end_scale);
223 scale = transform->get_scale();
224 lerp_value_from_prev(scale, d, _prev_d, scale, _end_scale);
227 if ((_flags & F_end_shear) != 0) {
228 if ((_flags & F_start_shear) != 0) {
229 lerp_value(shear, d, _start_shear, _end_shear);
231 }
else if ((_flags & F_bake_in_start) != 0) {
233 lerp_value(shear, d, _start_shear, _end_shear);
236 shear = transform->get_shear();
237 lerp_value_from_prev(shear, d, _prev_d, shear, _end_shear);
246 unsigned int transform_flags = _flags & (F_end_pos | F_end_hpr | F_end_quat | F_end_scale);
247 switch (transform_flags) {
283 case F_end_hpr | F_end_scale:
291 case F_end_quat | F_end_scale:
299 case F_end_pos | F_end_hpr:
307 case F_end_pos | F_end_quat:
315 case F_end_pos | F_end_scale:
316 if (transform->quat_given()) {
331 case F_end_pos | F_end_hpr | F_end_scale:
332 if ((_flags & F_end_shear) != 0) {
349 case F_end_pos | F_end_quat | F_end_scale:
350 if ((_flags & F_end_shear) != 0) {
370 <<
"Internal error in CLerpNodePathInterval::priv_step().\n";
372 if ((_flags & F_end_shear) != 0) {
374 if (transform_flags == (F_end_pos | F_end_hpr | F_end_scale) ||
375 transform_flags == (F_end_pos | F_end_quat | F_end_scale)) {
388 if ((_flags & F_fluid) != 0) {
395 if ((_flags & (F_end_color | F_end_color_scale | F_end_tex_offset | F_end_tex_rotate | F_end_tex_scale)) != 0) {
414 if ((_flags & F_end_color) != 0) {
417 if ((_flags & F_start_color) != 0) {
418 lerp_value(color, d, _start_color, _end_color);
422 color.set(1.0f, 1.0f, 1.0f, 1.0f);
424 state->get_attrib(ColorAttrib::get_class_type());
432 lerp_value_from_prev(color, d, _prev_d, color, _end_color);
435 state = state->add_attrib(ColorAttrib::make_flat(color), _override);
438 if ((_flags & F_end_color_scale) != 0) {
441 if ((_flags & F_start_color_scale) != 0) {
442 lerp_value(color_scale, d, _start_color_scale, _end_color_scale);
446 color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
448 state->get_attrib(ColorScaleAttrib::get_class_type());
454 lerp_value_from_prev(color_scale, d, _prev_d, color_scale, _end_color_scale);
457 state = state->add_attrib(ColorScaleAttrib::make(color_scale), _override);
460 if ((_flags & (F_end_tex_offset | F_end_tex_rotate | F_end_tex_scale)) != 0) {
462 CPT(TransformState) transform = TransformState::make_identity();
465 state->get_attrib(TexMatrixAttrib::get_class_type());
469 transform = tma->get_transform(_texture_stage);
474 if ((_flags & F_end_tex_offset) != 0) {
477 if ((_flags & F_start_tex_offset) != 0) {
478 lerp_value(tex_offset, d, _start_tex_offset, _end_tex_offset);
480 tex_offset = transform->get_pos2d();
481 lerp_value_from_prev(tex_offset, d, _prev_d, tex_offset,
485 transform = transform->set_pos2d(tex_offset);
488 if ((_flags & F_end_tex_rotate) != 0) {
489 PN_stdfloat tex_rotate;
491 if ((_flags & F_start_tex_rotate) != 0) {
492 lerp_value(tex_rotate, d, _start_tex_rotate, _end_tex_rotate);
494 tex_rotate = transform->get_rotate2d();
495 lerp_value_from_prev(tex_rotate, d, _prev_d, tex_rotate,
499 transform = transform->set_rotate2d(tex_rotate);
502 if ((_flags & F_end_tex_scale) != 0) {
505 if ((_flags & F_start_tex_scale) != 0) {
506 lerp_value(tex_scale, d, _start_tex_scale, _end_tex_scale);
508 tex_scale = transform->get_scale2d();
509 lerp_value_from_prev(tex_scale, d, _prev_d, tex_scale,
513 transform = transform->set_scale2d(tex_scale);
517 state = state->set_attrib(tma->add_stage(_texture_stage, transform, _override));
541 check_stopped(get_class_type(),
"priv_reverse_initialize");
559 check_stopped(get_class_type(),
"priv_reverse_initialize");
572 void CLerpNodePathInterval::
573 output(ostream &out)
const {
576 if ((_flags & F_end_pos) != 0) {
578 if ((_flags & F_start_pos) != 0) {
579 out <<
" from " << _start_pos;
581 out <<
" to " << _end_pos;
584 if ((_flags & F_end_hpr) != 0) {
586 if ((_flags & F_start_hpr) != 0) {
587 out <<
" from " << _start_hpr;
589 out <<
" to " << _end_hpr;
592 if ((_flags & F_end_quat) != 0) {
594 if ((_flags & F_start_quat) != 0) {
595 out <<
" from " << _start_quat;
597 out <<
" to " << _end_quat;
600 if ((_flags & F_end_scale) != 0) {
602 if ((_flags & F_start_scale) != 0) {
603 out <<
" from " << _start_scale;
605 out <<
" to " << _end_scale;
608 if ((_flags & F_end_shear) != 0) {
610 if ((_flags & F_start_shear) != 0) {
611 out <<
" from " << _start_shear;
613 out <<
" to " << _end_shear;
616 if ((_flags & F_end_color) != 0) {
618 if ((_flags & F_start_color) != 0) {
619 out <<
" from " << _start_color;
621 out <<
" to " << _end_color;
624 if ((_flags & F_end_color_scale) != 0) {
625 out <<
" color_scale";
626 if ((_flags & F_start_color_scale) != 0) {
627 out <<
" from " << _start_color_scale;
629 out <<
" to " << _end_color_scale;
643 void CLerpNodePathInterval::
645 if (_start_quat.dot(_end_quat) < 0.0f) {
647 _start_quat = -_start_quat;
650 _slerp_angle = _start_quat.
angle_rad(_end_quat);
652 if (_slerp_angle < 0.1f) {
656 _slerp_denom = csin_over_x(_slerp_angle);
657 _slerp = &CLerpNodePathInterval::slerp_angle_0;
659 }
else if (_slerp_angle > 3.14) {
668 _slerp_c = (_start_quat + _end_quat);
669 _slerp_c.normalize();
670 _slerp_angle = _end_quat.
angle_rad(_slerp_c);
671 _slerp_denom = csin(_slerp_angle);
673 _slerp = &CLerpNodePathInterval::slerp_angle_180;
678 _slerp_denom = csin(_slerp_angle);
679 _slerp = &CLerpNodePathInterval::slerp_basic;
682 nassertv(_slerp_denom != 0.0f);
683 _flags |= F_slerp_setup;
693 void CLerpNodePathInterval::
694 slerp_basic(
LQuaternion &result, PN_stdfloat t)
const {
695 nassertv(_slerp_denom != 0.0f);
696 PN_stdfloat ti = 1.0f - t;
697 PN_stdfloat ta = t * _slerp_angle;
698 PN_stdfloat tia = ti * _slerp_angle;
700 if (interval_cat.is_spam()) {
702 <<
"slerp_basic, (t = " << t <<
"), angle = " << _slerp_angle <<
"\n"
703 <<
"_start_quat = " << _start_quat <<
", _end_quat = "
704 << _end_quat <<
", denom = " << _slerp_denom <<
"\n";
707 result = (csin(tia) * _start_quat + csin(ta) * _end_quat) / _slerp_denom;
708 nassertv(!result.
is_nan());
718 void CLerpNodePathInterval::
719 slerp_angle_0(
LQuaternion &result, PN_stdfloat t)
const {
720 nassertv(_slerp_denom != 0.0f);
721 PN_stdfloat ti = 1.0f - t;
722 PN_stdfloat ta = t * _slerp_angle;
723 PN_stdfloat tia = ti * _slerp_angle;
725 if (interval_cat.is_spam()) {
727 <<
"slerp_angle_0, (t = " << t <<
"), angle = " << _slerp_angle
728 <<
"\n_start_quat = " << _start_quat <<
", _end_quat = "
729 << _end_quat <<
", denom = " << _slerp_denom <<
"\n";
732 result = (csin_over_x(tia) * ti * _start_quat + csin_over_x(ta) * t * _end_quat) / _slerp_denom;
733 nassertv(!result.
is_nan());
744 void CLerpNodePathInterval::
745 slerp_angle_180(
LQuaternion &result, PN_stdfloat t)
const {
746 nassertv(_slerp_denom != 0.0f);
752 PN_stdfloat ti = 1.0f - t;
753 PN_stdfloat ta = t * _slerp_angle;
754 PN_stdfloat tia = ti * _slerp_angle;
756 if (interval_cat.is_spam()) {
758 <<
"slerp_angle_180, first half (t = " << t <<
"), angle = "
759 << _slerp_angle <<
"\n_start_quat = " << _start_quat
760 <<
", _slerp_c = " << _slerp_c <<
", denom = "
761 << _slerp_denom <<
"\n";
764 result = (csin(tia) * _start_quat + csin(ta) * _slerp_c) / _slerp_denom;
770 PN_stdfloat ti = 1.0f - t;
771 PN_stdfloat ta = t * _slerp_angle;
772 PN_stdfloat tia = ti * _slerp_angle;
774 if (interval_cat.is_spam()) {
776 <<
"slerp_angle_180, second half (t = " << t <<
"), angle = "
777 << _slerp_angle <<
"\n_slerp_c = " << _slerp_c
778 <<
", _end_quat = " << _end_quat <<
", denom = "
779 << _slerp_denom <<
"\n";
782 result = (csin(tia) * _slerp_c + csin(ta) * _end_quat) / _slerp_denom;
785 nassertv(!result.
is_nan());
void set_start_scale(const LVecBase3 &scale)
Indicates the initial scale of the lerped node.
void set_start_shear(const LVecBase3 &shear)
Indicates the initial shear of the lerped node.
void set_start_hpr(const LVecBase3 &hpr)
Indicates the initial rotation of the lerped node.
virtual void priv_initialize(double t)
This replaces the first call to priv_step(), and indicates that the interval has just begun...
const RenderState * get_state(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete state object set on this node.
This is the base class for all three-component vectors and points.
void set_hpr_scale(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r, PN_stdfloat sx, PN_stdfloat sy, PN_stdfloat sz)
Sets the rotation and scale components of the transform, leaving translation untouched.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
void set_pos_hpr(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r)
Sets the translation and rotation component of the transform, leaving scale untouched.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
void set_scale(PN_stdfloat scale)
Sets the scale component of the transform, leaving translation and rotation untouched.
void set_start_quat(const LQuaternion &quat)
Indicates the initial rotation of the lerped node.
const string & get_name() const
Returns the interval's name.
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
void set_quat_scale(const LQuaternion &quat, const LVecBase3 &scale)
Sets the rotation and scale components of the transform, leaving translation untouched.
void set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the translation component of the transform, leaving rotation and scale untouched.
void set_pos_quat(const LVecBase3 &pos, const LQuaternion &quat)
Sets the translation and rotation component of the transform, leaving scale untouched.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Type get_color_type() const
Returns the type of color specified by this ColorAttrib.
void set_pos_quat_scale_shear(const LVecBase3 &pos, const LQuaternion &quat, const LVecBase3 &scale, const LVecBase3 &shear)
Completely replaces the transform with new translation, rotation, scale, and shear components...
double get_duration() const
Returns the duration of the interval in seconds.
void set_pos_quat_scale(const LVecBase3 &pos, const LQuaternion &quat, const LVecBase3 &scale)
Replaces the translation, rotation, and scale components, implicitly setting shear to 0...
const LColor & get_color() const
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
void set_quat(const LQuaternion &quat)
Sets the rotation component of the transform, leaving translation and scale untouched.
virtual void priv_reverse_initialize(double t)
Similar to priv_initialize(), but this is called when the interval is being played backwards; it indi...
const LVecBase4 & get_scale() const
Returns the scale to be applied to colors.
This is the base class for all two-component vectors and points.
virtual void priv_step(double t)
Advances the time on the interval.
void set_hpr(const LVecBase3f &hpr, CoordinateSystem cs=CS_default)
Sets the quaternion as the unit quaternion that is equivalent to these Euler angles.
Applies a scale to colors in the scene graph and on vertices.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
CLerpNodePathInterval(const string &name, double duration, BlendType blend_type, bool bake_in_start, bool fluid, const NodePath &node, const NodePath &other)
Constructs a lerp interval that will lerp some properties on the indicated node, possibly relative to...
This is the base class for all three-component vectors and points.
Applies a transform matrix to UV's before they are rendered.
void set_shear(PN_stdfloat shxy, PN_stdfloat shxz, PN_stdfloat shyz)
Sets the shear component of the transform, leaving translation, rotation, and scale untouched...
void set_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r)
Sets the rotation component of the transform, leaving translation and scale untouched.
void set_pos_hpr_scale_shear(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale, const LVecBase3 &shear)
Completely replaces the transform with new translation, rotation, scale, and shear components...
This is the base quaternion class.
float angle_rad(const LQuaternionf &other) const
Returns the angle between the orientation represented by this quaternion and the other one...
bool is_empty() const
Returns true if the NodePath contains no nodes.
Indicates what color should be applied to renderable geometry.
void set_start_pos(const LVecBase3 &pos)
Indicates the initial position of the lerped node.
void set_pos_hpr_scale(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r, PN_stdfloat sx, PN_stdfloat sy, PN_stdfloat sz)
Completely replaces the transform with new translation, rotation, and scale components.
void set_prev_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Sets the transform that represents this node's "previous" position, one frame ago, for the purposes of detecting motion for accurate collision calculations.
TypeHandle is the identifier used to differentiate C++ class types.
Defines the properties of a named stage of the multitexture pipeline.
LVecBase3f get_hpr(CoordinateSystem cs=CS_default) const
Extracts the equivalent Euler angles from the unit quaternion.
const TransformState * get_prev_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the transform that has been set as this node's "previous" position.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
void set_state(const RenderState *state, Thread *current_thread=Thread::get_current_thread())
Changes the complete state object on this node.
virtual void priv_reverse_instant()
This is called in lieu of priv_reverse_initialize()
The base class for a family of intervals that linearly interpolate one or more numeric values over ti...
virtual void priv_instant()
This is called in lieu of priv_initialize() .