فهرست منبع

Transform bones and animations by the armature world matrix

Mesh vertices are already transformed
Robert Carnecky 12 سال پیش
والد
کامیت
495eb628ac
1فایلهای تغییر یافته به همراه50 افزوده شده و 33 حذف شده
  1. 50 33
      utils/exporters/blender/2.66/scripts/addons/io_mesh_threejs/export_threejs.py

+ 50 - 33
utils/exporters/blender/2.66/scripts/addons/io_mesh_threejs/export_threejs.py

@@ -697,6 +697,25 @@ def generate_uvs(uv_layers, option_uv_coords):
 
     return ",".join("[%s]" % n for n in layers)
 
+# ##############################################################################
+# Model exporter - armature
+# (only the first armature will exported)
+# ##############################################################################
+def get_armature():
+    if len(bpy.data.armatures) == 0:
+        print("Warning: no armatures in the scene")
+        return None, None
+
+    armature = bpy.data.armatures[0]
+
+    # Someone please figure out a proper way to get the armature node
+    for object in bpy.data.objects:
+        if object.type == 'ARMATURE':
+            return armature, object
+
+    print("Warning: no node of type 'ARMATURE' in the scene")
+    return None, None
+
 # ##############################################################################
 # Model exporter - bones
 # (only the first armature will exported)
@@ -704,39 +723,39 @@ def generate_uvs(uv_layers, option_uv_coords):
 
 def generate_bones(option_bones, flipyz):
 
-    if not option_bones or len(bpy.data.armatures) == 0:
+    if not option_bones:
         return "", 0
 
-    hierarchy = []
+    armature, armatureObject = get_armature()
+    if armature is None or armatureObject is None:
+        return "", 0
 
-    armature = bpy.data.armatures[0]
+    hierarchy = []
 
     TEMPLATE_BONE = '{"parent":%d,"name":"%s","pos":[%g,%g,%g],"rotq":[0,0,0,1]}'
 
     for bone in armature.bones:
+        bonePos = None
+        boneIndex = None
         if bone.parent == None:
-            if flipyz:
-                joint = TEMPLATE_BONE % (-1, bone.name, bone.head.x, bone.head.z, -bone.head.y)
-                hierarchy.append(joint)
-            else:
-                joint = TEMPLATE_BONE % (-1, bone.name, bone.head.x, bone.head.y, bone.head.z)
-                hierarchy.append(joint)
+            bonePos = bone.head_local
+            boneIndex = -1
         else:
-            index = i = 0
+            bonePos = bone.head_local - bone.parent.head_local
+            boneIndex = i = 0
             for parent in armature.bones:
                 if parent.name == bone.parent.name:
-                    index = i
+                    boneIndex = i
                 i += 1
 
-            position = bone.head_local - bone.parent.head_local
-
-            if flipyz:
-                joint = TEMPLATE_BONE % (index, bone.name, position.x, position.z, -position.y)
-                hierarchy.append(joint)
-            else:
-                joint = TEMPLATE_BONE % (index, bone.name, position.x, position.y, position.z)
-                hierarchy.append(joint)
-
+        bonePosWorld = armatureObject.matrix_world * bonePos
+        if flipyz:
+            joint = TEMPLATE_BONE % (boneIndex, bone.name, bonePosWorld.x, bonePosWorld.z, -bonePosWorld.y)
+            hierarchy.append(joint)
+        else:
+            joint = TEMPLATE_BONE % (boneIndex, bone.name, bonePosWorld.x, bonePosWorld.y, bonePosWorld.z)
+            hierarchy.append(joint)
+                
     bones_string = ",".join(hierarchy)
 
     return bones_string, len(armature.bones)
@@ -754,7 +773,7 @@ def generate_indices_and_weights(meshes, option_skinning):
     indices = []
     weights = []
 
-    armature = bpy.data.armatures[0]
+    armature, armatureObject = get_armature()
 
     for mesh, object in meshes:
 
@@ -828,13 +847,15 @@ def generate_indices_and_weights(meshes, option_skinning):
 
 def generate_animation(option_animation_skeletal, option_frame_step, flipyz):
 
-    if not option_animation_skeletal or len(bpy.data.actions) == 0 or len(bpy.data.armatures) == 0:
+    if not option_animation_skeletal or len(bpy.data.actions) == 0:
         return ""
 
     # TODO: Add scaling influences
 
     action = bpy.data.actions[0]
-    armature = bpy.data.armatures[0]
+    armature, armatureObject = get_armature()
+    if armature is None or armatureObject is None:
+        return "", 0
 
     parents = []
     parent_index = -1
@@ -857,8 +878,8 @@ def generate_animation(option_animation_skeletal, option_frame_step, flipyz):
 
         for frame in range(int(start_frame), int(end_frame / option_frame_step) + 1):
 
-            pos, pchange = position(hierarchy, frame * option_frame_step)
-            rot, rchange = rotation(hierarchy, frame * option_frame_step)
+            pos, pchange = position(hierarchy, frame * option_frame_step, action, armatureObject.matrix_world)
+            rot, rchange = rotation(hierarchy, frame * option_frame_step, action, armatureObject.matrix_world)
 
             if flipyz:
                 px, py, pz = pos.x, pos.z, -pos.y
@@ -930,16 +951,13 @@ def handle_position_channel(channel, frame, position):
 
     return change
 
-def position(bone, frame):
+def position(bone, frame, action, armatureMatrix):
 
     position = mathutils.Vector((0,0,0))
     change = False
 
-    action = bpy.data.actions[0]
     ngroups = len(action.groups)
 
-
-
     if ngroups > 0:
 
         index = 0
@@ -982,7 +1000,7 @@ def position(bone, frame):
         position.y += (bone.head * parentInvertedLocalMatrix).y + parentHeadTailDiff.y
         position.z += (bone.head * parentInvertedLocalMatrix).z + parentHeadTailDiff.z
 
-    return position, change
+    return armatureMatrix*position, change
 
 def handle_rotation_channel(channel, frame, rotation):
 
@@ -1010,7 +1028,7 @@ def handle_rotation_channel(channel, frame, rotation):
 
     return change
 
-def rotation(bone, frame):
+def rotation(bone, frame, action, armatureMatrix):
 
     # TODO: calculate rotation also from rotation_euler channels
 
@@ -1018,7 +1036,6 @@ def rotation(bone, frame):
 
     change = False
 
-    action = bpy.data.actions[0]
     ngroups = len(action.groups)
 
     # animation grouped by bones
@@ -1049,7 +1066,7 @@ def rotation(bone, frame):
                 change = change or hasChanged
 
     rot3 = rotation.to_3d()
-    rotation.xyz = rot3 * bone.matrix_local.inverted()
+    rotation.xyz = armatureMatrix * bone.matrix_local.inverted() * rot3
 
     return rotation, change