Add BoneExpander3D and allow Spring / IK to set mutable bone axes #111815
      
        
          +7,196
        
        
          −197
        
        
          
        
      
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Add a BoneExpander. This applies scaling to the bone pose position and skin bind matrix, enabling visual scaling without modifying the bone pose basis.
Compared to #83903, this approach minimizes impact on projects that do not utilize scaling. Furthermore, by handling scaling settings externally, it should keep the Skeleton system itself clean.
There are several methods for scaling while avoiding global shearing. Other game engines like Unity typically solve this by using BoneConstraints for parent-child relationships without hierarchical parent-child relationships. Another approach involves using the inverse of the CopyTransformModifier to add a cancel bone without length as a child to the bone you want to scale.
mov_016.mp4
However, those three methods, including #83903, all use scaling, and adopting this result in IK or SpringBone is not straightforward.
One way to handle this is to convert the scale into bone translation (pose position) and change the SkeletonModifier's ForwardAxis retrieval from bone rest to bone pose. This is similar to what is done internally in several places within the glTF importer. Then, the restriction that scaling may cause breakage remains unchanged from previous versions.
While calculations might be possible in cases involving cancel bones, but we cannot guarantee the presence of cancel bones. And since Godot will never remove cases where global shears occur, I think it's safer to maintain consistency regarding the potential for breakage when scaling is used.
How to work
Modifications to the skin are not managed by the SkeletonModifier, so they are managed using signals.
To enable this, the list of skin references can be retrieved from the skeleton using get_skin_bindings(). However, since this API returns a HashSet and carries some risk, it is published only to the C++ core (not exposed to GDScript). Additionally, the
skeleton_renderedandskin_changedsignals are added to restore the original, unscaled skin after rendering. These signals are considered safe and are published to GDScript.During SkeletonModifier iteration, only the transformed translate is applied to the bone pose, and only the undeformed skin is retrieved. Then, scaling is applied to the skin when the skeleton_updated signal fires immediately before rendering. This method prevents skin corruption because even if multiple BoneExpanders process the same bone, the scaled skin is never retrieved. Finally, the unscaled skin is restored after rendering.
This implementation is quite experimental, but I believe it represents the best compromise currently available to keep Skeleton's internal processing clean and resolve issues externally.
However, be aware that performance issues may arise due to the extensive use of arrays for skin changes. Additionally, since skin changes are not inherited, combining this with RetargetModifier3D or baking IK animation to FK animation may result in unintended movement. These restrictions have been added to the documentation and as an experimental flag.
mutable_bone_axes
Add the
mutable_bone_axesoption to handle bones have deformed position to the following SkeletonModifier.Disabled:

Enabled:

bone_expander_demo.zip
This means using the bone pose origin instead of the bone rest origin. Enabling this option indicates an increase in computational cost and may slightly impact performance. Since SpringBone and IK cached bone lengths that were not dynamically changed.
Performance comparisons with the option enabled are as follows:
spring_and_ik_bench.zip
Note for reviewer: The
mutable_bone_axesoption is implemented for IK that hasn't been merged yet, so this PR exists in a commit that bases on all related PRs.