diff --git a/doc/classes/LookAtModifier3D.xml b/doc/classes/LookAtModifier3D.xml index 48f9d4b970f..1d458ef2363 100644 --- a/doc/classes/LookAtModifier3D.xml +++ b/doc/classes/LookAtModifier3D.xml @@ -91,8 +91,9 @@ The axis of the first rotation. This [SkeletonModifier3D] works by compositing the rotation by Euler angles to prevent to rotate the [member forward_axis]. - + The relative option. If [code]true[/code], the rotation is applied relative to the pose. If [code]false[/code], the rotation is applied relative to the rest. It means to replace the current pose with the [LookAtModifier3D]'s result. + [b]Note:[/b] This option affects the base angle for [member use_angle_limitation] unlike [IterateIK3D]'s [JointLimitation3D]. Since the [LookAtModifier3D] relies strongly on Euler rotation, the axis that determines the limitation and the actual rotation are strongly tied together. The threshold to start damping for [member secondary_limit_angle]. @@ -124,7 +125,7 @@ If [code]true[/code], limits the amount of rotation. For example, this helps to prevent a character's neck from rotating 360 degrees. - [b]Note:[/b] As with [AnimationTree] blending, interpolation is provided that favors [method Skeleton3D.get_bone_rest]. This means that interpolation does not select the shortest path in some cases. + [b]Note:[/b] As with [AnimationTree] blending, interpolation is provided that favors [method Skeleton3D.get_bone_rest] or [method Skeleton3D.get_bone_pose] depends on the [member relative] option. This means that interpolation does not select the shortest path in some cases. [b]Note:[/b] Some values for [member transition_type] (such as [constant Tween.TRANS_BACK], [constant Tween.TRANS_ELASTIC], and [constant Tween.TRANS_SPRING]) may exceed the limitations. If interpolation occurs while overshooting the limitations, the result might not respect the bone rest. diff --git a/scene/3d/aim_modifier_3d.cpp b/scene/3d/aim_modifier_3d.cpp index 931a0683caf..fc7dfe73037 100644 --- a/scene/3d/aim_modifier_3d.cpp +++ b/scene/3d/aim_modifier_3d.cpp @@ -204,8 +204,9 @@ void AimModifier3D::_process_constraint_by_node(int p_index, Skeleton3D *p_skele if (!nd) { return; } - Vector3 reference_origin = nd->get_global_transform_interpolated().origin - p_skeleton->get_global_transform_interpolated().origin; - _process_aim(p_index, p_skeleton, p_apply_bone, reference_origin, p_amount); + Transform3D skel_tr = p_skeleton->get_global_transform_interpolated(); + Vector3 reference_origin = nd->get_global_transform_interpolated().origin - skel_tr.origin; + _process_aim(p_index, p_skeleton, p_apply_bone, skel_tr.basis.get_rotation_quaternion().xform_inv(reference_origin), p_amount); } void AimModifier3D::_process_aim(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, Vector3 p_target, float p_amount) { diff --git a/scene/3d/look_at_modifier_3d.cpp b/scene/3d/look_at_modifier_3d.cpp index e02197cced4..e03ef428d55 100644 --- a/scene/3d/look_at_modifier_3d.cpp +++ b/scene/3d/look_at_modifier_3d.cpp @@ -559,6 +559,7 @@ void LookAtModifier3D::_process_modification(double p_delta) { forward_vector = Vector3(0, 0, 0); // The zero-vector to be used for checking in the line immediately below to avoid animation glitch. } else { destination = look_at_with_axes(bone_rest).basis.get_rotation_quaternion(); + forward_vector = bone_rest.basis.xform_inv(forward_vector_nrm); // Forward vector in the "current" bone rest. } } @@ -574,18 +575,17 @@ void LookAtModifier3D::_process_modification(double p_delta) { init_transition(); } else if (is_flippable && std::signbit(prev_forward_vector[secondary_rotation_axis]) != std::signbit(forward_vector[secondary_rotation_axis])) { // Flipping by angle_limitation can be detected by sign of secondary rotation axes during forward_vector is rotated more than 90 degree from forward_axis (means dot production is negative). - Vector3 prev_forward_vector_nrm = forward_vector.normalized(); Vector3 rest_forward_vector = get_vector_from_bone_axis(forward_axis); if (symmetry_limitation) { if ((is_not_max_influence || !Math::is_equal_approx(primary_limit_angle, (float)Math::TAU)) && - prev_forward_vector_nrm.dot(rest_forward_vector) < 0 && - forward_vector_nrm.dot(rest_forward_vector) < 0) { + prev_forward_vector.dot(rest_forward_vector) < 0 && + forward_vector.dot(rest_forward_vector) < 0) { init_transition(); } } else { if ((is_not_max_influence || !Math::is_equal_approx(primary_positive_limit_angle + primary_negative_limit_angle, (float)Math::TAU)) && - prev_forward_vector_nrm.dot(rest_forward_vector) < 0 && - forward_vector_nrm.dot(rest_forward_vector) < 0) { + prev_forward_vector.dot(rest_forward_vector) < 0 && + forward_vector.dot(rest_forward_vector) < 0) { init_transition(); } } @@ -596,7 +596,7 @@ void LookAtModifier3D::_process_modification(double p_delta) { remaining = MAX(0, remaining - time_step * p_delta); if (is_flippable) { // Interpolate through the rest same as AnimationTree blending for preventing to penetrate the bone into the body. - Quaternion rest = skeleton->get_bone_rest(bone).basis.get_rotation_quaternion(); + Quaternion rest = bone_rest.basis.get_rotation_quaternion(); float weight = Tween::run_equation(transition_type, ease_type, 1 - remaining, 0.0, 1.0, 1.0); destination = Animation::interpolate_via_rest(Animation::interpolate_via_rest(rest, from_q, 1 - weight, rest), destination, weight, rest); } else { diff --git a/scene/3d/look_at_modifier_3d.h b/scene/3d/look_at_modifier_3d.h index fea1e99b4ad..e4110ebc2f6 100644 --- a/scene/3d/look_at_modifier_3d.h +++ b/scene/3d/look_at_modifier_3d.h @@ -53,7 +53,7 @@ private: Vector3::Axis primary_rotation_axis = Vector3::AXIS_Y; Vector3::Axis secondary_rotation_axis = Vector3::AXIS_X; bool use_secondary_rotation = true; - bool relative = true; + bool relative = false; OriginFrom origin_from = ORIGIN_FROM_SELF; String origin_bone_name;