diff options
author | Willian Padovani Germano <wpgermano@gmail.com> | 2004-06-08 09:43:00 +0400 |
---|---|---|
committer | Willian Padovani Germano <wpgermano@gmail.com> | 2004-06-08 09:43:00 +0400 |
commit | 25a0df8b711c4b7841342a069975681cba14fb33 (patch) | |
tree | 316801ac8f901c26e58949d7a2f161950200f510 /release | |
parent | a15b430d716b1cba7c07af7b14959e6061d001cc (diff) |
Scripts: Campbell (ideasman) donated two more scripts: bvh motion capture import/export (thanks!).
Diffstat (limited to 'release')
-rw-r--r-- | release/scripts/bvh_export.py | 384 | ||||
-rw-r--r-- | release/scripts/bvh_import.py | 442 |
2 files changed, 826 insertions, 0 deletions
diff --git a/release/scripts/bvh_export.py b/release/scripts/bvh_export.py new file mode 100644 index 00000000000..8c0f95fdc25 --- /dev/null +++ b/release/scripts/bvh_export.py @@ -0,0 +1,384 @@ +#!BPY + +""" +Name: 'Motion Capture (*.bvh)' +Blender: 232 +Group: 'Export' +Tip: 'Export a (*.bvh) motion capture file' +""" +#===============================================# +# BVH Export script 1.0 by Campbell Barton # +# Copyright MetaVR 30/03/2004, # +# if you have any questions about this script # +# email me ideasman@linuxmail.org # +# # +#===============================================# + +# -------------------------------------------------------------------------- +# BVH Export v0.9 by Campbell Barton (AKA Ideasman) +# -------------------------------------------------------------------------- +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ***** END GPL LICENCE BLOCK ***** +# -------------------------------------------------------------------------- + +import Blender +from Blender import Scene, Object +import math +from math import * + +# Get the current scene. +scn = Scene.GetCurrent() +context = scn.getRenderingContext() + +frameRate = 0.3333 # 0.04 = 25fps +scale = 1 + +indent = ' ' # 2 space indent per object +prefixDelimiter = '_' + +# Vars used in eular rotation funtcion +RAD_TO_DEG = 180.0/3.14159265359 + + + +#====================================================# +# Search for children of this object and return them # +#====================================================# +def getChildren(parent): + children = [] # We'll assume none. + for child in Object.Get(): + if child.getParent() == Object.Get(parent): + children.append( child.getName() ) + return children + +#====================================================# +# MESSY BUT WORKS: Make a string that shows the # +# hierarchy as a list and then eval it # +#====================================================# +def getHierarchy(root, hierarchy): + hierarchy = hierarchy + '["' + root + '",' + for child in getChildren(root): + hierarchy = getHierarchy(child, hierarchy) + hierarchy += '],' + return hierarchy + + +#====================================================# +# Strips the prefix off the name before writing # +#====================================================# +def stripName(name): # name is a string + + # WARNING!!! Special case for a custom RIG for output + # for MetaVR's HPX compatable RIG. + print 'stripname', name[0:10] + if name[0:10] == 'Transform(': + name = name[10:] + while name[-1] != ')': + name = name[0:-1] + print name + name = name[:-1] + + + return name[1+name.find(prefixDelimiter): ] + + +#====================================================# +# Return a 6 deciaml point floating point value # +# as a string that dosent have any python chars # +#====================================================# +def saneFloat(float): + #return '%(float)b' % vars() # 6 fp as house.hqx + return str('%f' % float) + ' ' + + + +#====================================================# +# Recieves an object name, gets all the data for that# +# node from blender and returns it for formatting # +# and writing to a file. # +#====================================================# +def getNodeData(nodeName): + Object.Get(nodeName) + # Get real location + offset = Object.Get(nodeName).getLocation() + offset = (offset[0]*scale, offset[1]*scale, offset[2]*scale,) + + #=========================# + # Test for X/Y/Z IPO's # + #=========================# + obipo = Object.Get(nodeName).getIpo() + + # IF we dont have an IPO then dont check the curves. + # This was added to catch end nodes that never have an IPO, only an offset. + if obipo == None: + xloc=yloc=zloc=xrot=yrot=zrot = 0 + + else: # Do have an IPO, checkout which curves are in use. + # Assume the rot's/loc's exist until proven they dont + xloc=yloc=zloc=xrot=yrot=zrot = 1 + if obipo.getCurve('LocX') == None: + xloc = 0 + if obipo.getCurve('LocY') == None: + yloc = 0 + if obipo.getCurve('LocZ') == None: + zloc = 0 + + # Now for the rotations, Because of the conversion of rotation coords + # if there is one rotation er need to store all 3 + if obipo.getCurve('RotX') == None and \ + obipo.getCurve('RotY') == None and \ + obipo.getCurve('RotZ') == None: + xrot=yrot=zrot = 0 + + # DUMMY channels xloc, yloc, zloc, xrot, yrot, zrot + # [<bool>, <bool>, <bool>, <bool>, <bool>, <bool>] + channels = [xloc, yloc, zloc, xrot, yrot, zrot] + + return offset, channels + + +#====================================================# +# Return the BVH hierarchy to a file from a list # +# hierarchy: is a list of the empty hierarcht # +# bvhHierarchy: a string, in the bvh format to write # +# level: how many levels we are down the tree, # +# ...used for indenting # +# Also gathers channelList , so we know the order to # +# write the motiondata in # +#====================================================# +def hierarchy2bvh(hierarchy, bvhHierarchy, level, channelList, nodeObjectList): + nodeName = hierarchy[0] + + # Add object to nodeObjectList + nodeObjectList.append(Object.Get(nodeName)) + + #============# + # JOINT NAME # + #============# + bvhHierarchy += level * indent + if level == 0: + # Add object to nodeObjectList + nodeObjectList.append(Object.Get(nodeName)) + bvhHierarchy+= 'ROOT ' + bvhHierarchy += stripName(nodeName) + '\n' + # If this is the last object in the list then we + # dont bother withwriting its real name, use "End Site" instead + elif len(hierarchy) == 1: + bvhHierarchy+= 'End Site\n' + # Ok This is a normal joint + else: + # Add object to nodeObjectList + nodeObjectList.append(Object.Get(nodeName)) + bvhHierarchy+= 'JOINT ' + bvhHierarchy += stripName(nodeName) + '\n' + #================# + # END JOINT NAME # + #================# + + # Indent again, this line is just for the brackets + bvhHierarchy += level * indent + '{' + '\n' + + # Indent + level += 1 + + #================================================# + # Data for writing to a file offset and channels # + #================================================# + offset, channels = getNodeData(nodeName) + + #============# + # Offset # + #============# + bvhHierarchy += level * indent + 'OFFSET ' + saneFloat(scale * offset[0]) + ' ' + saneFloat(scale * offset[1]) + ' ' + saneFloat(scale * offset[2]) + '\n' + + #============# + # Channels # + #============# + if len(hierarchy) != 1: + # Channels, remember who is where so when we write motiondata + bvhHierarchy += level * indent + 'CHANNELS ' + # Count the channels + chCount = 0 + for chn in channels: + chCount += chn + bvhHierarchy += str(chCount) + ' ' + if channels[0]: + bvhHierarchy += 'Xposition ' + channelList.append([len(nodeObjectList)-1, 0]) + if channels[1]: + bvhHierarchy += 'Yposition ' + channelList.append([len(nodeObjectList)-1, 1]) + if channels[2]: + bvhHierarchy += 'Zposition ' + channelList.append([len(nodeObjectList)-1, 2]) + if channels[5]: + bvhHierarchy += 'Zrotation ' + channelList.append([len(nodeObjectList)-1, 5]) + if channels[3]: + bvhHierarchy += 'Xrotation ' + channelList.append([len(nodeObjectList)-1, 3]) + if channels[4]: + bvhHierarchy += 'Yrotation ' + channelList.append([len(nodeObjectList)-1, 4]) + + bvhHierarchy += '\n' + + # Loop through children if any and run this function (recursively) + for hierarchyIdx in range(len(hierarchy)-1): + bvhHierarchy, level, channelList, nodeObjectList = hierarchy2bvh(hierarchy[hierarchyIdx+1], bvhHierarchy, level, channelList, nodeObjectList) + # Unindent + level -= 1 + bvhHierarchy += level * indent + '}' + '\n' + + return bvhHierarchy, level, channelList, nodeObjectList + +# added by Ben Batt 30/3/2004 to make the exported rotations correct +def ZYXToZXY(x, y, z): + ''' + Converts a set of Euler rotations (x, y, z) (which are intended to be + applied in z, y, x order) into a set which are intended to be applied in + z, x, y order (the order expected by .bvh files) + ''' + A,B = cos(x),sin(x) + C,D = cos(y),sin(y) + E,F = cos(z),sin(z) + + x = asin(-B*C) + y = atan2(D, A*C) + z = atan2(-B*D*E + A*F, B*D*F + A*E) + + # this seems to be necessary - not sure why (right/left-handed coordinates?) + x = -x + return x*RAD_TO_DEG, y*RAD_TO_DEG, z*RAD_TO_DEG + + + +def getIpoLocation(object, frame): + x = y = z = 0 + obipo = object.getIpo() + for i in range(object.getIpo().getNcurves()): + if obipo.getCurves()[i].getName() =='LocX': + x = object.getIpo().EvaluateCurveOn(i,frame) + elif obipo.getCurves()[i].getName() =='LocY': + y = object.getIpo().EvaluateCurveOn(i,frame) + elif obipo.getCurves()[i].getName() =='LocZ': + z = object.getIpo().EvaluateCurveOn(i,frame) + return x, y, z + + +#====================================================# +# Return the BVH motion for the spesified frame # +# hierarchy: is a list of the empty hierarcht # +# bvhHierarchy: a string, in the bvh format to write # +# level: how many levels we are down the tree, # +# ...used for indenting # +#====================================================# +def motion2bvh(frame, chennelList, nodeObjectList): + + motionData = '' # We'll append the frames to the string. + + for chIdx in chennelList: + ob = nodeObjectList[chIdx[0]] + chType = chIdx[1] + + # Get object rotation + x, y, z = ob.getEuler() + + # Convert the rotation from ZYX order to ZXY order + x, y, z = ZYXToZXY(x, y, z) + + + # Using regular Locations stuffs upIPO locations stuffs up + # Get IPO locations instead + xloc, yloc, zloc = getIpoLocation(ob, frame) + + # WARNING non standard Location + xloc, zloc, yloc = -xloc, yloc, zloc + + + if chType == 0: + motionData += saneFloat(scale * (xloc)) + if chType == 1: + motionData += saneFloat(scale * (yloc)) + if chType == 2: + motionData += saneFloat(scale * (zloc)) + if chType == 3: + motionData += saneFloat(x) + if chType == 4: + motionData += saneFloat(y) + if chType == 5: + motionData += saneFloat(z) + + motionData += ' ' + + motionData += '\n' + return motionData + +def saveBVH(filename): + + # Here we store a serialized list of blender objects as they appier + # in the hierarchy, this is refred to when writing motiondata + nodeObjectList = [] + + # In this list we store a 2 values for each node + # 1) An index pointing to a blender object + # in objectList + # 2) The type if channel x/y/z rot:x/y/z - Use 0-5 to indicate this + chennelList = [] + + print '' + print 'BVH 1.0 by Campbell Barton (Ideasman) - ideasman@linuxmail.org' + + # Get the active object and recursively traverse its kids to build + # the BVH hierarchy, then eval the string to make a hierarchy list. + hierarchy = eval(getHierarchy(Object.GetSelected()[0].getName(),''))[0] # somhow this returns a tuple with one list in it. + + # Put all data in the file we have selected file. + file = open(filename, "w") + file.write('HIERARCHY\n') # all bvh files have this on the first line + + # Write the whole hirarchy to a list + bvhHierarchy, level, chennelList, nodeObjectList = hierarchy2bvh(hierarchy, '', 0, chennelList, nodeObjectList) + file.write( bvhHierarchy ) # Rwite the var fileBlock to the output. + bvhHierarchy = None # Save a tit bit of memory + + #====================================================# + # MOTION: Loop through the frames ande write out # + # the motion data for each # + #====================================================# + # Do some basic motion file header stuff + file.write('MOTION\n') + file.write( 'Frames: ' + str(1 + context.endFrame() - context.startFrame()) + '\n' ) + file.write( 'Frame Time: ' + saneFloat(frameRate) + '\n' ) + + #print 'WARNING- exact frames might be stuffed up- inclusive whatever, do some tests later on.' + frames = range(context.startFrame(), context.endFrame()+1) + print 'exporting ' + str(len(frames)) + ' of motion...' + + for frame in frames: + context.currentFrame(frame) + scn.update(1) # Update locations so we can write the new locations + #Blender.Window.RedrawAll() # causes crash + + file.write( motion2bvh(frame, chennelList, nodeObjectList) ) + + file.write('\n') # newline + file.close() + print 'done' + +Blender.Window.FileSelector(saveBVH, 'SELECT NEW BVH FILE')
\ No newline at end of file diff --git a/release/scripts/bvh_import.py b/release/scripts/bvh_import.py new file mode 100644 index 00000000000..c677906f79e --- /dev/null +++ b/release/scripts/bvh_import.py @@ -0,0 +1,442 @@ +#!BPY + +""" +Name: 'Motion Capture (*.bvh)' +Blender: 232 +Group: 'Import' +Tip: 'Import a (*.bvh) motion capture file' +""" + +#===============================================# +# BVH Import script 1.0 by Campbell Barton # +# 25/03/2004, euler rotation code taken from # +# Reevan Mckay's BVH import script v1.1 # +# if you have any questions about this script # +# email me ideasman@linuxmail.org # +#===============================================# + +#===============================================# +# TODO: # +# * Create bones when importing # +# * Make an IPO jitter removal script # +# * Work out a better naming system # +#===============================================# + +# -------------------------------------------------------------------------- +# BVH Import v0.9 by Campbell Barton (AKA Ideasman) +# -------------------------------------------------------------------------- +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ***** END GPL LICENCE BLOCK ***** +# -------------------------------------------------------------------------- + + +import string +import math +import Blender +from Blender import Window, Object, Scene, Ipo +from Blender.Scene import Render + + +# # PSYCO IS CRASHING ON MY SYSTEM +# # Attempt to load psyco, speed things up +# try: +# print 'using psyco to speed up BVH importing' +# import psyco +# psyco.full() +# +# except: +# print 'psyco is not present on this system' + + +# Update as we load? +debug = 0 + +# Global scale facctor # sHOULD BE 1 BY DEFAULT +scale = 1 + +# Get the current scene. +scn = Scene.GetCurrent() +context = scn.getRenderingContext() + +# Here we store the Ipo curves in the order they load. +channelCurves = [] + +# Object list +# We need this so we can loop through the objects and edit there IPO's +# Chenging there rotation to EULER rotation +objectList = [] + +def MAT(m): + if len(m) == 3: + return Blender.Mathutils.Matrix(m[0], m[1], m[2]) + elif len(m) == 4: + return Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3]) + + + +#===============================================# +# eulerRotation: converts X, Y, Z rotation # +# to eular Rotation. This entire function # +# is copied from Reevan Mckay's BVH script # +#===============================================# +# Vars used in eular rotation funtcion +DEG_TO_RAD = math.pi/180.0 +RAD_TO_DEG = 180.0/math.pi +PI=3.14159 + +def eulerRotate(x,y,z): + #================================= + def RVMatMult3 (mat1,mat2): + #================================= + mat3=[[0.0,0.0,0.0],[0.0,0.0,0.0],[0.0,0.0,0.0]] + for i in range(3): + for k in range(3): + for j in range(3): + mat3[i][k]=mat3[i][k]+mat1[i][j]*mat2[j][k] + mat1 = mat2 = i = k = j = None # Save memory + return mat3 + + + #================================= + def RVAxisAngleToMat3 (rot4): + # Takes a direction vector and + # a rotation (in rads) and + # returns the rotation matrix. + # Graphics Gems I p. 466: + #================================= + mat3=[[0.0,0.0,0.0],[0.0,0.0,0.0],[0.0,0.0,0.0]] + if math.fabs(rot4[3])>0.01: + s=math.sin(rot4[3]) + c=math.cos(rot4[3]) + t=1.0-math.cos(rot4[3]) + else: + s=rot4[3] + c=1.0 + t=0.0 + + x=rot4[0]; y=rot4[1]; z=rot4[2] + + mat3[0][0]=t*x*x+c + mat3[0][1]=t*x*y+s*z + mat3[0][2]=t*x*z-s*y + + mat3[1][0]=t*x*y-s*z + mat3[1][1]=t*y*y+c + mat3[1][2]=t*y*z+s*x + + mat3[2][0]=t*x*z+s*y + mat3[2][1]=t*y*z-s*x + mat3[2][2]=t*z*z+c + + rot4 = s = c = t = x = y = z = None # Save some memory + return mat3 + + eul = [x,y,z] + + for jj in range(3): + while eul[jj] < 0: + eul[jj] = eul[jj] + 360.0 + while eul[jj] >= 360.0: + eul[jj] = eul[jj] - 360.0 + + eul[0] = eul[0]*DEG_TO_RAD + eul[1] = eul[1]*DEG_TO_RAD + eul[2] = eul[2]*DEG_TO_RAD + + xmat=RVAxisAngleToMat3([1,0,0,eul[0]]) + ymat=RVAxisAngleToMat3([0,1,0,eul[1]]) + zmat=RVAxisAngleToMat3([0,0,1,eul[2]]) + + mat=[[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]] + + # Standard BVH multiplication order + mat=RVMatMult3 (zmat,mat) + mat=RVMatMult3 (xmat,mat) + mat=RVMatMult3 (ymat,mat) + + + ''' + # Screwy Animation Master BVH multiplcation order + mat=RVMatMult3 (ymat,mat) + mat=RVMatMult3 (xmat,mat) + mat=RVMatMult3 (zmat,mat) + ''' + mat = MAT(mat) + + eul = mat.toEuler() + x =- eul[0]/-10 + y =- eul[1]/-10 + z =- eul[2]/-10 + + + eul = mat = zmat = xmat = ymat = jj = None + return x, y, z # Returm euler roration values. + + + +#===============================================# +# makeJoint: Here we use the node data # +# from the BVA file to create an empty # +#===============================================# +def makeJoint(name, parent, prefix, offset, channels): + # Make Empty, with the prefix in front of the name + ob = Object.New('Empty', prefix + name) # New object, ob is shorter and nicer to use. + scn.link(ob) # place the object in the current scene + + # Offset Empty + ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale) + + # Make me a child of another empty. + # Vale of None will make the empty a root node (no parent) + if parent[-1] != None: + obParent = Object.Get(prefix + parent[-1]) # We use this a bit so refrence it here. + obParent.makeParent([ob], 0, 1) #ojbs, noninverse, 1 = not fast. + + # Add Ipo's for necessary channels + newIpo = Ipo.New('Object', prefix + name) + ob.setIpo(newIpo) + for channelType in channels: + if channelType == 'Xposition': + newIpo.addCurve('LocX') + newIpo.getCurve('LocX').setInterpolation('Linear') + if channelType == 'Yposition': + newIpo.addCurve('LocY') + newIpo.getCurve('LocY').setInterpolation('Linear') + if channelType == 'Zposition': + newIpo.addCurve('LocZ') + newIpo.getCurve('LocZ').setInterpolation('Linear') + + if channelType == 'Zrotation': + newIpo.addCurve('RotZ') + newIpo.getCurve('RotZ').setInterpolation('Linear') + if channelType == 'Yrotation': + newIpo.addCurve('RotY') + newIpo.getCurve('RotY').setInterpolation('Linear') + if channelType == 'Xrotation': + newIpo.addCurve('RotX') + newIpo.getCurve('RotX').setInterpolation('Linear') + + # Add to object list + objectList.append(ob) + + ob = newIpo = opParent = None + + # Redraw if debugging + if debug: Blender.Redraw() + + +#===============================================# +# makeEnd: Here we make an end node # +# This is needed when adding the last bone # +#===============================================# +def makeEnd(parent, prefix, offset): + # Make Empty, with the prefix in front of the name, end nodes have no name so call it its parents name+'_end' + ob = Object.New('Empty', prefix + parent[-1] + '_end') # New object, ob is shorter and nicer to use. + scn.link(ob) + + # Dont check for a parent, an end node MUST have a parent + obParent = Object.Get(prefix + parent[-1]) # We use this a bit so refrence it here. + obParent.makeParent([ob], 0, 1) #ojbs, noninverse, 1 = not fast. + + # Offset Empty + ob.setLocation(offset[0]*scale, offset[1]*scale, offset[2]*scale) + + # Redraw if debugging + if debug: Blender.Redraw() + + + +#===============================================# +# MAIN FUNCTION - All things are done from here # +#===============================================# +def loadBVH(filename): + print '' + print 'BVH Importer 1.0 by Campbell Barton (Ideasman) - ideasman@linuxmail.org' + + # File loading stuff + # Open the file for importing + file = open(filename, 'r') + fileData = file.readlines() + # Make a list of lines + lines = [] + for fileLine in fileData: + newLine = string.split(fileLine) + if newLine != []: + lines.append(string.split(fileLine)) + fileData = None + # End file loading code + + # Call object names with this prefix, mainly for scenes with multiple BVH's - Can imagine most partr names are the same + # So in future + #prefix = str(len(lines)) + '_' + + prefix = '_' + + # Create Hirachy as empties + if lines[0][0] == 'HIERARCHY': + print 'Importing the BVH Hierarchy for:', filename + else: + return 'ERROR: This is not a BVH file' + + # A liniar list of ancestors to keep track of a single objects heratage + # at any one time, this is appended and removed, dosent store tree- just a liniar list. + # ZERO is a place holder that means we are a root node. (no parents) + parent = [None] + + #channelList [(<objectName>, [channelType1, channelType2...]), (<objectName>, [channelType1, channelType2...)] + channelList = [] + channelIndex = -1 + + lineIdx = 1 # An index for the file. + while lineIdx < len(lines) -1: + #... + if lines[lineIdx][0] == 'ROOT' or lines[lineIdx][0] == 'JOINT': + # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.?? + + print len(parent) * ' ' + 'node:',lines[lineIdx][1],' parent:',parent[-1] + + name = lines[lineIdx][1] + lineIdx += 2 # Incriment to the next line (Offset) + offset = ( eval(lines[lineIdx][1]), eval(lines[lineIdx][2]), eval(lines[lineIdx][3]) ) + lineIdx += 1 # Incriment to the next line (Channels) + + # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation] + # newChannel has Indecies to the motiondata, + # -1 refers to the last value that will be added on loading at a value of zero + # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value. + newChannel = [-1, -1, -1, -1, -1, -1] + for channel in lines[lineIdx][2:]: + channelIndex += 1 # So the index points to the right channel + if channel == 'Xposition': + newChannel[0] = channelIndex + elif channel == 'Yposition': + newChannel[1] = channelIndex + elif channel == 'Zposition': + newChannel[2] = channelIndex + elif channel == 'Xrotation': + newChannel[3] = channelIndex + elif channel == 'Yrotation': + newChannel[4] = channelIndex + elif channel == 'Zrotation': + newChannel[5] = channelIndex + + channelList.append(newChannel) + + channels = lines[lineIdx][2:] + + # Call funtion that uses the gatrhered data to make an empty. + makeJoint(name, parent, prefix, offset, channels) + + # If we have another child then we can call ourselves a parent, else + parent.append(name) + + # Account for an end node + if lines[lineIdx][0] == 'End' and lines[lineIdx][1] == 'Site': # There is somtimes a name afetr 'End Site' but we will ignore it. + lineIdx += 2 # Incriment to the next line (Offset) + offset = ( eval(lines[lineIdx][1]), eval(lines[lineIdx][2]), eval(lines[lineIdx][3]) ) + makeEnd(parent, prefix, offset) + + # Just so we can remove the Parents in a uniform way- End end never has kids + # so this is a placeholder + parent.append(None) + + if lines[lineIdx] == ['}']: + parent = parent[:-1] # Remove the last item + + + #=============================================# + # BVH Structure loaded, Now import motion # + #=============================================# + if lines[lineIdx] == ['MOTION']: + print '\nImporting motion data' + lineIdx += 3 # Set the cursor to the forst frame + + #=============================================# + # Loop through frames, each line a frame # + #=============================================# + currentFrame = 1 + print 'frames: ', + + + #=============================================# + # Add a ZERO keyframe, this keeps the rig # + # so when we export we know where all the # + # joints start from # + #=============================================# + obIdx = 0 + while obIdx < len(objectList) -1: + if channelList[obIdx][0] != -1: + objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame,0)) + if channelList[obIdx][1] != -1: + objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame,0)) + if channelList[obIdx][2] != -1: + objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame,0)) + if channelList[obIdx][3] != '-1' or channelList[obIdx][4] != '-1' or channelList[obIdx][5] != '-1': + objectList[obIdx].getIpo().getCurve('RotX').addBezier((currentFrame,0)) + objectList[obIdx].getIpo().getCurve('RotY').addBezier((currentFrame,0)) + objectList[obIdx].getIpo().getCurve('RotZ').addBezier((currentFrame,0)) + obIdx += 1 + + while lineIdx < len(lines): + + # Exit loop if we are past the motiondata. + # Some BVH's have extra tags like 'CONSTRAINTS and MOTIONTAGS' + # I dont know what they do and I dont care, they'll be ignored here. + if len(lines[lineIdx]) < len(objectList): + print '...ending on unknown tags' + break + + + currentFrame += 1 # Incriment to next frame + + #=============================================# + # Import motion data and assign it to an IPO # + #=============================================# + lines[lineIdx].append('0') # Use this as a dummy var for objects that dont have a rotate channel. + obIdx = 0 + if debug: Blender.Redraw() + while obIdx < len(objectList) -1: + if channelList[obIdx][0] != -1: + objectList[obIdx].getIpo().getCurve('LocX').addBezier((currentFrame, scale * eval(lines[lineIdx][channelList[obIdx][0]]))) + if channelList[obIdx][1] != -1: + objectList[obIdx].getIpo().getCurve('LocY').addBezier((currentFrame, scale * eval(lines[lineIdx][channelList[obIdx][1]]))) + if channelList[obIdx][2] != -1: + objectList[obIdx].getIpo().getCurve('LocZ').addBezier((currentFrame, scale * eval(lines[lineIdx][channelList[obIdx][2]]))) + + if channelList[obIdx][3] != '-1' or channelList[obIdx][4] != '-1' or channelList[obIdx][5] != '-1': + x, y, z = eulerRotate(eval(lines[lineIdx][channelList[obIdx][3]]), eval(lines[lineIdx][channelList[obIdx][4]]), eval(lines[lineIdx][channelList[obIdx][5]])) + objectList[obIdx].getIpo().getCurve('RotX').addBezier((currentFrame, x)) + objectList[obIdx].getIpo().getCurve('RotY').addBezier((currentFrame, y)) + objectList[obIdx].getIpo().getCurve('RotZ').addBezier((currentFrame, z)) + obIdx += 1 + # Done importing motion data # + + lines[lineIdx] = None # Scrap old motion data, save some memory? + lineIdx += 1 + # We have finished now + print currentFrame, 'done.' + + # No point in looking further, when this loop is done + # There is nothine else left to do + print 'Imported ', currentFrame, ' frames' + break + + # Main file loop + lineIdx += 1 + +Blender.Window.FileSelector(loadBVH)
\ No newline at end of file |