|
@@ -42,7 +42,7 @@ import random
|
|
# Configuration
|
|
# Configuration
|
|
# #####################################################
|
|
# #####################################################
|
|
|
|
|
|
-# 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
|
|
# white, red, green, blue, yellow, cyan, magenta
|
|
COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
|
|
COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
|
|
|
|
|
|
@@ -51,36 +51,40 @@ COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
|
|
# Templates
|
|
# Templates
|
|
# #####################################################
|
|
# #####################################################
|
|
TEMPLATE_FILE_ASCII = """\
|
|
TEMPLATE_FILE_ASCII = """\
|
|
-// vertices: %(nvertex)d
|
|
|
|
-// faces: %(nface)d
|
|
|
|
-// materials: %(nmaterial)d
|
|
|
|
-//
|
|
|
|
-// Generated with Blender slim exporter (compatible with Blender 2.54 / 2.55)
|
|
|
|
-// https://github.com/alteredq/three.js/tree/master/utils/exporters/blender/
|
|
|
|
-
|
|
|
|
|
|
+/*
|
|
|
|
+ * File generated with Blender 2.55 Exporter
|
|
|
|
+ * https://github.com/mrdoob/three.js/tree/master/utils/exporters/blender/
|
|
|
|
+ *
|
|
|
|
+ * vertices: %(nvertex)d
|
|
|
|
+ * faces: %(nface)d
|
|
|
|
+ * materials: %(nmaterial)d
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
|
|
var model = {
|
|
var model = {
|
|
- 'materials': [%(materials)s],
|
|
|
|
|
|
|
|
- 'normals': [%(normals)s],
|
|
|
|
|
|
+ 'materials': [%(materials)s],
|
|
|
|
|
|
- 'vertices': [%(vertices)s],
|
|
|
|
|
|
+ 'normals': [%(normals)s],
|
|
|
|
|
|
- 'uvs': [%(uvs)s],
|
|
|
|
|
|
+ 'vertices': [%(vertices)s],
|
|
|
|
|
|
- 'triangles': [%(triangles)s],
|
|
|
|
- 'triangles_n': [%(triangles_n)s],
|
|
|
|
- 'triangles_uv': [%(triangles_uv)s],
|
|
|
|
- 'triangles_n_uv': [%(triangles_n_uv)s],
|
|
|
|
|
|
+ 'uvs': [%(uvs)s],
|
|
|
|
|
|
- 'quads': [%(quads)s],
|
|
|
|
- 'quads_n': [%(quads_n)s],
|
|
|
|
- 'quads_uv': [%(quads_uv)s],
|
|
|
|
- 'quads_n_uv': [%(quads_n_uv)s],
|
|
|
|
|
|
+ 'triangles': [%(triangles)s],
|
|
|
|
+ 'triangles_n': [%(triangles_n)s],
|
|
|
|
+ 'triangles_uv': [%(triangles_uv)s],
|
|
|
|
+ 'triangles_n_uv': [%(triangles_n_uv)s],
|
|
|
|
+
|
|
|
|
+ 'quads': [%(quads)s],
|
|
|
|
+ 'quads_n': [%(quads_n)s],
|
|
|
|
+ 'quads_uv': [%(quads_uv)s],
|
|
|
|
+ 'quads_n_uv': [%(quads_n_uv)s],
|
|
|
|
+
|
|
|
|
+ 'end': (new Date).getTime()
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
|
|
- 'end': (new Date).getTime()
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
postMessage( model );
|
|
postMessage( model );
|
|
"""
|
|
"""
|
|
|
|
|
|
@@ -134,18 +138,18 @@ def get_uv_indices(f, uvs, mesh):
|
|
def bbox(vertices):
|
|
def bbox(vertices):
|
|
"""Compute bounding box of vertex array.
|
|
"""Compute bounding box of vertex array.
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
if len(vertices)>0:
|
|
if len(vertices)>0:
|
|
minx = maxx = vertices[0].co.x
|
|
minx = maxx = vertices[0].co.x
|
|
miny = maxy = vertices[0].co.y
|
|
miny = maxy = vertices[0].co.y
|
|
minz = maxz = vertices[0].co.z
|
|
minz = maxz = vertices[0].co.z
|
|
-
|
|
|
|
|
|
+
|
|
for v in vertices[1:]:
|
|
for v in vertices[1:]:
|
|
if v.co.x < minx:
|
|
if v.co.x < minx:
|
|
minx = v.co.x
|
|
minx = v.co.x
|
|
elif v.co.x > maxx:
|
|
elif v.co.x > maxx:
|
|
maxx = v.co.x
|
|
maxx = v.co.x
|
|
-
|
|
|
|
|
|
+
|
|
if v.co.y < miny:
|
|
if v.co.y < miny:
|
|
miny = v.co.y
|
|
miny = v.co.y
|
|
elif v.co.y > maxy:
|
|
elif v.co.y > maxy:
|
|
@@ -157,14 +161,14 @@ def bbox(vertices):
|
|
maxz = v.co.z
|
|
maxz = v.co.z
|
|
|
|
|
|
return { 'x':[minx,maxx], 'y':[miny,maxy], 'z':[minz,maxz] }
|
|
return { 'x':[minx,maxx], 'y':[miny,maxy], 'z':[minz,maxz] }
|
|
-
|
|
|
|
|
|
+
|
|
else:
|
|
else:
|
|
return { 'x':[0,0], 'y':[0,0], 'z':[0,0] }
|
|
return { 'x':[0,0], 'y':[0,0], 'z':[0,0] }
|
|
|
|
|
|
def translate(vertices, t):
|
|
def translate(vertices, t):
|
|
"""Translate array of vertices by vector t.
|
|
"""Translate array of vertices by vector t.
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
for i in range(len(vertices)):
|
|
for i in range(len(vertices)):
|
|
vertices[i].co.x += t[0]
|
|
vertices[i].co.x += t[0]
|
|
vertices[i].co.y += t[1]
|
|
vertices[i].co.y += t[1]
|
|
@@ -173,37 +177,37 @@ def translate(vertices, t):
|
|
def center(vertices):
|
|
def center(vertices):
|
|
"""Center model (middle of bounding box).
|
|
"""Center model (middle of bounding box).
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
bb = bbox(vertices)
|
|
bb = bbox(vertices)
|
|
-
|
|
|
|
|
|
+
|
|
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
|
|
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
|
|
cy = bb['y'][0] + (bb['y'][1] - bb['y'][0])/2.0
|
|
cy = bb['y'][0] + (bb['y'][1] - bb['y'][0])/2.0
|
|
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
|
|
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
|
|
-
|
|
|
|
|
|
+
|
|
translate(vertices, [-cx,-cy,-cz])
|
|
translate(vertices, [-cx,-cy,-cz])
|
|
|
|
|
|
def top(vertices):
|
|
def top(vertices):
|
|
"""Align top of the model with the floor (Y-axis) and center it around X and Z.
|
|
"""Align top of the model with the floor (Y-axis) and center it around X and Z.
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
bb = bbox(vertices)
|
|
bb = bbox(vertices)
|
|
-
|
|
|
|
|
|
+
|
|
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
|
|
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
|
|
cy = bb['y'][1]
|
|
cy = bb['y'][1]
|
|
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
|
|
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
|
|
-
|
|
|
|
|
|
+
|
|
translate(vertices, [-cx,-cy,-cz])
|
|
translate(vertices, [-cx,-cy,-cz])
|
|
-
|
|
|
|
|
|
+
|
|
def bottom(vertices):
|
|
def bottom(vertices):
|
|
"""Align bottom of the model with the floor (Y-axis) and center it around X and Z.
|
|
"""Align bottom of the model with the floor (Y-axis) and center it around X and Z.
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
bb = bbox(vertices)
|
|
bb = bbox(vertices)
|
|
-
|
|
|
|
|
|
+
|
|
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
|
|
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
|
|
- cy = bb['y'][0]
|
|
|
|
|
|
+ cy = bb['y'][0]
|
|
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
|
|
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
|
|
-
|
|
|
|
|
|
+
|
|
translate(vertices, [-cx,-cy,-cz])
|
|
translate(vertices, [-cx,-cy,-cz])
|
|
|
|
|
|
# #####################################################
|
|
# #####################################################
|
|
@@ -221,73 +225,73 @@ def generate_uv(uv):
|
|
def generate_triangle(f):
|
|
def generate_triangle(f):
|
|
v = f[0].vertices
|
|
v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
- return TEMPLATE_TRI % (v[0], v[1], v[2],
|
|
|
|
|
|
+ return TEMPLATE_TRI % (v[0], v[1], v[2],
|
|
m)
|
|
m)
|
|
-
|
|
|
|
|
|
+
|
|
def generate_quad(f):
|
|
def generate_quad(f):
|
|
v = f[0].vertices
|
|
v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
- return TEMPLATE_QUAD % (v[0], v[1], v[2], v[3],
|
|
|
|
|
|
+ return TEMPLATE_QUAD % (v[0], v[1], v[2], v[3],
|
|
m)
|
|
m)
|
|
-
|
|
|
|
-def generate_triangle_n(f, normals, mesh):
|
|
|
|
|
|
+
|
|
|
|
+def generate_triangle_n(f, normals, mesh):
|
|
v = f[0].vertices
|
|
v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
n = get_normal_indices(v, normals, mesh)
|
|
n = get_normal_indices(v, normals, mesh)
|
|
-
|
|
|
|
- return TEMPLATE_TRI_N % (v[0], v[1], v[2],
|
|
|
|
- m,
|
|
|
|
|
|
+
|
|
|
|
+ return TEMPLATE_TRI_N % (v[0], v[1], v[2],
|
|
|
|
+ m,
|
|
n[0], n[1], n[2])
|
|
n[0], n[1], n[2])
|
|
-
|
|
|
|
-def generate_quad_n(f, normals, mesh):
|
|
|
|
|
|
+
|
|
|
|
+def generate_quad_n(f, normals, mesh):
|
|
v = f[0].vertices
|
|
v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
n = get_normal_indices(v, normals, mesh)
|
|
n = get_normal_indices(v, normals, mesh)
|
|
-
|
|
|
|
|
|
+
|
|
return TEMPLATE_QUAD_N % (v[0], v[1], v[2], v[3],
|
|
return TEMPLATE_QUAD_N % (v[0], v[1], v[2], v[3],
|
|
- m,
|
|
|
|
|
|
+ m,
|
|
n[0], n[1], n[2], n[3])
|
|
n[0], n[1], n[2], n[3])
|
|
|
|
|
|
def generate_triangle_uv(f, uvs, mesh):
|
|
def generate_triangle_uv(f, uvs, mesh):
|
|
- v = f[0].vertices
|
|
|
|
|
|
+ v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
uv = get_uv_indices(f, uvs, mesh)
|
|
uv = get_uv_indices(f, uvs, mesh)
|
|
-
|
|
|
|
- return TEMPLATE_TRI_UV % (v[0], v[1], v[2],
|
|
|
|
- m,
|
|
|
|
|
|
+
|
|
|
|
+ return TEMPLATE_TRI_UV % (v[0], v[1], v[2],
|
|
|
|
+ m,
|
|
uv[0], uv[1], uv[2])
|
|
uv[0], uv[1], uv[2])
|
|
-
|
|
|
|
|
|
+
|
|
def generate_quad_uv(f, uvs, mesh):
|
|
def generate_quad_uv(f, uvs, mesh):
|
|
- v = f[0].vertices
|
|
|
|
|
|
+ v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
uv = get_uv_indices(f, uvs, mesh)
|
|
uv = get_uv_indices(f, uvs, mesh)
|
|
-
|
|
|
|
|
|
+
|
|
return TEMPLATE_QUAD_UV % (v[0], v[1], v[2], v[3],
|
|
return TEMPLATE_QUAD_UV % (v[0], v[1], v[2], v[3],
|
|
- m,
|
|
|
|
|
|
+ m,
|
|
uv[0], uv[1], uv[2], uv[3])
|
|
uv[0], uv[1], uv[2], uv[3])
|
|
-
|
|
|
|
|
|
+
|
|
def generate_triangle_n_uv(f, normals, uvs, mesh):
|
|
def generate_triangle_n_uv(f, normals, uvs, mesh):
|
|
- v = f[0].vertices
|
|
|
|
|
|
+ v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
n = get_normal_indices(v, normals, mesh)
|
|
n = get_normal_indices(v, normals, mesh)
|
|
- uv = get_uv_indices(f, uvs, mesh)
|
|
|
|
-
|
|
|
|
- return TEMPLATE_TRI_N_UV % (v[0], v[1], v[2],
|
|
|
|
- m,
|
|
|
|
- n[0], n[1], n[2],
|
|
|
|
|
|
+ uv = get_uv_indices(f, uvs, mesh)
|
|
|
|
+
|
|
|
|
+ return TEMPLATE_TRI_N_UV % (v[0], v[1], v[2],
|
|
|
|
+ m,
|
|
|
|
+ n[0], n[1], n[2],
|
|
uv[0], uv[1], uv[2])
|
|
uv[0], uv[1], uv[2])
|
|
-
|
|
|
|
|
|
+
|
|
def generate_quad_n_uv(f, normals, uvs, mesh):
|
|
def generate_quad_n_uv(f, normals, uvs, mesh):
|
|
- v = f[0].vertices
|
|
|
|
|
|
+ v = f[0].vertices
|
|
m = f[0].material_index
|
|
m = f[0].material_index
|
|
n = get_normal_indices(v, normals, mesh)
|
|
n = get_normal_indices(v, normals, mesh)
|
|
- uv = get_uv_indices(f, uvs, mesh)
|
|
|
|
-
|
|
|
|
- return TEMPLATE_QUAD_N_UV % (v[0], v[1], v[2], v[3],
|
|
|
|
- m,
|
|
|
|
|
|
+ uv = get_uv_indices(f, uvs, mesh)
|
|
|
|
+
|
|
|
|
+ return TEMPLATE_QUAD_N_UV % (v[0], v[1], v[2], v[3],
|
|
|
|
+ m,
|
|
n[0], n[1], n[2], n[3],
|
|
n[0], n[1], n[2], n[3],
|
|
uv[0], uv[1], uv[2], uv[3])
|
|
uv[0], uv[1], uv[2], uv[3])
|
|
-
|
|
|
|
|
|
+
|
|
# #####################################################
|
|
# #####################################################
|
|
# Faces
|
|
# Faces
|
|
# #####################################################
|
|
# #####################################################
|
|
@@ -297,17 +301,17 @@ def sort_faces(faces, use_normals, use_uv_coords):
|
|
'triangles_flat_uv': [],
|
|
'triangles_flat_uv': [],
|
|
'triangles_smooth': [],
|
|
'triangles_smooth': [],
|
|
'triangles_smooth_uv': [],
|
|
'triangles_smooth_uv': [],
|
|
-
|
|
|
|
|
|
+
|
|
'quads_flat': [],
|
|
'quads_flat': [],
|
|
'quads_flat_uv': [],
|
|
'quads_flat_uv': [],
|
|
'quads_smooth': [],
|
|
'quads_smooth': [],
|
|
'quads_smooth_uv': []
|
|
'quads_smooth_uv': []
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
for i, f in enumerate(faces):
|
|
for i, f in enumerate(faces):
|
|
-
|
|
|
|
|
|
+
|
|
if len(f.vertices) == 3:
|
|
if len(f.vertices) == 3:
|
|
-
|
|
|
|
|
|
+
|
|
if use_normals and use_uv_coords:
|
|
if use_normals and use_uv_coords:
|
|
data['triangles_smooth_uv'].append([f,i])
|
|
data['triangles_smooth_uv'].append([f,i])
|
|
elif use_normals and not use_uv_coords:
|
|
elif use_normals and not use_uv_coords:
|
|
@@ -316,9 +320,9 @@ def sort_faces(faces, use_normals, use_uv_coords):
|
|
data['triangles_flat_uv'].append([f,i])
|
|
data['triangles_flat_uv'].append([f,i])
|
|
else:
|
|
else:
|
|
data['triangles_flat'].append([f,i])
|
|
data['triangles_flat'].append([f,i])
|
|
-
|
|
|
|
|
|
+
|
|
elif len(f.vertices) == 4:
|
|
elif len(f.vertices) == 4:
|
|
-
|
|
|
|
|
|
+
|
|
if use_normals and use_uv_coords:
|
|
if use_normals and use_uv_coords:
|
|
data['quads_smooth_uv'].append([f,i])
|
|
data['quads_smooth_uv'].append([f,i])
|
|
elif use_normals and not use_uv_coords:
|
|
elif use_normals and not use_uv_coords:
|
|
@@ -327,81 +331,81 @@ def sort_faces(faces, use_normals, use_uv_coords):
|
|
data['quads_flat_uv'].append([f,i])
|
|
data['quads_flat_uv'].append([f,i])
|
|
else:
|
|
else:
|
|
data['quads_flat'].append([f,i])
|
|
data['quads_flat'].append([f,i])
|
|
-
|
|
|
|
|
|
+
|
|
return data
|
|
return data
|
|
-
|
|
|
|
|
|
+
|
|
# #####################################################
|
|
# #####################################################
|
|
# Normals
|
|
# Normals
|
|
# #####################################################
|
|
# #####################################################
|
|
def extract_vertex_normals(mesh, use_normals):
|
|
def extract_vertex_normals(mesh, use_normals):
|
|
if not use_normals:
|
|
if not use_normals:
|
|
return {}
|
|
return {}
|
|
-
|
|
|
|
|
|
+
|
|
count = 0
|
|
count = 0
|
|
normals = {}
|
|
normals = {}
|
|
-
|
|
|
|
|
|
+
|
|
for f in mesh.faces:
|
|
for f in mesh.faces:
|
|
for v in f.vertices:
|
|
for v in f.vertices:
|
|
key = veckey3d(mesh.vertices[v].normal)
|
|
key = veckey3d(mesh.vertices[v].normal)
|
|
if key not in normals:
|
|
if key not in normals:
|
|
normals[key] = count
|
|
normals[key] = count
|
|
count += 1
|
|
count += 1
|
|
-
|
|
|
|
|
|
+
|
|
return normals
|
|
return normals
|
|
-
|
|
|
|
|
|
+
|
|
def generate_normals(normals, use_normals):
|
|
def generate_normals(normals, use_normals):
|
|
if not use_normals:
|
|
if not use_normals:
|
|
return ""
|
|
return ""
|
|
-
|
|
|
|
|
|
+
|
|
chunks = []
|
|
chunks = []
|
|
for key, index in sorted(normals.items(), key=operator.itemgetter(1)):
|
|
for key, index in sorted(normals.items(), key=operator.itemgetter(1)):
|
|
chunks.append(key)
|
|
chunks.append(key)
|
|
-
|
|
|
|
|
|
+
|
|
return ",".join(generate_normal(n) for n in chunks)
|
|
return ",".join(generate_normal(n) for n in chunks)
|
|
-
|
|
|
|
|
|
+
|
|
# #####################################################
|
|
# #####################################################
|
|
# UVs
|
|
# UVs
|
|
# #####################################################
|
|
# #####################################################
|
|
def extract_uvs(mesh, use_uv_coords):
|
|
def extract_uvs(mesh, use_uv_coords):
|
|
if not use_uv_coords:
|
|
if not use_uv_coords:
|
|
return {}
|
|
return {}
|
|
-
|
|
|
|
|
|
+
|
|
count = 0
|
|
count = 0
|
|
uvs = {}
|
|
uvs = {}
|
|
-
|
|
|
|
|
|
+
|
|
uv_layer = mesh.uv_textures.active.data
|
|
uv_layer = mesh.uv_textures.active.data
|
|
-
|
|
|
|
|
|
+
|
|
for face_index, face in enumerate(mesh.faces):
|
|
for face_index, face in enumerate(mesh.faces):
|
|
for uv_index, uv in enumerate(uv_layer[face_index].uv):
|
|
for uv_index, uv in enumerate(uv_layer[face_index].uv):
|
|
key = veckey2d(uv)
|
|
key = veckey2d(uv)
|
|
if key not in uvs:
|
|
if key not in uvs:
|
|
uvs[key] = count
|
|
uvs[key] = count
|
|
count += 1
|
|
count += 1
|
|
-
|
|
|
|
|
|
+
|
|
return uvs
|
|
return uvs
|
|
-
|
|
|
|
|
|
+
|
|
def generate_uvs(uvs, use_uv_coords):
|
|
def generate_uvs(uvs, use_uv_coords):
|
|
if not use_uv_coords:
|
|
if not use_uv_coords:
|
|
return ""
|
|
return ""
|
|
-
|
|
|
|
|
|
+
|
|
chunks = []
|
|
chunks = []
|
|
for key, index in sorted(uvs.items(), key=operator.itemgetter(1)):
|
|
for key, index in sorted(uvs.items(), key=operator.itemgetter(1)):
|
|
chunks.append(key)
|
|
chunks.append(key)
|
|
-
|
|
|
|
|
|
+
|
|
return ",".join(generate_uv(n) for n in chunks)
|
|
return ",".join(generate_uv(n) for n in chunks)
|
|
-
|
|
|
|
|
|
+
|
|
# #####################################################
|
|
# #####################################################
|
|
# Materials
|
|
# Materials
|
|
# #####################################################
|
|
# #####################################################
|
|
def generate_color(i):
|
|
def generate_color(i):
|
|
"""Generate hex color corresponding to integer.
|
|
"""Generate hex color corresponding to integer.
|
|
-
|
|
|
|
|
|
+
|
|
Colors should have well defined ordering.
|
|
Colors should have well defined ordering.
|
|
- First N colors are hardcoded, then colors are random
|
|
|
|
- (must seed random number generator with deterministic value
|
|
|
|
|
|
+ First N colors are hardcoded, then colors are random
|
|
|
|
+ (must seed random number generator with deterministic value
|
|
before getting colors).
|
|
before getting colors).
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
if i < len(COLORS):
|
|
if i < len(COLORS):
|
|
return "0x%06x" % COLORS[i]
|
|
return "0x%06x" % COLORS[i]
|
|
else:
|
|
else:
|
|
@@ -410,7 +414,7 @@ def generate_color(i):
|
|
def generate_mtl(materials):
|
|
def generate_mtl(materials):
|
|
"""Generate dummy materials.
|
|
"""Generate dummy materials.
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
mtl = {}
|
|
mtl = {}
|
|
for m in materials:
|
|
for m in materials:
|
|
index = materials[m]
|
|
index = materials[m]
|
|
@@ -425,15 +429,15 @@ def value2string(v):
|
|
if type(v)==str and v[0] != "0":
|
|
if type(v)==str and v[0] != "0":
|
|
return '"%s"' % v
|
|
return '"%s"' % v
|
|
return str(v)
|
|
return str(v)
|
|
-
|
|
|
|
|
|
+
|
|
def generate_materials(mtl, materials):
|
|
def generate_materials(mtl, materials):
|
|
- """Generate JS array of materials objects
|
|
|
|
|
|
+ """Generate JS array of materials objects
|
|
"""
|
|
"""
|
|
-
|
|
|
|
|
|
+
|
|
mtl_array = []
|
|
mtl_array = []
|
|
for m in mtl:
|
|
for m in mtl:
|
|
index = materials[m]
|
|
index = materials[m]
|
|
-
|
|
|
|
|
|
+
|
|
# add debug information
|
|
# add debug information
|
|
# materials should be sorted according to how
|
|
# materials should be sorted according to how
|
|
# they appeared in OBJ file (for the first time)
|
|
# they appeared in OBJ file (for the first time)
|
|
@@ -441,13 +445,13 @@ def generate_materials(mtl, materials):
|
|
mtl[m]['a_dbg_name'] = m
|
|
mtl[m]['a_dbg_name'] = m
|
|
mtl[m]['a_dbg_index'] = index
|
|
mtl[m]['a_dbg_index'] = index
|
|
mtl[m]['a_dbg_color'] = generate_color(index)
|
|
mtl[m]['a_dbg_color'] = generate_color(index)
|
|
-
|
|
|
|
|
|
+
|
|
mtl_raw = ",\n".join(['\t"%s" : %s' % (n, value2string(v)) for n,v in sorted(mtl[m].items())])
|
|
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_string = "\t{\n%s\n\t}" % mtl_raw
|
|
mtl_array.append([index, mtl_string])
|
|
mtl_array.append([index, mtl_string])
|
|
-
|
|
|
|
|
|
+
|
|
return ",\n\n".join([m for i,m in sorted(mtl_array)])
|
|
return ",\n\n".join([m for i,m in sorted(mtl_array)])
|
|
-
|
|
|
|
|
|
+
|
|
def extract_materials(mesh, scene):
|
|
def extract_materials(mesh, scene):
|
|
world = scene.world
|
|
world = scene.world
|
|
|
|
|
|
@@ -455,33 +459,33 @@ def extract_materials(mesh, scene):
|
|
for m in mesh.materials:
|
|
for m in mesh.materials:
|
|
if m:
|
|
if m:
|
|
materials[m.name] = {}
|
|
materials[m.name] = {}
|
|
- materials[m.name]['col_diffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
|
|
|
|
- m.diffuse_intensity * m.diffuse_color[1],
|
|
|
|
|
|
+ materials[m.name]['col_diffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
|
|
|
|
+ m.diffuse_intensity * m.diffuse_color[1],
|
|
m.diffuse_intensity * m.diffuse_color[2]]
|
|
m.diffuse_intensity * m.diffuse_color[2]]
|
|
-
|
|
|
|
- materials[m.name]['col_specular'] = [m.specular_intensity * m.specular_color[0],
|
|
|
|
- m.specular_intensity * m.specular_color[1],
|
|
|
|
|
|
+
|
|
|
|
+ materials[m.name]['col_specular'] = [m.specular_intensity * m.specular_color[0],
|
|
|
|
+ m.specular_intensity * m.specular_color[1],
|
|
m.specular_intensity * m.specular_color[2]]
|
|
m.specular_intensity * m.specular_color[2]]
|
|
-
|
|
|
|
- materials[m.name]['col_ambient'] = [m.ambient * world.ambient_color[0],
|
|
|
|
- m.ambient * world.ambient_color[1],
|
|
|
|
|
|
+
|
|
|
|
+ materials[m.name]['col_ambient'] = [m.ambient * world.ambient_color[0],
|
|
|
|
+ m.ambient * world.ambient_color[1],
|
|
m.ambient * world.ambient_color[2]]
|
|
m.ambient * world.ambient_color[2]]
|
|
-
|
|
|
|
|
|
+
|
|
materials[m.name]['transparency'] = m.alpha
|
|
materials[m.name]['transparency'] = m.alpha
|
|
-
|
|
|
|
|
|
+
|
|
# not sure about mapping values to Blinn-Phong shader
|
|
# not sure about mapping values to Blinn-Phong shader
|
|
# Blender uses INT from [1,511] with default 0
|
|
# Blender uses INT from [1,511] with default 0
|
|
# http://www.blender.org/documentation/blender_python_api_2_54_0/bpy.types.Material.html#bpy.types.Material.specular_hardness
|
|
# http://www.blender.org/documentation/blender_python_api_2_54_0/bpy.types.Material.html#bpy.types.Material.specular_hardness
|
|
- materials[m.name]["specular_coef"] = m.specular_hardness
|
|
|
|
-
|
|
|
|
|
|
+ materials[m.name]["specular_coef"] = m.specular_hardness
|
|
|
|
+
|
|
if m.active_texture and m.active_texture.type == 'IMAGE':
|
|
if m.active_texture and m.active_texture.type == 'IMAGE':
|
|
fn = bpy.path.abspath(m.active_texture.image.filepath)
|
|
fn = bpy.path.abspath(m.active_texture.image.filepath)
|
|
fn = os.path.normpath(fn)
|
|
fn = os.path.normpath(fn)
|
|
fn_strip = os.path.basename(fn)
|
|
fn_strip = os.path.basename(fn)
|
|
materials[m.name]['map_diffuse'] = fn_strip
|
|
materials[m.name]['map_diffuse'] = fn_strip
|
|
-
|
|
|
|
|
|
+
|
|
return materials
|
|
return materials
|
|
-
|
|
|
|
|
|
+
|
|
def generate_materials_string(mesh, scene):
|
|
def generate_materials_string(mesh, scene):
|
|
|
|
|
|
random.seed(42) # to get well defined color order for debug materials
|
|
random.seed(42) # to get well defined color order for debug materials
|
|
@@ -493,61 +497,61 @@ def generate_materials_string(mesh, scene):
|
|
materials[m.name] = i
|
|
materials[m.name] = i
|
|
else:
|
|
else:
|
|
materials["undefined_dummy_%0d" % i] = i
|
|
materials["undefined_dummy_%0d" % i] = i
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+
|
|
if not materials:
|
|
if not materials:
|
|
materials = { 'default':0 }
|
|
materials = { 'default':0 }
|
|
-
|
|
|
|
|
|
+
|
|
# default dummy materials
|
|
# default dummy materials
|
|
mtl = generate_mtl(materials)
|
|
mtl = generate_mtl(materials)
|
|
-
|
|
|
|
|
|
+
|
|
# extract real materials from the mesh
|
|
# extract real materials from the mesh
|
|
mtl.update(extract_materials(mesh, scene))
|
|
mtl.update(extract_materials(mesh, scene))
|
|
-
|
|
|
|
|
|
+
|
|
return generate_materials(mtl, materials)
|
|
return generate_materials(mtl, materials)
|
|
-
|
|
|
|
|
|
+
|
|
# #####################################################
|
|
# #####################################################
|
|
# ASCII exporter
|
|
# ASCII exporter
|
|
# #####################################################
|
|
# #####################################################
|
|
def generate_ascii_model(mesh, scene, use_normals, use_uv_coords, align_model):
|
|
def generate_ascii_model(mesh, scene, use_normals, use_uv_coords, align_model):
|
|
-
|
|
|
|
|
|
+
|
|
vertices = mesh.vertices[:]
|
|
vertices = mesh.vertices[:]
|
|
-
|
|
|
|
|
|
+
|
|
if align_model == 1:
|
|
if align_model == 1:
|
|
center(vertices)
|
|
center(vertices)
|
|
elif align_model == 2:
|
|
elif align_model == 2:
|
|
bottom(vertices)
|
|
bottom(vertices)
|
|
elif align_model == 3:
|
|
elif align_model == 3:
|
|
top(vertices)
|
|
top(vertices)
|
|
-
|
|
|
|
|
|
+
|
|
sfaces = sort_faces(mesh.faces, use_normals, use_uv_coords)
|
|
sfaces = sort_faces(mesh.faces, use_normals, use_uv_coords)
|
|
-
|
|
|
|
|
|
+
|
|
normals = extract_vertex_normals(mesh, use_normals)
|
|
normals = extract_vertex_normals(mesh, use_normals)
|
|
uvs = extract_uvs(mesh, use_uv_coords)
|
|
uvs = extract_uvs(mesh, use_uv_coords)
|
|
-
|
|
|
|
|
|
+
|
|
text = TEMPLATE_FILE_ASCII % {
|
|
text = TEMPLATE_FILE_ASCII % {
|
|
"vertices" : ",".join(generate_vertex(v) for v in vertices),
|
|
"vertices" : ",".join(generate_vertex(v) for v in vertices),
|
|
-
|
|
|
|
|
|
+
|
|
"triangles" : ",".join(generate_triangle(f) for f in sfaces['triangles_flat']),
|
|
"triangles" : ",".join(generate_triangle(f) for f in sfaces['triangles_flat']),
|
|
"triangles_n" : ",".join(generate_triangle_n(f, normals, mesh) for f in sfaces['triangles_smooth']),
|
|
"triangles_n" : ",".join(generate_triangle_n(f, normals, mesh) for f in sfaces['triangles_smooth']),
|
|
"triangles_uv" : ",".join(generate_triangle_uv(f, uvs, mesh) for f in sfaces['triangles_flat_uv']),
|
|
"triangles_uv" : ",".join(generate_triangle_uv(f, uvs, mesh) for f in sfaces['triangles_flat_uv']),
|
|
"triangles_n_uv": ",".join(generate_triangle_n_uv(f, normals, uvs, mesh) for f in sfaces['triangles_smooth_uv']),
|
|
"triangles_n_uv": ",".join(generate_triangle_n_uv(f, normals, uvs, mesh) for f in sfaces['triangles_smooth_uv']),
|
|
-
|
|
|
|
|
|
+
|
|
"quads" : ",".join(generate_quad(f) for f in sfaces['quads_flat']),
|
|
"quads" : ",".join(generate_quad(f) for f in sfaces['quads_flat']),
|
|
"quads_n" : ",".join(generate_quad_n(f, normals, mesh) for f in sfaces['quads_smooth']),
|
|
"quads_n" : ",".join(generate_quad_n(f, normals, mesh) for f in sfaces['quads_smooth']),
|
|
"quads_uv" : ",".join(generate_quad_uv(f, uvs, mesh) for f in sfaces['quads_flat_uv']),
|
|
"quads_uv" : ",".join(generate_quad_uv(f, uvs, mesh) for f in sfaces['quads_flat_uv']),
|
|
"quads_n_uv" : ",".join(generate_quad_n_uv(f, normals, uvs, mesh) for f in sfaces['quads_smooth_uv']),
|
|
"quads_n_uv" : ",".join(generate_quad_n_uv(f, normals, uvs, mesh) for f in sfaces['quads_smooth_uv']),
|
|
-
|
|
|
|
|
|
+
|
|
"uvs" : generate_uvs(uvs, use_uv_coords),
|
|
"uvs" : generate_uvs(uvs, use_uv_coords),
|
|
"normals" : generate_normals(normals, use_normals),
|
|
"normals" : generate_normals(normals, use_normals),
|
|
-
|
|
|
|
|
|
+
|
|
"materials" : generate_materials_string(mesh, scene),
|
|
"materials" : generate_materials_string(mesh, scene),
|
|
-
|
|
|
|
|
|
+
|
|
"nvertex" : len(mesh.vertices),
|
|
"nvertex" : len(mesh.vertices),
|
|
"nface" : len(mesh.faces),
|
|
"nface" : len(mesh.faces),
|
|
"nmaterial" : 0
|
|
"nmaterial" : 0
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
return text
|
|
return text
|
|
|
|
|
|
# #####################################################
|
|
# #####################################################
|
|
@@ -587,7 +591,7 @@ def save(operator, context, filepath="", use_modifiers=True, use_normals=True, u
|
|
x_rot = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
|
|
x_rot = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
|
|
mesh.transform(x_rot * obj.matrix_world)
|
|
mesh.transform(x_rot * obj.matrix_world)
|
|
mesh.calc_normals()
|
|
mesh.calc_normals()
|
|
-
|
|
|
|
|
|
+
|
|
faceUV = (len(mesh.uv_textures) > 0)
|
|
faceUV = (len(mesh.uv_textures) > 0)
|
|
vertexUV = (len(mesh.sticky) > 0)
|
|
vertexUV = (len(mesh.sticky) > 0)
|
|
|
|
|