looking for how to get the xyz positions of bones at each frame in an animation

I originally posted this in the general help section, and then someone suggested I move it here.

I’m working on a project that requires the 3D locations of the joints of an animated object (specifically a hand). Right now, I have been able to pose the hand using the python api but I can’t get the positions. When I try to get the 3D locations for each frame, only the rest positions come back. If anyone could even point me in the right direction, I would be very grateful. What I would like my program to do in the end is:

1.Create poses as a single animation through python interface (done)
2.Find all of the xyz values for the head/tail of the skeleton at each frame (missing :o)
3.Print said xyz values out to a file (done)

Since I will be generating a large number of figures (several thousand per batch), the solution needs to be fully automatic.

The part that I’m having difficulty with is locating the global position of the head (or tail) of a bone at each frame. In this bit of code, I update all of the bones, redraw the scene and then try to access the positions. I searched these forums and google without much luck. Thank you in advance :smiley:

Code:

for i in xrange(24): 
pbones[i].insertKey(hand_ob, frame, Object.Pose.ROT) 
Blender.set('curFrame', frame) 
pose.update() 
hand_ob.makeDisplayList() 
# Needed to apply the modifier Window.RedrawAll() 
# View the change scn= Scene.GetCurrent() 
ob = Blender.Object.Get('hand') 
pose = ob.getPose() 
posebone = pose.bones.values() 
#print posebone.head.x vals = (posebone[i].head.x,posebone[i].head.y,posebone[i].head.z) FILE.write(fmtString % vals)

This is my full program

Code:

import Blenderfrom Blender import *scn = Scene.GetCurrent()#Load in the Armaturehand = Armature.Get('hand')hand_ob = Object.Get('hand')hand.makeEditable()Blender.Redraw()#get the pose and actionpose = hand_ob.getPose()act = hand_ob.getAction()if not act: # Add a pose action if we dont have one act = Armature.NLA.NewAction() act.setActive(hand_ob)xbones=hand_ob.data.bones.values()pbones = pose.bones.values()#print pbones#frame = 1#pbones[0].quat[:] = 1.000,0.000,0.000,0.0000#for pbone in pbones: # set bones to no rotation# pbone.quat[:] = 1.000,0.000,0.000,0.0000# pbone.insertKey(hand_ob, frame, Object.Pose.ROT)# Set a different rotation at frame 25#for i in xrange(23): #pbones[i].quat[:] = 1,-1.0000,0.0000,00000#index 0 rotation-f 0 rotation-p # 0 flex 0 0import random#print random.random()filename = "test.dat"FILE = open(filename,"w")frame = 0for flexion1 in range(1,3): #print flexion for flexion2 in range(1,3): for flexion3 in range(1,3): # print frame frame = frame + 1 pi_sec = 1/15.1 FILE.write("
") #rotation = rotation - 0.5 #1, inplane, 0, out of plane value*pi_sec pbones[7].quat[:] = 1.000, 0,0,0 #index 1, (- 0...1)flexion, 0, 0 # 1, (- 0...1)rotation-palm, 0, +/-0.15 rotation planar flexion = random.random() rotation = random.random() pbones[10].quat[:] = 1.000,-(flexion1)/8.01,-0.0000,0 pbones[22].quat[:] = 1.000,-(flexion1)/8.01,-0.0000,00000 flexion = random.random() rotation = random.random() #middle pbones[13].quat[:] = 1.000,-(flexion2)/8.02,-0.0000,0 pbones[18].quat[:] = 1.000,-(flexion2)/8.02,-0.0000,00000 flexion = random.random() rotation = random.random() #ringp 11-21 pbones[11].quat[:] = 1.000,-(flexion3)/8.01,-0.0000,0 pbones[21].quat[:] = 1.000,-(flexion3)/8.01,-0.0000,00000 flexion = random.random() rotation = random.random() #pinky 9-23 pbones[9].quat[:] = 1.000,-(flexion)*1*0,-0.0000,0 pbones[23].quat[:] = 1.000,-(flexion)*1*0,-0.0000,00000 flexion = random.random() rotation = random.random() #1,0,0,0 #thumb 1,0, 0, flex #perpflex, 1 (0... 0.5)perp flex, 0 , towards palm (0...(0.2)...(0.6) #0 8 17 pbones[0].quat[:] = 1.000,-0.0000,-0.0000,-.00000 pbones[8].quat[:] = 1.000,-0.0000,-0.0000,0 pbones[17].quat[:] = 1.000,0.,.000,0.000000 fmtString = "%f	%f	%f	" for i in xrange(24): pbones[i].insertKey(hand_ob, frame, Object.Pose.ROT) #Blender.set('curFrame', frame) #pose.update() #hand_ob.makeDisplayList() # Needed to apply the modifier Window.RedrawAll() # View the change scn= Scene.GetCurrent() ob = Blender.Object.Get('hand') pose = ob.getPose() posebone = pose.bones.values() #print posebone.head.x vals = (posebone[i].head.x,posebone[i].head.y,posebone[i].head.z) FILE.write(fmtString % vals) FILE.close()hand_ob.makeDisplayList() #hand_ob.makeDisplayList() # Needed to apply the modifierWindow.RedrawAll() # View the change

you need to multiply the pose matrix by the world matrix of the armature object.
x,y,z = (bone.poseMatrix * ob.matrixWorld).translationPart()
hope that helps

I tried using the transformation matrix, but it comes up with the same values for each frame. Am I initializing the poseBone correctly?


hand_ob = Object.Get('hand')
pose = hand_ob.getPose()
pbones = pose.bones.values()

After updating each frame, I access the values:


posebone.poseMatrix[1][1]

It seems that no matter how I update the values, I can only get the rest positions. The animation plays/renders perfectly so all of the frames are there.
Edit: And thank you for the reply :slight_smile:

I think you need to iterate the frames. Something like this:

# That's 2.4x code...........
sce = Scene.GetCurrent()
context = sce.getRenderingContext()
fs = context.sFrame
fe = context.eFrame
fc = context.currentFrame()

for i in range(fs,fe+1):
    context.currentFrame(i)
    # Bla-bla-bla for each frame HERE.........

context.currentFrame(fc)


Regards,