2
$\begingroup$

I have two Armatures with different bone structure.

The goal is to get the rotational difference of one bone from a one Armature and translate it to the bone of the other Armature. enter image description here

Code **For a General approach:

import bpy

context = bpy.context
scene = context.scene

Rig_1 = bpy.context.scene.objects['__Rig'] 
Rig_2 = bpy.context.scene.objects['__Rig2'] 

Rig_1_RightArm = Rig_1.pose.bones["r_uparm"]
Rig_2_RightArm = Rig_2.pose.bones["r_uparm"]

scene.frame_set(1)
WorldSpace_RightArm_1-1 = Rig1.matrix_world @ Rig_1_RightArm.matrix 

bpy.context.view_layer.update()

scene.frame_set(2)
WorldSpace_RightArm_1-2 = Rig1.matrix_world @ Rig_1_RightArm.matrix 
WorldSpace_RightArm_2-2 = Rig2.matrix_world @ Rig_2_RightArm.matrix 

bpy.context.view_layer.update()

I've tried multiple methods and would like to know what to do beyond here, like using rotation_difference to between WorldSpace_RightArm_1-1 from frame 1 and WorldSpace_RightArm_1-2 from frame 2.

$\endgroup$
2
  • $\begingroup$ The pose bone loc/rot/scale is already relative to the bone's rest position. Have you tried just copying the pose.bones[x].location/rotation/scale over? Or if you have an action, just put the same action on both armas. $\endgroup$
    – scurest
    Mar 14, 2021 at 6:54
  • $\begingroup$ Using the Action editor doesn't work in this case, or atleast I could not get it to work, The bones are in different rotations editing wise. I tried a direct copy it didn't work but what would the a copy code look like to you. $\endgroup$ Mar 14, 2021 at 7:18

1 Answer 1

5
$\begingroup$

Object.convert_space

As mentioned in previous answer there is a convenience method available on the object that converts space.

Rather than totally doing my head in by trying to make a rotation difference am going to

  • Convert source and target pose bone matrices to world space
  • Decompose them, ie get their world space location, rotation and scale parts.
  • Recompose the target world matrix to have rotation part of source
  • Convert this to pose space of target bone and set as matrix.

Test method.

import bpy
from mathutils import Matrix

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
    snap_rotation(
        scene.objects["Armature"].pose.bones["Bone"],
        scene.objects["Armature.001"].pose.bones["Bone"]
    )
$\endgroup$
3
  • $\begingroup$ Close but not exactly because the bone of Armature 1 is not meant be the same rotation as bone of Armature 2, But you are suppose to get the difference in rotation in the 1st frame and apply it to the 2nd $\endgroup$ Mar 16, 2021 at 20:59
  • 1
    $\begingroup$ Ok, see what I am supposed to do now Much the same, get the world space rot diff of A,, use on B then convert back. Might get around to fixing later. Possibly related blender.stackexchange.com/questions/72120/… as it appears you are converting a T pose to an A pose. $\endgroup$
    – batFINGER
    Mar 16, 2021 at 21:16
  • $\begingroup$ If you have the time can you take a look at this blender.stackexchange.com/questions/216082/… .......... Its the same as comment above.This question is slightly different then the one in the link. $\endgroup$ Mar 24, 2021 at 5:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.