Rigged Anatomically Correct Skeleton (almost)

(nan0byt3) #1

I am working on making a skeleton as accurate as possible and rigging it.
So far I have a separate mesh for each bone, have made an armature bone for each.
I have just finished writing a script to aid in the development of this. It needs refinement but for now works.

Basically what was happening was I would put the armature bones in line with the mesh bones according to how that bone pivots, change the pivot center of the mesh bone to the center of the armature bone’s head, and then I would apply copy loc/rot/size constraints. But the mesh bone would stick out at strange angles due to the the constraints rotating the mesh face to the local xyz of the bone, the meshes original xyz direction being the same as global xyz.

Now I can run my script after lining up the armature bones with the mesh bones, select the armature, select the bone in the armature, select the mesh, and it will move the mesh’s pivot to the bones head, rotate the pivot to face the same as the bones rest position whilst keeping the mesh in place, then apply the constraints for me.

I made this because I noticed that you can change the location of the pivot point, but not rotate it (without actually rotating the mesh itself).

It also needs a lot of general cleaning, I only started learning python last week, so it leaves heaps to be desired. I actually found that this would help in animating/rigging any solid objects, for example I made a basic chest with 2 separate meshes, one for the lid and one for the box part. Put an armature bone with the head where it would hinge, and tail facing out, ran the script and all done, an animating lid.

For some reason I need to save the scene and reload it after running the script to have the mesh follow the bone in pose mode. Might be something to do with the constraints not being recognized even after a Windows.Redraw() and a sel_mesh_data.update(). I also need to make the script apply scale and rotation, before it starts changing stuff. This is so the mesh is directly linked to the armature/bones, so they can then be scaled in future to accommodate different body sizes/shapes.

Anyway here is the script in case anyone finds it helps. :smiley: Please post if you have any suggestions/comments on making it better/more durable.

import Blender
from Blender import *

print '------------start------------'

def main():
    editmode = Window.EditMode() 
    if editmode: Window.EditMode(0)

    # fill armature list and remove non-armatures
    arm_list= Object.Get()
    arm_list_len = len(arm_list)
    while arm_list_len:
        arm_list_len -=1
        if arm_list[arm_list_len].getType() != 'Armature':
            arm_list.pop(arm_list_len)

    # menu of armatures
    arm_menu= 'ARMATURES%t|' + ('|'.join(x.name for x in arm_list))
    choice_arm= Draw.PupMenu(arm_menu)-1
    if choice_arm != -2:
        sel_arm= arm_list[choice_arm] 
    else:
        return

    # get data from armature and make a bones list
    sel_arm_data= sel_arm.getData()
    bones_list= sel_arm_data.bones.values()

    # menu of bones
    bones_menu= 'BONES%t|' + ('|'.join(x.name for x in bones_list))
    choice_bone= Draw.PupMenu(bones_menu)-1
    if choice_bone != -2:
        sel_bone= bones_list[choice_bone] 
    else:
        return

    # get data from bone
    sel_bone_data= sel_bone

    # fill mesh list and remove non-meshes
    mesh_list= Object.Get()
    mesh_list_len= len(mesh_list)
    while mesh_list_len:
        mesh_list_len -=1
        if mesh_list[mesh_list_len].getType() != 'Mesh':
            mesh_list.pop(mesh_list_len)

    # menu of meshes
    mesh_menu= 'MESHES%t|' + ('|'.join(x.name for x in mesh_list))
    choice_mesh= Draw.PupMenu(mesh_menu)-1
    if choice_mesh != -2:
        sel_mesh= mesh_list[choice_mesh] 
    else:
        return

    # get mesh data from selected mesh
    sel_mesh_data= Mesh.Get(sel_mesh.name)
    menu_continue= 'Proceed?%t|OK'
    choice_continue= Draw.PupMenu(menu_continue)-1
    if choice_continue == -2:
        return
    
    # now to business
    new_origin= sel_bone.head['ARMATURESPACE']
    Blender.Window.SetCursorPos(new_origin)
    
    mesh_matrix= sel_mesh.getMatrix()
    mesh_quat= mesh_matrix.toQuat()
    bone_matrix= sel_bone.matrix['ARMATURESPACE']
    bone_quat= bone_matrix.toQuat()
    
    CenterCursor(sel_mesh)
    
    diff_matrix= Mathutils.DifferenceQuats(bone_quat,mesh_quat).negate().toMatrix().resize4x4()
    new_matrix= bone_quat.toMatrix().resize4x4() * mesh_matrix
    
    sel_mesh_data.transform(diff_matrix)
    sel_mesh.setMatrix(new_matrix)
    
    # add in constraints, this part is good
    cons_type= Constraint.Type.COPYLOC, Constraint.Type.COPYROT, Constraint.Type.COPYSIZE
    cons_type_len= len(cons_type)
    cons_names= 'LOC', 'ROT', 'SIZE'
    cons_names_len= len(cons_names)

    cloop1= 0
    while cloop1 < cons_type_len:
        sel_mesh.constraints.append(cons_type[cloop1])
        cloop1= cloop1+1

    cloop2= 0
    while cloop2 < cons_names_len:
        sel_mesh.constraints[cloop2].name= cons_names[cloop2]
        sel_mesh.constraints[cloop2].__setitem__(Constraint.Settings.TARGET, sel_arm)
        sel_mesh.constraints[cloop2].__setitem__(Constraint.Settings.BONE, sel_bone.name)
        cloop2= cloop2+1
    
    # some console output so you know what the hell you just did =)
    print 'Armature: ', sel_arm_data.name, '
Bone:', sel_bone_data.name, '
Mesh:', sel_mesh_data.name
    print '------------fin------------'

    # refresh window to see how much damage has occured =(
    sel_mesh_data.update()
    Blender.Redraw()
    
def CenterCursor(sel):
    cursor = Window.GetCursorPos()
    vcursor = Mathutils.Vector(cursor)
    if sel:
        if sel.type=='Mesh':
            loc = sel.getLocation('worldspace')
            vloc = Mathutils.Vector(loc)
            d = vcursor-vloc
            sel.setLocation(cursor)
            m = sel.getData(False,True)
            for v in m.verts:
                v.co-=d
    Blender.Redraw()

main()

Attachments


0 Likes

(Vertex Pusher) #2

First of all welcome to the forum nan0byt3 !

I don’t know why you are changing the pivot points of the mesh itself if you are parenting the mesh to an armature bone … This is not necessary … The root of the armature bone automatically becomes the pivot point of the parented mesh in Pose Mode … Unless you are intending to animate the skeleton in Object Mode without the use of the armature … Or just wanted to do some Python scripting practice :slight_smile: … ?

I can’t comment on your script since I don’t have any experience other then using them …

But I can tell you that anatomically not all bones move via a simple pivot … the jaws, the knee, and most especially the shoulder blades/scapula do not move/rotate around a pivot point (yes I know the jaws look like they are hinged but anatomically they have a dual sliding/hinging motion) .

So if you want to rig your skeleton “realistically” you should keep that in mind and work on how to apply the various constraints available (and if you have a SVN version of Blender with the Script/PyConstraint you can custom make your own constraints using Python) to achieve realistic motions .

Some anatomical motions are very difficult to figure out … trust me I am speaking from experience : http://blenderartists.org/forum/showthread.php?t=97107

Maybe you’ll have better luck then I have so far in solving some of the animation/motion issues … Good Luck !

0 Likes