-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Resolve bind poses from FBX clusters instead of FBX poses. #91036
Conversation
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.
FBX2GLTF doesn't use bind poses because of invalid data, this alternative approach is cool, and I like how it fetches the bind pose from either two successive skin clusters or a top-level bone.
@lyuma mentioned wanted to review it
Ran through all the dataset files containing skeletons:
After this fix there were no more obviously broken skeletons, and most seem to match FBX2glTF 100% accurately. Result categories out of 2264 files:
Example of the extent of skeleton difference caused by loading the bind pose: All in all, the testing indicates that this fix seems to be robust and fixes all the significant issues encountered before, without breaking any of the previously working cases. The roll issue and the occasional bone distortion is still significant enough, that I'd propose adding an importer option to disable attempting to import the bind pose, treating the initial pose as rest pose, like FBX2glTF does. Any thoughts? |
We need to debate adding a new option, but that can review that in a separate pr. That means you can stack the two prs together into that pr. |
Makes sense, in that case this PR is fine to merge by me! |
@lyuma provided some test cases with multiple bind poses per bone. Added explicit support for this in the form of warning the user if a bone has multiple conflicting bind pose definitions. Note that this may still mix up different bind poses for different parts of the mesh, but at least now bones do not get completely messed up and users should see a warning. I'd still highly recommend adding a setting for disabling importing bind poses (maybe even not importing them by default), as they seem to have quite a few problems in the wild, and even this solution is a bit hacky. |
I think this needs a rebase on master. |
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.
Looks great! The added check gives me more confidence it will not tear my armature apart in the rest.
We still need to discuss making an option for this behavior and what the default should be but again we should do this in a separate change.
please rebase as ifire said and squash your commits into one. I kept a copy of the history in my own fork so don't worry about losing history.
} | ||
const real_t max_error = 0.01f; | ||
if (error >= max_error) { | ||
WARN_PRINT(vformat("FBX: Node '%s' has multiple bind poses, using initial pose as rest pose.", node->get_name())); |
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.
A little worried this will logspam but let's keep it and it will help us diagnose issues during the beta test.
Not something we have to fix here, but we should figure out a better approach for import warnings. I want to show warnings and errors per-file in the import dock or in some dedicated place.
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.
Yeah was a little concerned about this as well, but it feels like something that should be informed to the user. Of course collecting them would be ideal.
On that note, we should also probably expose ufbx_metadata.warnings[]
there, as ufbx can report a bunch of suspicious stuff in the file.
d3ab316
to
8edbf70
Compare
Thanks! I'll squash the commits after seeing that the CI passes etc. Also ran through all the skeletons in my dataset (+ the entirety of the public dataset) again with the new changes. Seems like the new bind pose resolution method loads files correctly. 29 of 2636 files had multiple bind poses, and on manual review all seemed to be alright. One file had only a 4% error in bone pose, so that might have been a false positive. I just set the 1% relative error threshold arbitrarily, so could be looked into if necessary. |
Turns out that the information in FBX Pose objects is relatively often broken. Using skin cluster bind poses seems more reliable, but cannot capture the bind pose of the root bone.
8edbf70
to
0955690
Compare
Thanks! |
See #90986 for more context.
Skeletons imported with ufbx sometimes have broken bind poses:
ufbx previous
ufbx previous bind pose
this PR (both bind pose and initial pose are the same)
Turns out this was not a bug, either in ufbx or in the Godot ufbx importer. The issue is broken data in files, the Godot ufbx importer read the bind poses from FBX
Pose
objects. The rest pose matrices in these were correct for most files, but they seem to be incorrect in a significant minority of files.FBX2glTF does not attempt to import bind poses, so it avoids this problem. This PR introduces an alternative method of reading the bind pose data, and initial testing shows improved skeletons in all tested files. I'll do more rigorous testing in the background using the same process as in #90986.
One thing to consider is whether we should have an option whether to import the bind pose data or not. This would allow compatibility with FBX2glTF and allow users to hotfix potentially broken bind poses in files, though if testing indicates that the new method is fully robust, it may not be as necessary.