Skip to content

Commit cb76523

Browse files
committed
* Added Blender 2.54 exporter. (Crossing fingers so they don't change the scripting system again...)
1 parent db7003e commit cb76523

File tree

4 files changed

+359
-0
lines changed

4 files changed

+359
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# ##### BEGIN GPL LICENSE BLOCK #####
2+
#
3+
# This program is free software; you can redistribute it and/or
4+
# modify it under the terms of the GNU General Public License
5+
# as published by the Free Software Foundation; either version 2
6+
# of the License, or (at your option) any later version.
7+
#
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License
14+
# along with this program; if not, write to the Free Software Foundation,
15+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16+
#
17+
# ##### END GPL LICENSE BLOCK #####
18+
19+
# To support reload properly, try to access a package var, if it's there, reload everything
20+
if "bpy" in locals():
21+
import sys
22+
reload(sys.modules.get("io_mesh_threejs.export_threejs", sys))
23+
24+
25+
import bpy
26+
from bpy.props import *
27+
from io_utils import ExportHelper
28+
29+
30+
class ExportTHREEJS(bpy.types.Operator, ExportHelper):
31+
'''This script exports the selected object for the three.js engine.'''
32+
bl_idname = "export.threejs"
33+
bl_label = "Export Three.js"
34+
35+
filename_ext = ".js"
36+
37+
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
38+
use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
39+
use_uv_coords = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
40+
use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
41+
42+
@classmethod
43+
def poll(cls, context):
44+
return context.active_object != None
45+
46+
def execute(self, context):
47+
print("Selected: " + context.active_object.name)
48+
49+
if not self.properties.filepath:
50+
raise Exception("filename not set")
51+
52+
filepath = self.filepath
53+
import io_mesh_threejs.export_threejs
54+
return io_mesh_threejs.export_threejs.save(self, context, **self.properties)
55+
56+
def draw(self, context):
57+
layout = self.layout
58+
59+
row = layout.row()
60+
row.prop(self.properties, "use_modifiers")
61+
row.prop(self.properties, "use_normals")
62+
row = layout.row()
63+
row.prop(self.properties, "use_uv_coords")
64+
row.prop(self.properties, "use_colors")
65+
66+
67+
def menu_func(self, context):
68+
default_path = bpy.data.filepath.replace(".blend", ".js")
69+
self.layout.operator(ExportTHREEJS.bl_idname, text="Three.js (.js)").filepath = default_path
70+
71+
72+
def register():
73+
bpy.types.INFO_MT_file_export.append(menu_func)
74+
75+
76+
def unregister():
77+
bpy.types.INFO_MT_file_export.remove(menu_func)
78+
79+
if __name__ == "__main__":
80+
register()
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
# ##### BEGIN GPL LICENSE BLOCK #####
2+
#
3+
# This program is free software; you can redistribute it and/or
4+
# modify it under the terms of the GNU General Public License
5+
# as published by the Free Software Foundation; either version 2
6+
# of the License, or (at your option) any later version.
7+
#
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License
14+
# along with this program; if not, write to the Free Software Foundation,
15+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16+
#
17+
# ##### END GPL LICENSE BLOCK #####
18+
19+
# Based on export_ply.py
20+
# Contributors: Mr.doob, Kikko
21+
22+
"""
23+
This script exports the selected object for the three.js engine.
24+
"""
25+
26+
import bpy
27+
import os
28+
29+
def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True, use_colors=True):
30+
31+
def rvec3d(v):
32+
return round(v[0], 6), round(v[1], 6), round(v[2], 6)
33+
34+
def rvec2d(v):
35+
return round(v[0], 6), round(v[1], 6)
36+
37+
scene = context.scene
38+
obj = context.object
39+
40+
if not filepath.lower().endswith('.js'):
41+
filepath += '.js'
42+
43+
classname = filepath.split('/')[-1].replace('.js','')
44+
45+
if not obj:
46+
raise Exception("Error, Select 1 active object")
47+
48+
file = open(filepath, 'w')
49+
50+
if scene.objects.active:
51+
bpy.ops.object.mode_set(mode='OBJECT')
52+
53+
if use_modifiers:
54+
mesh = obj.create_mesh(scene, True, 'PREVIEW')
55+
else:
56+
mesh = obj.data
57+
58+
if not mesh:
59+
raise Exception("Error, could not get mesh data from active object")
60+
61+
# mesh.transform(obj.matrix_world) # XXX
62+
63+
faceUV = (len(mesh.uv_textures) > 0)
64+
vertexUV = (len(mesh.sticky) > 0)
65+
vertexColors = len(mesh.vertex_colors) > 0
66+
67+
if (not faceUV) and (not vertexUV):
68+
use_uv_coords = False
69+
if not vertexColors:
70+
use_colors = False
71+
72+
if not use_uv_coords:
73+
faceUV = vertexUV = False
74+
if not use_colors:
75+
vertexColors = False
76+
77+
if faceUV:
78+
active_uv_layer = mesh.uv_textures.active
79+
if not active_uv_layer:
80+
use_uv_coords = False
81+
faceUV = None
82+
else:
83+
active_uv_layer = active_uv_layer.data
84+
85+
if vertexColors:
86+
active_col_layer = mesh.vertex_colors.active
87+
if not active_col_layer:
88+
use_colors = False
89+
vertexColors = None
90+
else:
91+
active_col_layer = active_col_layer.data
92+
93+
# incase
94+
color = uvcoord = uvcoord_key = normal = normal_key = None
95+
96+
file.write('// Generated with Blender 2.54 exporter\n\n')
97+
98+
file.write('var %s = function () {\n\n' % classname)
99+
100+
file.write('\tvar scope = this;\n\n')
101+
102+
file.write('\tTHREE.Geometry.call( this );\n\n')
103+
104+
for v in mesh.vertices:
105+
file.write('\tv( %.6f, %.6f, %.6f );\n' % (v.co.x, v.co.z, -v.co.y)) # co
106+
107+
file.write('\n')
108+
109+
if use_normals:
110+
for f in mesh.faces:
111+
if len(f.vertices) == 3:
112+
file.write('\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.normal[0], f.normal[1], f.normal[2]))
113+
else:
114+
file.write('\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.vertices[3], f.normal[0], f.normal[1], f.normal[2]))
115+
116+
else:
117+
for f in mesh.faces:
118+
if len(f.vertices) == 3:
119+
file.write('\tf3( %d, %d, %d );\n' % (f.vertices[0], f.vertices[1], f.vertices[2]))
120+
else:
121+
file.write('\tf4( %d, %d, %d, %d );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.vertices[3]))
122+
123+
face_index_pairs = [ (face, index) for index, face in enumerate(mesh.faces)]
124+
125+
if use_uv_coords:
126+
file.write('\n')
127+
for f, f_index in face_index_pairs:
128+
tface = mesh.uv_textures[0].data[f_index]
129+
if len(f.vertices) == 3:
130+
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1]))
131+
else:
132+
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1], tface.uv4[0], 1.0-tface.uv4[1]))
133+
134+
file.write('\n')
135+
136+
file.write('\tfunction v( x, y, z ) {\n\n')
137+
file.write('\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n')
138+
file.write('\t}\n\n')
139+
140+
file.write('\tfunction f3( a, b, c, nx, ny, nz ) {\n\n')
141+
file.write('\t\tscope.faces.push( new THREE.Face3( a, b, c, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
142+
file.write('\t}\n\n')
143+
144+
file.write('\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n')
145+
file.write('\t\tscope.faces.push( new THREE.Face4( a, b, c, d, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
146+
file.write('\t}\n\n')
147+
148+
file.write('\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n')
149+
file.write('\t\tvar uv = [];\n')
150+
file.write('\t\tuv.push( new THREE.UV( u1, v1 ) );\n')
151+
file.write('\t\tuv.push( new THREE.UV( u2, v2 ) );\n')
152+
file.write('\t\tuv.push( new THREE.UV( u3, v3 ) );\n')
153+
file.write('\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n')
154+
file.write('\t\tscope.uvs.push( uv );\n')
155+
file.write('\t}\n\n')
156+
157+
file.write('}\n\n')
158+
159+
file.write('%s.prototype = new THREE.Geometry();\n' % classname)
160+
file.write('%s.prototype.constructor = %s;' % (classname, classname))
161+
162+
file.close()
163+
164+
print("writing", filepath, "done")
165+
166+
if use_modifiers:
167+
bpy.data.meshes.remove(mesh)
168+
169+
"""
170+
mesh_vertices = mesh.vertices # save a lookup
171+
ply_vertices = [] # list of dictionaries
172+
# vdict = {} # (index, normal, uv) -> new index
173+
vdict = [{} for i in range(len(mesh_vertices))]
174+
ply_faces = [[] for f in range(len(mesh.faces))]
175+
vert_count = 0
176+
for i, f in enumerate(mesh.faces):
177+
178+
smooth = f.use_smooth
179+
if not smooth:
180+
normal = tuple(f.normal)
181+
normal_key = rvec3d(normal)
182+
183+
if faceUV:
184+
uv = active_uv_layer[i]
185+
uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4 # XXX - crufty :/
186+
if vertexColors:
187+
col = active_col_layer[i]
188+
col = col.color1, col.color2, col.color3, col.color4
189+
190+
f_vertices = f.vertices
191+
192+
pf = ply_faces[i]
193+
for j, vidx in enumerate(f_vertices):
194+
v = mesh_vertices[vidx]
195+
196+
if smooth:
197+
normal = tuple(v.normal)
198+
normal_key = rvec3d(normal)
199+
200+
if faceUV:
201+
uvcoord = uv[j][0], 1.0 - uv[j][1]
202+
uvcoord_key = rvec2d(uvcoord)
203+
elif vertexUV:
204+
uvcoord = v.uvco[0], 1.0 - v.uvco[1]
205+
uvcoord_key = rvec2d(uvcoord)
206+
207+
if vertexColors:
208+
color = col[j]
209+
color = int(color[0] * 255.0), int(color[1] * 255.0), int(color[2] * 255.0)
210+
211+
212+
key = normal_key, uvcoord_key, color
213+
214+
vdict_local = vdict[vidx]
215+
pf_vidx = vdict_local.get(key) # Will be None initially
216+
217+
if pf_vidx == None: # same as vdict_local.has_key(key)
218+
pf_vidx = vdict_local[key] = vert_count
219+
ply_vertices.append((vidx, normal, uvcoord, color))
220+
vert_count += 1
221+
222+
pf.append(pf_vidx)
223+
224+
file.write('ply\n')
225+
file.write('format ascii 1.0\n')
226+
file.write('comment Created by Blender %s - www.blender.org, source file: %r\n' % (bpy.app.version_string, os.path.basename(bpy.data.filepath)))
227+
228+
file.write('element vertex %d\n' % len(ply_vertices))
229+
230+
file.write('property float x\n')
231+
file.write('property float y\n')
232+
file.write('property float z\n')
233+
234+
if use_normals:
235+
file.write('property float nx\n')
236+
file.write('property float ny\n')
237+
file.write('property float nz\n')
238+
if use_uv_coords:
239+
file.write('property float s\n')
240+
file.write('property float t\n')
241+
if use_colors:
242+
file.write('property uchar red\n')
243+
file.write('property uchar green\n')
244+
file.write('property uchar blue\n')
245+
246+
file.write('element face %d\n' % len(mesh.faces))
247+
file.write('property list uchar uint vertex_indices\n')
248+
file.write('end_header\n')
249+
250+
for i, v in enumerate(ply_vertices):
251+
file.write('%.6f %.6f %.6f ' % tuple(mesh_vertices[v[0]].co)) # co
252+
if use_normals:
253+
file.write('%.6f %.6f %.6f ' % v[1]) # no
254+
if use_uv_coords:
255+
file.write('%.6f %.6f ' % v[2]) # uv
256+
if use_colors:
257+
file.write('%u %u %u' % v[3]) # col
258+
file.write('\n')
259+
260+
for pf in ply_faces:
261+
if len(pf) == 3:
262+
file.write('3 %d %d %d\n' % tuple(pf))
263+
else:
264+
file.write('4 %d %d %d %d\n' % tuple(pf))
265+
266+
file.close()
267+
print("writing %r done" % filepath)
268+
269+
if use_modifiers:
270+
bpy.data.meshes.remove(mesh)
271+
"""
272+
273+
# XXX
274+
"""
275+
if is_editmode:
276+
Blender.Window.EditMode(1, '', 0)
277+
"""
278+
279+
return {'FINISHED'}
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)