Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2011-01-01 10:26:02 +0300
committerCampbell Barton <ideasman42@gmail.com>2011-01-01 10:26:02 +0300
commita1b1ac5781c00f0b98a4ab4400ed105682b52ee8 (patch)
tree8a7456d43caf5dd0ad3b9e5d18b8f08e920017a3 /release
parent7f3fe8a2df0f5ecabdc87f441ca033b83c9fe575 (diff)
committing 2.4x bvh exporter, updating to 2.5x.
Diffstat (limited to 'release')
-rw-r--r--release/scripts/op/io_anim_bvh/export_bvh.py297
1 files changed, 297 insertions, 0 deletions
diff --git a/release/scripts/op/io_anim_bvh/export_bvh.py b/release/scripts/op/io_anim_bvh/export_bvh.py
new file mode 100644
index 00000000000..dc2c4bec1a0
--- /dev/null
+++ b/release/scripts/op/io_anim_bvh/export_bvh.py
@@ -0,0 +1,297 @@
+#!BPY
+
+"""
+Name: 'Motion Capture (.bvh)...'
+Blender: 249.2
+Group: 'Export'
+Tooltip: 'Active Armature to BVH'
+"""
+
+
+__author__ = "Campbell Barton, Andrea Rugliancich"
+__url__ = ("blender.org", "blenderartists.org")
+__version__ = "10/12/30"
+__bpydoc__ = """\
+This script exports Blender armature motion data to BHV motion capture format
+"""
+
+
+# --------------------------------------------------------------------------
+# BVH Export by Campbell Barton (AKA Ideasman), Andrea Rugliancich
+# --------------------------------------------------------------------------
+# ***** 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, Mathutils, Window, sys
+TranslationMatrix = Mathutils.TranslationMatrix
+Matrix = Blender.Mathutils.Matrix
+Vector = Blender.Mathutils.Vector
+
+import BPyMessages
+
+
+def bvh_export(filepath, ob, pref_startframe, pref_endframe, pref_scale=1.0):
+
+ Window.EditMode(0)
+ Blender.Window.WaitCursor(1)
+
+ file = open(filepath, 'w')
+
+ # bvh_nodes = {}
+ arm_data = ob.data
+ bones = arm_data.bones.values()
+
+ # Build a dictionary of bone children.
+ # None is for parentless bones
+ bone_children = {None: []}
+
+ # initialize with blank lists
+ for bone in bones:
+ bone_children[bone.name] = []
+
+ for bone in bones:
+ parent = bone.parent
+ bone_name = bone.name
+ if parent:
+ bone_children[parent.name].append(bone_name)
+ else: # root node
+ bone_children[None].append(bone_name)
+
+ # sort the children
+ for children_list in bone_children.itervalues():
+ children_list.sort()
+
+ # build a (name:bone) mapping dict
+ bone_dict = {}
+ for bone in bones:
+ bone_dict[bone.name] = bone
+
+ # bone name list in the order that the bones are written
+ bones_serialized_names = []
+
+ bone_locs = {}
+
+ file.write('HIERARCHY\n')
+
+ def write_bones_recursive(bone_name, indent):
+ my_bone_children = bone_children[bone_name]
+
+ indent_str = '\t' * indent # cache?
+
+ bone = bone_dict[bone_name]
+ loc = bone.head['ARMATURESPACE']
+ bone_locs[bone_name] = loc
+
+ # make relative if we can
+ if bone.parent:
+ loc = loc - bone_locs[bone.parent.name]
+
+ if indent:
+ file.write('%sJOINT %s\n' % (indent_str, bone_name))
+ else:
+ file.write('%sROOT %s\n' % (indent_str, bone_name))
+
+ file.write('%s{\n' % indent_str)
+ file.write('%s\tOFFSET %.6f %.6f %.6f\n' % (indent_str, loc.x * pref_scale, loc.y * pref_scale, loc.z * pref_scale))
+ file.write('%s\tCHANNELS 6 Xposition Yposition Zposition Xrotation Yrotation Zrotation\n' % indent_str)
+
+
+ if my_bone_children:
+
+ # store the location for the children
+ # to het their relative offset
+
+ # Write children
+ for child_bone in my_bone_children:
+ bones_serialized_names.append(child_bone)
+ write_bones_recursive(child_bone, indent + 1)
+
+ else:
+ # Write the bone end.
+ file.write('%s\tEnd Site\n' % indent_str)
+ file.write('%s\t{\n' % indent_str)
+ loc = bone.tail['ARMATURESPACE'] - bone_locs[bone_name]
+ file.write('%s\t\tOFFSET %.6f %.6f %.6f\n' % (indent_str, loc.x * pref_scale, loc.y * pref_scale, loc.z * pref_scale))
+ file.write('%s\t}\n' % indent_str)
+
+ file.write('%s}\n' % indent_str)
+
+
+
+ if len(bone_children[None])==1:
+ key = bone_children[None][0]
+ bones_serialized_names.append(key)
+ indent = 0
+
+ write_bones_recursive(key, indent)
+
+ else:
+ # Write a dummy parent node
+ file.write('ROOT %s\n' % key)
+ file.write('{\n')
+ file.write('\tOFFSET 0.0 0.0 0.0\n')
+ file.write('\tCHANNELS 0\n') # Xposition Yposition Zposition Xrotation Yrotation Zrotation
+ key = None
+ indent = 1
+
+ write_bones_recursive(key, indent)
+
+ file.write('}\n')
+
+
+ # redefine bones as sorted by bones_serialized_names
+ # se we can write motion
+
+ pose_dict = ob.getPose().bones
+ #pose_bones = [(pose_dict[bone_name], bone_dict[bone_name].matrix['ARMATURESPACE'].copy().invert()) for bone_name in bones_serialized_names]
+
+ class decorated_bone(object):
+ __slots__ = (\
+ 'name',# bone name, used as key in many places
+ 'parent',# decorated bone parent, set in a later loop
+ 'rest_bone',# blender armature bone
+ 'pose_bone',# blender pose bone
+ 'pose_mat',# blender pose matrix
+ 'rest_arm_mat',# blender rest matrix (armature space)
+ 'rest_local_mat',# blender rest batrix (local space)
+ 'pose_imat',# pose_mat inverted
+ 'rest_arm_imat',# rest_arm_mat inverted
+ 'rest_local_imat') # rest_local_mat inverted
+
+ def __init__(self, bone_name):
+ self.name = bone_name
+ self.rest_bone = bone_dict[bone_name]
+ self.pose_bone = pose_dict[bone_name]
+
+
+ self.pose_mat = self.pose_bone.poseMatrix
+
+ mat = self.rest_bone.matrix
+ self.rest_arm_mat = mat['ARMATURESPACE'].copy()
+ self.rest_local_mat = mat['BONESPACE'].copy().resize4x4()
+
+ # inverted mats
+ self.pose_imat = self.pose_mat.copy().invert()
+ self.rest_arm_imat = self.rest_arm_mat.copy().invert()
+ self.rest_local_imat = self.rest_local_mat.copy().invert()
+
+ self.parent = None
+
+ def update_posedata(self):
+ self.pose_mat = self.pose_bone.poseMatrix
+ self.pose_imat = self.pose_mat.copy().invert()
+
+ def __repr__(self):
+ if self.parent:
+ return '["%s" child on "%s"]\n' % (self.name, self.parent.name)
+ else:
+ return '["%s" root bone]\n' % (self.name)
+
+
+ bones_decorated = [decorated_bone(bone_name) for bone_name in bones_serialized_names]
+
+ # Assign parents
+ bones_decorated_dict = {}
+ for dbone in bones_decorated:
+ bones_decorated_dict[dbone.name] = dbone
+
+ for dbone in bones_decorated:
+ parent = dbone.rest_bone.parent
+ if parent:
+ dbone.parent = bones_decorated_dict[parent.name]
+ del bones_decorated_dict
+ # finish assigning parents
+
+ file.write('MOTION\n')
+ file.write('Frames: %d\n' % (pref_endframe - pref_startframe + 1))
+ file.write('Frame Time: %.6f\n' % 0.03)
+
+ triple = '%.6f %.6f %.6f '
+ for frame in xrange(pref_startframe, pref_endframe + 1):
+ Blender.Set('curframe', frame)
+ for dbone in bones_decorated:
+ dbone.update_posedata()
+ for dbone in bones_decorated:
+ if dbone.parent:
+ trans = TranslationMatrix(dbone.rest_bone.head['ARMATURESPACE'])
+ itrans = TranslationMatrix(-dbone.rest_bone.head['ARMATURESPACE'])
+ mat2 = dbone.rest_arm_imat * dbone.pose_mat * dbone.parent.pose_imat *dbone.parent.rest_arm_mat #FASTER
+ mat2 = trans * mat2 * itrans
+ myloc = mat2.translationPart() + (dbone.rest_bone.head['ARMATURESPACE'] - dbone.parent.rest_bone.head['ARMATURESPACE'])
+ rot = mat2.copy().transpose().toEuler()
+ else:
+ trans = TranslationMatrix(dbone.rest_bone.head['ARMATURESPACE'])
+ itrans = TranslationMatrix(-dbone.rest_bone.head['ARMATURESPACE'])
+ mat2 = dbone.rest_arm_imat * dbone.pose_mat
+ mat2 = trans * mat2 * itrans
+ myloc = mat2.translationPart() + dbone.rest_bone.head['ARMATURESPACE']
+ rot = mat2.copy().transpose().toEuler()
+
+ file.write(triple % (myloc[0] * pref_scale, myloc[1] * pref_scale, myloc[2] * pref_scale))
+ file.write(triple % (-rot[0], -rot[1], -rot[2])) #NEGATED
+
+ file.write('\n')
+
+ numframes = pref_endframe - pref_startframe + 1
+ file.close()
+
+ print'BVH Exported: %s frames:%d\n' % (filepath, numframes)
+ Blender.Window.WaitCursor(0)
+
+
+def bvh_export_ui(filepath):
+ # Dont overwrite
+ if not BPyMessages.Warning_SaveOver(filepath):
+ return
+
+ scn = Scene.GetCurrent()
+ ob_act = scn.objects.active
+ if not ob_act or ob_act.type != 'Armature':
+ BPyMessages.Error_NoArmatureActive()
+
+ arm_ob = scn.objects.active
+
+ if not arm_ob or arm_ob.type != 'Armature':
+ Blender.Draw.PupMenu('No Armature object selected.')
+ return
+
+ ctx = scn.getRenderingContext()
+ orig_frame = Blender.Get('curframe')
+ pref_startframe = Blender.Draw.Create(int(ctx.startFrame()))
+ pref_endframe = Blender.Draw.Create(int(ctx.endFrame()))
+
+ block = [\
+ ("Start Frame: ", pref_startframe, 1, 30000, "Start Bake from what frame?: Default 1"),\
+ ("End Frame: ", pref_endframe, 1, 30000, "End Bake on what Frame?"),\
+ ]
+
+ if not Blender.Draw.PupBlock("Export MDD", block):
+ return
+
+ pref_startframe, pref_endframe = \
+ min(pref_startframe.val, pref_endframe.val),\
+ max(pref_startframe.val, pref_endframe.val)
+
+ bvh_export(filepath, ob_act, pref_startframe, pref_endframe)
+ Blender.Set('curframe', orig_frame)
+
+if __name__ == '__main__':
+ Blender.Window.FileSelector(bvh_export_ui, 'EXPORT BVH', sys.makename(ext='.bvh'))