1
$\begingroup$

I am using Blender 2.49b. I have a hand model and I would like to set the bone rotation (in quaternions) to take values from text (Bone%i.txt); on each column of the text I have 4 values (W,X,Y,Z). My hand model consists of 25 bones, as can be seen in the following image.

enter image description here

So, I wrote the following script to do the job

from Blender import *
import math

# Path to data directory
dataDirectory = 'C:/Users/andarist/Desktop/Data'

# Number of frames to render
numFrames = 100

# Range of bones
handIndices = range(1,26)

# Bone file name patterns
bonePattern = 'Bone%i.txt'

# Hand object pattern
handObjectPattern = 'Bone.%03i'

# Global scale
scale = 1.0

# Global speed
speed = 1

def FrameChange():
    pass

def SetIpoForFrame(frame):
    frameIdx = (Get('curframe') - 1) * speed
    Set('curframe', frame)
    frameIdx = (frame - 1) * speed
    dataStore = Registry.GetKey('MoCapImporter')
    nanmap = { }

    # Move bones
    for handIdx in handIndices:
        handObj = Object.Get(handObjectPattern % handIdx)
        pos = dataStore['Bone'][handIdx-1][frameIdx]
        nanmap[handObjectPattern % handIdx] = False
        if(pos == None):
            nanmap[handObjectPattern % handIdx] = True
            pos = nanpos
        handObj.setRotation(scale*pos[0], scale*pos[1], scale*pos[2], scale*pos[3])
        handObj.insertIpoKey(Object.IpoKeyTypes.LOCROTSIZE)

    Scene.GetCurrent().update()

def LoadFile(pattern, index):
    fileName = dataDirectory + '/' + (pattern % index)
    file = open(fileName)
    lines = file.readlines()
    output = []
    for line in lines:
        c = line.split()
        if(c[1] == 'NaN'):
            output.append(None)
        else:
            output.append((float(c[0]), float(c[1]), float(c[2]), float(c[3])))
    file.close()
    print "Read %i lines from %s" % (len(output), fileName)
    return output

def Main():
    dataStore = { 'Bone': [] }
    # Attempt to load the data
    for handIdx in handIndices:
        data = LoadFile(bonePattern, handIdx)
        dataStore['Bone'].append(data)
    Registry.SetKey('MoCapImporter', dataStore, False)  

    for i in range(1, numFrames+1):
        print "Frame %i/%i" % (i, numFrames)
        SetIpoForFrame(i)


if((event == 'FrameChanged') or (event == 'Render')):
    FrameChange()
elif(event == ''):
    Main()

However, it seems that the Object.Get function cannot find the bone.%3i from Armatures hand, and I get the following error

enter image description here

Thanks in advance for your help and consideration.

Best Wishes,

Andreas

$\endgroup$
5
  • $\begingroup$ 2.49 .. From memory Blender.Object.Get(handObjectPattern % handIdx) returns a blender object, whereas you want to get a bone from the hand objects pose bone collection. Is there a getPose() and or PoseBoneDictionary()... $\endgroup$
    – batFINGER
    Mar 2, 2016 at 11:39
  • $\begingroup$ Unfortunately I cannot find such a function as getPose() or PoseBoneDictionary(). $\endgroup$
    – Andreas
    Mar 2, 2016 at 13:58
  • 1
    $\begingroup$ Do you really need to stay with the 6 year old version of blender? Have you tried opening your models in a recent version? You will get more python help if you are using a more recent version. $\endgroup$
    – sambler
    Mar 2, 2016 at 15:05
  • $\begingroup$ getPose example on the Pose module page blender.org/api/249PythonDoc/Pose-module.html, in particular pose = arm_ob.getPose() pbones = pose.bones.values() Agree with @sambler if you are unfamiliar with 2.49 API why not start afresh and open in recent version. $\endgroup$
    – batFINGER
    Mar 3, 2016 at 12:12
  • 1
    $\begingroup$ Thanks everyone for your help. It is true that it is much easier in later versions of Blender (e.g.v2.76). The solution to the problem is given at this post: blender.stackexchange.com/questions/48488 $\endgroup$
    – Andreas
    Mar 10, 2016 at 13:00

2 Answers 2

1
$\begingroup$

Might be hard finding someone that remembers how to use python in 2.49. The 2.49 api docs are still available here.

The second example on the armature page might be what you are looking for - while the docs list Get() as a function the example uses arm_ob.getData()

scn= Scene.GetCurrent()
arm_ob= scn.objects.active
arm_data= arm_ob.getData()
bones= arm_data.bones.values()

for bone in bones:
    # use bone here
$\endgroup$
0
$\begingroup$

Thanks everyone for your help. The answer is given by Mutant Bob on a different threat: Set the Rotation (in Quaternion WXZY) of a bone using API 2.49

    arm_ob = scn.objects.active
    bones = arm_ob.pose.bones

    for handIdx in handIndices:
        print(handIdx)
        pos = dataStore['Bone'][handIdx - 1][frameIdx]
        bone = bones[handIdx - 1]
        bone.rotation_quaternion = pos
        arm_ob.keyframe_insert(data_path = ("pose.bones[\"%s\"].rotation_quaternion"%bone.name ) )
        #bone.insertIpoKey(Object.IpoKeyTypes.LOCROTSIZE)

    scn.update()
$\endgroup$

Not the answer you're looking for? Browse other questions tagged .