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 tessface & co are available!
48 if not mesh
.tessfaces
and mesh
.polygons
:
51 has_uv
= bool(mesh
.tessface_uv_textures
)
52 has_vcol
= bool(mesh
.tessface_vertex_colors
)
65 active_uv_layer
= mesh
.tessface_uv_textures
.active
66 if not active_uv_layer
:
70 active_uv_layer
= active_uv_layer
.data
73 active_col_layer
= mesh
.tessface_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
.tessfaces
))]
89 for i
, f
in enumerate(mesh
.tessfaces
):
91 smooth
= not use_normals
or f
.use_smooth
94 normal_key
= rvec3d(normal
)
97 uv
= active_uv_layer
[i
]
98 uv
= uv
.uv1
, uv
.uv2
, uv
.uv3
, uv
.uv4
100 col
= active_col_layer
[i
]
101 col
= col
.color1
[:], col
.color2
[:], col
.color3
[:], col
.color4
[:]
106 for j
, vidx
in enumerate(f_verts
):
111 normal_key
= rvec3d(normal
)
114 uvcoord
= uv
[j
][0], uv
[j
][1]
115 uvcoord_key
= rvec2d(uvcoord
)
119 color
= (int(color
[0] * 255.0),
120 int(color
[1] * 255.0),
121 int(color
[2] * 255.0),
123 key
= normal_key
, uvcoord_key
, color
125 vdict_local
= vdict
[vidx
]
126 pf_vidx
= vdict_local
.get(key
) # Will be None initially
128 if pf_vidx
is None: # same as vdict_local.has_key(key)
129 pf_vidx
= vdict_local
[key
] = vert_count
130 ply_verts
.append((vidx
, normal
, uvcoord
, color
))
136 fw("format ascii 1.0\n")
137 fw("comment Created by Blender %s - "
138 "www.blender.org, source file: %r\n" %
139 (bpy
.app
.version_string
, os
.path
.basename(bpy
.data
.filepath
)))
141 fw("element vertex %d\n" % len(ply_verts
))
143 fw("property float x\n"
145 "property float z\n")
148 fw("property float nx\n"
149 "property float ny\n"
150 "property float nz\n")
152 fw("property float s\n"
153 "property float t\n")
155 fw("property uchar red\n"
156 "property uchar green\n"
157 "property uchar blue\n")
159 fw("element face %d\n" % len(mesh
.tessfaces
))
160 fw("property list uchar uint vertex_indices\n")
163 for i
, v
in enumerate(ply_verts
):
164 fw("%.6f %.6f %.6f" % mesh_verts
[v
[0]].co
[:]) # co
166 fw(" %.6f %.6f %.6f" % v
[1]) # no
168 fw(" %.6f %.6f" % v
[2]) # uv
170 fw(" %u %u %u" % v
[3]) # col
175 fw("3 %d %d %d\n" % tuple(pf
))
177 fw("4 %d %d %d %d\n" % tuple(pf
))
180 print("writing %r done" % filepath
)
188 use_mesh_modifiers
=True,
195 scene
= context
.scene
196 obj
= context
.active_object
198 if global_matrix
is None:
199 from mathutils
import Matrix
200 global_matrix
= Matrix()
202 if bpy
.ops
.object.mode_set
.poll():
203 bpy
.ops
.object.mode_set(mode
='OBJECT')
205 if use_mesh_modifiers
and obj
.modifiers
:
206 mesh
= obj
.to_mesh(scene
, True, 'PREVIEW')
208 mesh
= obj
.data
.copy()
211 raise Exception("Error, could not get mesh data from active object")
213 mesh
.transform(global_matrix
* obj
.matrix_world
)
217 ret
= save_mesh(filepath
, mesh
,
218 use_normals
=use_normals
,
219 use_uv_coords
=use_uv_coords
,
220 use_colors
=use_colors
,
223 if use_mesh_modifiers
:
224 bpy
.data
.meshes
.remove(mesh
)