mirror of
https://github.com/godotengine/godot.git
synced 2026-02-07 19:32:36 +00:00
Merge pull request #115689 from TokageItLab/fix-look-at-mod
Fix LookAtModifier3D / AimModifier3D forward vector
This commit is contained in:
@@ -91,8 +91,9 @@
|
||||
<member name="primary_rotation_axis" type="int" setter="set_primary_rotation_axis" getter="get_primary_rotation_axis" enum="Vector3.Axis" default="1">
|
||||
The axis of the first rotation. This [SkeletonModifier3D] works by compositing the rotation by Euler angles to prevent to rotate the [member forward_axis].
|
||||
</member>
|
||||
<member name="relative" type="bool" setter="set_relative" getter="is_relative" default="true">
|
||||
<member name="relative" type="bool" setter="set_relative" getter="is_relative" default="false">
|
||||
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.
|
||||
</member>
|
||||
<member name="secondary_damp_threshold" type="float" setter="set_secondary_damp_threshold" getter="get_secondary_damp_threshold">
|
||||
The threshold to start damping for [member secondary_limit_angle].
|
||||
@@ -124,7 +125,7 @@
|
||||
</member>
|
||||
<member name="use_angle_limitation" type="bool" setter="set_use_angle_limitation" getter="is_using_angle_limitation" default="false">
|
||||
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.
|
||||
</member>
|
||||
<member name="use_secondary_rotation" type="bool" setter="set_use_secondary_rotation" getter="is_using_secondary_rotation" default="true">
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user