- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 23.5k
 
          Add SkeletonModifier3D IKs as IKModifier3D
          #110120
        
          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
base: master
Are you sure you want to change the base?
Conversation
ffd8842    to
    6c2c13b      
    Compare
  
    | 
           Cool PR  | 
    
ca9d2b8    to
    ecc0595      
    Compare
  
    SkeletonModifier3Ds for IK as ManyBoneIK3DSkeletonModifier3D IKs as ManyBoneIK3D
      52af90b    to
    a3dda7d      
    Compare
  
    4d811b0    to
    6e06853      
    Compare
  
    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.
I'm leaving some comments about property validation of ChainIK3D (the base class), since the logic and flow for bone-name <-> bone-index assignment, and updating of skeleton joints is overly complex and I fear there may be corner cases where the update is not done, or done multiple times.
Some examples of corner cases: if the bone name is assigned but not the bone index, or if the bone name and bone index are both assigned but set to different bones. And the same thing but before / after skeleton is assigned. And same thing but for joints but not root bone.
I wish that the flow could be made simpler. For example joint dirty flag + skeleton changed. Or go through a single update function.
I also would like if we can choose bone-name or bone-index, rather than supporting both, since allowing the user to set name or index (or both) adds even more complexity
| 
           What are the chances of this appearing in 4.6?  | 
    
| 
           We are making progress with focusing on 4.6, doing regular biweekly animation meetings on the contributor chat.  | 
    
6e06853    to
    349d9b4      
    Compare
  
    | 
           Rebased to the latest. @lyuma I have responded to the code review comments, but fundamentally, the design of the ManyBoneIK class is based on other nodes (BoneConstraint3D and SpringBoneSimulator3D) already merged, as mentioned in #110120 (comment). Therefore, I assume there is not much we can specifically address here as it should be resolved at the same time as those other nodes. I suppose the design of the internal struct mentioned in #110120 (comment) could be improved, but since the problem is how to deal the internal array, I believe it can definitely be sent as a future follow up without breaking compatibility.  | 
    
349d9b4    to
    250ed2f      
    Compare
  
    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.
Discussed in animation meeting with @TokageItLab @SaracenOne @fire and @aaronfranke . I think we are good with merging this, and we can add blog post, do more testing and fix issues afterwards.
250ed2f    to
    799c1e9      
    Compare
  
    3ed7fde    to
    15bbd6a      
    Compare
  
    SkeletonModifier3D IKs as ManyBoneIK3DSkeletonModifier3D IKs as ModifierIK3D
      | 
           ManyBoneIK3D has been renamed to ModifierIK3D now. Since the opinion is raised by other maintainers that the name ManyBoneIK3D is somewhat unclear. Since the name SkeletonIK3D is unavailable until Godot 5, the following are the candidates proposed among the maintainers: 
 IKGroup3D sounds to have a role beyond that of a superclass (it sounds like a parent class that has an IK as a children in the scene tree) for me. InverseKinematics3D might be acceptable as a superclass name, but considering Godot as a whole, there was an argument that it was too generic. SkeletonInverseKinematics3D feels quite verbose, and considering the name FABRIK3D should not be SkeletonFABRIK3D, SkeletonFABRInverseKinematics3D or SkeletonForwardAndBackwardReachingInverseKinematics3D, I believe it should be avoided. Considering that the words “Skeleton” and “Bone” are used as an identifier to avoid generality, the third identifier could be a "Modifier". Also, considering naming consistency with subclasses like "ChainIK3D", I tentatively prefer "ModifierIK3D". Please suggest other name candidates if you have any.  | 
    
| 
           What about   | 
    
| 
           IKModifier3D  | 
    
| 
           @ettiSurreal IKModifier was also a candidate, but considering that its subclasses are ChainIK and IterateIK, I thought consistency with them might suggest using “IK” as the suffix. However, considering consistency with modifiers like LookAtModifier, “IKModifier” is fine. So it’s just a matter of whether to prioritize consistency with child or sibling classes. Let's do quick poll on whether to use IKModifier3D or ModifierIK3D by reactions: 🚀 IKModifier3D  | 
    
| 
           The justification can be that the names of the subclasses could be shortened versions of TwoBoneIKModifier3D, ChainIKModifier3D, and so on.  | 
    
15bbd6a    to
    3a0315a      
    Compare
  
    SkeletonModifier3D IKs as ModifierIK3DSkeletonModifier3D IKs as IKModifier3D
      | 
           I have adopted the name IKModifier for the base class. 
 @ettiSurreal Considering the possibility that SkeletonIK may become available in Godot 5 and rename this to that, I assume the child classes can remain as-is. @AThousandShips Thank you very much for the large amount of proofreading. I appreciate it, as reviewing this much must have taken a lot of time. Regarding line break spacing, it wasn't marked as outdated since diffs don't detect it, but I should have fixed it.  | 
    
3a0315a    to
    bf22eb2      
    Compare
  
    
Add several IK modifiers. As the nameTentatively it now named asSkeletonIK3Dconflicts with an older node, I will adopt the provisional nameManyBoneIK3D. Considering that the LookAtModifier targets only a single bone, I think this is a reasonable name.IKModifier3D.ManyBoneIK3D has the following extended classes:
There may be demand for FullbodyIK3D, but for now, this PR aims to fulfill the need for SkeletonModificationStack3D which was removed from 3.x to 4.0. (So don't close - godotengine/godot-proposals#6039)
I expect that FullbodyIK3D could be implemented in the future by extending one of the base classes. Until then, I assume PhysicalBoneSimulator can serve as a substitute in some extent.
Also this PR includes refactoring to unify enums for bone direction among some SkeletonModifiers.
IKModifier3D
It has a virtual method for having multiple configurations and a virtual bone structure for simulating IK to be able to hold poses and rests separately from the Skeleton.
TwoBoneIK3D
It provides deterministic results by constructing a plane from each joint and pole target and finding the intersection of two circles (disks in 3D). This IK can handle twist by setting the knuckle direction.
tbik.mp4
If there are more than one bones between each set bone, their rotations are ignored, and the straight line connecting the root-middle and middle-end joints are treated as virtual bones.
Godot.Engine.2025.08.30.-.22.29.34.06.mp4
ChainIK3D
It has a virtual method that generates a chain by setting root bone and end bone.
SplineIK3D
This IK aligning bones on Path3D. Bone twist is determined relatively based on the curve's tilt.
Godot.Engine.2025.08.30.-.22.29.34.05.mp4
If the root bone joint and the start point of Curve3D are apart, it assumes that there is a linear line segment between them. If the end bone joint exceeds the path length, bend the first joint exceeding the path length as close as possible to the end point of the Curve3D, and from there it is extended straight ahead - it should look almost the same as Blender's SplineIK.
IterateIK3D
It has a virtual method to approach the goal by repeating small rotations.
Godot.Engine.2025.08.30.-.22.29.34.04.mp4
Each bone chain (setting) has one effector, which is processed in order of setting list. You can set some limitations for each joint.
Limitations currently only support rotation axis and cone shapes. You can set arbitrary rotation offsets on each joint. BTW, there is potential for future reuse in SpringBone (ref. vrm-c/vrm-specification#496). Also I expect that kusudama shapes like godotengine/godot-proposals#11208 will be added in the future.
Known issue
Moving the position breaks the rendering of the Limitation gizmo because binding to position alone is impossible. To fix it, an approach such as canceling rotation within the shader like godotengine/godot-proposals#9735 is required. Currently, it is drawn by a hack to bind the limitation to the parent joint. See also #111815.
Incompatibility with old SkeletonIK3D
Regarding the pole target (magnet), I tried implementing it but finally decided against it because I couldn't stabilize it. This was due to strong conflicts with limitations and the difficulty in acquiring good results with solvers other than FABRIK. Even with FABRIK (both the version implemented this time and the current SkeletonIK3D), it is difficult to consistently obtain ideal results.
For these purposes, I determined it is more appropriate to use IK that can deterministically control direction, such as the TwoBoneIK and SplineIK described above, depending on the use case.
If someone needs a magnet no matter what, it possibly could be added later as a follow up PR. (If it can be stabilized)
If you want rotation on a plane, you can set the RotationAxis for absolute axis specification. For dynamic planes, you can use a LookAtModifier to orient the chain root specific (knuckle) axis to secondary (or same) target before IterateIK, which should achieve that. In other words, probably the general (other software's) chain IK's pole is processed in this way - only determining the twist of the first joint.
Also, omitted the functionality to apply the target's rotation to the tip. If we needed, the correct approach should be to allow users to specify a node in BoneConstraint3D (CopyTransformModifier3D) for arbitrary rotation transformations, rather than hard-coding it into the IK. See also #110336.
Demo project
ik_test.zip