浏览代码

Removed old FBX converter again after it got readded in merge.

alteredq 12 年之前
父节点
当前提交
af239f04e9
共有 1 个文件被更改,包括 0 次插入1678 次删除
  1. 0 1678
      utils/exporters/fbx/convert_fbx_three.py

+ 0 - 1678
utils/exporters/fbx/convert_fbx_three.py

@@ -1,1678 +0,0 @@
-"""FBX to Three.js converter (based on FBX import example from Autodesk FBX SDK)
-
-Converts FBX scene file into Three.js scene format (one scene file and several ascii model files plus textures).
-
--------------------------
-How to use this converter
--------------------------
-
-python convert_fbx_three.py scene.fbx output_folder
-
-------------
-Dependencies
-------------
-
-Requires Autodesk FBX SDK Python bindings.
-
-Full SDK can be downloaded from here:
-
-    http://usa.autodesk.com/adsk/servlet/pc/item?siteID=123112&id=10775847
-
----------------------------
-How to load generated scene
----------------------------
-
-<script type="text/javascript" src="ThreeExtras.js"></script>
-
-<script type="text/javascript">
-
-    ...
-
-    SCENE_URL = "http://example.com/output_folder/scene.js";
-    SceneUtils.loadScene( SCENE_URL, callback_sync, callback_async, callback_progress );
-
-    ...
-
-    /*
-    callback_sync     - called after the scene file is loaded (procedural elements like cubes and spheres or materials without textures are now ready)
-    callback_progress - called after each asynchronous elements gets loaded (textures and model files)
-    callback_async    - called after all asynchronous elements (models and textures) are loaded, now whole scene is ready
-
-    Scene is fully created, just needs to be passed to renderer, together with camera.
-    Individual scene elements are also returned for convenient access via hashmap (addressable by their id).
-
-    progress = {
-
-        total_models:    X,
-        total_textures:  Y,
-        loaded_models:   A,
-        loaded_textures: B
-
-    };
-
-    result = {
-
-        scene: new THREE.Scene(),
-        geometries: { ... },
-        materials: { ... },
-        textures: { ... },
-        objects: { ... },
-        cameras: { ... },
-        lights: { ... },
-        fogs: { ... },
-
-        currentCamera: THREE.Camera( ... )
-
-    };
-
-    */
-
-    var callback_progress = function( progress, result ) { ... };
-    var callback_sync = function( result ) { ... };
-    var callback_async = function( result ) { ... };
-
-    };
-
-</script>
-
-
---------
-Features
---------
-
-- scene + models + materials + textures
-- multiple UV layers
-
--------------------
-Current limitations
--------------------
-
-- only very small subset from FBX is currently supported
-    - static meshes
-    - triangles and quads
-    - max two UV layers
-    - Lambert and Phong materials (partial: Three doesn't support emissive color)
-- no lights yet
-- no cameras yet (default one is created instead)
-
-------
-Author
-------
-AlteredQualia http://alteredqualia.com
-
-"""
-
-import os
-import sys
-import random
-import math
-import pprint
-import shutil
-import string
-import os.path
-
-# load platform specific binary modules
-platform_map = {
-"Windows" :
-    {
-    "folder": "win",
-    "versions" : {
-        2 : "Python26_x86",
-        3 : "Python31_x86"
-        }
-    },
-"Linux" :
-    {
-    "folder": "linux",
-    "versions" : {
-        2 : "Python26_x86",
-        3 : "Python31_x86"
-        }
-    },
-"Darwin"  :
-    {
-    "folder": "mac",
-    "versions" : {
-        2 : "Python26_x86",
-        3 : "Python31_x86"
-        }
-    }
-}
-
-import platform
-system = platform.system()
-version = sys.version_info[0]
-if system in platform_map:
-    if version in platform_map[system]["versions"]:
-        mod_path = os.path.join(sys.path[0], "modules", platform_map[system]["folder"], platform_map[system]["versions"][version])
-        print mod_path
-        sys.path.append(mod_path)
-
-# #####################################################
-# Configuration
-# #####################################################
-DEFAULTS = {
-"bgcolor" : [0, 0, 0],
-"bgalpha" : 1.0,
-"camera"  :
-    {
-        "name" : "default_camera",
-        "type" : "perspective",
-        "near" : 1,
-        "far"  : 10000,
-        "fov"  : 60,
-        "aspect": 1.333,
-        "position" : [0, 0, 10],
-        "target"   : [0, 0, 0]
-    }
-}
-
-MATERIALS_IN_SCENE = True
-DEBUG_FBX_JSON = True
-
-# 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]
-
-
-# #####################################################
-# Templates - scene
-# #####################################################
-TEMPLATE_SCENE_ASCII = u"""\
-// Converted from: %(fname)s
-//  Generated with FBX -> Three.js converter
-//  http://github.com/alteredq/three.js/blob/master/utils/exporters/fbx/convert_fbx_three.py
-
-var url_base     = %(url_base)s,
-    url_models   = url_base + "models/",
-    url_textures = url_base + "textures/";
-
-var scene = {
-%(sections)s
-
-"defaults" :
-{
-    "bgcolor" : %(bgcolor)s,
-    "bgalpha" : %(bgalpha)f,
-    "camera"  : %(defcamera)s
-}
-
-}
-
-postMessage( scene );
-
-"""
-
-TEMPLATE_SECTION = """
-"%s" :
-{
-%s
-},
-"""
-
-TEMPLATE_OBJECT = """\
-    %(object_id)s : {
-        "geometry"  : %(geometry_id)s,
-        "materials" : [ %(material_id)s ],
-        "position"  : %(position)s,
-        "rotation"  : %(rotation)s,
-        "scale"	    : %(scale)s,
-        "visible"   : true
-    }"""
-
-TEMPLATE_GEOMETRY = """\
-    %(geometry_id)s : {
-        "type" : "ascii_mesh",
-        "url"  : url_models + %(model_file)s
-    }"""
-
-TEMPLATE_TEXTURE = """\
-    %(texture_id)s : {
-        "url": url_textures + %(texture_file)s
-    }"""
-
-TEMPLATE_MATERIAL_SCENE = """\
-    %(material_id)s : {
-        "type": %(type)s,
-        "parameters": { %(parameters)s }
-    }"""
-
-TEMPLATE_CAMERA_PERSPECTIVE = """\
-    %(camera_id)s : {
-        "type"  : "perspective",
-        "fov"   : %(fov)f,
-        "aspect": %(aspect)f,
-        "near"  : %(near)f,
-        "far"   : %(far)f,
-        "position": %(position)s,
-        "target"  : %(target)s
-    }"""
-
-TEMPLATE_CAMERA_ORTHO = """\
-    %(camera_id)s: {
-        "type"  : "ortho",
-        "left"  : %(left)f,
-        "right" : %(right)f,
-        "top"   : %(top)f,
-        "bottom": %(bottom)f,
-        "near"  : %(near)f,
-        "far"   : %(far)f,
-        "position": %(position)s,
-        "target"  : %(target)s
-    }"""
-
-TEMPLATE_VEC3 = '[ %f, %f, %f ]'
-TEMPLATE_VEC2 = '[ %f, %f ]'
-TEMPLATE_STRING = '"%s"'
-TEMPLATE_HEX = "0x%06x"
-
-# #####################################################
-# Templates - model
-# #####################################################
-TEMPLATE_MODEL_ASCII = u"""\
-// Converted from: %(fname)s
-//  vertices: %(nvertex)d
-//  faces: %(nface)d
-//  materials: %(nmaterial)d
-//
-//  Generated with FBX -> Three.js converter
-//  http://github.com/alteredq/three.js/blob/master/utils/exporters/fbx/convert_fbx_three.py
-
-var model = {
-    'materials': [%(materials)s],
-
-    'normals': [%(normals)s],
-
-    'vertices': [%(vertices)s],
-
-    'uvs': [%(uvs)s],
-    'uvs2': [%(uvs2)s],
-
-    'triangles': [%(triangles)s],
-    'trianglesUvs': [%(trianglesUvs)s],
-    'trianglesNormals': [%(trianglesNormals)s],
-    'trianglesNormalsUvs': [%(trianglesNormalsUvs)s],
-
-    'quads': [%(quads)s],
-    'quadsUvs': [%(quadsUvs)s],
-    'quadsNormals': [%(quadsNormals)s],
-    'quadsNormalsUvs': [%(quadsNormalsUvs)s],
-
-    'end': (new Date).getTime()
-    }
-
-postMessage( model );
-"""
-
-TEMPLATE_VERTEX = "%f,%f,%f"
-
-TEMPLATE_UV_TRI = "%f,%f,%f,%f,%f,%f"
-TEMPLATE_UV_QUAD = "%f,%f,%f,%f,%f,%f,%f,%f"
-
-TEMPLATE_TRI = "%d,%d,%d,%d"
-TEMPLATE_QUAD = "%d,%d,%d,%d,%d"
-
-TEMPLATE_TRI_UV = "%d,%d,%d,%d,%d,%d,%d"
-TEMPLATE_QUAD_UV = "%d,%d,%d,%d,%d,%d,%d,%d,%d"
-
-TEMPLATE_TRI_N = "%d,%d,%d,%d,%d,%d,%d"
-TEMPLATE_QUAD_N = "%d,%d,%d,%d,%d,%d,%d,%d,%d"
-
-TEMPLATE_TRI_N_UV = "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d"
-TEMPLATE_QUAD_N_UV = "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d"
-
-TEMPLATE_N = "%f,%f,%f"
-TEMPLATE_UV = "%f,%f"
-
-# #####################################################
-# Templates - misc
-# #####################################################
-TEMPLATE_HTACCESS = """\
-<Files *.js>
-SetOutputFilter DEFLATE
-</Files>
-"""
-
-# #####################################################
-# Parser - global settings
-# #####################################################
-def extract_color(color):
-    return [color.mRed, color.mGreen, color.mBlue]
-
-def extract_vec2(v):
-    return [v[0], v[1]]
-
-def extract_vec3(v):
-    return [v[0], v[1], v[2]]
-
-def extract_global_settings(settings):
-    settings = {
-    "ambient_color" : extract_color(settings.GetAmbientColor()),
-    "default_camera": settings.GetDefaultCamera().Buffer()
-    }
-
-    return settings
-
-def extract_object_properties(object):
-    info = {}
-
-    property = object.GetFirstProperty()
-    while property.IsValid():
-        name = property.GetName().Buffer()
-
-        value = "UNIDENTIFIED"
-
-        ptype = property.GetPropertyDataType().GetType()
-        if ptype in [eBOOL1, eDOUBLE1, eINTEGER1, eDOUBLE4, eDOUBLE3, eFLOAT1]:
-            value = property.Get()
-        elif ptype == eSTRING:
-            value = property.Get().Buffer()
-
-        info[name] = {
-        "label" : property.GetLabel().Buffer(),
-        "type"  : property.GetPropertyDataType().GetName(),
-        "value" : value
-        }
-
-        property = object.GetNextProperty(property)
-
-    return info
-
-def extract_node_generic_info(node):
-    info = []
-
-    node_info = {
-    "name"       : node.GetName(),
-    "type"       : node.ClassId.GetFbxFileTypeName(),
-    "properties" : extract_object_properties(node)
-    }
-
-    info.append(node_info)
-
-    for i in range(node.GetChildCount()):
-        info += extract_node_generic_info(node.GetChild(i))
-
-    return info
-
-def extract_generic_info(scene):
-    info_list = []
-
-    root_node = scene.GetRootNode()
-    for i in range(root_node.GetChildCount()):
-        child = root_node.GetChild(i)
-        info_list += extract_node_generic_info(child)
-
-    info_dict = {}
-    for item in info_list:
-        name = item["name"]
-        info_dict[name] = item["properties"]
-
-    return info_dict
-
-# #####################################################
-# Parser - hierarchy
-# #####################################################
-def extract_node_hierarchy(node, depth):
-    hierarchy = { "name" : node.GetName(), "depth" : depth, "children" : [] }
-
-    for i in range(node.GetChildCount()):
-        hierarchy["children"].append(extract_node_hierarchy(node.GetChild(i), depth + 1))
-
-    return hierarchy
-
-def extract_hierarchy(scene):
-    root = scene.GetRootNode()
-
-    hierarchy = { "name" : "root", "depth" : 0, "children" : [] }
-
-    for i in range(root.GetChildCount()):
-        hierarchy["children"].append(extract_node_hierarchy(root.GetChild(i), 1))
-
-    return hierarchy
-
-# #####################################################
-# Parser - mesh - layers
-# #####################################################
-def extract_layer_groups(layer, poly_count):
-    group = []
-
-    polygroups = layer.GetPolygonGroups()
-    if polygroups and \
-       polygroups.GetMappingMode() == KFbxLayerElement.eBY_POLYGON and \
-       polygroups.GetReferenceMode() == KFbxLayerElement.eINDEX:
-
-        polygroups_index_array = polygroups.GetIndexArray()
-        group = []
-        for p in range(poly_count):
-            group_id = polygroups_index_array.GetAt(p)
-            group.append(group_id)
-
-    return group
-
-def extract_layer_materials(layer, poly_count, mesh):
-    material_index_layer = []
-
-    materials = layer.GetMaterials()
-    if materials:
-        index_array = materials.GetIndexArray()
-        index_array_count = index_array.GetCount()
-        for i in range(index_array_count):
-            material_index_layer.append(index_array.GetAt(i))
-
-    return material_index_layer
-
-def extract_layer_uvs(layer, poly_count, mesh):
-    uv_values = []
-    uv_index_layer = []
-
-    uvs = layer.GetUVs()
-    if uvs:
-        uvs_array = uvs.GetDirectArray()
-        uvs_count = uvs_array.GetCount()
-
-        # values
-        for i in range(uvs_count):
-            uv = extract_vec2(uvs_array.GetAt(i))
-            uv_values.append(uv)
-
-        # indices
-        if uvs.GetMappingMode() == KFbxLayerElement.eBY_CONTROL_POINT \
-           and uvs.GetReferenceMode() == KFbxLayerElement.eDIRECT:
-
-            for p in range(poly_count):
-                tmp = []
-                polygon_size = mesh.GetPolygonSize(p)
-                for v in range(polygon_size):
-                    id = mesh.GetPolygonVertex(p, v)
-                    tmp.append(id)
-
-                uv_index_layer.append(tmp)
-
-        elif uvs.GetMappingMode() == KFbxLayerElement.eBY_CONTROL_POINT \
-           and uvs.GetReferenceMode() == KFbxLayerElement.eINDEX_TO_DIRECT:
-
-            uvs_index_array = uvs.GetIndexArray()
-            for p in range(poly_count):
-                tmp = []
-                polygon_size = mesh.GetPolygonSize(p)
-                for v in range(polygon_size):
-                    control_point_index = mesh.GetPolygonVertex(p, v)
-                    id = uvs_index_array.GetAt(control_point_index)
-                    tmp.append(id)
-
-                uv_index_layer.append(tmp)
-
-        elif uvs.GetMappingMode() == KFbxLayerElement.eBY_POLYGON_VERTEX \
-            and ( uvs.GetReferenceMode() == KFbxLayerElement.eDIRECT \
-                  or uvs.GetReferenceMode() == KFbxLayerElement.eINDEX_TO_DIRECT ):
-
-            for p in range(poly_count):
-                tmp = []
-                polygon_size = mesh.GetPolygonSize(p)
-                for v in range(polygon_size):
-                    id = mesh.GetTextureUVIndex(p, v)
-                    tmp.append(id)
-
-                uv_index_layer.append(tmp)
-
-    return uv_values, uv_index_layer
-
-def extract_layer_colors(layer, poly_count, mesh):
-    color_values = []
-    color_index_layer = []
-
-    colors = layer.GetVertexColors()
-    if colors:
-        colors_array = colors.GetDirectArray()
-        colors_count = colors_array.GetCount()
-
-        # values
-        tmp = []
-        for i in range(colors_count):
-            color = extract_color(colors_array.GetAt(i))
-            color_values.append(color)
-
-        # indices
-        if colors.GetMappingMode() == KFbxLayerElement.eBY_CONTROL_POINT \
-           and colors.GetReferenceMode() == KFbxLayerElement.eDIRECT:
-
-            for p in range(poly_count):
-                tmp = []
-                polygon_size = mesh.GetPolygonSize(p)
-                for v in range(polygon_size):
-                    id = mesh.GetPolygonVertex(p, v)
-                    tmp.append(id)
-
-                color_index_layer.append(tmp)
-
-        elif colors.GetMappingMode() == KFbxLayerElement.eBY_CONTROL_POINT \
-            and colors.GetReferenceMode() == KFbxLayerElement.eINDEX_TO_DIRECT:
-
-            for p in range(poly_count):
-                tmp = []
-                polygon_size = mesh.GetPolygonSize(p)
-                for v in range(polygon_size):
-                    control_point_index = mesh.GetPolygonVertex(p, v)
-                    id = colors.GetIndexArray().GetAt(control_point_index)
-                    tmp.append(id)
-
-                color_index_layer.append(tmp)
-
-        elif colors.GetMappingMode() == KFbxLayerElement.eBY_POLYGON_VERTEX \
-            and colors.GetReferenceMode() == KFbxLayerElement.eDIRECT:
-
-            vertex_id = 0
-            for p in range(poly_count):
-                tmp = []
-                polygon_size = mesh.GetPolygonSize(p)
-                for v in range(polygon_size):
-                    tmp.append(vertex_id)
-                    vertex_id += 1
-
-                color_index_layer.append(tmp)
-
-        elif colors.GetMappingMode() == KFbxLayerElement.eBY_POLYGON_VERTEX \
-            and colors.GetReferenceMode() == KFbxLayerElement.eINDEX_TO_DIRECT:
-
-            colors_index_array = colors.GetIndexArray()
-            vertex_id = 0
-            for p in range(poly_count):
-                tmp = []
-                polygon_size = mesh.GetPolygonSize(p)
-                for v in range(polygon_size):
-                    id = colors_index_array.GetAt(vertex_id)
-                    tmp.append(id)
-                    vertex_id += 1
-
-                color_index_layer.append(tmp)
-
-    return color_values, color_index_layer
-
-# #####################################################
-# Parser - mesh - polygons
-# #####################################################
-def extract_polygons(mesh):
-    poly_count = mesh.GetPolygonCount()
-    layer_count = mesh.GetLayerCount()
-    control_points = mesh.GetControlPoints()
-
-    layers_groups = []
-    layers_uvs = []
-    layers_colors = []
-
-    indices_uv = []
-    indices_color = []
-    indices_vertex = []
-    indices_material = []
-
-    # per layer data
-    for l in range(layer_count):
-
-        layer = mesh.GetLayer(l)
-
-        # groups
-        group = extract_layer_groups(layer, poly_count)
-        if group:
-            groups_layers.append(group)
-
-        # uvs
-        uv_values, uv_index_layer = extract_layer_uvs(layer, poly_count, mesh)
-
-        if uv_values:
-            layers_uvs.append(uv_values)
-
-        if uv_index_layer:
-            indices_uv.append(uv_index_layer)
-
-        # colors
-        color_values, color_index_layer = extract_layer_colors(layer, poly_count, mesh)
-
-        if color_values:
-            layers_colors.append(color_values)
-
-        if color_index_layer:
-            indices_color.append(color_index_layer)
-
-        # materials
-        material_index_layer = extract_layer_materials(layer, poly_count, mesh)
-        if material_index_layer:
-            indices_material.append(material_index_layer)
-
-    # single layer data
-    for p in range(poly_count):
-        face_vertex_index = []
-        polygon_size = mesh.GetPolygonSize(p)
-        for v in range(polygon_size):
-            control_point_index = mesh.GetPolygonVertex(p, v)
-            face_vertex_index.append(control_point_index)
-
-        indices_vertex.append(face_vertex_index)
-
-
-    polygons = {}
-    conditional_set(polygons, "indices_vertex", indices_vertex)
-    conditional_set(polygons, "indices_uv", indices_uv)
-    conditional_set(polygons, "indices_color", indices_color)
-    conditional_set(polygons, "indices_material", indices_material)
-    conditional_set(polygons, "layers_uvs", layers_uvs)
-    conditional_set(polygons, "layers_colors", layers_colors)
-    conditional_set(polygons, "layers_groups", layers_groups)
-
-    return polygons
-
-def extract_control_points(mesh):
-    control_points_count = mesh.GetControlPointsCount()
-    control_points = mesh.GetControlPoints()
-    layer_count = mesh.GetLayerCount()
-
-    coordinates = []
-    layers_normals = []
-
-    for i in range(control_points_count):
-        coordinates.append( extract_vec3( control_points[i] ) )
-
-    for layer in range(layer_count):
-        normals = mesh.GetLayer(layer).GetNormals()
-        if normals:
-            znormals = []
-            for i in range(control_points_count):
-                if normals.GetMappingMode() == KFbxLayerElement.eBY_CONTROL_POINT:
-                    if normals.GetReferenceMode() == KFbxLayerElement.eDIRECT:
-                        znormals.append( extract_vec3( normals.GetDirectArray().GetAt(i) ) )
-
-            if znormals:
-                layers_normals.append( znormals )
-
-
-    points = {}
-
-    conditional_set(points, "coordinates", coordinates)
-    conditional_set(points, "normals", layers_normals)
-
-    return points
-
-# #####################################################
-# Parser - mesh - materials
-# #####################################################
-def extract_materials(mesh):
-    materials_layers = []
-
-    material_count = 0
-    layer_count = mesh.GetLayerCount()
-
-    node = None
-    if mesh:
-        node = mesh.GetNode()
-        if node:
-            material_count = node.GetMaterialCount()
-
-    for layer in range(layer_count):
-        layer_materials = []
-
-        materials = mesh.GetLayer(layer).GetMaterials()
-        if materials:
-            if materials.GetReferenceMode() == KFbxLayerElement.eINDEX:
-                #Materials are in an undefined external table
-                continue
-
-            if material_count > 0:
-
-                for i in range(material_count):
-                    material = node.GetMaterial(i)
-
-                    zmaterial = {
-                    "name" : material.GetName()
-                    }
-
-                    # Get the implementation to see if it's a hardware shader.
-                    implementation = GetImplementation(material, "ImplementationHLSL")
-                    implemenation_type = "HLSL"
-                    if not implementation:
-                        implementation = GetImplementation(material, "ImplementationCGFX")
-                        implemenation_type = "CGFX"
-                    if implementation:
-                        # Now we have a hardware shader, let's read it
-                        zmaterial["hardware_shader_type"] = implemenation_type.Buffer()
-                        # Skipped parsing of shaders
-
-                    elif material.GetClassId().Is(KFbxSurfaceLambert.ClassId):
-                        ambient = material.GetAmbientColor()
-                        diffuse = material.GetDiffuseColor()
-                        emissive = material.GetEmissiveColor()
-
-                        zmaterial["ambient"] = [ambient.Get()[0], ambient.Get()[1], ambient.Get()[2]]
-                        zmaterial["diffuse"] = [diffuse.Get()[0], diffuse.Get()[1], diffuse.Get()[2]]
-                        zmaterial["emissive"] = [emissive.Get()[0], emissive.Get()[1], emissive.Get()[2]]
-
-                        zmaterial["opacity"] = material.GetTransparencyFactor().Get()
-
-                    elif (material.GetClassId().Is(KFbxSurfacePhong.ClassId)):
-                        ambient = material.GetAmbientColor()
-                        diffuse = material.GetDiffuseColor()
-                        emissive = material.GetEmissiveColor()
-                        specular = material.GetSpecularColor()
-
-                        zmaterial["ambient"] = [ambient.Get()[0], ambient.Get()[1], ambient.Get()[2]]
-                        zmaterial["diffuse"] = [diffuse.Get()[0], diffuse.Get()[1], diffuse.Get()[2]]
-                        zmaterial["emissive"] = [emissive.Get()[0], emissive.Get()[1], emissive.Get()[2]]
-                        zmaterial["specular"] = [specular.Get()[0], specular.Get()[1], specular.Get()[2]]
-
-                        zmaterial["opacity"] = material.GetTransparencyFactor().Get()
-
-                        zmaterial["shininess"] = material.GetShininess().Get()
-                        zmaterial["reflectivity"] = material.GetReflectionFactor().Get()
-
-                    zmaterial["shading_model"] = material.GetShadingModel().Get().Buffer()
-                    layer_materials.append(zmaterial)
-
-        if layer_materials:
-            materials_layers.append(layer_materials)
-
-    return materials_layers
-
-# #####################################################
-# Parser - mesh - textures
-# #####################################################
-def extract_texture_info(texture, blend_mode):
-    mapping_types = [ "Null", "Planar", "Spherical", "Cylindrical", "Box", "Face", "UV", "Environment" ]
-    alpha_sources = [ "None", "RGB Intensity", "Black" ]
-    blend_modes   = [ "Translucent", "Add", "Modulate", "Modulate2" ]
-    material_uses = [ "Model Material", "Default Material" ]
-    texture_uses  = [ "Standard", "Shadow Map", "Light Map", "Spherical Reflection Map", "Sphere Reflection Map" ]
-    planar_mapping_normals = [ "X", "Y", "Z" ]
-
-    info = {
-    "name"      : texture.GetName(),
-    "filename"  : texture.GetFileName(),
-    "scale_u"   : texture.GetScaleU(),
-    "scale_v"   : texture.GetScaleV(),
-    "swap_uv"   : texture.GetSwapUV(),
-    "translation_u" : texture.GetTranslationU(),
-    "translation_v" : texture.GetTranslationV(),
-    "rotation_u"    : texture.GetRotationU(),
-    "rotation_v"    : texture.GetRotationV(),
-    "rotation_w"    : texture.GetRotationW(),
-    "mapping"       : mapping_types[texture.GetMappingType()],
-    "alpha_source"  : alpha_sources[texture.GetAlphaSource()],
-    "cropping_left"   : texture.GetCroppingLeft(),
-    "cropping_top"    : texture.GetCroppingTop(),
-    "cropping_right"  : texture.GetCroppingRight(),
-    "cropping_bottom" : texture.GetCroppingBottom(),
-    "alpha"         : texture.GetDefaultAlpha(),
-    "material_use" : material_uses[texture.GetMaterialUse()],
-    "texture_use"  : texture_uses[texture.GetTextureUse()]
-    }
-
-
-    if texture.GetMappingType() == KFbxTexture.ePLANAR:
-        info["planar_mapping_normal"] = planar_mapping_normals[texture.GetPlanarMappingNormal()]
-
-    if blend_mode >= 0:
-        info["blend_mode"] = blend_modes[blend_mode]
-
-    return info
-
-def extract_texture_info_by_property(property, material_index):
-    textures = []
-
-    if property.IsValid():
-
-        #Here we have to check if it's layeredtextures, or just textures:
-        layered_texture_count = property.GetSrcObjectCount(KFbxLayeredTexture.ClassId)
-        if layered_texture_count > 0:
-            for j in range(layered_texture_count):
-                ltexture = {
-                "layered_texture" : j,
-                "layers" : []
-                }
-
-                layered_texture = property.GetSrcObject(KFbxLayeredTexture.ClassId, j)
-                texture_count = layered_texture.GetSrcObjectCount(KFbxTexture.ClassId)
-                for k in range(texture_count):
-                    ztexture = lLayeredTexture.GetSrcObject(KFbxTexture.ClassId, k)
-                    if ztexture:
-                        # NOTE the blend mode is ALWAYS on the LayeredTexture and NOT the one on the texture.
-                        # Why is that?  because one texture can be shared on different layered textures and might
-                        # have different blend modes.
-
-                        blend_mode = layered_texture.GetTextureBlendMode(k)
-                        texture = {
-                        "material_index" : material_index,
-                        "texture_index"  : k,
-                        "property_name"  : property.GetName().Buffer(),
-                        "blend_mode"     : blend_mode,
-                        "info"           : extract_texture_info(ztexture, blend_mode)
-                        }
-
-                        ltexture["layers"].append(texture)
-
-                textures.append(ltexture)
-
-        # no layered texture simply get on the property
-        else:
-
-            texture_count = property.GetSrcObjectCount(KFbxTexture.ClassId)
-            for j in range(texture_count):
-                ztexture = property.GetSrcObject(KFbxTexture.ClassId, j)
-                if ztexture:
-                    texture = {
-                    "material_index" : material_index,
-                    "info"           : extract_texture_info(ztexture, -1)
-                    }
-                    textures.append(texture)
-
-    return textures
-
-def extract_textures(mesh):
-    textures = {}
-    node = mesh.GetNode()
-    materials_count = node.GetSrcObjectCount(KFbxSurfaceMaterial.ClassId)
-    for material_index in range(materials_count):
-        material = node.GetSrcObject(KFbxSurfaceMaterial.ClassId, material_index)
-
-        #go through all the possible textures
-        if material:
-            for texture_index in range(KFbxLayerElement.LAYERELEMENT_TYPE_TEXTURE_COUNT):
-                property = material.FindProperty(KFbxLayerElement.TEXTURE_CHANNEL_NAMES[texture_index])
-                texture = extract_texture_info_by_property(property, material_index)
-                if texture:
-                    textures[property.GetName().Buffer()] = texture
-
-    return textures
-
-def extract_material_mapping(mesh):
-    return {}
-
-def extract_material_connections(mesh):
-    return {}
-
-def extract_link(mesh):
-    return {}
-
-def extract_shape(mesh):
-    return {}
-
-def extract_mesh(node):
-    mesh = node.GetNodeAttribute()
-
-    zmesh = {}
-
-    conditional_set(zmesh, "name", node.GetName())
-    conditional_set(zmesh, "shape", extract_shape(mesh))
-    conditional_set(zmesh, "link", extract_link(mesh))
-    conditional_set(zmesh, "control_points", extract_control_points(mesh))
-    conditional_set(zmesh, "faces", extract_polygons(mesh))
-    conditional_set(zmesh, "textures", extract_textures(mesh))
-    conditional_set(zmesh, "materials", extract_materials(mesh))
-    conditional_set(zmesh, "material_mapping", extract_material_mapping(mesh))
-    conditional_set(zmesh, "material_connections", extract_material_connections(mesh))
-
-    return zmesh
-
-# #####################################################
-# Parser - nodes (todo)
-# #####################################################
-def extract_marker(node):
-    return {}
-
-def extract_nurb(node):
-    return {}
-
-def extract_patch(node):
-    return {}
-
-def extract_skeleton(node):
-    return {}
-
-def extract_camera(node):
-    return {}
-
-def extract_light(node):
-    return {}
-
-# #####################################################
-# Parser - nodes (generic)
-# #####################################################
-def extract_target(node):
-    if node.GetTarget():
-        return node.GetTarget().GetName()
-    return ""
-
-def extract_transform(node):
-    translation = node.GetGeometricTranslation(KFbxNode.eSOURCE_SET)
-    rotation = node.GetGeometricRotation(KFbxNode.eSOURCE_SET)
-    scale = node.GetGeometricScaling(KFbxNode.eSOURCE_SET)
-
-    transform = {
-    "translation": [ translation[0], translation[1], translation[2] ],
-    "rotation"   : [ rotation[0], rotation[1], rotation[2] ],
-    "scale"      : [ scale[0], scale[1], scale[2] ],
-    }
-
-    return transform
-
-def extract_transform_propagation(node):
-    rotation_order = node.GetRotationOrder(KFbxNode.eSOURCE_SET)
-
-    order_map = {
-    eEULER_XYZ  : "Euler XYZ",
-    eEULER_XZY  : "Euler XZY",
-    eEULER_YZX  : "Euler YZX",
-    eEULER_YXZ  : "Euler YXZ",
-    eEULER_ZXY  : "Euler ZXY",
-    eEULER_ZYX  : "Euler ZYX",
-    eSPHERIC_XYZ:"Spheric XYZ"
-    }
-
-    order = "Euler XYZ"
-
-    if rotation_order in order_map:
-        order = order_map[rotation_order]
-
-    # Use the Rotation space only for the limits
-    # (keep using eEULER_XYZ for the rest)
-
-    if node.GetUseRotationSpaceForLimitOnly(KFbxNode.eSOURCE_SET):
-        only_limits = 1
-    else:
-        only_limits = 0
-
-    inherit_type = node.GetTransformationInheritType()
-
-    inherit_map = {
-    eINHERIT_RrSs   : "RrSs",
-    eINHERIT_RSrs   : "RSrs",
-    eINHERIT_Rrs    : "Rrs"
-    }
-
-    if inherit_type in inherit_map:
-        inheritance = inherit_map[inherit_type]
-
-    transform_propagation = {
-    "rotation_order" : order,
-    "only_limits"    : only_limits,
-    "inheritance"    : inheritance
-    }
-
-    return transform_propagation
-
-def extract_pivots(node):
-    return {}
-
-def extract_user_properties(node):
-    return {}
-
-def extract_node_content(node):
-    nodes = []
-
-    if node.GetNodeAttribute() == None:
-        return "NULL"
-
-    else:
-        attribute_type = node.GetNodeAttribute().GetAttributeType()
-
-        ztype = "undefined"
-        data = {}
-
-        type_map = {
-        KFbxNodeAttribute.eMARKER   : ["marker",    extract_marker],
-        KFbxNodeAttribute.eSKELETON : ["skeleton",  extract_skeleton],
-        KFbxNodeAttribute.eMESH     : ["mesh",      extract_mesh],
-        KFbxNodeAttribute.eNURB     : ["nurb",      extract_nurb],
-        KFbxNodeAttribute.ePATCH    : ["patch",     extract_patch],
-        KFbxNodeAttribute.eCAMERA   : ["camera",    extract_camera],
-        KFbxNodeAttribute.eLIGHT    : ["light",     extract_light]
-        }
-
-        if attribute_type in type_map:
-            ztype = type_map[attribute_type][0]
-            data = type_map[attribute_type][1](node)
-
-        content = { }
-
-        conditional_set(content, "type", ztype)
-        conditional_set(content, "data", data)
-        conditional_set(content, "target", extract_target(node))
-        conditional_set(content, "pivots", extract_pivots(node))
-        conditional_set(content, "transform", extract_transform(node))
-        conditional_set(content, "transform_propagation", extract_transform_propagation(node))
-        conditional_set(content, "user_properties", extract_user_properties(node))
-
-    nodes.append(content)
-
-    for i in range(node.GetChildCount()):
-        nodes += extract_node_content(node.GetChild(i))
-
-    return nodes
-
-def extract_nodes(scene):
-    nodes = []
-
-    root = scene.GetRootNode()
-    if root:
-        for i in range(root.GetChildCount()):
-            nodes += extract_node_content(root.GetChild(i))
-
-    return nodes
-
-def filter_mesh(item):
-    return item["type"] == "mesh"
-
-def extract_meshes(scene):
-    nodes = extract_nodes(scene)
-    meshes = filter(filter_mesh, nodes)
-    return meshes
-
-# #####################################################
-# JSON extractors
-# #####################################################
-def get_material_texture(material_index, textures, property):
-    result = [t for t in textures.get(property, []) if t["material_index"] == material_index]
-    return result
-
-def collect_textures(data):
-    texture_set = set()
-
-    for mesh in data["meshes"]:
-        for texture_type in mesh["data"]["textures"]:
-            for texture in mesh["data"]["textures"][texture_type]:
-                texture_file = base_filename(texture["info"]["filename"])
-                texture_set.add(texture_file)
-
-    return list(texture_set)
-
-# #####################################################
-# Generator - model
-# #####################################################
-def generate_vertex(v):
-    return TEMPLATE_VERTEX % (v[0], v[1], v[2])
-
-def generate_triangle(f):
-    v = f['vertex']
-    return TEMPLATE_TRI % (v[0], v[1], v[2],
-                           f['material'])
-
-def generate_triangle_uv(f):
-    v = f['vertex']
-    uv = f['uv']
-    return TEMPLATE_TRI_UV % (v[0], v[1], v[2],
-                              f['material'],
-                              uv[0], uv[1], uv[2])
-
-def generate_triangle_n(f):
-    v = f['vertex']
-    n = f['normal']
-    return TEMPLATE_TRI_N % (v[0], v[1], v[2],
-                             f['material'],
-                             n[0], n[1], n[2])
-
-def generate_triangle_n_uv(f):
-    v = f['vertex']
-    n = f['normal']
-    uv = f['uv']
-    return TEMPLATE_TRI_N_UV % (v[0], v[1], v[2],
-                                f['material'],
-                                n[0], n[1], n[2],
-                                uv[0], uv[1], uv[2])
-
-def generate_quad(f):
-    vi = f['vertex']
-    return TEMPLATE_QUAD % (vi[0], vi[1], vi[2], vi[3],
-                            f['material'])
-
-def generate_quad_uv(f):
-    v = f['vertex']
-    uv = f['uv']
-    return TEMPLATE_QUAD_UV % (v[0], v[1], v[2], v[3],
-                               f['material'],
-                               uv[0], uv[1], uv[2], uv[3])
-
-def generate_quad_n(f):
-    v = f['vertex']
-    n = f['normal']
-    return TEMPLATE_QUAD_N % (v[0], v[1], v[2], v[3],
-                              f['material'],
-                              n[0], n[1], n[2], n[3])
-
-def generate_quad_n_uv(f):
-    v = f['vertex']
-    n = f['normal']
-    uv = f['uv']
-    return TEMPLATE_QUAD_N_UV % (v[0], v[1], v[2], v[3],
-                                 f['material'],
-                                 n[0], n[1], n[2], n[3],
-                                 uv[0], uv[1], uv[2], uv[3])
-
-def generate_normal(n):
-    return TEMPLATE_N % (n[0], n[1], n[2])
-
-def generate_uv(uv):
-    return TEMPLATE_UV % (uv[0], uv[1])
-
-# #####################################################
-# Generator - scene
-# #####################################################
-def generate_vec3(vec):
-    return TEMPLATE_VEC3 % (vec[0], vec[1], vec[2])
-
-def generate_vec2(vec):
-    return TEMPLATE_VEC2 % (vec[0], vec[1])
-
-def generate_hex(number):
-    return TEMPLATE_HEX % number
-
-def generate_string(s):
-    return TEMPLATE_STRING % s
-
-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 layer in materials:
-        for material in layer:
-            chunks.append(material["name"])
-
-    return ",".join(chunks)
-
-def generate_objects(data):
-    chunks = []
-
-    for mesh in data["meshes"]:
-        object_id = mesh["data"]["name"]
-        geometry_id = "geo_%s" % object_id
-
-        material_id = generate_material_id_list(mesh["data"]["materials"])
-
-        position = mesh["transform"]["translation"]
-        rotation = mesh["transform"]["rotation"]
-        scale = mesh["transform"]["scale"]
-
-        # hunt for local transform
-        if object_id in data["generic_info"]:
-            gi = data["generic_info"][object_id]
-            lt = gi.get("Lcl Translation", {})
-            local_translation = lt.get("value", [0,0,0])
-            position[0] += local_translation[0]
-            position[1] += local_translation[1]
-            position[2] += local_translation[2]
-
-        object_string = TEMPLATE_OBJECT % {
-        "object_id"   : generate_string(object_id),
-        "geometry_id" : generate_string(geometry_id),
-        "material_id" : generate_string(material_id),
-        "position"    : generate_vec3(position),
-        "rotation"    : generate_vec3(rotation),
-        "scale"       : generate_vec3(scale)
-        }
-        chunks.append(object_string)
-
-    return ",\n\n".join(chunks)
-
-def generate_geometries(data):
-    chunks = []
-
-    for mesh in data["meshes"]:
-        geometry_id = "geo_%s" % mesh["data"]["name"]
-        model_filename = get_mesh_filename(mesh)
-
-        geometry_string = TEMPLATE_GEOMETRY % {
-        "geometry_id" : generate_string(geometry_id),
-        "model_file"  : generate_string(model_filename)
-        }
-        chunks.append(geometry_string)
-
-    return ",\n\n".join(chunks)
-
-def generate_textures_scene(data):
-    chunks = []
-    texture_set = set()
-
-    for mesh in data["meshes"]:
-        for texture_type in mesh["data"]["textures"]:
-            for texture in mesh["data"]["textures"][texture_type]:
-                texture_id = texture["info"]["name"]
-
-                if texture_id not in texture_set:
-                    texture_set.add(texture_id)
-                    texture_file = base_filename(texture["info"]["filename"])
-
-                    texture_string = TEMPLATE_TEXTURE % {
-                    "texture_id"   : generate_string(texture_id),
-                    "texture_file" : generate_string(texture_file)
-                    }
-                    chunks.append(texture_string)
-
-    return ",\n\n".join(chunks)
-
-def generate_materials_scene(data):
-    chunks = []
-
-    type_map = {
-    "Lambert"   : "MeshLambertMaterial",
-    "Phong"     : "MeshPhongMaterial"
-    }
-
-    for mesh in data["meshes"]:
-        for layer in mesh["data"]["materials"]:
-            for material_index in range(len(layer)):
-                material = layer[material_index]
-                material_id = material["name"]
-                shading = material["shading_model"]
-                material_type = type_map.get(shading, "MeshBasicMaterial")
-
-                parameters = "color: %s" % generate_hex(rgb2int(material["diffuse"]))
-
-                if shading == "Phong":
-                    parameters += ", ambient: %s" % generate_hex(rgb2int(material["ambient"]))
-                    parameters += ", specular: %s" % generate_hex(rgb2int(material["specular"]))
-                    parameters += ", shininess: %f" % material["shininess"]
-
-                # TODO: proper handling of textures
-                colorMap = get_material_texture(material_index, mesh["data"]["textures"], "DiffuseColor")
-                lightMap = get_material_texture(material_index, mesh["data"]["textures"], "AmbientColor")
-                bumpMap  = get_material_texture(material_index, mesh["data"]["textures"], "Bump")
-
-                if map:
-                    parameters += ", map: %s" % generate_string(colorMap[0]["info"]["name"])
-                if lightMap:
-                    parameters += ", lightMap: %s" % generate_string(lightMap[0]["info"]["name"])
-                if bumpMap:
-                    parameters += ", bumpMap: %s" % generate_string(bumpMap[0]["info"]["name"])
-
-                material_string = TEMPLATE_MATERIAL_SCENE % {
-                "material_id" : generate_string(material_id),
-                "type"        : generate_string(material_type),
-                "parameters"  : parameters
-                }
-                chunks.append(material_string)
-
-    return ",\n\n".join(chunks)
-
-# TODO
-
-def generate_cameras(data):
-    cameras = data.get("cameras", [])
-    if not cameras:
-        cameras.append(DEFAULTS["camera"])
-
-    chunks = []
-    for camera in cameras:
-        if camera["type"] == "perspective":
-            camera_string = TEMPLATE_CAMERA_PERSPECTIVE % {
-            "camera_id" : generate_string(camera["name"]),
-            "fov"       : camera["fov"],
-            "aspect"    : camera["aspect"],
-            "near"      : camera["near"],
-            "far"       : camera["far"],
-            "position"  : generate_vec3(camera["position"]),
-            "target"    : generate_vec3(camera["target"])
-            }
-        elif camera["type"] == "ortho":
-            camera_string = TEMPLATE_CAMERA_ORTHO % {
-            "camera_id" : generate_string(camera["name"]),
-            "left"      : camera["left"],
-            "right"     : camera["right"],
-            "top"       : camera["top"],
-            "bottom"    : camera["bottom"],
-            "near"      : camera["near"],
-            "far"       : camera["far"],
-            "position"  : generate_vec3(camera["position"]),
-            "target"    : generate_vec3(camera["target"])
-            }
-
-        chunks.append(camera_string)
-
-    return ",\n\n".join(chunks)
-
-def generate_lights(data):
-    return ""
-
-def generate_ascii_scene(data):
-    objects = generate_objects(data)
-    geometries = generate_geometries(data)
-    textures = generate_textures_scene(data)
-    materials = generate_materials_scene(data)
-    cameras = generate_cameras(data)
-    lights = generate_lights(data)
-
-    sections = [
-    ["objects",    objects],
-    ["geometries", geometries],
-    ["textures",   textures],
-    ["materials",  materials],
-    ["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"],
-    "url_base"  : generate_string(data["base_folder"]),
-    "sections"  : sections_string,
-    "bgcolor"   : generate_vec3(DEFAULTS["bgcolor"]),
-    "bgalpha"   : DEFAULTS["bgalpha"],
-    "defcamera" : generate_string(default_camera)
-    }
-
-    text = TEMPLATE_SCENE_ASCII % parameters
-
-    return text
-
-# #####################################################
-# Generator - materials
-# #####################################################
-def generate_color(i):
-    """Generate hex color corresponding to integer.
-
-    Colors should have well defined ordering.
-    First N colors are hardcoded, then colors are random
-    (must seed random number  generator with deterministic value
-    before getting colors).
-    """
-
-    if i < len(COLORS):
-        return "0x%06x" % COLORS[i]
-    else:
-        return "0x%06x" % int(0xffffff * random.random())
-
-def value2string(v):
-    if type(v)==str and v[0:2] != "0x":
-        return '"%s"' % v
-    return str(v)
-
-def generate_material_model(material, index):
-    m = {
-    'DbgName'    :generate_string(material["name"]),
-    'DbgIndex'   :index,
-    'DbgColor'   :generate_color(index),
-    "shading"       :generate_string(material["shading_model"]),
-    "opacity"       : material["opacity"]
-    }
-
-    if material["shading_model"] in ["Lambert", "Phong"]:
-        m["colorAmbient"] = material["ambient"]
-        m["colorDiffuse"] = material["diffuse"]
-        m["col_emissive"] = material["emissive"]
-
-    if material["shading_model"] in ["Phong"]:
-        m["colorSpecular"] = material["specular"]
-        m["shininess"] = material["shininess"]
-
-    if not MATERIALS_IN_SCENE:
-        conditional_set(m, "mapDiffuse", material.get("mapDiffuse", 0))
-        conditional_set(m, "mapLightmap", material.get("mapLightmap", 0))
-
-    mtl_raw = ",\n".join(['\t"%s" : %s' % (n, value2string(v)) for n,v in sorted(m.items())])
-    mtl_string = "\t{\n%s\n\t}" % mtl_raw
-
-    return mtl_string
-
-# #####################################################
-# Generator - models
-# #####################################################
-def generate_ascii_model(data):
-    materials = data["materials"]
-
-    vertices = data["control_points"]["coordinates"]
-
-    normals = []
-    if "normals" in data["control_points"]:
-        normals = data["control_points"]["normals"][0]
-
-    uvs = []
-    uvs2 = []
-    if "layers_uvs" in data["faces"]:
-        n_uvs = len(data["faces"]["layers_uvs"])
-        if n_uvs > 0:
-            uvs = data["faces"]["layers_uvs"][0]
-        if n_uvs > 1:
-            uvs2 = data["faces"]["layers_uvs"][1]
-
-
-    triangles = []
-    trianglesUvs = []
-    trianglesNormals = []
-    trianglesNormalsUvs = []
-
-    quads = []
-    quadsUvs = []
-    quadsNormals = []
-    quadsNormalsUvs = []
-
-    indices_vertex = data["faces"]["indices_vertex"]
-    for vi in range(len(indices_vertex)):
-
-        vertex_index = indices_vertex[vi]
-
-        material_index = 0
-        if vi < len(data["faces"]["indices_material"][0]):
-            material_index = data["faces"]["indices_material"][0][vi]
-
-        face = {
-        'vertex'   : vertex_index,
-        'material' : material_index
-        }
-
-        if normals:
-            face["normal"] = vertex_index
-
-        if uvs and "indices_uv" in data["faces"]:
-            indices_uv = data["faces"]["indices_uv"]
-            face["uv"] = indices_uv[0][vi]
-            if len(indices_uv) > 1:
-                face["uv2"] = indices_uv[1][vi]
-
-
-        if len(vertex_index) == 3:
-            if normals:
-                if uvs:
-                    where = trianglesNormalsUvs
-                else:
-                    where = trianglesNormals
-            else:
-                if uvs:
-                    where = trianglesUvs
-                else:
-                    where = triangles
-
-        elif len(vertex_index) == 4:
-            if normals:
-                if uvs:
-                    where = quadsNormalsUvs
-                else:
-                    where = quadsNormals
-            else:
-                if uvs:
-                    where = quadsUvs
-                else:
-                    where = quads
-
-        where.append(face)
-
-    nvertex = len(vertices)
-    nface = len(indices_vertex)
-    nmaterial = 0
-
-    text = TEMPLATE_MODEL_ASCII % {
-    "fname"     : source_file,
-    "nvertex"   : nvertex,
-    "nface"     : nface,
-    "nmaterial" : nmaterial,
-
-    "materials" : "".join(generate_material_model(m, i) for i, m in enumerate(materials[0])),
-
-    "normals"   : ",".join(generate_normal(n) for n in normals),
-    "vertices"  : ",".join(generate_vertex(v) for v in vertices),
-
-    "uvs"       : ",".join(generate_uv(u) for u in uvs),
-    "uvs2"      : ",".join(generate_uv(u) for u in uvs2),
-
-    "triangles"     : ",".join(generate_triangle(f) for f in triangles),
-    "trianglesUvs"  : ",".join(generate_triangle_uv(f) for f in trianglesUvs),
-    "trianglesNormals"   : ",".join(generate_triangle_n(f) for f in trianglesNormals),
-    "trianglesNormalsUvs": ",".join(generate_triangle_n_uv(f) for f in trianglesNormalsUvs),
-
-    "quads"         : ",".join(generate_quad(f) for f in quads),
-    "quadsUvs"      : ",".join(generate_quad_uv(f) for f in quadsUvs),
-    "quadsNormals"       : ",".join(generate_quad_n(f) for f in quadsNormals),
-    "quadsNormalsUvs"    : ",".join(generate_quad_n_uv(f) for f in quadsNormalsUvs)
-    }
-
-    return text
-
-# #####################################################
-# Helpers
-# #####################################################
-def sanitize(text):
-    chunks = []
-    for ch in text:
-        if ch in (string.ascii_letters + string.digits + "_."):
-            chunks.append(ch)
-        else:
-            chunks.append("_")
-
-    return "".join(chunks)
-
-def base_filename(path):
-    return os.path.basename(path)
-
-def rgb2int(rgb):
-    color = (int(rgb[0]*255) << 16) + (int(rgb[1]*255) << 8) + int(rgb[2]*255);
-    return color
-
-def conditional_set(where, label, what):
-    """Set dictionary property only if it exists"""
-
-    if what:
-        where[label] = what
-
-def dump_data(data):
-    """Generate pretty printed view of data."""
-
-    chunks = []
-
-    pp = pprint.PrettyPrinter(indent=2, width=160)
-    if type(data) == list:
-        for d in data:
-            chunks.append(pp.pformat(d))
-    elif type(data) == dict:
-        chunks.append(pp.pformat(data))
-
-    return "\n\n".join(chunks)
-
-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)
-
-def abort(message):
-    print message
-    sys.exit(1)
-
-def write_file(fname, content):
-    out = open(fname, "w")
-    out.write(content)
-    out.close()
-
-def copy_files(textures, src_folder, dst_folder):
-    for texture in textures:
-        src_file = os.path.join(src_folder, texture)
-        if os.path.isfile(src_file):
-            shutil.copy(src_file, dst_folder)
-        else:
-            print "WARNING: couldn't find [%s]" % src_file
-
-# #####################################################
-# Main
-# #####################################################
-if __name__ == "__main__":
-
-    try:
-        from FbxCommon import *
-
-    except ImportError:
-
-        import platform
-
-        msg = ""
-
-        if platform.system() == 'Windows' or platform.system() == 'Microsoft':
-            msg = '"Python26/Lib/site-packages"'
-
-        elif platform.system() == 'Linux':
-            msg = '"/usr/local/lib/python2.6/site-packages"'
-
-        elif platform.system() == 'Darwin':
-            msg = '"/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages"'
-
-        abort('You need to copy the content in compatible subfolder under /lib/python<version> into your python install folder such as %s folder.' % msg)
-
-    sdkManager, scene = InitializeSdkObjects()
-
-    if len(sys.argv) < 3:
-        abort("Usage: convert_fbx_three.py [scene.fbx] [scene_folder]")
-
-    source_file = sys.argv[1]
-    output_folder = sys.argv[2]
-
-    junk, base_folder = os.path.split(os.path.normpath(output_folder))
-
-    result = LoadScene(sdkManager, scene, source_file)
-
-    if not result:
-        abort("An error occurred while loading the scene ...")
-
-    random.seed(42) # to get well defined debug color order for materials
-
-    ensure_folder_exist(output_folder)
-    ensure_folder_exist(output_folder+"/models")
-    ensure_folder_exist(output_folder+"/textures")
-
-    meshes = extract_meshes(scene)
-    generic_info = extract_generic_info(scene)
-
-    scene_text = ""
-    data = {
-    "meshes"      : meshes,
-    "generic_info": generic_info,
-    "source_file" : source_file,
-    "base_folder" : base_folder+"/"
-    }
-    scene_text += generate_ascii_scene(data)
-
-    if DEBUG_FBX_JSON:
-        scene_text += "/*" + dump_data(meshes) + "\n\n\n" + dump_data(generic_info) + "*/"
-
-    scene_file = os.path.join(output_folder, "scene.js")
-    htaccess_file = os.path.join(output_folder, ".htaccess")
-
-    write_file(scene_file, scene_text)
-    write_file(htaccess_file, TEMPLATE_HTACCESS)
-
-    for mesh in meshes:
-        model_text = generate_ascii_model(mesh["data"])
-        model_file = os.path.join(output_folder, "models", get_mesh_filename(mesh))
-        write_file(model_file, model_text)
-
-    textures_src_folder = os.path.dirname(source_file)
-    textures_dst_folder = os.path.join(output_folder, "textures")
-    copy_files(collect_textures(data), textures_src_folder, textures_dst_folder)
-
-    # Destroy all objects created by the FBX SDK
-
-    sdkManager.Destroy()