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.
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
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:
But the Bones are not Aligned so the rotation is values are different:
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
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 )
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:
Now I Change the Frame which moves Armature 1:
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
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.