remove reload() from builtins since python3 no longer uses this.
[blender.git] / release / scripts / op / io_mesh_ply / export_ply.py
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 # <pep8 compliant>
20
21 # Copyright (C) 2004, 2005: Bruce Merry, bmerry@cs.uct.ac.za
22 # Contributors: Bruce Merry, Campbell Barton
23
24 """
25 This script exports Stanford PLY files from Blender. It supports normals,
26 colours, and texture coordinates per face or per vertex.
27 Only one mesh can be exported at a time.
28 """
29
30 import bpy
31 import os
32
33
34 def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True, use_colors=True):
35     
36     def rvec3d(v):
37         return round(v[0], 6), round(v[1], 6), round(v[2], 6)
38
39
40     def rvec2d(v):
41         return round(v[0], 6), round(v[1], 6)
42     
43     scene = context.scene
44     obj = context.object
45
46     if not obj:
47         raise Exception("Error, Select 1 active object")
48
49     file = open(filepath, 'w')
50
51     if scene.objects.active:
52         bpy.ops.object.mode_set(mode='OBJECT')
53
54     if use_modifiers:
55         mesh = obj.create_mesh(scene, True, 'PREVIEW')
56     else:
57         mesh = obj.data
58
59     if not mesh:
60         raise Exception("Error, could not get mesh data from active object")
61
62     # mesh.transform(obj.matrix_world) # XXX
63
64     faceUV = (len(mesh.uv_textures) > 0)
65     vertexUV = (len(mesh.sticky) > 0)
66     vertexColors = len(mesh.vertex_colors) > 0
67
68     if (not faceUV) and (not vertexUV):
69         use_uv_coords = False
70     if not vertexColors:
71         use_colors = False
72
73     if not use_uv_coords:
74         faceUV = vertexUV = False
75     if not use_colors:
76         vertexColors = False
77
78     if faceUV:
79         active_uv_layer = mesh.uv_textures.active
80         if not active_uv_layer:
81             use_uv_coords = False
82             faceUV = None
83         else:
84             active_uv_layer = active_uv_layer.data
85
86     if vertexColors:
87         active_col_layer = mesh.vertex_colors.active
88         if not active_col_layer:
89             use_colors = False
90             vertexColors = None
91         else:
92             active_col_layer = active_col_layer.data
93
94     # incase
95     color = uvcoord = uvcoord_key = normal = normal_key = None
96
97     mesh_verts = mesh.vertices # save a lookup
98     ply_verts = [] # list of dictionaries
99     # vdict = {} # (index, normal, uv) -> new index
100     vdict = [{} for i in range(len(mesh_verts))]
101     ply_faces = [[] for f in range(len(mesh.faces))]
102     vert_count = 0
103     for i, f in enumerate(mesh.faces):
104
105
106         smooth = f.use_smooth
107         if not smooth:
108             normal = tuple(f.normal)
109             normal_key = rvec3d(normal)
110
111         if faceUV:
112             uv = active_uv_layer[i]
113             uv = uv.uv1, uv.uv2, uv.uv3, uv.uv4 # XXX - crufty :/
114         if vertexColors:
115             col = active_col_layer[i]
116             col = col.color1, col.color2, col.color3, col.color4
117
118         f_verts = f.vertices
119
120         pf = ply_faces[i]
121         for j, vidx in enumerate(f_verts):
122             v = mesh_verts[vidx]
123
124             if smooth:
125                 normal = tuple(v.normal)
126                 normal_key = rvec3d(normal)
127
128             if faceUV:
129                 uvcoord = uv[j][0], 1.0 - uv[j][1]
130                 uvcoord_key = rvec2d(uvcoord)
131             elif vertexUV:
132                 uvcoord = v.uvco[0], 1.0 - v.uvco[1]
133                 uvcoord_key = rvec2d(uvcoord)
134
135             if vertexColors:
136                 color = col[j]
137                 color = int(color[0] * 255.0), int(color[1] * 255.0), int(color[2] * 255.0)
138
139
140             key = normal_key, uvcoord_key, color
141
142             vdict_local = vdict[vidx]
143             pf_vidx = vdict_local.get(key) # Will be None initially
144
145             if pf_vidx is None: # same as vdict_local.has_key(key)
146                 pf_vidx = vdict_local[key] = vert_count
147                 ply_verts.append((vidx, normal, uvcoord, color))
148                 vert_count += 1
149
150             pf.append(pf_vidx)
151
152     file.write('ply\n')
153     file.write('format ascii 1.0\n')
154     file.write('comment Created by Blender %s - www.blender.org, source file: %r\n' % (bpy.app.version_string, os.path.basename(bpy.data.filepath)))
155
156     file.write('element vertex %d\n' % len(ply_verts))
157
158     file.write('property float x\n')
159     file.write('property float y\n')
160     file.write('property float z\n')
161
162     if use_normals:
163         file.write('property float nx\n')
164         file.write('property float ny\n')
165         file.write('property float nz\n')
166     if use_uv_coords:
167         file.write('property float s\n')
168         file.write('property float t\n')
169     if use_colors:
170         file.write('property uchar red\n')
171         file.write('property uchar green\n')
172         file.write('property uchar blue\n')
173
174     file.write('element face %d\n' % len(mesh.faces))
175     file.write('property list uchar uint vertex_indices\n')
176     file.write('end_header\n')
177
178     for i, v in enumerate(ply_verts):
179         file.write('%.6f %.6f %.6f ' % tuple(mesh_verts[v[0]].co)) # co
180         if use_normals:
181             file.write('%.6f %.6f %.6f ' % v[1]) # no
182         if use_uv_coords:
183             file.write('%.6f %.6f ' % v[2]) # uv
184         if use_colors:
185             file.write('%u %u %u' % v[3]) # col
186         file.write('\n')
187
188     for pf in ply_faces:
189         if len(pf) == 3:
190             file.write('3 %d %d %d\n' % tuple(pf))
191         else:
192             file.write('4 %d %d %d %d\n' % tuple(pf))
193
194     file.close()
195     print("writing %r done" % filepath)
196
197     if use_modifiers:
198         bpy.data.meshes.remove(mesh)
199
200     # XXX
201     """
202     if is_editmode:
203         Blender.Window.EditMode(1, '', 0)
204     """
205     
206     return {'FINISHED'}