mirror of
https://github.com/wahyd4/three.js.git
synced 2026-08-11 14:06:02 +10:00
Cleaned up Blender exporter (visually, code-wise and whitespaces-wise)
This commit is contained in:
@@ -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 = layout.row()
|
||||
row.prop(self.properties, "option_flip_yz")
|
||||
layout.separator()
|
||||
|
||||
row = layout.row()
|
||||
row.prop(self.properties, "align_model")
|
||||
layout.separator()
|
||||
row.label(text="Geometry:")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(self.properties, "option_vertices")
|
||||
row.prop(self.properties, "option_normals")
|
||||
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, "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_normals")
|
||||
layout.separator()
|
||||
|
||||
row = layout.row()
|
||||
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()
|
||||
|
||||
|
||||
# ################################################################
|
||||
|
||||
@@ -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'}
|
||||
|
||||
Reference in New Issue
Block a user