Browse Source

Merge branch 'master' of http://github.com/mrdoob/three.js

alteredq 14 years ago
parent
commit
4c35acca89

+ 67 - 40
utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/__init__.py

@@ -20,7 +20,7 @@
 # Init
 # ################################################################
 
-# To support reload properly, try to access a package var, 
+# To support reload properly, try to access a package var,
 # if it's there, reload everything
 
 if "bpy" in locals():
@@ -44,16 +44,16 @@ bpy.types.Object.THREE_meshCollider = bpy.props.BoolProperty()
 bpy.types.Material.THREE_useVertexColors = bpy.props.BoolProperty()
 
 class OBJECT_PT_hello( bpy.types.Panel ):
-    
+
     bl_label = "THREE"
     bl_space_type = "PROPERTIES"
     bl_region_type = "WINDOW"
     bl_context = "object"
- 
+
     def draw(self, context):
         layout = self.layout
         obj = context.object
-        
+
         row = layout.row()
         row.label(text="Selected object: " + obj.name )
 
@@ -65,16 +65,16 @@ class OBJECT_PT_hello( bpy.types.Panel ):
 
 
 class MATERIAL_PT_hello( bpy.types.Panel ):
-    
+
     bl_label = "THREE"
     bl_space_type = "PROPERTIES"
     bl_region_type = "WINDOW"
     bl_context = "material"
- 
+
     def draw(self, context):
         layout = self.layout
         mat = context.material
-        
+
         row = layout.row()
         row.label(text="Selected material: " + mat.name )
 
@@ -123,20 +123,20 @@ import json
 
 def file_exists(filename):
     """Return true if file exists and accessible for reading.
-    
-    Should be safer than just testing for existence due to links and 
+
+    Should be safer than just testing for existence due to links and
     permissions magic on Unix filesystems.
-    
+
     @rtype: boolean
     """
-    
+
     try:
         f = open(filename, 'r')
         f.close()
         return True
     except IOError:
         return False
-    
+
 def get_settings_fullpath():
     return os.path.join(bpy.app.tempdir, SETTINGS_FILE_EXPORT)
 
@@ -153,40 +153,42 @@ def save_settings_export(properties):
     "option_uv_coords"       : properties.option_uv_coords,
     "option_edges"           : properties.option_edges,
 
-    "option_truncate"     : properties.option_truncate,
+    "option_vertices_truncate"     : properties.option_vertices_truncate,
     "option_scale"        : properties.option_scale,
 
     "align_model"         : properties.align_model
     }
-    
+
     fname = get_settings_fullpath()
     f = open(fname, "w")
     json.dump(settings, f)
-    
+
 def restore_settings_export(properties):
-    
+
     settings = {}
 
     fname = get_settings_fullpath()
     if file_exists(fname):
         f = open(fname, "r")
         settings = json.load(f)
-    
-    properties.option_export_scene = settings.get("option_export_scene", False)
-
-    properties.option_flip_yz = settings.get("option_flip_yz", True)
 
-    properties.option_materials = settings.get("option_materials", True)
+    properties.option_vertices = settings.get("option_vertices", True)
+    properties.option_vertices_truncate = settings.get("option_vertices_truncate", False)
+    properties.option_faces = settings.get("option_faces", True)
     properties.option_normals = settings.get("option_normals", True)
+    properties.option_edges = settings.get("option_edges", False)
+
     properties.option_colors = settings.get("option_colors", True)
     properties.option_uv_coords = settings.get("option_uv_coords", True)
-    properties.option_edges = settings.get("option_edges", False)
-    
-    properties.option_truncate = settings.get("option_truncate", False)
-    properties.option_scale = settings.get("option_scale", 1.0)
-    
+    properties.option_materials = settings.get("option_materials", True)
+
     properties.align_model = settings.get("align_model", "None")
 
+    properties.option_scale = settings.get("option_scale", 1.0)
+    properties.option_flip_yz = settings.get("option_flip_yz", True)
+
+    properties.option_export_scene = settings.get("option_export_scene", False)
+
 # ################################################################
 # Exporter
 # ################################################################
@@ -199,10 +201,13 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
 
     filename_ext = ".js"
 
-    option_flip_yz = BoolProperty(name = "Flip YZ", description = "Flip YZ", default = True)
-
     option_vertices = BoolProperty(name = "Vertices", description = "Export vertices", default = True)
+    option_vertices_deltas = BoolProperty(name = "Deltas", description = "Delta vertices", default = False)
+    option_vertices_truncate = BoolProperty(name = "Truncate", description = "Truncate vertices", default = False)
+
     option_faces = BoolProperty(name = "Faces", description = "Export faces", default = True)
+    option_faces_deltas = BoolProperty(name = "Deltas", description = "Delta faces", default = False)
+
     option_normals = BoolProperty(name = "Normals", description = "Export normals", default = True)
     option_edges = BoolProperty(name = "Edges", description = "Export edges", default = False)
 
@@ -210,14 +215,14 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
     option_uv_coords = BoolProperty(name = "UVs", description = "Export texture coordinates", default = True)
     option_materials = BoolProperty(name = "Materials", description = "Export materials", default = True)
 
-    option_export_scene = BoolProperty(name = "Scene", description = "Export scene", default = False)
-
-    option_truncate = BoolProperty(name = "Truncate", description = "Truncate decimals", default = False)
-    option_scale = FloatProperty(name = "Scale", description = "Scale data", min = 0.01, max = 1000.0, soft_min = 0.01, soft_max = 1000.0, default = 1.0)
-
     align_types = [("None","None","None"), ("Center","Center","Center"), ("Bottom","Bottom","Bottom"), ("Top","Top","Top")]
     align_model = EnumProperty(name = "Align model", description = "Align model", items = align_types, default = "None")
 
+    option_scale = FloatProperty(name = "Scale", description = "Scale vertices", min = 0.01, max = 1000.0, soft_min = 0.01, soft_max = 1000.0, default = 1.0)
+    option_flip_yz = BoolProperty(name = "Flip YZ", description = "Flip YZ", default = True)
+
+    option_export_scene = BoolProperty(name = "Scene", description = "Export scene", default = False)
+
     def invoke(self, context, event):
         restore_settings_export(self.properties)
         return ExportHelper.invoke(self, context, event)
@@ -242,25 +247,34 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
         layout = self.layout
 
         row = layout.row()
-        row.prop(self.properties, "option_export_scene")
-        layout.separator()
+        row.label(text="Geometry:")
 
         row = layout.row()
-        row.prop(self.properties, "option_flip_yz")
+        row.prop(self.properties, "option_vertices")
+        row = layout.row()
+        row.enabled = self.properties.option_vertices
+        # row.prop(self.properties, "option_vertices_deltas")
+        row.prop(self.properties, "option_vertices_truncate")
         layout.separator()
 
         row = layout.row()
-        row.prop(self.properties, "align_model")
+        row.prop(self.properties, "option_faces")
+        row = layout.row()
+        row.enabled = self.properties.option_faces
+        # row.prop(self.properties, "option_faces_deltas")
         layout.separator()
 
         row = layout.row()
-        row.prop(self.properties, "option_vertices")
         row.prop(self.properties, "option_normals")
+        layout.separator()
+
         row = layout.row()
-        row.prop(self.properties, "option_faces")
         row.prop(self.properties, "option_edges")
         layout.separator()
 
+        row = layout.row()
+        row.label(text="Materials:")
+
         row = layout.row()
         row.prop(self.properties, "option_uv_coords")
         row.prop(self.properties, "option_colors")
@@ -269,8 +283,21 @@ class ExportTHREEJS(bpy.types.Operator, ExportHelper):
         layout.separator()
 
         row = layout.row()
-        row.prop(self.properties, "option_truncate")
+        row.label(text="Settings:")
+
+        row = layout.row()
+        row.prop(self.properties, "align_model")
+        row = layout.row()
+        row.prop(self.properties, "option_flip_yz")
         row.prop(self.properties, "option_scale")
+        layout.separator()
+
+        row = layout.row()
+        row.label(text="Beta:")
+
+        row = layout.row()
+        row.prop(self.properties, "option_export_scene")
+        layout.separator()
 
 
 # ################################################################

+ 190 - 190
utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/export_threejs.py

@@ -49,7 +49,7 @@ DEFAULTS = {
 "rotation" : [-math.pi/2, 0, 0],
 "scale"    : [1, 1, 1],
 
-"camera"  : 
+"camera"  :
     {
         "name" : "default_camera",
         "type" : "perspective",
@@ -71,7 +71,7 @@ DEFAULTS = {
  }
 }
 
-# default colors for debugging (each material gets one distinct color): 
+# default colors for debugging (each material gets one distinct color):
 # white, red, green, blue, yellow, cyan, magenta
 COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
 
@@ -90,7 +90,7 @@ TEMPLATE_SCENE_ASCII = """\
  * geometries: %(ngeometries)s
  * materials:  %(nmaterials)s
  * textures:   %(ntextures)s
- */  
+ */
 
 var scene = {
 
@@ -99,14 +99,14 @@ var scene = {
 
 %(sections)s
 
-"transform" : 
+"transform" :
 {
     "position"  : %(position)s,
     "rotation"  : %(rotation)s,
     "scale"     : %(scale)s,
 },
 
-"defaults" : 
+"defaults" :
 {
     "bgcolor" : %(bgcolor)s,
     "bgalpha" : %(bgalpha)f,
@@ -120,7 +120,7 @@ close();
 """
 
 TEMPLATE_SECTION = """
-"%s" : 
+"%s" :
 {
 %s
 },
@@ -154,7 +154,7 @@ TEMPLATE_TEXTURE = """\
 TEMPLATE_MATERIAL_SCENE = """\
     %(material_id)s : {
         "type": %(type)s,
-        "parameters": { %(parameters)s } 
+        "parameters": { %(parameters)s }
     }"""
 
 TEMPLATE_CAMERA_PERSPECTIVE = """\
@@ -225,9 +225,9 @@ TEMPLATE_FILE_ASCII = """\
 var model = {
 
     "version" : 2,
-    
+
     "scale" : %(scale)f,
-    
+
     "materials": [%(materials)s],
 
     "vertices": [%(vertices)s],
@@ -271,15 +271,15 @@ def veckey3d(v):
 
 def veckey2d(v):
     return round(v[0], 6), round(v[1], 6)
-    
+
 def get_normal_indices(v, normals, mesh):
     n = []
     mv = mesh.vertices
 
     for i in v:
-        normal = mv[i].normal        
+        normal = mv[i].normal
         key = veckey3d(normal)
-        
+
         n.append( normals[key] )
 
     return n
@@ -315,7 +315,7 @@ def write_file(fname, content):
 
 def ensure_folder_exist(foldername):
     """Create folder (with whole path) if it doesn't exist yet."""
-    
+
     if not os.access(foldername, os.R_OK|os.W_OK|os.X_OK):
         os.makedirs(foldername)
 
@@ -323,13 +323,13 @@ def ensure_extension(filepath, extension):
     if not filepath.lower().endswith(extension):
         filepath += extension
     return filepath
-    
+
 def generate_mesh_filename(meshname, filepath):
     normpath = os.path.normpath(filepath)
     path, ext = os.path.splitext(normpath)
     return "%s.%s%s" % (path, meshname, ext)
-    
-    
+
+
 # #####################################################
 # Utils - alignment
 # #####################################################
@@ -410,36 +410,36 @@ def bottom(vertices):
     translate(vertices, [-cx,-cy,-cz])
 
 # #####################################################
-# Elements rendering 
+# Elements rendering
 # #####################################################
 
 def hexcolor(c):
     return ( int(c[0] * 255) << 16  ) + ( int(c[1] * 255) << 8 ) + int(c[2] * 255)
 
-def generate_vertices(vertices, option_truncate, option_vertices):
+def generate_vertices(vertices, option_vertices_truncate, option_vertices):
     if not option_vertices:
         return ""
 
-    return ",".join(generate_vertex(v, option_truncate) for v in vertices)
+    return ",".join(generate_vertex(v, option_vertices_truncate) for v in vertices)
 
-def generate_vertex(v, option_truncate):
-    if not option_truncate:
+def generate_vertex(v, option_vertices_truncate):
+    if not option_vertices_truncate:
         return TEMPLATE_VERTEX % (v.co.x, v.co.y, v.co.z)
     else:
         return TEMPLATE_VERTEX_TRUNCATE % (v.co.x, v.co.y, v.co.z)
 
 def generate_normal(n):
     return TEMPLATE_N % (n[0], n[1], n[2])
-    
+
 def generate_vertex_color(c):
     return TEMPLATE_C % c
-    
+
 def generate_uv(uv):
     return TEMPLATE_UV % (uv[0], 1.0 - uv[1])
 
 def generate_edge(e):
     return TEMPLATE_EDGE % (e.vertices[0], e.vertices[1])
-    
+
 # #####################################################
 # Model exporter - faces
 # #####################################################
@@ -460,20 +460,20 @@ def generate_faces(normals, uvs, colors, mesh, option_normals, option_colors, op
 
 def generate_face(f, faceIndex, normals, uvs, colors, mesh, option_normals, option_colors, option_uv_coords, option_materials, flipyz):
     isTriangle = ( len(f.vertices) == 3 )
-    
+
     if isTriangle:
         nVertices = 3
     else:
         nVertices = 4
-        
+
     hasMaterial = option_materials
-    
+
     hasFaceUvs = False # not supported in Blender
     hasFaceVertexUvs = option_uv_coords
 
     hasFaceNormals = False # don't export any face normals (as they are computed in engine)
     hasFaceVertexNormals = option_normals
-    
+
     hasFaceColors = False       # not supported in Blender
     hasFaceVertexColors = option_colors
 
@@ -485,12 +485,12 @@ def generate_face(f, faceIndex, normals, uvs, colors, mesh, option_normals, opti
     faceType = setBit(faceType, 4, hasFaceNormals)
     faceType = setBit(faceType, 5, hasFaceVertexNormals)
     faceType = setBit(faceType, 6, hasFaceColors)
-    faceType = setBit(faceType, 7, hasFaceVertexColors)    
-    
+    faceType = setBit(faceType, 7, hasFaceVertexColors)
+
     faceData = []
-    
+
     # order is important, must match order in JSONLoader
-    
+
     # face type
     # vertex indices
     # material index
@@ -498,15 +498,15 @@ def generate_face(f, faceIndex, normals, uvs, colors, mesh, option_normals, opti
     # face vertex uvs indices
     # face color index
     # face vertex colors indices
-    
-    faceData.append(faceType)    
-    
+
+    faceData.append(faceType)
+
     # must clamp in case on polygons bigger than quads
 
     for i in range(nVertices):
         index = f.vertices[i]
         faceData.append(index)
-    
+
     if hasMaterial:
         faceData.append( f.material_index )
 
@@ -521,7 +521,7 @@ def generate_face(f, faceIndex, normals, uvs, colors, mesh, option_normals, opti
         for i in range(nVertices):
             index = n[i]
             faceData.append(index)
-            
+
     if hasFaceVertexColors:
         c = get_color_indices(faceIndex, colors, mesh)
         for i in range(nVertices):
@@ -544,10 +544,10 @@ def extract_vertex_normals(mesh, option_normals):
 
     for f in mesh.faces:
         for v in f.vertices:
-            
-            normal = mesh.vertices[v].normal            
+
+            normal = mesh.vertices[v].normal
             key = veckey3d(normal)
-                
+
             if key not in normals:
                 normals[key] = count
                 count += 1
@@ -569,7 +569,7 @@ def generate_normals(normals, option_normals):
 # #####################################################
 
 def extract_vertex_colors(mesh, option_colors):
-    
+
     if not option_colors:
         return {}, 0
 
@@ -579,10 +579,10 @@ def extract_vertex_colors(mesh, option_colors):
     color_layer = mesh.vertex_colors.active.data
 
     for face_index, face in enumerate(mesh.faces):
-        
+
         face_colors = color_layer[face_index]
         face_colors = face_colors.color1, face_colors.color2, face_colors.color3, face_colors.color4
-    
+
         for c in face_colors:
             key = hexcolor(c)
             if key not in colors:
@@ -697,7 +697,7 @@ def generate_materials(mtl, materials, draw_type):
         if draw_type in [ "BOUNDS", "WIRE" ]:
             mtl[m]['wireframe'] = True
             mtl[m]['DbgColor'] = 0xff0000
-            
+
         mtl_raw = ",\n".join(['\t"%s" : %s' % (n, value2string(v)) for n,v in sorted(mtl[m].items())])
         mtl_string = "\t{\n%s\n\t}" % mtl_raw
         mtl_array.append([index, mtl_string])
@@ -712,7 +712,7 @@ def extract_materials(mesh, scene, option_colors):
         if m:
             materials[m.name] = {}
             material = materials[m.name]
-            
+
             material['colorDiffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
                                         m.diffuse_intensity * m.diffuse_color[1],
                                         m.diffuse_intensity * m.diffuse_color[2]]
@@ -724,7 +724,7 @@ def extract_materials(mesh, scene, option_colors):
             world_ambient_color = [0, 0, 0]
             if world:
                 world_ambient_color = world.ambient_color
-                
+
             material['colorAmbient'] = [m.ambient * world_ambient_color[0],
                                         m.ambient * world_ambient_color[1],
                                         m.ambient * world_ambient_color[2]]
@@ -744,7 +744,7 @@ def extract_materials(mesh, scene, option_colors):
                 material['mapDiffuse'] = fn_strip
 
             material["vertexColors"] = m.THREE_useVertexColors and option_colors
-            
+
             # can't really use this reliably to tell apart Phong from Lambert
             # as Blender defaults to non-zero specular color
             #if m.specular_intensity > 0.0 and (m.specular_color[0] > 0 or m.specular_color[1] > 0 or m.specular_color[2] > 0):
@@ -771,11 +771,11 @@ def generate_materials_string(mesh, scene, option_colors, draw_type):
         materials = { 'default':0 }
 
     # default dummy materials
-    
+
     mtl = generate_mtl(materials)
 
     # extract real materials from the mesh
-    
+
     mtl.update(extract_materials(mesh, scene, option_colors))
 
     return generate_materials(mtl, materials, draw_type)
@@ -784,18 +784,18 @@ def generate_materials_string(mesh, scene, option_colors, draw_type):
 # ASCII model generator
 # #####################################################
 
-def generate_ascii_model(mesh, scene, 
-                         option_vertices, 
-                         option_faces, 
-                         option_normals, 
-                         option_edges, 
-                         option_uv_coords, 
-                         option_materials, 
-                         option_colors, 
-                         align_model, 
-                         flipyz, 
-                         option_truncate, 
-                         option_scale, 
+def generate_ascii_model(mesh, scene,
+                         option_vertices,
+                         option_vertices_truncate,
+                         option_faces,
+                         option_normals,
+                         option_edges,
+                         option_uv_coords,
+                         option_materials,
+                         option_colors,
+                         align_model,
+                         flipyz,
+                         option_scale,
                          draw_type):
 
     vertices = mesh.vertices[:]
@@ -813,15 +813,15 @@ def generate_ascii_model(mesh, scene,
 
     materials_string = ""
     nmaterial = 0
-    
+
     edges_string = ""
     nedges = 0
-    
+
     if option_materials:
         materials_string, nmaterial = generate_materials_string(mesh, scene, option_colors, draw_type)
 
     if option_edges:
-        nedges = len(mesh.edges) 
+        nedges = len(mesh.edges)
         edges_string  = ",".join(generate_edge(e) for e in mesh.edges)
 
     text = TEMPLATE_FILE_ASCII % {
@@ -841,7 +841,7 @@ def generate_ascii_model(mesh, scene,
 
     "materials" : materials_string,
 
-    "vertices" : generate_vertices(vertices, option_truncate, option_vertices),
+    "vertices" : generate_vertices(vertices, option_vertices_truncate, option_vertices),
 
     "faces"    : generate_faces(normals, uvs, colors, mesh, option_normals, option_colors, option_uv_coords, option_materials, flipyz, option_faces),
 
@@ -851,29 +851,29 @@ def generate_ascii_model(mesh, scene,
 
     return text
 
-    
+
 # #####################################################
 # Model exporter - export single mesh
 # #####################################################
 
-def export_mesh(obj, scene, filepath, 
-                option_vertices, 
-                option_faces, 
-                option_normals, 
-                option_edges, 
-                option_uv_coords, 
-                option_materials, 
-                option_colors, 
-                align_model, 
-                flipyz, 
-                option_truncate, 
-                option_scale, 
+def export_mesh(obj, scene, filepath,
+                option_vertices,
+                option_vertices_truncate,
+                option_faces,
+                option_normals,
+                option_edges,
+                option_uv_coords,
+                option_materials,
+                option_colors,
+                align_model,
+                flipyz,
+                option_scale,
                 export_single_model):
 
     """Export single mesh"""
 
     # collapse modifiers into mesh
-    
+
     mesh = obj.create_mesh(scene, True, 'RENDER')
 
     if not mesh:
@@ -910,18 +910,18 @@ def export_mesh(obj, scene, filepath,
         if not active_col_layer:
             option_colors = False
 
-    text = generate_ascii_model(mesh, scene, 
-                                option_vertices, 
-                                option_faces, 
-                                option_normals, 
-                                option_edges, 
-                                option_uv_coords, 
-                                option_materials, 
-                                option_colors, 
-                                align_model, 
-                                flipyz, 
-                                option_truncate, 
-                                option_scale, 
+    text = generate_ascii_model(mesh, scene,
+                                option_vertices,
+                                option_vertices_truncate,
+                                option_faces,
+                                option_normals,
+                                option_edges,
+                                option_uv_coords,
+                                option_materials,
+                                option_colors,
+                                align_model,
+                                flipyz,
+                                option_scale,
                                 obj.draw_type)
 
     write_file(filepath, text)
@@ -931,8 +931,8 @@ def export_mesh(obj, scene, filepath,
     bpy.data.meshes.remove(mesh)
 
     print("writing", filepath, "done")
-    
-    
+
+
 # #####################################################
 # Scene exporter - render elements
 # #####################################################
@@ -948,49 +948,49 @@ def generate_vec2(vec):
 
 def generate_hex(number):
     return TEMPLATE_HEX % number
-    
+
 def generate_string(s):
     return TEMPLATE_STRING % s
-    
+
 def generate_string_list(src_list):
     return ", ".join(generate_string(item) for item in src_list)
-    
+
 def generate_section(label, content):
     return TEMPLATE_SECTION % (label, content)
-    
+
 def get_mesh_filename(mesh):
     object_id = mesh["data"]["name"]
     filename = "%s.js" % sanitize(object_id)
     return filename
-    
+
 def generate_material_id_list(materials):
     chunks = []
     for material in materials:
         chunks.append(material.name)
-    
+
     return chunks
-    
+
 def generate_group_id_list(obj):
     chunks = []
-    
+
     for group in bpy.data.groups:
         if obj.name in group.objects:
             chunks.append(group.name)
-        
+
     return chunks
-    
+
 def generate_bool_property(property):
     if property:
         return "true"
     return "false"
-    
+
 # #####################################################
 # Scene exporter - objects
 # #####################################################
 
 def generate_objects(data):
     chunks = []
-    
+
     for obj in data["objects"]:
         if obj.type == "MESH":
             object_id = obj.name
@@ -1018,11 +1018,11 @@ def generate_objects(data):
 
             castsShadow = obj.THREE_castsShadow
             meshCollider = obj.THREE_meshCollider
-                
+
             visible = True
             if obj.draw_type in ["BOUNDS", "WIRE"] and meshCollider:
                 visible = False
-            
+
             object_string = TEMPLATE_OBJECT % {
             "object_id"   : generate_string(object_id),
             "geometry_id" : generate_string(geometry_id),
@@ -1039,55 +1039,55 @@ def generate_objects(data):
             "visible"      : generate_bool_property(visible)
             }
             chunks.append(object_string)
-        
+
     return ",\n\n".join(chunks), len(chunks)
-    
+
 # #####################################################
 # Scene exporter - geometries
 # #####################################################
 
 def generate_geometries(data):
     chunks = []
-    
+
     geo_set = set()
-    
+
     for obj in data["objects"]:
         if obj.type == "MESH":
-            
+
             if len(obj.modifiers) > 0:
                 name = obj.name
             else:
                 name = obj.data.name
-            
+
             if name not in geo_set:
 
                 geometry_id = "geo_%s" % name
                 model_filename = os.path.basename(generate_mesh_filename(name, data["filepath"]))
-                
+
                 geometry_string = TEMPLATE_GEOMETRY % {
                 "geometry_id" : generate_string(geometry_id),
                 "model_file"  : generate_string(model_filename)
                 }
                 chunks.append(geometry_string)
-                
+
                 geo_set.add(name)
-        
+
     return ",\n\n".join(chunks), len(chunks)
-    
+
 # #####################################################
 # Scene exporter - textures
 # #####################################################
 
 def generate_textures_scene(data):
     chunks = []
-    
+
     # TODO: extract just textures actually used by some objects in the scene
-    
+
     for img in bpy.data.images:
-        
+
         texture_id = img.name
         texture_file = extract_texture_filename(img)
-    
+
         texture_string = TEMPLATE_TEXTURE % {
         "texture_id"   : generate_string(texture_id),
         "texture_file" : generate_string(texture_file)
@@ -1101,16 +1101,16 @@ def extract_texture_filename(image):
     fn = os.path.normpath(fn)
     fn_strip = os.path.basename(fn)
     return fn_strip
-    
+
 # #####################################################
 # Scene exporter - materials
 # #####################################################
 
 def extract_material_data(m):
     world = bpy.context.scene.world
-    
+
     material = { 'name': m.name }
-    
+
     material['colorDiffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
                                 m.diffuse_intensity * m.diffuse_color[1],
                                 m.diffuse_intensity * m.diffuse_color[2]]
@@ -1122,7 +1122,7 @@ def extract_material_data(m):
     world_ambient_color = [0, 0, 0]
     if world:
         world_ambient_color = world.ambient_color
-        
+
     material['colorAmbient'] = [m.ambient * world_ambient_color[0],
                                 m.ambient * world_ambient_color[1],
                                 m.ambient * world_ambient_color[2]]
@@ -1137,8 +1137,8 @@ def extract_material_data(m):
 
     material['mapDiffuse'] = ""
     material['mapLight'] = ""
-    material['mapNormal'] = ""    
-        
+    material['mapNormal'] = ""
+
     # just take first textures of each, for the moment three.js materials can't handle more
 
     for i in range(len(m.texture_slots)):
@@ -1155,23 +1155,23 @@ def extract_material_data(m):
                         material['mapDiffuse'] = name
                     else:
                         material['mapLight'] = name
-                
+
                 if material['mapDiffuse'] and material['mapNormal'] and material['mapLight']:
                     break
-        
+
     if m.specular_intensity > 0.0 and (m.specular_color[0] > 0 or m.specular_color[1] > 0 or m.specular_color[2] > 0):
         material['shading'] = "Phong"
     else:
         material['shading'] = "Lambert"
-        
+
     return material
-    
+
 def generate_material_string(material):
     type_map = {
     "Lambert"   : "MeshLambertMaterial",
     "Phong"     : "MeshPhongMaterial"
     }
-    
+
     material_id = material["name"]
     shading = material["shading"]
     material_type = type_map.get(shading, "MeshBasicMaterial")
@@ -1203,14 +1203,14 @@ def generate_material_string(material):
     "type"        : generate_string(material_type),
     "parameters"  : parameters
     }
-    
+
     return material_string
-    
+
 def generate_materials_scene(data):
     chunks = []
 
     # TODO: extract just materials actually used by some objects in the scene
-    
+
     for m in bpy.data.materials:
         material = extract_material_data(m)
         material_string = generate_material_string(material)
@@ -1226,7 +1226,7 @@ def generate_cameras(data):
     cameras = data.get("cameras", [])
     if not cameras:
         cameras.append(DEFAULTS["camera"])
-        
+
     chunks = []
     for camera in cameras:
 
@@ -1253,9 +1253,9 @@ def generate_cameras(data):
             "position"  : generate_vec3(camera["position"]),
             "target"    : generate_vec3(camera["target"])
             }
-            
+
         chunks.append(camera_string)
-        
+
     return ",\n\n".join(chunks)
 
 # #####################################################
@@ -1266,7 +1266,7 @@ def generate_lights(data):
     lights = data.get("lights", [])
     if not lights:
         lights.append(DEFAULTS["light"])
-        
+
     chunks = []
     for light in lights:
 
@@ -1287,9 +1287,9 @@ def generate_lights(data):
             "color"         : rgb2int(light["color"]),
             "intensity"     : light["intensity"]
             }
-            
+
         chunks.append(light_string)
-            
+
     return ",\n\n".join(chunks)
 
 # #####################################################
@@ -1305,7 +1305,7 @@ def generate_ascii_scene(data):
 
     cameras = generate_cameras(data)
     lights = generate_lights(data)
-    
+
     sections = [
     ["objects",    objects],
     ["geometries", geometries],
@@ -1314,16 +1314,16 @@ def generate_ascii_scene(data):
     ["cameras",    cameras],
     ["lights",     lights]
     ]
-    
+
     chunks = []
     for label, content in sections:
         if content:
             chunks.append(generate_section(label, content))
 
     sections_string = "\n".join(chunks)
-    
+
     default_camera = "default_camera"
-    
+
     parameters = {
     "fname"     : data["source_file"],
 
@@ -1337,16 +1337,16 @@ def generate_ascii_scene(data):
     "ngeometries"   : ngeometries,
     "ntextures"     : ntextures,
     "nmaterials"    : nmaterials,
-    
+
     "position"      : generate_vec3(DEFAULTS["position"]),
     "rotation"      : generate_vec3(DEFAULTS["rotation"]),
     "scale"         : generate_vec3(DEFAULTS["scale"])
     }
 
     text = TEMPLATE_SCENE_ASCII % parameters
-    
+
     return text
-    
+
 def export_scene(scene, filepath, flipyz):
 
     source_file = os.path.basename(bpy.data.filepath)
@@ -1360,25 +1360,25 @@ def export_scene(scene, filepath, flipyz):
     "flipyz"      : flipyz
     }
     scene_text += generate_ascii_scene(data)
-    
+
     write_file(filepath, scene_text)
 
 # #####################################################
 # Main
 # #####################################################
 
-def save(operator, context, filepath = "", 
-         option_flip_yz = True, 
-         option_vertices = True, 
-         option_faces = True, 
-         option_normals = True, 
-         option_edges = False, 
-         option_uv_coords = True, 
-         option_materials = True, 
-         option_colors = True, 
-         align_model = 0, 
-         option_export_scene = False, 
-         option_truncate = False, 
+def save(operator, context, filepath = "",
+         option_flip_yz = True,
+         option_vertices = True,
+         option_vertices_truncate = False,
+         option_faces = True,
+         option_normals = True,
+         option_edges = False,
+         option_uv_coords = True,
+         option_materials = True,
+         option_colors = True,
+         align_model = 0,
+         option_export_scene = False,
          option_scale = 1.0):
 
     filepath = ensure_extension(filepath, '.js')
@@ -1393,16 +1393,16 @@ def save(operator, context, filepath = "",
         export_scene(scene, filepath, option_flip_yz)
 
         geo_set = set()
-        
+
         for obj in scene.objects:
             if obj.type == "MESH":
-                
+
                 # create extra copy of geometry with applied modifiers
                 # (if they exist)
-                
+
                 if len(obj.modifiers) > 0:
                     name = obj.name
-                    
+
                 # otherwise can share geometry
 
                 else:
@@ -1410,18 +1410,18 @@ def save(operator, context, filepath = "",
 
                 if name not in geo_set:
                     fname = generate_mesh_filename(name, filepath)
-                    export_mesh(obj, scene, fname, 
-                                option_vertices, 
-                                option_faces, 
-                                option_normals, 
-                                option_edges, 
-                                option_uv_coords, 
-                                option_materials, 
-                                option_colors, 
-                                False, 
-                                option_flip_yz, 
-                                option_truncate, 
-                                option_scale, 
+                    export_mesh(obj, scene, fname,
+                                option_vertices,
+                                option_vertices_truncate,
+                                option_faces,
+                                option_normals,
+                                option_edges,
+                                option_uv_coords,
+                                option_materials,
+                                option_colors,
+                                False,
+                                option_flip_yz,
+                                option_scale,
                                 False)
 
                     geo_set.add(name)
@@ -1432,19 +1432,19 @@ def save(operator, context, filepath = "",
         if not obj:
             raise Exception("Error, Select 1 active object or select 'export scene'")
 
-        export_mesh(obj, scene, filepath, 
-                    option_vertices, 
-                    option_faces, 
-                    option_normals, 
-                    option_edges, 
-                    option_uv_coords, 
-                    option_materials, 
-                    option_colors, 
-                    align_model, 
-                    option_flip_yz, 
-                    option_truncate, 
-                    option_scale, 
+        export_mesh(obj, scene, filepath,
+                    option_vertices,
+                    option_vertices_truncate,
+                    option_faces,
+                    option_normals,
+                    option_edges,
+                    option_uv_coords,
+                    option_materials,
+                    option_colors,
+                    align_model,
+                    option_flip_yz,
+                    option_scale,
                     True)
 
-    
+
     return {'FINISHED'}