AnswerBun.com

Mysterious offset when alter armature's edit bones?

Blender Asked by Logic1 on September 18, 2020

I copy the locations for each bone in my armature (left) by using a Template armature (right) to copy from.

But I see that all parented object get moved after I have applied the changes:
enter image description here
You can see the “Cube” object moves after running the script. I have found no way to overcome this offset.

I have included the .blend file which contains the script and the two armatures (“run script” to test).


Also here is just the script. It tries to copy the edit bones from the template avatar to the final avatar, then it attempts to remove the offsets for all child objects (but slight offsets still persists):

import bpy
from mathutils import Matrix

def get_bone_children(parent, objects): 
    children = [] 
    for ob in objects: 
        if ob.parent_bone == parent.name: 
            print(bpy.data.objects[ob.name])
            children.append(bpy.data.objects[ob.name]) 
    return children 

armature = bpy.data.objects['Armature'] #The "destination" armature
bones = bpy.data.armatures['Armature.001'].bones #the source "template" bones

for i, bone in enumerate(bones):
    #match the head/tail local positions between the two armatures
    head_pos = bone.head_local 
    tail_pos = bone.tail_local 

    armature.data.bones[bone.name].head_local = head_pos
    armature.data.bones[bone.name].tail_local = tail_pos #Removed from main loop because makehuman rigs showed overlapping bones, besides the tail is unnecessary for pose

    bpy.ops.object.mode_set(mode='EDIT') #must do this or else the new positions will not be updated
    bpy.ops.object.mode_set(mode='OBJECT')

    pBone = armature.pose.bones.get(bone.name)
    children = get_bone_children(armature.data.bones[bone.name], bpy.data.objects)
    for c in children: #Parent object to a bone and object becomes offsets - https://blender.stackexchange.com/a/139180/32655
        c.matrix_parent_inverse = (armature.matrix_world * Matrix.Translation(pBone.tail - pBone.head) * pBone.matrix).inverted()

bpy.ops.object.mode_set(mode='EDIT') #must do this or else the new positions will not be updated
bpy.ops.object.mode_set(mode='OBJECT')

Could somebody please kindly help me figure out why my child objects are being offset?

One Answer

As Serge L suggested it was possible to achieve the expected result by first removing the parent/child relationships from each object, then modifying the edit_bones to match the template skeleton, followed by finally re-creating the parent/child relationships for those objects.

Here is some code that finally got things working for me:

import bpy
from mathutils import Matrix

def get_bone_children(parent, objects): 
    children = [] 
    for ob in objects: 
        if ob.parent_bone == parent.name: 
            print(bpy.data.objects[ob.name])
            children.append(bpy.data.objects[ob.name]) 
    return children 

def clear_parent(child): #clear parent keep transform - https://blenderartists.org/t/preserving-child-transform-after-removing-parent/616845/3
    # Save the transform matrix before de-parenting
    matrixcopy = child.matrix_world.copy()    
    # Clear the parent
    child.parent = None        
    child.parent_bone = ''
    # Restore childs location / rotation / scale
    child.matrix_world = matrixcopy

armature = bpy.data.objects['Armature']
bones = bpy.data.armatures['Armature.001'].bones #the template bones

bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active = armature
bpy.ops.object.mode_set(mode='POSE') #must do this or else context will not be correct
for pb in armature.pose.bones: #Reset Rotation , Translation and Scale of bones through Script - https://blender.stackexchange.com/a/147342/32655
    pb.matrix_basis = Matrix() #  == Matrix.Identity(4)
bpy.ops.object.mode_set(mode='OBJECT')

childObjects = [] #stores all bones in this armature
for i, bone in enumerate(bones):
    children = [] #all of the children connected to this bone
    for c in get_bone_children(armature.data.bones[bone.name], bpy.data.objects): #Parent object to a bone and object becomes offsets - https://blender.stackexchange.com/a/139180/32655
        children.append(c)
        clear_parent(c)         
    childObjects.append([bone, children])

for i, bone in enumerate(bones):
    #match the head/tail local positions between the two armatures
    head_pos = bone.head_local 
    tail_pos = bone.tail_local 

    armature.data.bones[bone.name].head_local = head_pos
    armature.data.bones[bone.name].tail_local = tail_pos #Removed from main loop because makehuman rigs showed overlapping bones, besides the tail is unnecessary for pose

    #These lines are critical!!
    bpy.ops.object.mode_set(mode='EDIT') #must do this or else the new positions will not be updated
    bpy.ops.object.mode_set(mode='OBJECT')

#restore parent relationships
for i, childObject in enumerate(childObjects):
    bone = childObject[0]
    children = childObject[1]
    for c in children:  

        matrixcopy = c.matrix_world.copy()    

        c.parent = armature
        c.parent_bone = bone.name
        c.parent_type = 'BONE'

        c.matrix_world = matrixcopy

Answered by Logic1 on September 18, 2020

Add your own answers!

Related Questions

Differentially rotate

0  Asked on September 29, 2020 by leonardo-mutti

   

Rigid Body Physics: Sliding Pivot Point

0  Asked on September 24, 2020 by mike-n

 

cloth simulation bug?

0  Asked on September 23, 2020 by jiyevi7242

 

Rig pose of proxy armature isn’t saved

2  Asked on September 23, 2020 by mick

 

How to stop eyes clipping through head mesh?

0  Asked on September 20, 2020 by ryan

   

placing origin at end of Bezier Curve

1  Asked on September 19, 2020 by travelbugs

   

Mysterious offset when alter armature’s edit bones?

1  Asked on September 18, 2020 by logic1

   

Camera tracking data import

1  Asked on September 18, 2020 by oliver-silvrus

     

What’s happening with vector displacement 2.79b?

1  Asked on September 17, 2020 by user3109736

   

Understanding (and fixing) non-manifold geometry

1  Asked on September 9, 2020 by deep_forrest

   

Align axis to object normals

1  Asked on September 6, 2020

 

Blender build for Raspberry Pi3?

3  Asked on September 2, 2020 by iowaqas

     

vertex coordinates in panel made with python script do not update

0  Asked on August 29, 2020 by sodiumnitrate

   

Add color noise to render

1  Asked on August 27, 2020 by evarate

 

Ask a Question

Get help from others!

© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP