Skip to content
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

BoneAttachments do not take into account IK #48188

Closed
setzer22 opened this issue Apr 25, 2021 · 6 comments
Closed

BoneAttachments do not take into account IK #48188

setzer22 opened this issue Apr 25, 2021 · 6 comments

Comments

@setzer22
Copy link

setzer22 commented Apr 25, 2021

Godot version:
3.3.stable

OS/device including version:
GNU/Linux

Issue description:
BoneAttachments do not play well with IK. If IK updates bones, it does so by setting the global_pose_override. However, bone attachments do not look at this value and instead keep using the original global_pose.

This is an issue for example when games want to have an arm controlled by IK, and at the same time have an item attached to the end of that arm.

EDIT: I initially thought the issue was here. But after looking a bit more into the code, it seems the value of global_pos is mutated, and set to the value of global_pos_override, so I don't understand where the issue is.

I've had a quick line at the source, and this line is the culprit:

sp->set_transform(b.pose_global);

Here, instead of b.pose_global, it should be interpolating with b.global_pose_override when that's set. Ideally, it should follow the exact same logic used here for the interpolation:

if (b.global_pose_override_amount >= 0.999) {

Steps to reproduce:

  1. Add an animated 3D model to the scene.
  2. Add a BoneAttachment and make it point to one of the bones. Add a child cube to the attachment object.
  3. Setup a SkeletonIK so that the attached bone will move.
  4. Move around the IK target.

Here, the object should be moving together with the bones at their current position (affected by IK), but instead it's moving to the old bone position (as if it was unaffected by IK).

Discussion

A fix for this looks easy enough and I will attempt it myself if nobody else is interested in working on it. But I'd like to ask first whether you consider this an acceptable contribution before I take the time to submit a PR.

@akien-mga
Copy link
Member

@TwistedTwigleg
Copy link
Contributor

If possible, can you share a minimum reproduction project showing the issue? I have tested BoneAttachment3D nodes (Godot 4.0 - though SkeletonIK code should be the same) and they have been in sync for me. I will test in Godot 3.3 though, as perhaps the issue is just 3.3 specific.

If the issue is that the first/root bone in the IK chain has twist rotation out of alignment, #48166 may fix the issue if the skeleton you are using has a -Z bone forward direction.

@TwistedTwigleg
Copy link
Contributor

I just tested an animated skeleton in Godot 3.3, and BoneAttachment nodes are correctly positioned and in sync for me.

@smix8
Copy link
Contributor

smix8 commented Apr 25, 2021

Can't reproduce this issue with my own test skeletons.

Bone attachment uses the skeleton bone global pose on each update for its own position.

The bone global pose is automatically updated by the SkeletonIK with the global_pose_override while active, they are the same after the update.

One possible explanation for this issue could be that something else (script or other node) is resetting or removing the global_pose_override overrwite on the current frame. If your bone attachment is processing before the SkeletonIK node in your SceneTree it will use the normal global pose and be placed at the wrong position.

@setzer22
Copy link
Author

Thanks for the feedback. Something must be off in my particular setup that's triggering this issue then. I couldn't "not reproduce this" on any of my attempts. I'll upload a reproduction project later today 😅

One possible explanation for this issue could be that something else (script or other node) is resetting or removing the global_pose_override overrwite on the current frame. If your bone attachment is processing before the SkeletonIK node in your SceneTree it will use the normal global pose and be placed at the wrong position.

This looked promising. Indeed, my SkeletonIK node was after the BoneAttachment node in the scene tree. However, I switched their order, and even tried playing with their process priority and I still can't get the right behaviour.

@setzer22
Copy link
Author

setzer22 commented Apr 26, 2021

I found the issue. It's not a bug in Godot, but rather an incompatibility with the way I set up my skeletons. There's an extra bone on the character's hand to tweak held item locations. However, this bone is not parented to hierarchy, but rather using a constraint in Blender. Bone constraints don't export to Godot, so the parenting was lost (or rather, baked into the animations). This is why it appeared as if IK was being ignored: The IK solver was moving a bone and I was expecting the child to follow, but the child wasn't actually a child.

Again, this has nothing to do with Godot per se, so I'll just close the issue. Thank you very much for your suggestions and help! 😄

@akien-mga akien-mga added archived and removed bug labels Apr 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants