|
@@ -0,0 +1,593 @@
|
|
|
+bl_info = {
|
|
|
+ "name": "Babylon.js",
|
|
|
+ "author": "David Catuhe",
|
|
|
+ "version": (1, 0),
|
|
|
+ "blender": (2, 67, 0),
|
|
|
+ "location": "File > Export > Babylon.js (.babylon)",
|
|
|
+ "description": "Export Babylon.js scenes (.babylon)",
|
|
|
+ "warning": "",
|
|
|
+ "wiki_url": "",
|
|
|
+ "tracker_url": "",
|
|
|
+ "category": "Import-Export"}
|
|
|
+
|
|
|
+import math
|
|
|
+import os
|
|
|
+import bpy
|
|
|
+import string
|
|
|
+import bpy_extras.io_utils
|
|
|
+from bpy.props import *
|
|
|
+import mathutils, math
|
|
|
+import struct
|
|
|
+import shutil
|
|
|
+from os import remove
|
|
|
+from bpy_extras.io_utils import (ExportHelper, axis_conversion)
|
|
|
+from bpy.props import (BoolProperty, FloatProperty, StringProperty, EnumProperty, FloatVectorProperty)
|
|
|
+
|
|
|
+class SubMesh:
|
|
|
+ materialIndex = 0
|
|
|
+ verticesStart = 0
|
|
|
+ verticesCount = 0
|
|
|
+ indexStart = 0
|
|
|
+ indexCount = 0
|
|
|
+
|
|
|
+class MultiMaterial:
|
|
|
+ name = ""
|
|
|
+ materials = []
|
|
|
+
|
|
|
+class Export_babylon(bpy.types.Operator, ExportHelper):
|
|
|
+ """Export Babylon.js scene (.babylon)"""
|
|
|
+ bl_idname = "scene.babylon"
|
|
|
+ bl_label = "Export Babylon.js scene"
|
|
|
+
|
|
|
+ filename_ext = ".babylon"
|
|
|
+ filepath = ""
|
|
|
+
|
|
|
+ # global_scale = FloatProperty(name="Scale", min=0.01, max=1000.0, default=1.0)
|
|
|
+
|
|
|
+ def execute(self, context):
|
|
|
+ return Export_babylon.save(self, context, **self.as_keywords(ignore=("check_existing", "filter_glob", "global_scale")))
|
|
|
+
|
|
|
+ def mesh_triangulate(mesh):
|
|
|
+ import bmesh
|
|
|
+ bm = bmesh.new()
|
|
|
+ bm.from_mesh(mesh)
|
|
|
+ bmesh.ops.triangulate(bm, faces=bm.faces)
|
|
|
+ bm.to_mesh(mesh)
|
|
|
+ mesh.calc_tessface()
|
|
|
+ bm.free()
|
|
|
+
|
|
|
+ def write_array3(file_handler, name, array):
|
|
|
+ file_handler.write(",\""+name+"\":[" + "%.4f,%.4f,%.4f"%(array[0],array[1],array[2]) + "]")
|
|
|
+
|
|
|
+ def write_color(file_handler, name, color):
|
|
|
+ file_handler.write(",\""+name+"\":[" + "%.4f,%.4f,%.4f"%(color.r,color.g,color.b) + "]")
|
|
|
+
|
|
|
+ def write_vector(file_handler, name, vector):
|
|
|
+ file_handler.write(",\""+name+"\":[" + "%.4f,%.4f,%.4f"%(vector.x,vector.z,vector.y) + "]")
|
|
|
+
|
|
|
+ def write_string(file_handler, name, string, noComma=False):
|
|
|
+ if noComma == False:
|
|
|
+ file_handler.write(",")
|
|
|
+ file_handler.write("\""+name+"\":\"" + string + "\"")
|
|
|
+
|
|
|
+ def write_float(file_handler, name, float):
|
|
|
+ file_handler.write(",\""+name+"\":" + "%.4f"%(float))
|
|
|
+
|
|
|
+ def write_int(file_handler, name, int, noComma=False):
|
|
|
+ if noComma == False:
|
|
|
+ file_handler.write(",")
|
|
|
+ file_handler.write("\""+name+"\":" + str(int))
|
|
|
+
|
|
|
+ def write_bool(file_handler, name, bool):
|
|
|
+ if bool:
|
|
|
+ file_handler.write(",\""+name+"\":" + "true")
|
|
|
+ else:
|
|
|
+ file_handler.write(",\""+name+"\":" + "false")
|
|
|
+
|
|
|
+ def export_camera(object, scene, file_handler):
|
|
|
+ invWorld = object.matrix_world.copy()
|
|
|
+ invWorld.invert()
|
|
|
+
|
|
|
+ target = mathutils.Vector((0, 1, 0)) * invWorld
|
|
|
+
|
|
|
+ file_handler.write("{")
|
|
|
+ Export_babylon.write_string(file_handler, "name", object.name, True)
|
|
|
+ Export_babylon.write_string(file_handler, "id", object.name)
|
|
|
+ Export_babylon.write_vector(file_handler, "position", object.location)
|
|
|
+ Export_babylon.write_vector(file_handler, "target", target)
|
|
|
+ Export_babylon.write_float(file_handler, "fov", object.data.angle)
|
|
|
+ Export_babylon.write_float(file_handler, "minZ", object.data.clip_start)
|
|
|
+ Export_babylon.write_float(file_handler, "maxZ", object.data.clip_end)
|
|
|
+ Export_babylon.write_float(file_handler, "speed", 1.0)
|
|
|
+ Export_babylon.write_float(file_handler, "inertia", 0.9)
|
|
|
+ Export_babylon.write_bool(file_handler, "checkCollisions", object.data.checkCollisions)
|
|
|
+ Export_babylon.write_bool(file_handler, "applyGravity", object.data.applyGravity)
|
|
|
+ Export_babylon.write_array3(file_handler, "ellipsoid", object.data.ellipsoid)
|
|
|
+ file_handler.write("}")
|
|
|
+
|
|
|
+ def export_light(object, scene, file_handler):
|
|
|
+ light_type_items = {'POINT': 0, 'SUN': 1, 'SPOT': 2, 'HEMI': 3, 'AREA': 0}
|
|
|
+ light_type = light_type_items[object.data.type]
|
|
|
+
|
|
|
+ file_handler.write("{")
|
|
|
+ Export_babylon.write_string(file_handler, "name", object.name, True)
|
|
|
+ Export_babylon.write_string(file_handler, "id", object.name)
|
|
|
+ Export_babylon.write_float(file_handler, "type", light_type)
|
|
|
+ if light_type == 0:
|
|
|
+ Export_babylon.write_vector(file_handler, "data", object.location)
|
|
|
+ elif light_type == 1:
|
|
|
+ matrix_world = object.matrix_world.copy()
|
|
|
+ matrix_world.translation = mathutils.Vector((0, 0, 0))
|
|
|
+ direction = mathutils.Vector((0, 0, -1)) * matrix_world
|
|
|
+ Export_babylon.write_vector(file_handler, "data", direction)
|
|
|
+ elif light_type == 2:
|
|
|
+ Export_babylon.write_vector(file_handler, "data", object.location)
|
|
|
+ matrix_world = object.matrix_world.copy()
|
|
|
+ matrix_world.translation = mathutils.Vector((0, 0, 0))
|
|
|
+ direction = mathutils.Vector((0, 0, -1)) * matrix_world
|
|
|
+ Export_babylon.write_vector(file_handler, "direction", direction)
|
|
|
+ Export_babylon.write_float(file_handler, "angle", object.data.spot_size)
|
|
|
+ Export_babylon.write_float(file_handler, "exponent", object.data.spot_blend * 2)
|
|
|
+ else:
|
|
|
+ matrix_world = object.matrix_world.copy()
|
|
|
+ matrix_world.translation = mathutils.Vector((0, 0, 0))
|
|
|
+ direction = mathutils.Vector((0, 0, -1)) * matrix_world
|
|
|
+ Export_babylon.write_vector(file_handler, "data", -direction)
|
|
|
+ Export_babylon.write_color(file_handler, "groundColor", mathutils.Color((0, 0, 0)))
|
|
|
+
|
|
|
+ Export_babylon.write_float(file_handler, "intensity", object.data.energy)
|
|
|
+
|
|
|
+ if object.data.use_diffuse:
|
|
|
+ Export_babylon.write_color(file_handler, "diffuse", object.data.color)
|
|
|
+ else:
|
|
|
+ Export_babylon.write_color(file_handler, "diffuse", mathutils.Color((0, 0, 0)))
|
|
|
+
|
|
|
+ if object.data.use_specular:
|
|
|
+ Export_babylon.write_color(file_handler, "specular", object.data.color)
|
|
|
+ else:
|
|
|
+ Export_babylon.write_color(file_handler, "specular", mathutils.Color((0, 0, 0)))
|
|
|
+
|
|
|
+ file_handler.write("}")
|
|
|
+
|
|
|
+ def export_texture(slot, level, texture, scene, file_handler, filepath):
|
|
|
+ # Copy image to output
|
|
|
+ try:
|
|
|
+ image = texture.texture.image
|
|
|
+ imageFilepath = os.path.normpath(bpy.path.abspath(image.filepath))
|
|
|
+ basename = os.path.basename(imageFilepath)
|
|
|
+ targetdir = os.path.dirname(filepath)
|
|
|
+ targetpath = os.path.join(targetdir, basename)
|
|
|
+
|
|
|
+ if image.packed_file:
|
|
|
+ image.save_render(targetpath)
|
|
|
+ else:
|
|
|
+ sourcepath = bpy.path.abspath(image.filepath)
|
|
|
+ shutil.copy(sourcepath, targetdir)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+ # Export
|
|
|
+ file_handler.write(",\""+slot+"\":{")
|
|
|
+ Export_babylon.write_string(file_handler, "name", basename, True)
|
|
|
+ Export_babylon.write_float(file_handler, "level", level)
|
|
|
+ Export_babylon.write_float(file_handler, "hasAlpha", texture.texture.use_alpha)
|
|
|
+
|
|
|
+ coordinatesMode = 0;
|
|
|
+ if (texture.mapping == "CUBE"):
|
|
|
+ coordinatesMode = 3;
|
|
|
+ if (texture.mapping == "SPHERE"):
|
|
|
+ coordinatesMode = 1;
|
|
|
+ Export_babylon.write_int(file_handler, "coordinatesMode", coordinatesMode)
|
|
|
+ Export_babylon.write_float(file_handler, "uOffset", texture.offset.x)
|
|
|
+ Export_babylon.write_float(file_handler, "vOffset", texture.offset.y)
|
|
|
+ Export_babylon.write_float(file_handler, "uScale", texture.scale.x)
|
|
|
+ Export_babylon.write_float(file_handler, "vScale", texture.scale.y)
|
|
|
+ Export_babylon.write_float(file_handler, "uAng", 0)
|
|
|
+ Export_babylon.write_float(file_handler, "vAng", 0)
|
|
|
+ Export_babylon.write_float(file_handler, "wAng", 0)
|
|
|
+
|
|
|
+ if (texture.texture.extension == "REPEAT"):
|
|
|
+ Export_babylon.write_bool(file_handler, "wrapU", True)
|
|
|
+ Export_babylon.write_bool(file_handler, "wrapV", True)
|
|
|
+ else:
|
|
|
+ Export_babylon.write_bool(file_handler, "wrapU", False)
|
|
|
+ Export_babylon.write_bool(file_handler, "wrapV", False)
|
|
|
+
|
|
|
+ Export_babylon.write_int(file_handler, "coordinatesIndex", 0)
|
|
|
+
|
|
|
+ file_handler.write("}")
|
|
|
+
|
|
|
+ def export_material(material, scene, file_handler, filepath):
|
|
|
+ file_handler.write("{")
|
|
|
+ Export_babylon.write_string(file_handler, "name", material.name, True)
|
|
|
+ Export_babylon.write_string(file_handler, "id", material.name)
|
|
|
+ Export_babylon.write_color(file_handler, "ambient", material.ambient * material.diffuse_color)
|
|
|
+ Export_babylon.write_color(file_handler, "diffuse", material.diffuse_intensity * material.diffuse_color)
|
|
|
+ Export_babylon.write_color(file_handler, "specular", material.specular_intensity * material.specular_color)
|
|
|
+ Export_babylon.write_float(file_handler, "specularPower", material.specular_hardness)
|
|
|
+ Export_babylon.write_color(file_handler, "emissive", material.emit * material.diffuse_color)
|
|
|
+ Export_babylon.write_float(file_handler, "alpha", material.alpha)
|
|
|
+ Export_babylon.write_bool(file_handler, "backFaceCulling", material.game_settings.use_backface_culling)
|
|
|
+
|
|
|
+ # Textures
|
|
|
+ for mtex in material.texture_slots:
|
|
|
+ if mtex and mtex.texture and mtex.texture.type == 'IMAGE':
|
|
|
+ if mtex.texture.image:
|
|
|
+ if (mtex.use_map_color_diffuse and(mtex.texture_coords != 'REFLECTION')):
|
|
|
+ # Diffuse
|
|
|
+ Export_babylon.export_texture("diffuseTexture", mtex.diffuse_color_factor, mtex, scene, file_handler, filepath)
|
|
|
+ if mtex.use_map_ambient:
|
|
|
+ # Ambient
|
|
|
+ Export_babylon.export_texture("ambientTexture", mtex.ambient_factor, mtex, scene, file_handler, filepath)
|
|
|
+ if mtex.use_map_alpha:
|
|
|
+ # Opacity
|
|
|
+ Export_babylon.export_texture("opacityTexture", mtex.alpha_factor, mtex, scene, file_handler, filepath)
|
|
|
+ if mtex.use_map_color_diffuse and (mtex.texture_coords == 'REFLECTION'):
|
|
|
+ # Reflection
|
|
|
+ Export_babylon.export_texture("reflectionTexture", mtex.diffuse_color_factor, mtex, scene, file_handler, filepath)
|
|
|
+ if mtex.use_map_emit:
|
|
|
+ # Emissive
|
|
|
+ Export_babylon.export_texture("emissiveTexture", mtex.emit_factor, mtex, scene, file_handler, filepath)
|
|
|
+
|
|
|
+ file_handler.write("}")
|
|
|
+
|
|
|
+ def export_multimaterial(multimaterial, scene, file_handler):
|
|
|
+ file_handler.write("{")
|
|
|
+ Export_babylon.write_string(file_handler, "name", multimaterial.name, True)
|
|
|
+ Export_babylon.write_string(file_handler, "id", multimaterial.name)
|
|
|
+
|
|
|
+ file_handler.write(",\"materials\":[")
|
|
|
+ first = True
|
|
|
+ for materialName in multimaterial.materials:
|
|
|
+ if first != True:
|
|
|
+ file_handler.write(",")
|
|
|
+ file_handler.write("\"" + materialName +"\"")
|
|
|
+ first = False
|
|
|
+ file_handler.write("]")
|
|
|
+ file_handler.write("}")
|
|
|
+
|
|
|
+ def export_mesh(object, scene, file_handler, multiMaterials):
|
|
|
+ # Get mesh
|
|
|
+ mesh = object.to_mesh(scene, True, "PREVIEW")
|
|
|
+
|
|
|
+ # Transform
|
|
|
+ matrix_world = object.matrix_world.copy()
|
|
|
+ matrix_world.translation = mathutils.Vector((0, 0, 0))
|
|
|
+ mesh.transform(matrix_world)
|
|
|
+
|
|
|
+ # Triangulate mesh if required
|
|
|
+ Export_babylon.mesh_triangulate(mesh)
|
|
|
+
|
|
|
+ # Getting vertices and indices
|
|
|
+ vertices=",\"vertices\":["
|
|
|
+ indices=",\"indices\":["
|
|
|
+ hasUV = True;
|
|
|
+ hasUV2 = True;
|
|
|
+
|
|
|
+ if len(mesh.tessface_uv_textures) > 0:
|
|
|
+ UVmap=mesh.tessface_uv_textures[0].data
|
|
|
+ else:
|
|
|
+ hasUV = False
|
|
|
+
|
|
|
+ if len(mesh.tessface_uv_textures) > 1:
|
|
|
+ UV2map=mesh.tessface_uv_textures[1].data
|
|
|
+ else:
|
|
|
+ hasUV2 = False
|
|
|
+
|
|
|
+ alreadySavedVertices = []
|
|
|
+ vertices_UVs=[]
|
|
|
+ vertices_UV2s=[]
|
|
|
+ vertices_indices=[]
|
|
|
+ subMeshes = []
|
|
|
+
|
|
|
+ for v in range(0, len(mesh.vertices)):
|
|
|
+ alreadySavedVertices.append(False)
|
|
|
+ vertices_UVs.append([])
|
|
|
+ vertices_UV2s.append([])
|
|
|
+ vertices_indices.append([])
|
|
|
+
|
|
|
+
|
|
|
+ materialsCount = max(1, len(object.material_slots))
|
|
|
+ verticesCount = 0
|
|
|
+ indicesCount = 0
|
|
|
+
|
|
|
+ for materialIndex in range(materialsCount):
|
|
|
+ subMeshes.append(SubMesh())
|
|
|
+ subMeshes[materialIndex].materialIndex = materialIndex
|
|
|
+ subMeshes[materialIndex].verticesStart = verticesCount
|
|
|
+ subMeshes[materialIndex].indexStart = indicesCount
|
|
|
+
|
|
|
+ for face in mesh.tessfaces: # For each face
|
|
|
+
|
|
|
+ if face.material_index != materialIndex:
|
|
|
+ continue
|
|
|
+
|
|
|
+ for v in range(3): # For each vertex in face
|
|
|
+ vertex_index = face.vertices[v]
|
|
|
+ vertex = mesh.vertices[vertex_index]
|
|
|
+ position = vertex.co
|
|
|
+ normal = vertex.normal
|
|
|
+
|
|
|
+ if hasUV:
|
|
|
+ vertex_UV = UVmap[face.index].uv[v]
|
|
|
+
|
|
|
+ if hasUV2:
|
|
|
+ vertex_UV2 = UV2map[face.index].uv[v]
|
|
|
+
|
|
|
+ # Check if the current vertex is already saved
|
|
|
+ alreadySaved = alreadySavedVertices[vertex_index]
|
|
|
+ index_UV = 0
|
|
|
+ if alreadySaved:
|
|
|
+ alreadySaved=False
|
|
|
+
|
|
|
+ if hasUV:
|
|
|
+ for vUV in vertices_UVs[vertex_index]:
|
|
|
+ if (vUV[0]==vertex_UV[0] and vUV[1]==vertex_UV[1]):
|
|
|
+ if hasUV2:
|
|
|
+ vUV2 = vertices_UV2s[vertex_index][index_UV]
|
|
|
+ if (vUV2[0]==vertex_UV2[0] and vUV2[1]==vertex_UV2[1]):
|
|
|
+ if vertices_indices[vertex_index][index_UV] >= subMeshes[materialIndex].verticesStart:
|
|
|
+ alreadySaved=True
|
|
|
+ break
|
|
|
+ else:
|
|
|
+ alreadySaved=True
|
|
|
+ break
|
|
|
+ index_UV+=1
|
|
|
+ else:
|
|
|
+ for savedIndex in vertices_indices[vertex_index]:
|
|
|
+ if savedIndex >= subMeshes[materialIndex].verticesStart:
|
|
|
+ alreadySaved=True
|
|
|
+ break
|
|
|
+ index_UV+=1
|
|
|
+
|
|
|
+ if (alreadySaved):
|
|
|
+ # Reuse vertex
|
|
|
+ index=vertices_indices[vertex_index][index_UV]
|
|
|
+ else:
|
|
|
+ # Export new one
|
|
|
+ index=verticesCount
|
|
|
+ alreadySavedVertices[vertex_index]=True
|
|
|
+ if hasUV:
|
|
|
+ vertices_UVs[vertex_index].append(vertex_UV)
|
|
|
+ if hasUV2:
|
|
|
+ vertices_UV2s[vertex_index].append(vertex_UV2)
|
|
|
+ vertices_indices[vertex_index].append(index)
|
|
|
+
|
|
|
+ vertices+="%.4f,%.4f,%.4f,"%(position.x,position.z,position.y)
|
|
|
+ vertices+="%.4f,%.4f,%.4f,"%(normal.x,normal.z,normal.y)
|
|
|
+ if hasUV:
|
|
|
+ vertices+="%.4f,%.4f,"%(vertex_UV[0], vertex_UV[1])
|
|
|
+
|
|
|
+ if hasUV2:
|
|
|
+ vertices+="%.4f,%.4f,"%(vertex_UV2[0], vertex_UV2[1])
|
|
|
+
|
|
|
+ verticesCount += 1
|
|
|
+ indices+="%i,"%(index)
|
|
|
+ indicesCount += 1
|
|
|
+
|
|
|
+ subMeshes[materialIndex].verticesCount = verticesCount - subMeshes[materialIndex].verticesStart
|
|
|
+ subMeshes[materialIndex].indexCount = indicesCount - subMeshes[materialIndex].indexStart
|
|
|
+
|
|
|
+ vertices=vertices.rstrip(',')
|
|
|
+ indices=indices.rstrip(',')
|
|
|
+
|
|
|
+ vertices+="]\n"
|
|
|
+ indices+="]\n"
|
|
|
+
|
|
|
+ # Writing mesh
|
|
|
+ file_handler.write("{")
|
|
|
+
|
|
|
+ Export_babylon.write_string(file_handler, "name", object.name, True)
|
|
|
+ Export_babylon.write_string(file_handler, "id", object.name)
|
|
|
+ if object.parent != None:
|
|
|
+ Export_babylon.write_string(file_handler, "parentId", object.parent.name)
|
|
|
+
|
|
|
+ if len(object.material_slots) == 1:
|
|
|
+ material = object.material_slots[0].material
|
|
|
+ Export_babylon.write_string(file_handler, "materialId", object.material_slots[0].name)
|
|
|
+
|
|
|
+ if material.game_settings.face_orientation != "BILLBOARD":
|
|
|
+ billboardMode = 0
|
|
|
+ else:
|
|
|
+ billboardMode = 7
|
|
|
+ elif len(object.material_slots) > 1:
|
|
|
+ multimat = MultiMaterial()
|
|
|
+ multimat.name = "Multimaterial#" + str(len(multiMaterials))
|
|
|
+ Export_babylon.write_string(file_handler, "materialId", multimat.name)
|
|
|
+ for mat in object.material_slots:
|
|
|
+ multimat.materials.append(mat.name)
|
|
|
+
|
|
|
+ multiMaterials.append(multimat)
|
|
|
+ billboardMode = 0
|
|
|
+ else:
|
|
|
+ billboardMode = 0
|
|
|
+
|
|
|
+ Export_babylon.write_vector(file_handler, "position", object.location)
|
|
|
+ Export_babylon.write_vector(file_handler, "rotation", mathutils.Vector((0, 0, 0)))
|
|
|
+ Export_babylon.write_vector(file_handler, "scaling", mathutils.Vector((1, 1, 1)))
|
|
|
+ Export_babylon.write_bool(file_handler, "isVisible", object.is_visible(scene))
|
|
|
+ Export_babylon.write_bool(file_handler, "isEnabled", True)
|
|
|
+ Export_babylon.write_bool(file_handler, "checkCollisions", object.data.checkCollisions)
|
|
|
+ Export_babylon.write_int(file_handler, "billboardMode", billboardMode)
|
|
|
+
|
|
|
+ if hasUV and hasUV2:
|
|
|
+ Export_babylon.write_int(file_handler, "uvCount", 2)
|
|
|
+ elif hasUV:
|
|
|
+ Export_babylon.write_int(file_handler, "uvCount", 1)
|
|
|
+ else:
|
|
|
+ Export_babylon.write_int(file_handler, "uvCount", 0)
|
|
|
+
|
|
|
+ file_handler.write(vertices)
|
|
|
+ file_handler.write(indices)
|
|
|
+
|
|
|
+ # Sub meshes
|
|
|
+ file_handler.write(",\"subMeshes\":[")
|
|
|
+ first = True
|
|
|
+ for subMesh in subMeshes:
|
|
|
+ if first == False:
|
|
|
+ file_handler.write(",")
|
|
|
+ file_handler.write("{")
|
|
|
+ Export_babylon.write_int(file_handler, "materialIndex", subMesh.materialIndex, True)
|
|
|
+ Export_babylon.write_int(file_handler, "verticesStart", subMesh.verticesStart)
|
|
|
+ Export_babylon.write_int(file_handler, "verticesCount", subMesh.verticesCount)
|
|
|
+ Export_babylon.write_int(file_handler, "indexStart", subMesh.indexStart)
|
|
|
+ Export_babylon.write_int(file_handler, "indexCount", subMesh.indexCount)
|
|
|
+ file_handler.write("}")
|
|
|
+ first = False
|
|
|
+ file_handler.write("]")
|
|
|
+
|
|
|
+ # Closing
|
|
|
+ file_handler.write("}")
|
|
|
+
|
|
|
+
|
|
|
+ def save(operator, context, filepath="",
|
|
|
+ use_apply_modifiers=False,
|
|
|
+ use_triangulate=True,
|
|
|
+ use_compress=False):
|
|
|
+
|
|
|
+ # Open file
|
|
|
+ file_handler = open(filepath, 'w')
|
|
|
+
|
|
|
+ if bpy.ops.object.mode_set.poll():
|
|
|
+ bpy.ops.object.mode_set(mode='OBJECT')
|
|
|
+
|
|
|
+ # Writing scene
|
|
|
+ scene=context.scene
|
|
|
+
|
|
|
+ world = scene.world
|
|
|
+ if world:
|
|
|
+ world_ambient = world.ambient_color
|
|
|
+ else:
|
|
|
+ world_ambient = Color((0.0, 0.0, 0.0))
|
|
|
+
|
|
|
+ file_handler.write("{")
|
|
|
+ file_handler.write("\"autoClear\":true")
|
|
|
+ Export_babylon.write_color(file_handler, "clearColor", world_ambient)
|
|
|
+ Export_babylon.write_color(file_handler, "ambientColor", world_ambient)
|
|
|
+ Export_babylon.write_vector(file_handler, "gravity", scene.gravity)
|
|
|
+
|
|
|
+ # Cameras
|
|
|
+ file_handler.write(",\"cameras\":[")
|
|
|
+ first = True
|
|
|
+ for object in [object for object in scene.objects if object.is_visible(scene)]:
|
|
|
+ if (object.type == 'CAMERA'):
|
|
|
+ if first != True:
|
|
|
+ file_handler.write(",")
|
|
|
+
|
|
|
+ first = False
|
|
|
+ data_string = Export_babylon.export_camera(object, scene, file_handler)
|
|
|
+ file_handler.write("]")
|
|
|
+
|
|
|
+ # Active camera
|
|
|
+ if scene.camera != None:
|
|
|
+ Export_babylon.write_string(file_handler, "activeCamera", scene.camera.name)
|
|
|
+
|
|
|
+ # Lights
|
|
|
+ file_handler.write(",\"lights\":[")
|
|
|
+ first = True
|
|
|
+ for object in [object for object in scene.objects if object.is_visible(scene)]:
|
|
|
+ if (object.type == 'LAMP'):
|
|
|
+ if first != True:
|
|
|
+ file_handler.write(",")
|
|
|
+
|
|
|
+ first = False
|
|
|
+ data_string = Export_babylon.export_light(object, scene, file_handler)
|
|
|
+ file_handler.write("]")
|
|
|
+
|
|
|
+ # Materials
|
|
|
+ materials = [mat for mat in bpy.data.materials if mat.users >= 1]
|
|
|
+ file_handler.write(",\"materials\":[")
|
|
|
+ first = True
|
|
|
+ for material in materials:
|
|
|
+ if first != True:
|
|
|
+ file_handler.write(",")
|
|
|
+
|
|
|
+ first = False
|
|
|
+ data_string = Export_babylon.export_material(material, scene, file_handler, filepath)
|
|
|
+ file_handler.write("]")
|
|
|
+
|
|
|
+ # Meshes
|
|
|
+ file_handler.write(",\"meshes\":[")
|
|
|
+ multiMaterials = []
|
|
|
+ first = True
|
|
|
+ for object in [object for object in scene.objects]:
|
|
|
+ if (object.type == 'MESH'):
|
|
|
+ if first != True:
|
|
|
+ file_handler.write(",")
|
|
|
+
|
|
|
+ first = False
|
|
|
+ data_string = Export_babylon.export_mesh(object, scene, file_handler, multiMaterials)
|
|
|
+ file_handler.write("]")
|
|
|
+
|
|
|
+ # Multi-materials
|
|
|
+ file_handler.write(",\"multiMaterials\":[")
|
|
|
+ first = True
|
|
|
+ for multimaterial in multiMaterials:
|
|
|
+ if first != True:
|
|
|
+ file_handler.write(",")
|
|
|
+
|
|
|
+ first = False
|
|
|
+ data_string = Export_babylon.export_multimaterial(multimaterial, scene, file_handler)
|
|
|
+ file_handler.write("]")
|
|
|
+
|
|
|
+ # Closing
|
|
|
+ file_handler.write("}")
|
|
|
+ file_handler.close()
|
|
|
+
|
|
|
+ return {'FINISHED'}
|
|
|
+
|
|
|
+# UI
|
|
|
+bpy.types.Mesh.checkCollisions = BoolProperty(
|
|
|
+ name="Check collisions",
|
|
|
+ default = False)
|
|
|
+
|
|
|
+bpy.types.Camera.checkCollisions = BoolProperty(
|
|
|
+ name="Check collisions",
|
|
|
+ default = False)
|
|
|
+
|
|
|
+bpy.types.Camera.applyGravity = BoolProperty(
|
|
|
+ name="Apply Gravity",
|
|
|
+ default = False)
|
|
|
+
|
|
|
+bpy.types.Camera.ellipsoid = FloatVectorProperty(
|
|
|
+ name="Ellipsoid",
|
|
|
+ default = mathutils.Vector((0.2, 0.9, 0.2)))
|
|
|
+
|
|
|
+class ObjectPanel(bpy.types.Panel):
|
|
|
+ bl_label = "Babylon.js"
|
|
|
+ bl_space_type = "PROPERTIES"
|
|
|
+ bl_region_type = "WINDOW"
|
|
|
+ bl_context = "data"
|
|
|
+
|
|
|
+ def draw(self, context):
|
|
|
+ ob = context.object
|
|
|
+ if not ob or not ob.data:
|
|
|
+ return
|
|
|
+
|
|
|
+ layout = self.layout
|
|
|
+ isMesh = isinstance(ob.data, bpy.types.Mesh)
|
|
|
+ isCamera = isinstance(ob.data, bpy.types.Camera)
|
|
|
+
|
|
|
+ if isMesh:
|
|
|
+ layout.prop(ob.data, 'checkCollisions')
|
|
|
+ elif isCamera:
|
|
|
+ layout.prop(ob.data, 'checkCollisions')
|
|
|
+ layout.prop(ob.data, 'applyGravity')
|
|
|
+ layout.prop(ob.data, 'ellipsoid')
|
|
|
+
|
|
|
+### REGISTER ###
|
|
|
+
|
|
|
+def menu_func(self, context):
|
|
|
+ self.layout.operator(Export_babylon.bl_idname, text="Babylon.js (.babylon)")
|
|
|
+
|
|
|
+def register():
|
|
|
+ bpy.utils.register_module(__name__)
|
|
|
+ bpy.types.INFO_MT_file_export.append(menu_func)
|
|
|
+
|
|
|
+def unregister():
|
|
|
+ bpy.utils.unregister_module(__name__)
|
|
|
+ bpy.types.INFO_MT_file_export.remove(menu_func)
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ register()
|