1 # ##### BEGIN GPL LICENSE BLOCK #####
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.
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.
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.
17 # ##### END GPL LICENSE BLOCK #####
22 This script exports Stanford PLY files from Blender. It supports normals,
23 colors, and texture coordinates per face or per vertex.
24 Only one mesh can be exported at a time.
31 def save_mesh(filepath
,
39 return round(v
[0], 6), round(v
[1], 6), round(v
[2], 6)
42 return round(v
[0], 6), round(v
[1], 6)
44 file = open(filepath
, "w", encoding
="utf8", newline
="\n")
47 # Be sure tessellated loop trianlges are available!
48 if not mesh
.loop_triangles
and mesh
.polygons
:
49 mesh
.calc_loop_triangles()
51 has_uv
= bool(mesh
.uv_layers
)
52 has_vcol
= bool(mesh
.vertex_colors
)
65 active_uv_layer
= mesh
.uv_layers
.active
66 if not active_uv_layer
:
70 active_uv_layer
= active_uv_layer
.data
73 active_col_layer
= mesh
.vertex_colors
.active
74 if not active_col_layer
:
78 active_col_layer
= active_col_layer
.data
81 color
= uvcoord
= uvcoord_key
= normal
= normal_key
= None
83 mesh_verts
= mesh
.vertices
# save a lookup
84 ply_verts
= [] # list of dictionaries
85 # vdict = {} # (index, normal, uv) -> new index
86 vdict
= [{} for i
in range(len(mesh_verts
))]
87 ply_faces
= [[] for f
in range(len(mesh
.loop_triangles
))]
89 for i
, f
in enumerate(mesh
.loop_triangles
):
91 smooth
= not use_normals
or f
.use_smooth
94 normal_key
= rvec3d(normal
)
97 uv
= [active_uv_layer
[l
].uv
[:] for l
in f
.loops
]
99 col
= [active_col_layer
[l
].color
[:] for l
in f
.loops
]
102 for j
, vidx
in enumerate(f
.vertices
):
107 normal_key
= rvec3d(normal
)
110 uvcoord
= uv
[j
][0], uv
[j
][1]
111 uvcoord_key
= rvec2d(uvcoord
)
115 color
= (int(color
[0] * 255.0),
116 int(color
[1] * 255.0),
117 int(color
[2] * 255.0),
118 int(color
[3] * 255.0),
120 key
= normal_key
, uvcoord_key
, color
122 vdict_local
= vdict
[vidx
]
123 pf_vidx
= vdict_local
.get(key
) # Will be None initially
125 if pf_vidx
is None: # same as vdict_local.has_key(key)
126 pf_vidx
= vdict_local
[key
] = vert_count
127 ply_verts
.append((vidx
, normal
, uvcoord
, color
))
133 fw("format ascii 1.0\n")
134 fw("comment Created by Blender %s - "
135 "www.blender.org, source file: %r\n" %
136 (bpy
.app
.version_string
, os
.path
.basename(bpy
.data
.filepath
)))
138 fw("element vertex %d\n" % len(ply_verts
))
140 fw("property float x\n"
142 "property float z\n")
145 fw("property float nx\n"
146 "property float ny\n"
147 "property float nz\n")
149 fw("property float s\n"
150 "property float t\n")
152 fw("property uchar red\n"
153 "property uchar green\n"
154 "property uchar blue\n"
155 "property uchar alpha\n")
157 fw("element face %d\n" % len(mesh
.loop_triangles
))
158 fw("property list uchar uint vertex_indices\n")
161 for i
, v
in enumerate(ply_verts
):
162 fw("%.6f %.6f %.6f" % mesh_verts
[v
[0]].co
[:]) # co
164 fw(" %.6f %.6f %.6f" % v
[1]) # no
166 fw(" %.6f %.6f" % v
[2]) # uv
168 fw(" %u %u %u %u" % v
[3]) # col
173 fw("3 %d %d %d\n" % tuple(pf
))
175 fw("4 %d %d %d %d\n" % tuple(pf
))
178 print("writing %r done" % filepath
)
186 use_mesh_modifiers
=True,
193 obj
= context
.active_object
195 if global_matrix
is None:
196 from mathutils
import Matrix
197 global_matrix
= Matrix()
199 if bpy
.ops
.object.mode_set
.poll():
200 bpy
.ops
.object.mode_set(mode
='OBJECT')
202 if use_mesh_modifiers
and obj
.modifiers
:
203 mesh
= obj
.to_mesh(context
.depsgraph
, True)
206 mesh
= obj
.data
.copy()
209 raise Exception("Error, could not get mesh data from active object")
211 mesh
.transform(global_matrix
@ obj
.matrix_world
)
215 ret
= save_mesh(filepath
, mesh
,
216 use_normals
=use_normals
,
217 use_uv_coords
=use_uv_coords
,
218 use_colors
=use_colors
,
221 bpy
.data
.meshes
.remove(mesh
)