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

Add Rest Fixer to importer retarget #62939

Merged
merged 1 commit into from
Jul 16, 2022

Conversation

TokageItLab
Copy link
Member

@TokageItLab TokageItLab commented Jul 12, 2022

Implement T-poser(Fix Silhouette) and Re-rester(Overwrite Axis) as said in godotengine/godot-proposals#4510.

It's still a draft. I've verified that the algorithm actually works, but the iterating process is messed up and needs to be refactored. Refactored.

1_3.mp4

Overwrite Axis

Rotate the axis of the joint. In Blender parlance, this is the function to rotate the EditBone.

This feature solves the problem that if you have two T-pose models, the joint axes of each may not coincide.

re-rest

For example, one model bends at the waist when the X axis is rotated +, while the other model bends at the waist when the Z axis is rotated +. In this case, the current animation format of Godot 4 cannot share the animation.

Therefore, we will unify the rest and skin model axes with the rest pose specified in the SkeletonProfile, and rewrite the rotation animation values to allow them to be shared.

Note

  • When using this feature, any extra bone rest rotations that exist between the mapped bones will be discarded.
  • Some bone mappings will be required and a red button will appear on the GUI if those bones are missing. If those bones are not present, the conversion will still take place, but may fail.1
  • The default SkeletonProfileHumanoid rest is defined according to the rule that the Y axis from parent to child is the roll axis and +X rotation is used for internal rotation ≈ muscle contraction.

Fix Silhouette

Match the silhouette of a model to the silhouette specified in SkeletonProfile.

The correction is made if the angle of the bone is larger than the threshold angle compared to the angle of the reference pose.

If there are parts which you do not want the correction to be applied, you can specify the name of the ProfileBone in the filter.

image

Currently, due to issues with the implementation of the importer plugin, this String must be typed manually. There is scope for improvement, such as making it an enum pull-down later, but since the process of importer plugin itself needs to be refactored, it is out of the scope of this PR.2

Note

  • A rotation track will always be added to the mapped bones. This is to prevent animation inconsistencies caused by changes to the Rest silhouette, since if no track is present, the pose during animation is dependent on Rest.
  • The default SkeletonProfileHumanoid is defined as a T-pose with the palm facing down, with the thumb of the hand snapped at 45 degrees and the others at 90 degrees.
  • No roll compensation is performed, and it is recommended that you use a model with the palms facing down rather than forward when using SkeletonProfileHumanoid.

Other fixes

SkeletonProfile

Added many properties to SkeletonProfile. Also, SkeletonProfile can now be exported from SkeletonEditor (for advanced users).

Most of the exported properties have default values except for rest-pose and names, which must be adjusted accordingly.

Renamer

Added an option to renamer to make skeleton a unique node.

uq

Unless you have defined a hierarchy of scenes to be imported, you basically need to enable it. If you want to use multiple profiles in one project, you will also need to change the SkeletonName accordingly.


There are known issues.

When a position track exists, it forces "the physique of the model to which the animation is applied" to be "the physique of the model for which the animation was created". To address this issue, I will be implementing a Position Track Optimizer next PR.

The Re-rester(Overwrite Axis) rotates the joint axes of the imported model, this means that if there is an attachment that references the joint axes as a glTF Extention, it will break it. Also, shared animations can bend joints in odd directions.

To solve these problems, there is a real-time retargeting method, which I plan to distribute as a Custom module or GDExtention in the future. To do so, we need to expose much of Animation's playback/blend API to the public, and this modification is planned next to the Position Track Optimizer.


Test model

Blender Chan! / CC by SearKitchen
https://sketchfab.com/3d-models/blender-chan-6835f0d60e0c4813812c0247e3b73da7

Footnotes

  1. This is due to the fact that Godot 4 animations contain rests from the parent, so if a bone with a particular rotation is missing, the child bones will have different rests and will not be compatible. Discarding all bone rotations would solve this problem, but is not recommended because it would lose the meaning of the axes. There is a smarter solution that to insert fake bones, but I think the smartest solution is to use rest-relative animation or real-time retargeting which are planned to be implemented as extensions.

  2. get_internal_option_visibility() is not sufficient because it can only retrieve options implemented in the core and can only read option values. Also get_property_list() and validate_property() can't get other import options so it means that we cant get bone_map in there. So the PostImportPlugin need to be implemented such as validate_option(PropertyInfo &property, const Dictionary &p_options).

Copy link
Contributor

@lyuma lyuma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking pretty good overall

editor/import/post_import_plugin_skeleton_rest_fixer.cpp Outdated Show resolved Hide resolved
scene/3d/skeleton_3d.cpp Outdated Show resolved Hide resolved
scene/resources/skeleton_profile.cpp Outdated Show resolved Hide resolved
@TokageItLab TokageItLab force-pushed the implement-rest-fixer branch 3 times, most recently from 1a8fe68 to fbcef42 Compare July 13, 2022 20:16
@TokageItLab TokageItLab requested a review from reduz July 13, 2022 20:19
@TokageItLab TokageItLab force-pushed the implement-rest-fixer branch 5 times, most recently from b6d5035 to 6deb02c Compare July 15, 2022 04:38
@TokageItLab
Copy link
Member Author

TokageItLab commented Jul 15, 2022

At the suggestion of @fire, BoneMapper bone selecting GUI has been changed to EnumSuggestion from Enum. This is because it may be easier to enter the bone names manually when there are many bones.

@TokageItLab TokageItLab force-pushed the implement-rest-fixer branch 3 times, most recently from 26d462f to 02674c5 Compare July 15, 2022 07:41
doc/classes/SkeletonProfile.xml Outdated Show resolved Hide resolved
doc/classes/SkeletonProfile.xml Outdated Show resolved Hide resolved
doc/classes/SkeletonProfile.xml Outdated Show resolved Hide resolved
doc/classes/SkeletonProfile.xml Outdated Show resolved Hide resolved
doc/classes/SkeletonProfile.xml Outdated Show resolved Hide resolved
@akien-mga akien-mga merged commit 5a6b13b into godotengine:master Jul 16, 2022
@akien-mga
Copy link
Member

Thanks!

@TokageItLab TokageItLab deleted the implement-rest-fixer branch September 16, 2022 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants