[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [1926] trunk/py/scripts/addons/ io_anim_bvh: support to export different rotation orders as well as pose bone native order .

Campbell Barton ideasman42 at gmail.com
Sat May 14 18:22:22 CEST 2011


Revision: 1926
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=1926
Author:   campbellbarton
Date:     2011-05-14 16:22:21 +0000 (Sat, 14 May 2011)
Log Message:
-----------
support to export different rotation orders as well as pose bone native order.

Modified Paths:
--------------
    trunk/py/scripts/addons/io_anim_bvh/__init__.py
    trunk/py/scripts/addons/io_anim_bvh/export_bvh.py
    trunk/py/scripts/addons/io_anim_bvh/import_bvh.py

Modified: trunk/py/scripts/addons/io_anim_bvh/__init__.py
===================================================================
--- trunk/py/scripts/addons/io_anim_bvh/__init__.py	2011-05-14 15:06:59 UTC (rev 1925)
+++ trunk/py/scripts/addons/io_anim_bvh/__init__.py	2011-05-14 16:22:21 UTC (rev 1926)
@@ -37,8 +37,9 @@
     import imp
     if "import_bvh" in locals():
         imp.reload(import_bvh)
+    if "export_bvh" in locals():
+        imp.reload(export_bvh)
 
-
 import bpy
 from bpy.props import StringProperty, FloatProperty, IntProperty, BoolProperty, EnumProperty
 from io_utils import ImportHelper, ExportHelper
@@ -95,6 +96,19 @@
     frame_start = IntProperty(name="Start Frame", description="Starting frame to export", default=0)
     frame_end = IntProperty(name="End Frame", description="End frame to export", default=0)
 
+    rotate_mode = EnumProperty(items=(
+            ('NATIVE', "Euler (Native)", "Use the rotation order defined in the BVH file"),
+            ('XYZ', "Euler (XYZ)", "Convert rotations to euler XYZ"),
+            ('XZY', "Euler (XZY)", "Convert rotations to euler XZY"),
+            ('YXZ', "Euler (YXZ)", "Convert rotations to euler YXZ"),
+            ('YZX', "Euler (YZX)", "Convert rotations to euler YZX"),
+            ('ZXY', "Euler (ZXY)", "Convert rotations to euler ZXY"),
+            ('ZYX', "Euler (ZYX)", "Convert rotations to euler ZYX"),
+            ),
+                name="Rotation",
+                description="Rotation conversion.",
+                default='NATIVE')
+
     @classmethod
     def poll(cls, context):
         obj = context.object

Modified: trunk/py/scripts/addons/io_anim_bvh/export_bvh.py
===================================================================
--- trunk/py/scripts/addons/io_anim_bvh/export_bvh.py	2011-05-14 15:06:59 UTC (rev 1925)
+++ trunk/py/scripts/addons/io_anim_bvh/export_bvh.py	2011-05-14 16:22:21 UTC (rev 1926)
@@ -23,8 +23,12 @@
 
 import bpy
 
+def write_armature(context, filepath, frame_start, frame_end, global_scale=1.0, rotate_mode="NATIVE"):
 
-def write_armature(context, filepath, frame_start, frame_end, global_scale=1.0):
+    def ensure_rot_order(rot_order_str):
+        if set(rot_order_str) != {'X', 'Y', 'Z'}:
+            rot_order_str = "XYZ"
+        return rot_order_str
 
     from mathutils import Matrix, Vector, Euler
     from math import degrees
@@ -62,9 +66,15 @@
         indent_str = "\t" * indent
 
         bone = arm.bones[bone_name]
+        pose_bone = obj.pose.bones[bone_name]
         loc = bone.head_local
         node_locations[bone_name] = loc
 
+        if rotate_mode == "NATIVE":
+            rot_order_str = ensure_rot_order(pose_bone.rotation_mode)
+        else:
+            rot_order_str = rotate_mode
+
         # make relative if we can
         if bone.parent:
             loc = loc - node_locations[bone.parent.name]
@@ -77,9 +87,9 @@
         file.write("%s{\n" % indent_str)
         file.write("%s\tOFFSET %.6f %.6f %.6f\n" % (indent_str, loc.x * global_scale, loc.y * global_scale, loc.z * global_scale))
         if bone.use_connect and bone.parent:
-            file.write("%s\tCHANNELS 3 Xrotation Yrotation Zrotation\n" % indent_str)
+            file.write("%s\tCHANNELS 3 %srotation %srotation %srotation\n" % (indent_str, rot_order_str[0], rot_order_str[1], rot_order_str[2]))
         else:
-            file.write("%s\tCHANNELS 6 Xposition Yposition Zposition Xrotation Yrotation Zrotation\n" % indent_str)
+            file.write("%s\tCHANNELS 6 Xposition Yposition Zposition %srotation %srotation %srotation\n" % (indent_str, rot_order_str[0], rot_order_str[1], rot_order_str[2]))
 
         if my_children:
             # store the location for the children
@@ -137,13 +147,30 @@
         "rest_local_imat",  # rest_local_mat inverted
         "prev_euler",  # last used euler to preserve euler compability in between keyframes
         "connected",  # is the bone connected to the parent bone?
+        "rot_order",
+        "rot_order_str",
         )
 
+        _eul_order_lookup = {
+            'XYZ': (0, 1, 2),
+            'XZY': (0, 2, 1),
+            'YXZ': (1, 0, 2),
+            'YZX': (1, 2, 0),
+            'ZXY': (2, 0, 1),
+            'ZYX': (2, 1, 0)}
+
         def __init__(self, bone_name):
             self.name = bone_name
             self.rest_bone = arm.bones[bone_name]
             self.pose_bone = obj.pose.bones[bone_name]
 
+            if rotate_mode == "NATIVE":
+                self.rot_order_str = ensure_rot_order(self.pose_bone.rotation_mode)
+            else:
+                self.rot_order_str = rotate_mode
+
+            self.rot_order = __class__._eul_order_lookup[self.rot_order_str]
+
             self.pose_mat = self.pose_bone.matrix
 
             mat = self.rest_bone.matrix
@@ -156,7 +183,7 @@
             self.rest_local_imat = self.rest_local_mat.inverted()
 
             self.parent = None
-            self.prev_euler = Euler((0.0, 0.0, 0.0))
+            self.prev_euler = Euler((0.0, 0.0, 0.0), self.rot_order_str)
             self.connected = (self.rest_bone.use_connect and self.rest_bone.parent)
 
         def update_posedata(self):
@@ -209,12 +236,12 @@
                 loc = mat_final.to_translation() + dbone.rest_bone.head
 
             # keep eulers compatible, no jumping on interpolation.
-            rot = mat_final.to_3x3().inverted().to_euler('XYZ', dbone.prev_euler)
+            rot = mat_final.to_3x3().inverted().to_euler(dbone.rot_order_str, dbone.prev_euler)
 
             if not dbone.connected:
                 file.write("%.6f %.6f %.6f " % (loc * global_scale)[:])
 
-            file.write("%.6f %.6f %.6f " % (-degrees(rot[0]), -degrees(rot[1]), -degrees(rot[2])))
+            file.write("%.6f %.6f %.6f " % (-degrees(rot[dbone.rot_order[0]]), -degrees(rot[dbone.rot_order[1]]), -degrees(rot[dbone.rot_order[2]])))
 
             dbone.prev_euler = rot
 
@@ -229,12 +256,14 @@
           frame_start=-1,
           frame_end=-1,
           global_scale=1.0,
+          rotate_mode="NATIVE",
           ):
 
     write_armature(context, filepath,
            frame_start=frame_start,
            frame_end=frame_end,
            global_scale=global_scale,
+           rotate_mode=rotate_mode,
            )
 
     return {'FINISHED'}

Modified: trunk/py/scripts/addons/io_anim_bvh/import_bvh.py
===================================================================
--- trunk/py/scripts/addons/io_anim_bvh/import_bvh.py	2011-05-14 15:06:59 UTC (rev 1925)
+++ trunk/py/scripts/addons/io_anim_bvh/import_bvh.py	2011-05-14 16:22:21 UTC (rev 1926)
@@ -45,7 +45,7 @@
     'has_rot',  # Conveinience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 channels[5]!=-1)
     'temp')  # use this for whatever you want
 
-    _eul_order_lookup = {\
+    _eul_order_lookup = {
         (0, 1, 2): 'XYZ',
         (0, 2, 1): 'XZY',
         (1, 0, 2): 'YXZ',



More information about the Bf-extensions-cvs mailing list