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

global_pose_to_local_pose function in Skeleton3D node not working properly #53895

Closed
TwistedTwigleg opened this issue Oct 16, 2021 · 2 comments · Fixed by #53821
Closed

global_pose_to_local_pose function in Skeleton3D node not working properly #53895

TwistedTwigleg opened this issue Oct 16, 2021 · 2 comments · Fixed by #53821

Comments

@TwistedTwigleg
Copy link
Contributor

Godot version

4.0 (#53821)

System information

Ubuntu Linux, Vulkan

Issue description

The global_pose_to_local_pose function in the Skeleton3D no longer works correctly. Previously, if you passed a valid global position it would convert and give you a usable pose for set_local_pose_override, however this is no longer the case. Something in the recent skeletons changes (I think in #53765) seems to have broken the function and it's conversion.

It seems to be mostly an issue with local overrides on top of local overrides, as the effect gets more and more compounded.

This was discovered in #53821 while working on getting the IK system to work with the skeleton changes.

Steps to reproduce

  • Get a Spatial node
  • Convert the spatial node global transform to a global pose using world_transform_to_global_pose
  • Convert the global pose to a local pose using global_pose_to_local_pose
  • Set it to the bone using set_bone_local_pose_override (seems to work as expected)
  • Get another spatial node
  • Convert the second spatial node's global transform to a global pose using world_transform_to_global_pose
  • Convert the second global pose to a local pose using global_pose_to_local_pose
  • Set it to the second bone using set_bone_local_pose_override
  • Notice it doesn't place the bone at the expected position, despite the conversion functions being called.
  • To confirm the global poses are valid, use set_global_pose_override and use the global poses. You get the expected result.

Based on my recent testing, it seems multiplying the by the affine inverse of the local_pose fixes the issue. However, this shouldn't be needed as the global_pose_to_local_pose should handle any conversions necessary to convert a valid global pose to a valid local pose, without the user needing to perform additional steps or know to multiply by the inverse of the local pose of the parent bone.

  • To fix, multiply the local pose returned by the global_pose_to_local_pose function by get_bone_global_pose(parent_bone_id_here).affine_inverse().

Minimal reproduction project

LocalPose_Bug.zip

@TwistedTwigleg
Copy link
Contributor Author

Now that I know multiplying by the inverse of the parent global pose works, it may be a really simple adjustment to the global_pose_to_local_pose function to fix it.

@TwistedTwigleg
Copy link
Contributor Author

Okay, I think I found the fix! Changing:

Transform3D conversion_transform = bones[parent_bone_idx].pose_global.affine_inverse();
https://github.com/godotengine/godot/blob/master/scene/3d/skeleton_3d.cpp#L1116

To: Transform3D conversion_transform = get_bone_global_pose(parent_bone_idx).affine_inverse(); fixes the issue.

I'll update #53821 accordingly 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants