-
-
Notifications
You must be signed in to change notification settings - Fork 23.8k
Fix SkeletonModification2DTwoBoneIK with negative scales. #81051
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix SkeletonModification2DTwoBoneIK with negative scales. #81051
Conversation
b8b6998 to
48ff535
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, but it feels like you could keep the general else block from before commit then handle both cases at once:
- for the first line, a -1/+1 multiplier would do the trick
- the second line is always the same, could be preserved at end of else block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About the first point, you mean creating a variable to hold -1 ou 1, them multiplying angle_0 + joint_one_bone->get_bone_angle() by the variable? Can you show me what you mean?
About the second point, like this?
if (isnan(angle_0) || isnan(angle_1)) {
// We cannot solve for this angle! Do nothing to avoid setting the rotation (and scale) to NaN.
} else {
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());
}EDIT: I agree in letting the second line at the end of else block so I'm changing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, using a float multiplier like this:
float sign_multiplier = same_scale_sign ? -1.0f : 1.0f;
joint_one_bone->set_global_rotation(angle_atan + sign_multiplier * (angle_0 + joint_one_bone->get_bone_angle()));There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But looking at your comment below, else looks fine too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same remark here except you already got a big else block so you'd just have to use the sign multiplier to factorize.
Unless there's a particular policy on this file that developers prefer explicit full line operations with +/- rather than -1/+1 multipliers to make it easier to read? I haven't checked other math code so I don't know what style they picked.
EDIT: I'd say it is indeed very clear on this block because all the lines are uniform and the +/- symbols perfectly aligned; while above, the global_rotation and rotation lines are alternating so it's not that easy to spot what's different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm holding back with this because could impact the readability and I really want to maintain clear which is the main logic and which is the exception (different scales).
I don't think that would be easy to understand from something like this:
angle_atan + joint_one_bone->get_bone_angle() * rotation_dir
Or this:
angle_atan + (angle_0 + joint_one_bone->get_bone_angle()) * rotation_dir
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, you can keep the else case then. In this case, for consistency you can also keep the else case above and don't use a multiplier. You can add a comment indicating which one is the more rare case if you want.
48ff535 to
fc845ce
Compare
- Identifies when only one scale axis is negative and change the logic - Take in count scales when drawing gizmo - Fix typo
fc845ce to
3e02983
Compare
|
can this be pushed as patch update.. the ik bug is making the ik chain unusable |
|
I'm not actually happy with this solution (using |
| 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().abs().x, joint_two_bone->get_global_scale().abs().y); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is attempting to give scale to bones length and could probably be solving by calculating length with scale: #83397 (comment)
|
is there anything blocking this PR as of now? |
Is better to wait someone with knowledge like @TokageItLab to review |
|
Since TwoBoneIK is separated from any other node in the first place, so the change should be safe, at least from a code standpoint. Also, if this change is mainly dedicated to flips due to scaling, then there seems to be fine. I am a little concerned about whether it will work well when combined with the #91731 fix. If we can confirm that much, I think it is safe to merge. BTW, since the ModificationStack2D is experimental to begin with, so I think in the future it will be necessary to migrate into SkeletonModifier2D in the same way as the SkeletonModifier3D. |
|
Is this plan for 4.3 or 4.4? |
|
@TokageItLab We can review this for 4.4 |
|
The pull request became stale and requires a rebase. @SaracenOne, @TokageItLab, @fire and Cthulhu discussed this briefly at the animation meeting. We discussed the problems with using the scale to flip 2d and 3d animation in general. We wanted a proposal for modifying the godot human skeleton profile to add a hard-defined mirror boolean for regular and mirrored left hand to right hand. |
There is a list? All I know is that is not possible to differ 2D matrices that had X scaled by -1 from those that had Y scaled by -1 and rotate by 180º. At least not without a variable to store this information.
I don't understand how this would work under the hood. There is a change in "modification" logic? Or would be something like: if (!mirrored) {
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());
}Instead of my propose: 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());
} |
This doesn't make sense to me, or are you talking about skeleton2d mirror boolean, not human skeleton profile? Mirroring is required at runtime in almost any 2d skeleton. For left and right facing variants of each animation. Maybe I am not getting what this proposal would do/be about and how it would solve this problem. Sad to see this being stale |
|
Can this be merged in 4.5? If not, what specifically is blocking it? If the concern is only that it needs a rebase, I have already rebased this PR and #83330 locally in my custom build of Godot 4.5, and would be happy to contribute it back if desired. I don't understand the suggestion for a proposal. This PR does not add a new mirroring feature; it fixes a longstanding bug when Node2D transforms interact with Skeleton2Ds. I have verified that this fixes the issue in my project. Why would a proposal be needed for this bugfix? |
|
We really need this to be fixed... |
|
We really do. This PR used to basically fix the issue 99% of the time, but the original code changed too much and I'm too unfamiliar with the engine to rebase it now. At least there's a bunch of GDScript solutions for 2DIK |
|
I just saw @thiagola92's comment that they no longer plan to work on this PR. I have created a separate PR that rebases this one (#110298) per my previous comment -- please review/test and let me know if there are any issues. |
|
Superseded by #110298 |
Issues: #80252
This is an attempt to fix
SkeletonModification2DTwoBoneIKwhen only one scale is negative.Note: Last bone will be inverted due to issue #80643 (PR to fix this: #81048)