Skip to main content
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
Bumped by Community user
added 105 characters in body
Source Link

Testing forBelow is my approach using code from other answers. The code is just for the Right Upper Arm bone, not the entire model which is the goal

Testing for just the Right Upper Arm

Below is my approach using code from other answers. The code is just for the Right Upper Arm bone, not the entire model which is the goal

edited title
Link

Python, How to Convert Rotations of T-pose Pose Bones in Armature 1 to a Pose Bones in Armature 2? Finding Rotational difference

Source Link

Python, How to Convert Rotations of T-pose Pose Bones in Armature 1 to a Pose in Armature 2? Finding Rotational difference

The goal is to get the rotational difference of the bones between Armature 1 and Armature 2 in its T-pose(not exactly), then apply the difference to a pose of Armature 2.

The purpose is so the model of Armature 1 follows Armature 2.

Testing for just the Right Upper Arm

Lets say I have two Armatures in normal poses. I want Armature 1 to follow Armature 2. The Armature 1 on the Left is the Source and Armature 2 on the Right is the Target:

enter image description here

But the Bones are not Aligned so the rotation is values are different:

enter image description here

First, Save the rotation variable of Armature 2 Right Arm, then set the Right Arm bone vector of Armature 2 to vector of Armature 1

Code:

import bpy
from mathutils import Matrix
from mathutils import Quaternion

context = bpy.context
scene = context.scene
RobloxRig = bpy.context.scene.objects['__Rig'] 
UpperRightArm = RobloxRig.pose.bones["RightUpperArm"]


CloudRig = bpy.context.scene.objects['CloudRig'] 
CloudRig_UpperRightArm = CloudRig.pose.bones["r_uparm"]

def snap_rotation(source, target):

    Ms = source.id_data.convert_space(
       pose_bone=source,
       matrix=source.matrix,
       from_space='POSE',
    )

    Mt = target.id_data.convert_space(
       pose_bone=target,
       matrix=target.matrix,
       from_space='POSE',
    ) 
     
    _, q, _ = Ms.decompose()
    t, _, s = Mt.decompose()

    M = (
       Matrix.Translation(t) @
       q.to_matrix().to_4x4() @ 
       Matrix.Diagonal(s.to_4d())
    )

    target.matrix = target.id_data.convert_space(
       pose_bone=target,
       matrix=M,
       to_space='POSE',
    )    

if __name__ == "__main__":
   context = bpy.context
   scene = context.scene

   scene.frame_set(720) #Frame of Normal pose
   bpy.context.view_layer.update()

   Mt = UpperRightArm.matrix
     
   loc1, rot1, scale1 = Mt.decompose()

   NormalRot = Quaternion(rot1)


   snap_rotation(
       CloudRig_UpperRightArm,
       UpperRightArm 
   )

Output: enter image description here

Now that Bone Vector of Armature 2 is aligned with Armature 1, Save the new rotation, Set it back to normal and get the rotational difference.

bpy.context.view_layer.update()

Mt = UpperRightArm.matrix
     
loc2, rot2, scale2 = Mt.decompose()

#New Rotation
NextRot = Quaternion(rot2)

#Setting back to normal using from code above values
M = (
    Matrix.Translation(loc1) @
    rot1.to_matrix().to_4x4() @ 
    Matrix.Diagonal(scale1.to_4d())
    )
    
UpperRightArm.matrix = M

#Getting Difference
RotationalDifference =  NormalRot - NextRot

Output, Just back to normal after taking the value:

enter image description here

Now I Change the Frame which moves Armature 1:

scene.frame_set(730)
bpy.context.view_layer.update()

enter image description here

This Final part which Doesn't work I set the vector of the Armature 1 to Armature 2 like before then added the difference.

snap_rotation(
    CloudRig_UpperRightArm,
    UpperRightArm 
)

bpy.context.view_layer.update()

Mt2 = UpperRightArm.matrix
     
loc3, rot3, scale3 = Mt2.decompose()

FinalRot =  RotationalDifference + Quaternion(rot3) 

M2 = (
    Matrix.Translation(loc3) @
    FinalRot.to_matrix().to_4x4() @ 
    Matrix.Diagonal(scale3.to_4d())
    )

UpperRightArm.matrix = M2

Wrong Output: enter image description here

Here is what's expected: enter image description here

A small difference is that it applies to all bones. If I get one bone it would be easy to get the rest.

Please help, Thank you.