Human Armature Animation

I’m new to blender and python. As a part of this project that I’m working on, I’m given the 3D positions of the various human joints for numerous frames and my model needs to change its position accordingly.

So far, I’ve been able to write a code that create a skeleton model, reads the input file and correctly animates the model accordingly,


import bpy, math
from mathutils import Vector, Matrix
filein = 'scripts\inputdata.txt'
file = open(filein, 'r')

c=0
x=[]
y=[]
z=[]
frame=0
frame_num=0

def RepresentsInt(s):
    try: 
        int(s)
        return True
    except ValueError:
        return False
show=0 
for line in file:
    
    if (line == "
"):
        continue
    word = line.split()
    if RepresentsInt(word[0][0]) or RepresentsInt(word[0][1]):
        c=c+1
        word = line.split()
        x.append(float(word[0]))
        y.append(float(word[1]))
        z.append(float(word[2]))
        
        if (c==20):
            
            def createRig(name, origin, boneTable):
                # Create armature and object
                bpy.ops.object.add(
                    type='ARMATURE', 
                    enter_editmode=True,
                    location=origin)
                ob = bpy.context.object
                ob.show_x_ray = True
                ob.name = name
                amt = ob.data
                amt.name = name+'Amt'
                amt.show_axes = True
             
                # Create bones
                bpy.ops.object.mode_set(mode='EDIT')
                for (bname, pname, vector) in boneTable:        
                    bone = amt.edit_bones.new(bname)
                    if pname:
                        if (bname == 'HIP_LT')or(bname =='HIP_RT'):
                            parent = amt.edit_bones[pname]
                            bone.parent = parent
                            bone.head = (x[0],y[0],z[0])
                            bone.use_connect = False
                            
                        else:
                            parent = amt.edit_bones[pname]
                            bone.parent = parent
                            bone.head = parent.tail
                            bone.use_connect = False
                            (trans, rot, scale) = parent.matrix.decompose()
                    else:
                        bone.head = origin
                    bone.tail = Vector(vector) 
                bpy.ops.object.mode_set(mode='OBJECT')

                current_frame = show  
                bpy.ops.anim.change_frame(frame=current_frame)  
                bpy.context.active_object.hide = False  
                bpy.context.active_object.keyframe_insert(data_path="hide",   
                                                            index=-1,   
                                                            frame=current_frame)      
                      
                hide=0
                for hide in range(140):

                    if hide==show:
                        continue
                    
                    current_frame = hide  
                    bpy.ops.anim.change_frame(frame=current_frame)  
                    bpy.context.active_object.hide = True  
                    bpy.context.active_object.keyframe_insert(data_path="hide",   
                                                                index=-1,   
                                                                frame=current_frame)  
                return ob
             
            def run(origo):
                origin = Vector(origo)

                boneTable1 = [
                    ('SPINE', None, (x[2],y[2],z[2])),
                    ('NECK', 'SPINE', (x[3],y[3],z[3])),
                    ('SHOULDER_RT', 'SPINE', (x[8],y[8],z[8])),
                    ('SHOULDER_LT', 'SPINE', (x[4],y[4],z[4])),
                    ('UPPER_ARM_RT', 'SHOULDER_RT', (x[9],y[9],z[9])),
                    ('UPPER_ARM_LT', 'SHOULDER_LT', (x[5],y[5],z[5])),
                    ('LOWER_ARM_RT', 'UPPER_ARM_RT', (x[10],y[10],z[10])),
                    ('LOWER_ARM_LT', 'UPPER_ARM_LT', (x[6],y[6],z[6])),
                    ('HAND_RT', 'LOWER_ARM_RT', (x[11],y[11],z[11])),
                    ('HAND_LT', 'LOWER_ARM_LT', (x[7],y[7],z[7])),
                    ('HIP_RT', 'SPINE', (x[16],y[16],z[16])),
                    ('HIP_LT', 'SPINE', (x[12],y[12],z[12])),
                    ('UPPER_LEG_RT', 'HIP_RT', (x[17],y[17],z[17])),
                    ('UPPER_LEG_LT', 'HIP_LT', (x[13],y[13],z[13])),
                    ('UPPER_LEG_RT', 'UPPER_LEG_RT', (x[17],y[17],z[17])),
                    ('UPPER_LEG_LT', 'UPPER_LEG_LT', (x[13],y[13],z[13])),
                    ('LOWER_LEG_RT', 'UPPER_LEG_RT', (x[18],y[18],z[18])),
                    ('LOWER_LEG_LT', 'UPPER_LEG_LT', (x[14],y[14],z[14])),
                    ('FOOT_RT', 'LOWER_LEG_RT', (x[19],y[19],z[19])),
                    ('FOOT_LT', 'LOWER_LEG_LT', (x[15],y[15],z[15])),        
                ]
                bent = createRig('Bent', origin, boneTable1)
                
            if __name__ == "__main__":
                frame = frame + 1
                show = show + 1
                run((x[1],y[1],z[1]))
                
    else:
        c=0
        x=[]
        y=[]
        z=[]
        continue
            

A sample of the text file is as follows:

Starting new Skeleton

-0.036035 0.186498 2.44292
-0.0343151 0.253264 2.43064
-0.0286381 0.587856 2.38675
-0.0384686 0.748153 2.31253
-0.198844 0.495284 2.41571
-0.246691 0.216 2.47964
-0.305575 0.0033233 2.47963
-0.30525 -0.0561769 2.48506
0.134717 0.491634 2.40681
0.154541 0.210303 2.44875
0.167281 0.00301409 2.37609
0.161279 -0.0477938 2.36475
-0.11082 0.11611 2.44928
-0.167379 -0.302815 2.50598
-0.230857 -0.592188 2.55993
-0.241168 -0.706819 2.53712
0.0345527 0.108866 2.4533
0.0683884 -0.303279 2.53471
0.0332512 -0.62717 2.62327
0.0844642 -0.722471 2.61996
Starting new Skeleton

-0.0412893 0.184449 2.4439
-0.0394423 0.251715 2.43195
-0.0328688 0.588258 2.38885
-0.0423515 0.749065 2.31555
-0.202652 0.4943 2.41605
-0.249755 0.213982 2.47786
-0.305866 0.00137444 2.47353
-0.304916 -0.0640791 2.47949
0.130098 0.492331 2.40986
0.149291 0.20954 2.45012
0.163685 0.00216371 2.37847
0.158581 -0.0630526 2.36533
-0.116143 0.112974 2.4492
-0.173712 -0.303295 2.51102
-0.231984 -0.593073 2.56049
-0.24078 -0.708081 2.53598
0.0290188 0.107104 2.45438
0.0675733 -0.302036 2.52583
0.0450438 -0.631484 2.61522
0.112904 -0.735422 2.62614

and so on…

Now, because blender does not render armatures, I need to create a mesh around my skeleton so that it’s visible at rendering.

I’m done with creating the mesh by making a few changes to the previous code.
I’ll attach the updated code below.

I figured that since the armature is not visible anyway, I should focus on using the hide setting solely on the mesh, but like you’ll see in the updated code I’ve commented out that section in the code above because every time I run it, blender just stops responding and hangs mid-way.

Any suggestions?

Here’s the updated code:

import bpy, math
from mathutils import Vector, Matrix
filein = ‘scripts\inputdata.txt’
file = open(filein, ‘r’)

c=0
x=[]
y=[]
z=[]
frame=0
frame_num=0

def RepresentsInt(s):
try:
int(s)
return True
except ValueError:
return False
show=0
for line in file:

if (line == "

"):
continue
word = line.split()
if RepresentsInt(word[0][0]) or RepresentsInt(word[0][1]):
c=c+1
word = line.split()
x.append(float(word[0]))
y.append(float(word[1]))
z.append(float(word[2]))

    if (c==20):
        
        def createRig(name, origin, boneTable):
            
            # Create armature and object
            amt = bpy.data.armatures.new('MyRigData')
            ob = bpy.data.objects.new('MyRig', amt)
            ob.location = origin
            ob.show_x_ray = True
            # Link object to scene
            scn = bpy.context.scene
            scn.objects.link(ob)
            scn.objects.active = ob
            scn.update()
            
            bpy.ops.object.editmode_toggle()
            
            # Create bones
            bpy.ops.object.mode_set(mode='EDIT')
            for (bname, pname, vector) in boneTable:        
                bone = amt.edit_bones.new(bname)
                if pname:
                    if (bname == 'HIP_LT')or(bname =='HIP_RT'):
                        parent = amt.edit_bones[pname]
                        bone.parent = parent
                        bone.head = (x[0],y[0],z[0])
                        bone.use_connect = False
                        
                    else:
                        parent = amt.edit_bones[pname]
                        bone.parent = parent
                        bone.head = parent.tail
                        bone.use_connect = False
                        (trans, rot, scale) = parent.matrix.decompose()
                else:
                    bone.head = origin
                bone.tail = Vector(vector) 
                
                # Create mesh and object
                me = bpy.data.meshes.new('Mesh')
                ob2 = bpy.data.objects.new('MeshObject', me)
                ob2.location = origin
                # Link object to scene
                scn = bpy.context.scene
                scn.objects.link(ob2)
                scn.objects.active = ob2
                scn.update()
                
                # List of vertex coordinates
                verts = [
                    (bone.head.x+0.05,bone.head.x+0.0,bone.head.z+0.05),
                    (bone.head.x-0.05,bone.head.y+0.0,bone.head.z+0.05),
                    (bone.head.x+0.05,bone.head.y+0.0,bone.head.z-0.05),
                    (bone.head.x-0.05,bone.head.y+0.0,bone.head.z-0.05),
                    (bone.tail.x+0.05,bone.tail.y+0.0,bone.tail.z+0.05),
                    (bone.tail.x-0.05,bone.tail.y+0.0,bone.tail.z+0.05),
                    (bone.tail.x+0.05,bone.tail.y+0.0,bone.tail.z-0.05),
                    (bone.tail.x-0.05,bone.tail.y+0.0,bone.tail.z-0.05)
                ]
                # List of faces
                faces = [
                    (0, 1, 3, 2),
                    (0, 4, 6, 2),
                    (4, 5, 7, 6),
                    (5, 1, 3, 7),
                    (1, 5, 4, 0),
                    (3, 7, 6, 2),
                ]
                       
                me.from_pydata(verts, [], faces)
                me.update(calc_edges=True)
                
                '''
                bpy.ops.object.mode_set(mode='OBJECT')
                         
                
                

                current_frame = show  
                bpy.ops.anim.change_frame(frame=current_frame)  
                bpy.context.active_object.hide = False  
                bpy.context.active_object.keyframe_insert(data_path="hide",   
                                                            index=-1,   
                                                            frame=current_frame)      
                      
               
                hide=0
                for hide in range(140):

                    if hide==show:
                        continue
                    
                    current_frame = hide  
                    bpy.ops.anim.change_frame(frame=current_frame)  
                    bpy.context.active_object.hide = True  
                    bpy.context.active_object.keyframe_insert(data_path="hide",   
                                                                index=-1,   
                                                                frame=current_frame)  
                
                bpy.ops.object.mode_set(mode='EDIT')
                '''
                                  
            return ob
         
        def run(origo):
            origin = Vector(origo)

            boneTable1 = [
                ('SPINE', None, (x[2],y[2],z[2])),
                ('NECK', 'SPINE', (x[3],y[3],z[3])),
                ('SHOULDER_RT', 'SPINE', (x[8],y[8],z[8])),
                ('SHOULDER_LT', 'SPINE', (x[4],y[4],z[4])),
                ('UPPER_ARM_RT', 'SHOULDER_RT', (x[9],y[9],z[9])),
                ('UPPER_ARM_LT', 'SHOULDER_LT', (x[5],y[5],z[5])),
                ('LOWER_ARM_RT', 'UPPER_ARM_RT', (x[10],y[10],z[10])),
                ('LOWER_ARM_LT', 'UPPER_ARM_LT', (x[6],y[6],z[6])),
                ('HAND_RT', 'LOWER_ARM_RT', (x[11],y[11],z[11])),
                ('HAND_LT', 'LOWER_ARM_LT', (x[7],y[7],z[7])),
                ('HIP_RT', 'SPINE', (x[16],y[16],z[16])),
                ('HIP_LT', 'SPINE', (x[12],y[12],z[12])),
                ('UPPER_LEG_RT', 'HIP_RT', (x[17],y[17],z[17])),
                ('UPPER_LEG_LT', 'HIP_LT', (x[13],y[13],z[13])),
                ('UPPER_LEG_RT', 'UPPER_LEG_RT', (x[17],y[17],z[17])),
                ('UPPER_LEG_LT', 'UPPER_LEG_LT', (x[13],y[13],z[13])),
                ('LOWER_LEG_RT', 'UPPER_LEG_RT', (x[18],y[18],z[18])),
                ('LOWER_LEG_LT', 'UPPER_LEG_LT', (x[14],y[14],z[14])),
                ('FOOT_RT', 'LOWER_LEG_RT', (x[19],y[19],z[19])),
                ('FOOT_LT', 'LOWER_LEG_LT', (x[15],y[15],z[15])),        
            ]
            bent = createRig('Bent', origin, boneTable1)
            
        if __name__ == "__main__":
            frame = frame + 1
            show = show + 1
            run((x[1],y[1],z[1]))
            
else:
    c=0
    x=[]
    y=[]
    z=[]
    continue