mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
Fixed Skeleton2D TwoBoneIK and LookAt mirroring
Co-authored-by: thiagola92 <thiagola92@gmail.com>
This commit is contained in:
parent
3c7f9b9372
commit
bc0eba5296
2 changed files with 42 additions and 30 deletions
|
@ -141,37 +141,32 @@ void SkeletonModification2DLookAt::_execute(float p_delta) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform2D operation_transform = operation_bone->get_global_transform();
|
real_t angle_to_target = operation_bone->get_angle_to(target_node_reference->get_global_position());
|
||||||
Transform2D target_trans = target_node_reference->get_global_transform();
|
|
||||||
|
|
||||||
// Look at the target!
|
// Account for the direction the bone faces in
|
||||||
operation_transform = operation_transform.looking_at(target_trans.get_origin());
|
angle_to_target -= operation_bone->get_bone_angle();
|
||||||
// Apply whatever scale it had prior to looking_at
|
|
||||||
operation_transform.set_scale(operation_bone->get_global_scale());
|
|
||||||
|
|
||||||
// Account for the direction the bone faces in:
|
|
||||||
operation_transform.set_rotation(operation_transform.get_rotation() - operation_bone->get_bone_angle());
|
|
||||||
|
|
||||||
// Apply additional rotation
|
// Apply additional rotation
|
||||||
operation_transform.set_rotation(operation_transform.get_rotation() + additional_rotation);
|
angle_to_target += additional_rotation;
|
||||||
|
|
||||||
// Apply constraints in globalspace:
|
if (enable_constraint) {
|
||||||
if (enable_constraint && !constraint_in_localspace) {
|
real_t new_angle = angle_to_target;
|
||||||
operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), constraint_angle_min, constraint_angle_max, constraint_angle_invert));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert from a global transform to a local transform via the Bone2D node
|
if (constraint_in_localspace) {
|
||||||
operation_bone->set_global_transform(operation_transform);
|
new_angle += operation_bone->get_rotation();
|
||||||
operation_transform = operation_bone->get_transform();
|
new_angle = clamp_angle(new_angle, constraint_angle_min, constraint_angle_max, constraint_angle_invert);
|
||||||
|
operation_bone->set_rotation(new_angle);
|
||||||
// Apply constraints in localspace:
|
} else {
|
||||||
if (enable_constraint && constraint_in_localspace) {
|
new_angle += operation_bone->get_global_rotation();
|
||||||
operation_transform.set_rotation(clamp_angle(operation_transform.get_rotation(), constraint_angle_min, constraint_angle_max, constraint_angle_invert));
|
new_angle = clamp_angle(new_angle, constraint_angle_min, constraint_angle_max, constraint_angle_invert);
|
||||||
|
operation_bone->set_global_rotation(new_angle);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
operation_bone->rotate(angle_to_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the local pose override, and to make sure child bones are also updated, set the transform of the bone.
|
// Set the local pose override, and to make sure child bones are also updated, set the transform of the bone.
|
||||||
stack->skeleton->set_bone_local_pose_override(bone_idx, operation_transform, stack->strength, true);
|
stack->skeleton->set_bone_local_pose_override(bone_idx, operation_bone->get_transform(), stack->strength, true);
|
||||||
operation_bone->set_transform(operation_transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonModification2DLookAt::_setup_modification(SkeletonModificationStack2D *p_stack) {
|
void SkeletonModification2DLookAt::_setup_modification(SkeletonModificationStack2D *p_stack) {
|
||||||
|
|
|
@ -142,7 +142,7 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adopted from the links below:
|
// Adapted from the links below:
|
||||||
// http://theorangeduck.com/page/simple-two-joint
|
// http://theorangeduck.com/page/simple-two-joint
|
||||||
// https://www.alanzucconi.com/2018/05/02/ik-2d-2/
|
// https://www.alanzucconi.com/2018/05/02/ik-2d-2/
|
||||||
// With modifications by TwistedTwigleg
|
// With modifications by TwistedTwigleg
|
||||||
|
@ -150,9 +150,10 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) {
|
||||||
float joint_one_to_target = target_difference.length();
|
float joint_one_to_target = target_difference.length();
|
||||||
float angle_atan = target_difference.angle();
|
float angle_atan = target_difference.angle();
|
||||||
|
|
||||||
float bone_one_length = joint_one_bone->get_length() * MIN(joint_one_bone->get_global_scale().x, joint_one_bone->get_global_scale().y);
|
float bone_one_length = joint_one_bone->get_length() * MIN(joint_one_bone->get_global_scale().abs().x, joint_one_bone->get_global_scale().abs().y);
|
||||||
float bone_two_length = joint_two_bone->get_length() * MIN(joint_two_bone->get_global_scale().x, joint_two_bone->get_global_scale().y);
|
float bone_two_length = joint_two_bone->get_length() * MIN(joint_two_bone->get_global_scale().abs().x, joint_two_bone->get_global_scale().abs().y);
|
||||||
bool override_angles_due_to_out_of_range = false;
|
bool override_angles_due_to_out_of_range = false;
|
||||||
|
bool same_scale_sign = true;
|
||||||
|
|
||||||
if (joint_one_to_target < target_minimum_distance) {
|
if (joint_one_to_target < target_minimum_distance) {
|
||||||
joint_one_to_target = target_minimum_distance;
|
joint_one_to_target = target_minimum_distance;
|
||||||
|
@ -165,6 +166,10 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) {
|
||||||
override_angles_due_to_out_of_range = true;
|
override_angles_due_to_out_of_range = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (joint_one_bone->get_global_scale().sign().x != joint_one_bone->get_global_scale().sign().y) {
|
||||||
|
same_scale_sign = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!override_angles_due_to_out_of_range) {
|
if (!override_angles_due_to_out_of_range) {
|
||||||
float angle_0 = Math::acos(((joint_one_to_target * joint_one_to_target) + (bone_one_length * bone_one_length) - (bone_two_length * bone_two_length)) / (2.0 * joint_one_to_target * bone_one_length));
|
float angle_0 = Math::acos(((joint_one_to_target * joint_one_to_target) + (bone_one_length * bone_one_length) - (bone_two_length * bone_two_length)) / (2.0 * joint_one_to_target * bone_one_length));
|
||||||
float angle_1 = Math::acos(((bone_two_length * bone_two_length) + (bone_one_length * bone_one_length) - (joint_one_to_target * joint_one_to_target)) / (2.0 * bone_two_length * bone_one_length));
|
float angle_1 = Math::acos(((bone_two_length * bone_two_length) + (bone_one_length * bone_one_length) - (joint_one_to_target * joint_one_to_target)) / (2.0 * bone_two_length * bone_one_length));
|
||||||
|
@ -177,12 +182,23 @@ void SkeletonModification2DTwoBoneIK::_execute(float p_delta) {
|
||||||
if (std::isnan(angle_0) || std::isnan(angle_1)) {
|
if (std::isnan(angle_0) || std::isnan(angle_1)) {
|
||||||
// We cannot solve for this angle! Do nothing to avoid setting the rotation (and scale) to NaN.
|
// We cannot solve for this angle! Do nothing to avoid setting the rotation (and scale) to NaN.
|
||||||
} else {
|
} else {
|
||||||
joint_one_bone->set_global_rotation(angle_atan - angle_0 - joint_one_bone->get_bone_angle());
|
if (same_scale_sign) {
|
||||||
|
joint_one_bone->set_global_rotation(angle_atan - angle_0 - joint_one_bone->get_bone_angle());
|
||||||
|
} else {
|
||||||
|
joint_one_bone->set_global_rotation(angle_atan + angle_0 + joint_one_bone->get_bone_angle());
|
||||||
|
}
|
||||||
|
|
||||||
joint_two_bone->set_rotation(-Math::PI - angle_1 - joint_two_bone->get_bone_angle() + joint_one_bone->get_bone_angle());
|
joint_two_bone->set_rotation(-Math::PI - angle_1 - joint_two_bone->get_bone_angle() + joint_one_bone->get_bone_angle());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
joint_one_bone->set_global_rotation(angle_atan - joint_one_bone->get_bone_angle());
|
if (same_scale_sign) {
|
||||||
joint_two_bone->set_global_rotation(angle_atan - joint_two_bone->get_bone_angle());
|
joint_one_bone->set_global_rotation(angle_atan - joint_one_bone->get_bone_angle());
|
||||||
|
joint_two_bone->set_global_rotation(angle_atan - joint_two_bone->get_bone_angle());
|
||||||
|
} else {
|
||||||
|
joint_one_bone->set_global_rotation(angle_atan + joint_one_bone->get_bone_angle());
|
||||||
|
joint_two_bone->set_global_rotation(angle_atan + joint_two_bone->get_bone_angle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, joint_one_bone->get_transform(), stack->strength, true);
|
stack->skeleton->set_bone_local_pose_override(joint_one_bone_idx, joint_one_bone->get_transform(), stack->strength, true);
|
||||||
|
@ -211,7 +227,8 @@ void SkeletonModification2DTwoBoneIK::_draw_editor_gizmo() {
|
||||||
}
|
}
|
||||||
stack->skeleton->draw_set_transform(
|
stack->skeleton->draw_set_transform(
|
||||||
stack->skeleton->to_local(operation_bone_one->get_global_position()),
|
stack->skeleton->to_local(operation_bone_one->get_global_position()),
|
||||||
operation_bone_one->get_global_rotation() - stack->skeleton->get_global_rotation());
|
operation_bone_one->get_global_rotation() - stack->skeleton->get_global_rotation(),
|
||||||
|
operation_bone_one->get_global_scale());
|
||||||
|
|
||||||
Color bone_ik_color = Color(1.0, 0.65, 0.0, 0.4);
|
Color bone_ik_color = Color(1.0, 0.65, 0.0, 0.4);
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue