Browse Source

Included changes from branch by @crobi, which correctly exported the rotation for bones. His old branch was made before the newest exporter which supported multiple animations. This exporter merges the two branches together.

Ryan Lee 11 years ago
parent
commit
41d0f663e8

+ 10 - 4
utils/exporters/blender/2.65/scripts/addons/io_mesh_threejs/__init__.py

@@ -25,7 +25,8 @@ bl_info = {
     "name": "three.js format",
     "name": "three.js format",
     "author": "mrdoob, kikko, alteredq, remoe, pxf, n3tfr34k",
     "author": "mrdoob, kikko, alteredq, remoe, pxf, n3tfr34k",
     "version": (1, 4, 0),
     "version": (1, 4, 0),
-    "blender": (2, 65, 0),
+    "blender": (2, 6, 6),
+    "api": 35622,
     "location": "File > Import-Export",
     "location": "File > Import-Export",
     "description": "Import-Export three.js meshes",
     "description": "Import-Export three.js meshes",
     "warning": "",
     "warning": "",
@@ -201,6 +202,7 @@ def save_settings_export(properties):
 
 
     "option_animation_morph" : properties.option_animation_morph,
     "option_animation_morph" : properties.option_animation_morph,
     "option_animation_skeletal" : properties.option_animation_skeletal,
     "option_animation_skeletal" : properties.option_animation_skeletal,
+    "option_frame_index_as_time" : properties.option_frame_index_as_time,
 
 
     "option_frame_step" : properties.option_frame_step,
     "option_frame_step" : properties.option_frame_step,
     "option_all_meshes" : properties.option_all_meshes,
     "option_all_meshes" : properties.option_all_meshes,
@@ -220,7 +222,7 @@ def save_settings_export(properties):
     "option_vertices_truncate" : properties.option_vertices_truncate,
     "option_vertices_truncate" : properties.option_vertices_truncate,
     "option_scale"        : properties.option_scale,
     "option_scale"        : properties.option_scale,
 
 
-    "align_model"         : properties.align_model
+    "align_model"         : properties.align_model,
     }
     }
 
 
     fname = get_settings_fullpath()
     fname = get_settings_fullpath()
@@ -263,6 +265,7 @@ def restore_settings_export(properties):
 
 
     properties.option_animation_morph = settings.get("option_animation_morph", False)
     properties.option_animation_morph = settings.get("option_animation_morph", False)
     properties.option_animation_skeletal = settings.get("option_animation_skeletal", False)
     properties.option_animation_skeletal = settings.get("option_animation_skeletal", False)
+    properties.option_frame_index_as_time = settings.get("option_frame_index_as_time", False)
 
 
     properties.option_frame_step = settings.get("option_frame_step", 1)
     properties.option_frame_step = settings.get("option_frame_step", 1)
     properties.option_all_meshes = settings.get("option_all_meshes", True)
     properties.option_all_meshes = settings.get("option_all_meshes", True)
@@ -311,6 +314,7 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
 
 
     option_animation_morph = BoolProperty(name = "Morph animation", description = "Export animation (morphs)", default = False)
     option_animation_morph = BoolProperty(name = "Morph animation", description = "Export animation (morphs)", default = False)
     option_animation_skeletal = BoolProperty(name = "Skeletal animation", description = "Export animation (skeletal)", default = False)
     option_animation_skeletal = BoolProperty(name = "Skeletal animation", description = "Export animation (skeletal)", default = False)
+    option_frame_index_as_time = BoolProperty(name = "Frame index as time", description = "Use (original) frame index as frame time", default = False)
 
 
     option_frame_step = IntProperty(name = "Frame step", description = "Animation frame step", min = 1, max = 1000, soft_min = 1, soft_max = 1000, default = 1)
     option_frame_step = IntProperty(name = "Frame step", description = "Animation frame step", min = 1, max = 1000, soft_min = 1, soft_max = 1000, default = 1)
     option_all_meshes = BoolProperty(name = "All meshes", description = "All meshes (merged)", default = True)
     option_all_meshes = BoolProperty(name = "All meshes", description = "All meshes (merged)", default = True)
@@ -321,7 +325,7 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
 
 
     @classmethod
     @classmethod
     def poll(cls, context):
     def poll(cls, context):
-        return context.active_object is not None
+        return context.active_object != None
 
 
     def execute(self, context):
     def execute(self, context):
         print("Selected: " + context.active_object.name)
         print("Selected: " + context.active_object.name)
@@ -410,6 +414,8 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
         row = layout.row()
         row = layout.row()
         row.prop(self.properties, "option_animation_skeletal")
         row.prop(self.properties, "option_animation_skeletal")
         row = layout.row()
         row = layout.row()
+        row.prop(self.properties, "option_frame_index_as_time")
+        row = layout.row()
         row.prop(self.properties, "option_frame_step")
         row.prop(self.properties, "option_frame_step")
         layout.separator()
         layout.separator()
 
 
@@ -450,4 +456,4 @@ def unregister():
     bpy.types.INFO_MT_file_import.remove(menu_func_import)
     bpy.types.INFO_MT_file_import.remove(menu_func_import)
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
-    register()
+    register()

+ 226 - 84
utils/exporters/blender/2.65/scripts/addons/io_mesh_threejs/export_threejs.py

@@ -42,7 +42,7 @@ DEFAULTS = {
 "bgalpha" : 1.0,
 "bgalpha" : 1.0,
 
 
 "position" : [0, 0, 0],
 "position" : [0, 0, 0],
-"rotation" : [0, 0, 0],
+"rotation" : [-math.pi/2, 0, 0],
 "scale"    : [1, 1, 1],
 "scale"    : [1, 1, 1],
 
 
 "camera"  :
 "camera"  :
@@ -90,7 +90,7 @@ TEMPLATE_SCENE_ASCII = """\
 	"formatVersion" : 3.2,
 	"formatVersion" : 3.2,
 	"type"          : "scene",
 	"type"          : "scene",
 	"sourceFile"    : "%(fname)s",
 	"sourceFile"    : "%(fname)s",
-	"generatedBy"   : "Blender 2.65 Exporter",
+	"generatedBy"   : "Blender 2.7 Exporter",
 	"objects"       : %(nobjects)s,
 	"objects"       : %(nobjects)s,
 	"geometries"    : %(ngeometries)s,
 	"geometries"    : %(ngeometries)s,
 	"materials"     : %(nmaterials)s,
 	"materials"     : %(nmaterials)s,
@@ -269,7 +269,7 @@ TEMPLATE_FILE_ASCII = """\
 	"metadata" :
 	"metadata" :
 	{
 	{
 		"formatVersion" : 3.1,
 		"formatVersion" : 3.1,
-		"generatedBy"   : "Blender 2.65 Exporter",
+		"generatedBy"   : "Blender 2.66 Exporter",
 		"vertices"      : %(nvertex)d,
 		"vertices"      : %(nvertex)d,
 		"faces"         : %(nface)d,
 		"faces"         : %(nface)d,
 		"normals"       : %(nnormal)d,
 		"normals"       : %(nnormal)d,
@@ -308,7 +308,8 @@ TEMPLATE_MODEL_ASCII = """\
 
 
 	"skinWeights" : [%(weights)s],
 	"skinWeights" : [%(weights)s],
 
 
-	"animations" : [%(animations)s]
+	"animation"  : {%(animation)s},
+        "animations" : [%(animations)s]
 """
 """
 
 
 TEMPLATE_VERTEX = "%g,%g,%g"
 TEMPLATE_VERTEX = "%g,%g,%g"
@@ -762,44 +763,56 @@ def get_armature():
 # (only the first armature will exported)
 # (only the first armature will exported)
 # ##############################################################################
 # ##############################################################################
 
 
-def generate_bones(option_bones, flipyz):
+def generate_bones(meshes, option_bones, flipyz):
 
 
     if not option_bones:
     if not option_bones:
         return "", 0
         return "", 0
 
 
-    armature, armatureObject = get_armature()
-    if armature is None or armatureObject is None:
+    armature, armature_object = get_armature()
+    if armature_object is None:
         return "", 0
         return "", 0
 
 
     hierarchy = []
     hierarchy = []
+    armature_matrix = armature_object.matrix_world
+    pose_bones = armature_object.pose.bones
+    #pose_bones = armature.bones
 
 
-    TEMPLATE_BONE = '{"parent":%d,"name":"%s","pos":[%g,%g,%g],"rotq":[0,0,0,1]}'
+    TEMPLATE_BONE = '{"parent":%d,"name":"%s","pos":[%g,%g,%g],"rotq":[%g,%g,%g,%g],"scl":[%g,%g,%g]}'
 
 
-    for bone in armature.bones:
-        bonePos = None
+    for pose_bone in pose_bones:
+        armature_bone = pose_bone.bone
+        #armature_bone = pose_bone
+        bonePos = armature_matrix * armature_bone.head_local
         boneIndex = None
         boneIndex = None
-        if bone.parent is None:
-            bonePos = bone.head_local
-            boneIndex = -1
+
+        if armature_bone.parent is None:
+            bone_matrix = armature_matrix * armature_bone.matrix_local
+            bone_index = -1
         else:
         else:
-            bonePos = bone.head_local - bone.parent.head_local
-            boneIndex = i = 0
-            for parent in armature.bones:
-                if parent.name == bone.parent.name:
-                    boneIndex = i
+            parent_matrix = armature_matrix * armature_bone.parent.matrix_local
+            bone_matrix = armature_matrix * armature_bone.matrix_local
+            bone_matrix = parent_matrix.inverted() * bone_matrix
+
+            bone_index = i = 0
+            for pose_parent in pose_bones:
+                armature_parent = pose_parent.bone
+                #armature_parent = pose_parent
+                if armature_parent.name == armature_bone.parent.name:
+                    bone_index = i
                 i += 1
                 i += 1
 
 
-        bonePosWorld = armatureObject.matrix_world * bonePos
+        pos, rot, scl = bone_matrix.decompose()
+
         if flipyz:
         if flipyz:
-            joint = TEMPLATE_BONE % (boneIndex, bone.name, bonePosWorld.x, bonePosWorld.z, -bonePosWorld.y)
+            joint = TEMPLATE_BONE % (bone_index, armature_bone.name, pos.x, pos.z, -pos.y, rot.x, rot.z, -rot.y, rot.w, scl.x, scl.z, scl.y)
             hierarchy.append(joint)
             hierarchy.append(joint)
         else:
         else:
-            joint = TEMPLATE_BONE % (boneIndex, bone.name, bonePosWorld.x, bonePosWorld.y, bonePosWorld.z)
+            joint = TEMPLATE_BONE % (bone_index, armature_bone.name, pos.x, pos.y,  pos.z, rot.x, rot.y,  rot.z, rot.w, scl.x, scl.y, scl.z)
             hierarchy.append(joint)
             hierarchy.append(joint)
-                
-    bones_string = ",".join(hierarchy)
 
 
-    return bones_string, len(armature.bones)
+    bones_string = ",".join(hierarchy)
+    
+    return bones_string, len(pose_bones)
 
 
 
 
 # ##############################################################################
 # ##############################################################################
@@ -814,7 +827,7 @@ def generate_indices_and_weights(meshes, option_skinning):
     indices = []
     indices = []
     weights = []
     weights = []
 
 
-    armature, armatureObject = get_armature()
+    armature, armature_object = get_armature()
 
 
     for mesh, object in meshes:
     for mesh, object in meshes:
 
 
@@ -845,9 +858,9 @@ def generate_indices_and_weights(meshes, option_skinning):
                 weight = group.weight
                 weight = group.weight
 
 
                 bone_array.append( (index, weight) )
                 bone_array.append( (index, weight) )
-
+                
             bone_array.sort(key = operator.itemgetter(1), reverse=True)
             bone_array.sort(key = operator.itemgetter(1), reverse=True)
-
+            
             # select first N bones
             # select first N bones
 
 
             for i in range(MAX_INFLUENCES):
             for i in range(MAX_INFLUENCES):
@@ -859,7 +872,7 @@ def generate_indices_and_weights(meshes, option_skinning):
                     index = bone_proxy[0]
                     index = bone_proxy[0]
                     weight = bone_proxy[1]
                     weight = bone_proxy[1]
 
 
-                    for j, bone in enumerate(armature.bones):
+                    for j, bone in enumerate(armature_object.pose.bones):
                         if object.vertex_groups[index].name == bone.name:
                         if object.vertex_groups[index].name == bone.name:
                             indices.append('%d' % j)
                             indices.append('%d' % j)
                             weights.append('%g' % weight)
                             weights.append('%g' % weight)
@@ -873,8 +886,8 @@ def generate_indices_and_weights(meshes, option_skinning):
                 else:
                 else:
                     indices.append('0')
                     indices.append('0')
                     weights.append('0')
                     weights.append('0')
-
-
+    
+    
     indices_string = ",".join(indices)
     indices_string = ",".join(indices)
     weights_string = ",".join(weights)
     weights_string = ",".join(weights)
 
 
@@ -886,23 +899,33 @@ def generate_indices_and_weights(meshes, option_skinning):
 # (only the first action will exported)
 # (only the first action will exported)
 # ##############################################################################
 # ##############################################################################
 
 
-def generate_animation(option_animation_skeletal, option_frame_step, flipyz, action_index):
+def generate_animation(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time, index):
 
 
-    if not option_animation_skeletal or len(bpy.data.actions) == 0 or len(bpy.data.actions) == 0:
+    if not option_animation_skeletal or len(bpy.data.actions) == 0:
         return ""
         return ""
 
 
     # TODO: Add scaling influences
     # TODO: Add scaling influences
 
 
-    action = bpy.data.actions[action_index]
-    armature, armatureObject = get_armature()
-    if armature is None or armatureObject is None:
+    action = bpy.data.actions[index]
+    
+    # get current context and then switch to dopesheet temporarily
+    
+    current_context = bpy.context.area.type
+    
+    bpy.context.area.type = "DOPESHEET_EDITOR"
+    bpy.context.space_data.mode = "ACTION"    
+    
+    # set active action
+    bpy.context.area.spaces.active.action = action
+    
+    armature, armature_object = get_armature()
+    if armature_object is None or armature is None:
         return "", 0
         return "", 0
-    armatureMat = armatureObject.matrix_world
-    l,r,s = armatureMat.decompose()
-    armatureRotMat = r.to_matrix()
-
-    parents = []
-    parent_index = -1
+        
+    #armature_object = bpy.data.objects['marine_rig']
+    
+        
+    armature_matrix = armature_object.matrix_world
 
 
     fps = bpy.data.scenes[0].render.fps
     fps = bpy.data.scenes[0].render.fps
 
 
@@ -911,75 +934,180 @@ def generate_animation(option_animation_skeletal, option_frame_step, flipyz, act
 
 
     frame_length = end_frame - start_frame
     frame_length = end_frame - start_frame
 
 
-    TEMPLATE_KEYFRAME_FULL  = '{"time":%g,"pos":[%g,%g,%g],"rot":[%g,%g,%g,%g],"scl":[1,1,1]}'
-    TEMPLATE_KEYFRAME       = '{"time":%g,"pos":[%g,%g,%g],"rot":[%g,%g,%g,%g]}'
-    TEMPLATE_KEYFRAME_POS   = '{"time":%g,"pos":[%g,%g,%g]}'
-    TEMPLATE_KEYFRAME_ROT   = '{"time":%g,"rot":[%g,%g,%g,%g]}'
+    used_frames = int(frame_length / option_frame_step) + 1
 
 
-    for hierarchy in armature.bones:
+    TEMPLATE_KEYFRAME_FULL  = '{"time":%g,"pos":[%g,%g,%g],"rot":[%g,%g,%g,%g],"scl":[%g,%g,%g]}'
+    TEMPLATE_KEYFRAME_BEGIN = '{"time":%g'
+    TEMPLATE_KEYFRAME_END   = '}'
+    TEMPLATE_KEYFRAME_POS   = ',"pos":[%g,%g,%g]'
+    TEMPLATE_KEYFRAME_ROT   = ',"rot":[%g,%g,%g,%g]'
+    TEMPLATE_KEYFRAME_SCL   = ',"scl":[%g,%g,%g]'
 
 
-        keys = []
+    keys = []
+    channels_location = []
+    channels_rotation = []
+    channels_scale = []
+    
+    # Precompute per-bone data
+    for pose_bone in armature_object.pose.bones:
+        armature_bone = pose_bone.bone
+        keys.append([])
+        channels_location.append(  find_channels(action, armature_bone, "location"))
+        channels_rotation.append(  find_channels(action, armature_bone, "rotation_quaternion"))
+        channels_rotation.append(  find_channels(action, armature_bone, "rotation_euler"))
+        channels_scale.append(     find_channels(action, armature_bone, "scale"))
+
+    # Process all frames
+    for frame_i in range(0, used_frames):
+
+        #print("Processing frame %d/%d" % (frame_i, used_frames))
+        # Compute the index of the current frame (snap the last index to the end)
+        frame = start_frame + frame_i * option_frame_step
+        if frame_i == used_frames-1:
+            frame = end_frame
+
+        # Compute the time of the frame
+        if option_frame_index_as_time:
+            time = frame - start_frame
+        else:
+            time = (frame - start_frame) / fps
 
 
-        for frame in range(int(start_frame), int(end_frame / option_frame_step) + 1):
+        # Let blender compute the pose bone transformations
+        bpy.data.scenes[0].frame_set(frame)
 
 
-            pos, pchange = position(hierarchy, frame * option_frame_step, action, armatureMat)
-            rot, rchange = rotation(hierarchy, frame * option_frame_step, action, armatureRotMat)
+        # Process all bones for the current frame
+        bone_index = 0
+        for pose_bone in armature_object.pose.bones:
+
+            # Extract the bone transformations
+            if pose_bone.parent is None:
+                bone_matrix = armature_matrix * pose_bone.matrix
+            else:
+                parent_matrix = armature_matrix * pose_bone.parent.matrix
+                bone_matrix = armature_matrix * pose_bone.matrix
+                bone_matrix = parent_matrix.inverted() * bone_matrix
+            pos, rot, scl = bone_matrix.decompose()
+
+            pchange = True or has_keyframe_at(channels_location[bone_index], frame)
+            rchange = True or has_keyframe_at(channels_rotation[bone_index], frame)
+            schange = True or has_keyframe_at(channels_scale[bone_index], frame)
 
 
             if flipyz:
             if flipyz:
                 px, py, pz = pos.x, pos.z, -pos.y
                 px, py, pz = pos.x, pos.z, -pos.y
                 rx, ry, rz, rw = rot.x, rot.z, -rot.y, rot.w
                 rx, ry, rz, rw = rot.x, rot.z, -rot.y, rot.w
+                sx, sy, sz = scl.x, scl.z, scl.y
             else:
             else:
                 px, py, pz = pos.x, pos.y, pos.z
                 px, py, pz = pos.x, pos.y, pos.z
                 rx, ry, rz, rw = rot.x, rot.y, rot.z, rot.w
                 rx, ry, rz, rw = rot.x, rot.y, rot.z, rot.w
+                sx, sy, sz = scl.x, scl.y, scl.z
 
 
             # START-FRAME: needs pos, rot and scl attributes (required frame)
             # START-FRAME: needs pos, rot and scl attributes (required frame)
 
 
-            if frame == int(start_frame):
+            if frame == start_frame:
 
 
-                time = (frame * option_frame_step - start_frame) / fps
-                keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw)
-                keys.append(keyframe)
+                keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw, sx, sy, sz)
+                keys[bone_index].append(keyframe)
 
 
             # END-FRAME: needs pos, rot and scl attributes with animation length (required frame)
             # END-FRAME: needs pos, rot and scl attributes with animation length (required frame)
 
 
-            elif frame == int(end_frame / option_frame_step):
+            elif frame == end_frame:
 
 
-                time = frame_length / fps
-                keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw)
-                keys.append(keyframe)
+                keyframe = TEMPLATE_KEYFRAME_FULL % (time, px, py, pz, rx, ry, rz, rw, sx, sy, sz)
+                keys[bone_index].append(keyframe)
 
 
             # MIDDLE-FRAME: needs only one of the attributes, can be an empty frame (optional frame)
             # MIDDLE-FRAME: needs only one of the attributes, can be an empty frame (optional frame)
 
 
             elif pchange == True or rchange == True:
             elif pchange == True or rchange == True:
 
 
-                time = (frame * option_frame_step - start_frame) / fps
-
-                if pchange == True and rchange == True:
-                    keyframe = TEMPLATE_KEYFRAME % (time, px, py, pz, rx, ry, rz, rw)
-                elif pchange == True:
-                    keyframe = TEMPLATE_KEYFRAME_POS % (time, px, py, pz)
-                elif rchange == True:
-                    keyframe = TEMPLATE_KEYFRAME_ROT % (time, rx, ry, rz, rw)
+                keyframe = TEMPLATE_KEYFRAME_BEGIN % time
+                if pchange == True:
+                    keyframe = keyframe + TEMPLATE_KEYFRAME_POS % (px, py, pz)
+                if rchange == True:
+                    keyframe = keyframe + TEMPLATE_KEYFRAME_ROT % (rx, ry, rz, rw)
+                if schange == True:
+                    keyframe = keyframe + TEMPLATE_KEYFRAME_SCL % (sx, sy, sz)
+                keyframe = keyframe + TEMPLATE_KEYFRAME_END
 
 
-                keys.append(keyframe)
+                keys[bone_index].append(keyframe)
+            bone_index += 1
 
 
-        keys_string = ",".join(keys)
+    # Gather data
+    parents = []
+    bone_index = 0
+    for pose_bone in armature_object.pose.bones:
+        keys_string = ",".join(keys[bone_index])
+        parent_index = bone_index - 1 # WTF? Also, this property is not used by three.js
         parent = '{"parent":%d,"keys":[%s]}' % (parent_index, keys_string)
         parent = '{"parent":%d,"keys":[%s]}' % (parent_index, keys_string)
-        parent_index += 1
+        bone_index += 1
         parents.append(parent)
         parents.append(parent)
-
     hierarchy_string = ",".join(parents)
     hierarchy_string = ",".join(parents)
-    animation_string = '"name":"%s","fps":%d,"length":%g,"hierarchy":[%s]' % (action.name, fps, (frame_length / fps), hierarchy_string)
 
 
+    if option_frame_index_as_time:
+        length = frame_length
+    else:
+        length = frame_length / fps
+
+    animation_string = '"name":"%s","fps":%d,"length":%g,"hierarchy":[%s]' % (action.name, fps, length, hierarchy_string)
+
+    bpy.data.scenes[0].frame_set(start_frame)
+
+    # reset context
+    
+    bpy.context.area.type = current_context
+    
     return animation_string
     return animation_string
 
 
-def generate_all_animations(option_animation_skeletal, option_frame_step, flipyz):
+def find_channels(action, bone, channel_type):
+    bone_name = bone.name
+    ngroups = len(action.groups)
+    result = []
+
+    # Variant 1: channels grouped by bone names
+    if ngroups > 0:
+
+        # Find the channel group for the given bone
+        group_index = -1
+        for i in range(ngroups):
+            if action.groups[i].name == bone_name:
+                group_index = i
+
+        # Get all desired channels in that group
+        if group_index > -1:
+            for channel in action.groups[group_index].channels:
+                if channel_type in channel.data_path:
+                    result.append(channel)
+
+    # Variant 2: no channel groups, bone names included in channel names
+    else:
+
+        bone_label = '"%s"' % bone_name
+
+        for channel in action.fcurves:
+            data_path = channel.data_path
+            if bone_label in data_path and channel_type in data_path:
+                result.append(channel)
+
+    return result
+
+def find_keyframe_at(channel, frame):
+    for keyframe in channel.keyframe_points:
+        if keyframe.co[0] == frame:
+            return keyframe
+    return None
+
+def has_keyframe_at(channels, frame):
+    for channel in channels:
+        if not find_keyframe_at(channel, frame) is None:
+            return True
+    return False
+
+def generate_all_animations(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time):
     all_animations_string = ""
     all_animations_string = ""
     if option_animation_skeletal:
     if option_animation_skeletal:
         for index in range(0, len(bpy.data.actions)):
         for index in range(0, len(bpy.data.actions)):
             if index != 0 :
             if index != 0 :
                 all_animations_string += ", \n"
                 all_animations_string += ", \n"
-            all_animations_string += "{" + generate_animation(option_animation_skeletal, option_frame_step, flipyz, index) + "}"
+            all_animations_string += "{" + generate_animation(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time,index) + "}"
     return all_animations_string
     return all_animations_string
 
 
 def handle_position_channel(channel, frame, position):
 def handle_position_channel(channel, frame, position):
@@ -1036,7 +1164,7 @@ def position(bone, frame, action, armatureMatrix):
 
 
     position = position * bone.matrix_local.inverted()
     position = position * bone.matrix_local.inverted()
 
 
-    if bone.parent is None:
+    if bone.parent == None:
 
 
         position.x += bone.head.x
         position.x += bone.head.x
         position.y += bone.head.y
         position.y += bone.head.y
@@ -1344,6 +1472,7 @@ def generate_ascii_model(meshes, morphs,
                          filepath,
                          filepath,
                          option_animation_morph,
                          option_animation_morph,
                          option_animation_skeletal,
                          option_animation_skeletal,
+                         option_frame_index_as_time,
                          option_frame_step):
                          option_frame_step):
 
 
     vertices = []
     vertices = []
@@ -1421,7 +1550,7 @@ def generate_ascii_model(meshes, morphs,
 
 
     faces_string, nfaces = generate_faces(normals, uv_layers, colors, meshes, option_normals, option_colors, option_uv_coords, option_materials, option_faces)
     faces_string, nfaces = generate_faces(normals, uv_layers, colors, meshes, option_normals, option_colors, option_uv_coords, option_materials, option_faces)
 
 
-    bones_string, nbone = generate_bones(option_bones, flipyz)
+    bones_string, nbone = generate_bones(meshes, option_bones, flipyz)
     indices_string, weights_string = generate_indices_and_weights(meshes, option_skinning)
     indices_string, weights_string = generate_indices_and_weights(meshes, option_skinning)
 
 
     materials_string = ",\n\n".join(materials)
     materials_string = ",\n\n".join(materials)
@@ -1444,7 +1573,8 @@ def generate_ascii_model(meshes, morphs,
     "bones"     : bones_string,
     "bones"     : bones_string,
     "indices"   : indices_string,
     "indices"   : indices_string,
     "weights"   : weights_string,
     "weights"   : weights_string,
-    "animations" : generate_all_animations(option_animation_skeletal, option_frame_step, flipyz)
+    "animation" : generate_animation(option_animation_skeletal, option_frame_step, flipyz, 0),
+    "animations" : generate_all_animations(option_animation_skeletal, option_frame_step, flipyz, option_frame_index_as_time)
     }
     }
 
 
     text = TEMPLATE_FILE_ASCII % {
     text = TEMPLATE_FILE_ASCII % {
@@ -1483,6 +1613,10 @@ def extract_meshes(objects, scene, export_single_model, option_scale, flipyz):
             if not mesh:
             if not mesh:
                 raise Exception("Error, could not get mesh data from object [%s]" % object.name)
                 raise Exception("Error, could not get mesh data from object [%s]" % object.name)
 
 
+            # preserve original name
+
+            mesh.name = object.name
+
             if export_single_model:
             if export_single_model:
 
 
                 if flipyz:
                 if flipyz:
@@ -1523,6 +1657,7 @@ def generate_mesh_string(objects, scene,
                 filepath,
                 filepath,
                 option_animation_morph,
                 option_animation_morph,
                 option_animation_skeletal,
                 option_animation_skeletal,
+                option_frame_index_as_time,
                 option_frame_step):
                 option_frame_step):
 
 
     meshes = extract_meshes(objects, scene, export_single_model, option_scale, flipyz)
     meshes = extract_meshes(objects, scene, export_single_model, option_scale, flipyz)
@@ -1587,6 +1722,7 @@ def generate_mesh_string(objects, scene,
                                 filepath,
                                 filepath,
                                 option_animation_morph,
                                 option_animation_morph,
                                 option_animation_skeletal,
                                 option_animation_skeletal,
+                                option_frame_index_as_time,
                                 option_frame_step)
                                 option_frame_step)
 
 
     # remove temp meshes
     # remove temp meshes
@@ -1614,7 +1750,8 @@ def export_mesh(objects,
                 option_copy_textures,
                 option_copy_textures,
                 option_animation_morph,
                 option_animation_morph,
                 option_animation_skeletal,
                 option_animation_skeletal,
-                option_frame_step):
+                option_frame_step,
+                option_frame_index_as_time):
 
 
     """Export single mesh"""
     """Export single mesh"""
 
 
@@ -1637,6 +1774,7 @@ def export_mesh(objects,
                 filepath,
                 filepath,
                 option_animation_morph,
                 option_animation_morph,
                 option_animation_skeletal,
                 option_animation_skeletal,
+                option_frame_index_as_time,
                 option_frame_step)
                 option_frame_step)
 
 
     write_file(filepath, text)
     write_file(filepath, text)
@@ -2181,7 +2319,7 @@ def generate_cameras(data):
                     "target"    : generate_vec3([0, 0, 0])
                     "target"    : generate_vec3([0, 0, 0])
                     }
                     }
 
 
-            elif camera.id_data.type == "ORTHO":
+                elif camera.id_data.type == "ORTHO":
 
 
                     camera_string = TEMPLATE_CAMERA_ORTHO % {
                     camera_string = TEMPLATE_CAMERA_ORTHO % {
                     "camera_id" : generate_string(camera.name),
                     "camera_id" : generate_string(camera.name),
@@ -2273,7 +2411,6 @@ def generate_lights(data):
 
 
     return ",\n\n".join(chunks), len(chunks)
     return ",\n\n".join(chunks), len(chunks)
 
 
-
 # #####################################################
 # #####################################################
 # Scene exporter - embedded meshes
 # Scene exporter - embedded meshes
 # #####################################################
 # #####################################################
@@ -2432,8 +2569,10 @@ def save(operator, context, filepath = "",
          option_copy_textures = False,
          option_copy_textures = False,
          option_animation_morph = False,
          option_animation_morph = False,
          option_animation_skeletal = False,
          option_animation_skeletal = False,
+         option_all_animations = False,
          option_frame_step = 1,
          option_frame_step = 1,
-         option_all_meshes = True):
+         option_all_meshes = True,
+         option_frame_index_as_time = False):
 
 
     #print("URL TYPE", option_url_base_html)
     #print("URL TYPE", option_url_base_html)
 
 
@@ -2497,9 +2636,10 @@ def save(operator, context, filepath = "",
                                                         filepath,
                                                         filepath,
                                                         option_animation_morph,
                                                         option_animation_morph,
                                                         option_animation_skeletal,
                                                         option_animation_skeletal,
+                                                        option_frame_index_as_time,
                                                         option_frame_step)
                                                         option_frame_step)
 
 
-                        embeds[name] = model_string
+                        embeds[object.data.name] = model_string
 
 
                     else:
                     else:
 
 
@@ -2522,7 +2662,8 @@ def save(operator, context, filepath = "",
                                     option_copy_textures,
                                     option_copy_textures,
                                     option_animation_morph,
                                     option_animation_morph,
                                     option_animation_skeletal,
                                     option_animation_skeletal,
-                                    option_frame_step)
+                                    option_frame_step,
+                                    option_frame_index_as_time)
 
 
                     geo_set.add(name)
                     geo_set.add(name)
 
 
@@ -2555,6 +2696,7 @@ def save(operator, context, filepath = "",
                     option_copy_textures,
                     option_copy_textures,
                     option_animation_morph,
                     option_animation_morph,
                     option_animation_skeletal,
                     option_animation_skeletal,
-                    option_frame_step)
+                    option_frame_step,
+                    option_frame_index_as_time)
 
 
-    return {'FINISHED'}
+    return {'FINISHED'}

+ 0 - 2
utils/exporters/blender/2.65/scripts/addons/io_mesh_threejs/import_threejs.py

@@ -130,7 +130,6 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
     if face_data["hasVertexNormals"]:
     if face_data["hasVertexNormals"]:
 
 
         print("setting vertex normals")
         print("setting vertex normals")
-        me.update(calc_tessface = True)
 
 
         for fi in range(len(faces)):
         for fi in range(len(faces)):
 
 
@@ -269,7 +268,6 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
             me.materials.append(m)
             me.materials.append(m)
 
 
         print("setting materials (faces)")
         print("setting materials (faces)")
-        me.update(calc_tessface = True)
 
 
         for fi in range(len(faces)):
         for fi in range(len(faces)):