Avoid writing redundant zeros
[blender-addons.git] / io_scene_vrml2 / export_vrml2.py
blob0a664e27e64a6f145adaae00f5d406f1b9d5ce92
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 #####
19 # <pep8-80 compliant>
21 import bpy
22 import bpy_extras
23 import bmesh
24 import os
25 from bpy_extras import object_utils
28 def save_bmesh(fw, bm,
29 use_color, color_type, material_colors,
30 use_uv, uv_image,
31 path_mode, copy_set):
33 base_src = os.path.dirname(bpy.data.filepath)
34 base_dst = os.path.dirname(fw.__self__.name)
36 fw('Shape {\n')
37 fw('\tappearance Appearance {\n')
38 if use_uv:
39 fw('\t\ttexture ImageTexture {\n')
40 filepath = uv_image.filepath
41 filepath_full = os.path.normpath(bpy.path.abspath(filepath, library=uv_image.library))
42 filepath_ref = bpy_extras.io_utils.path_reference(filepath_full, base_src, base_dst, path_mode, "textures", copy_set, uv_image.library)
43 filepath_base = os.path.basename(filepath_full)
45 images = [
46 filepath_ref,
47 filepath_base,
49 if path_mode != 'RELATIVE':
50 images.append(filepath_full)
52 fw('\t\t\turl [ %s ]\n' % " ".join(['"%s"' % f for f in images]) )
53 del images
54 del filepath_ref, filepath_base, filepath_full, filepath
55 fw('\t\t}\n') # end 'ImageTexture'
56 else:
57 fw('\t\tmaterial Material {\n')
58 fw('\t\t}\n') # end 'Material'
59 fw('\t}\n') # end 'Appearance'
61 fw('\tgeometry IndexedFaceSet {\n')
62 fw('\t\tcoord Coordinate {\n')
63 fw('\t\t\tpoint [ ')
64 v = None
65 for v in bm.verts:
66 fw("%.6f %.6f %.6f " % v.co[:])
67 del v
68 fw(']\n') # end 'point[]'
69 fw('\t\t}\n') # end 'Coordinate'
71 if use_color:
72 if color_type == 'MATERIAL':
73 fw('\t\tcolorPerVertex FALSE\n')
74 fw('\t\tcolor Color {\n')
75 fw('\t\t\tcolor [ ')
76 c = None
77 for c in material_colors:
78 fw(c)
79 del c
80 fw(']\n') # end 'color[]'
81 fw('\t\t}\n') # end 'Color'
82 elif color_type == 'VERTEX':
83 fw('\t\tcolorPerVertex TRUE\n')
84 fw('\t\tcolor Color {\n')
85 fw('\t\t\tcolor [ ')
86 v = None
87 c_none = "0.00 0.00 0.00 "
88 color_layer = bm.loops.layers.color.active
89 assert(color_layer is not None)
90 for v in bm.verts:
91 # weak, use first loops color
92 try:
93 l = v.link_loops[0]
94 except:
95 l = None
96 fw(c_none if l is None else ("%.2f %.2f %.2f " % l[color_layer][:]))
98 del v
99 fw(']\n') # end 'color[]'
100 fw('\t\t}\n') # end 'Color'
102 # ---
104 if color_type == 'MATERIAL':
105 fw('\t\tcolorIndex [ ')
106 i = None
107 for f in bm.faces:
108 i = f.material_index
109 if i >= len(material_colors):
110 i = 0
111 fw("%d " % i)
112 del i
113 fw(']\n') # end 'colorIndex[]'
114 elif color_type == 'VERTEX':
115 pass
117 if use_uv:
118 fw('\t\ttexCoord TextureCoordinate {\n')
119 fw('\t\t\tpoint [ ')
120 v = None
121 uv_layer = bm.loops.layers.uv.active
122 assert(uv_layer is not None)
123 for f in bm.faces:
124 for l in f.loops:
125 fw("%.4f %.4f " % l[uv_layer].uv[:])
127 del f
128 fw(']\n') # end 'point[]'
129 fw('\t\t}\n') # end 'TextureCoordinate'
131 # ---
133 fw('\t\ttexCoordIndex [ ')
134 i = None
135 for i in range(0, len(bm.faces) * 3, 3):
136 fw("%d %d %d -1 " % (i, i + 1, i + 2))
137 del i
138 fw(']\n') # end 'coordIndex[]'
140 fw('\t\tcoordIndex [ ')
141 f = fv = None
142 for f in bm.faces:
143 fv = f.verts[:]
144 fw("%d %d %d -1 " % (fv[0].index, fv[1].index, fv[2].index))
145 del f, fv
146 fw(']\n') # end 'coordIndex[]'
148 fw('\t}\n') # end 'IndexedFaceSet'
149 fw('}\n') # end 'Shape'
152 def save_object(fw, global_matrix,
153 scene, obj,
154 use_mesh_modifiers,
155 use_color, color_type,
156 use_uv,
157 path_mode, copy_set):
159 assert(obj.type == 'MESH')
161 if use_mesh_modifiers:
162 is_editmode = (obj.mode == 'EDIT')
163 if is_editmode:
164 bpy.ops.object.editmode_toggle()
166 me = obj.to_mesh(scene, True, 'PREVIEW', calc_tessface=False)
167 bm = bmesh.new()
168 bm.from_mesh(me)
170 if is_editmode:
171 bpy.ops.object.editmode_toggle()
172 else:
173 me = obj.data
174 if obj.mode == 'EDIT':
175 bm_orig = bmesh.from_edit_mesh(me)
176 bm = bm_orig.copy()
177 else:
178 bm = bmesh.new()
179 bm.from_mesh(me)
181 bm.transform(global_matrix * obj.matrix_world)
182 bmesh.ops.triangulate(bm, faces=bm.faces)
184 # default empty
185 material_colors = []
186 uv_image = None
188 if use_color:
189 if color_type == 'VERTEX':
190 if bm.loops.layers.color.active is None:
191 # fallback to material
192 color_type = 'MATERIAL'
193 if color_type == 'MATERIAL':
194 if not me.materials:
195 use_color = False
196 else:
197 material_colors = [
198 "%.2f %.2f %.2f " % (m.diffuse_color[:] if m else (1.0, 1.0, 1.0))
199 for m in me.materials]
200 assert(color_type in {'VERTEX', 'MATERIAL'})
202 if use_uv:
203 if bm.loops.layers.uv.active is None:
204 use_uv = False
205 uv_image = object_utils.object_image_guess(obj, bm=bm)
206 if uv_image is None:
207 use_uv = False
209 save_bmesh(fw, bm,
210 use_color, color_type, material_colors,
211 use_uv, uv_image,
212 path_mode, copy_set)
214 bm.free()
217 def save(operator,
218 context,
219 filepath="",
220 global_matrix=None,
221 use_selection=False,
222 use_mesh_modifiers=True,
223 use_color=True,
224 color_type='MATERIAL',
225 use_uv=True,
226 path_mode='AUTO'):
228 scene = context.scene
230 # store files to copy
231 copy_set = set()
233 file = open(filepath, 'w', encoding='utf-8')
234 fw = file.write
235 fw('#VRML V2.0 utf8\n')
236 fw('#modeled using blender3d http://blender.org\n')
238 if use_selection:
239 objects = context.selected_objects
240 else:
241 objects = scene.objects
243 for obj in objects:
244 if obj.type == 'MESH':
245 fw("\n# %r\n" % obj.name)
246 save_object(fw, global_matrix,
247 scene, obj,
248 use_mesh_modifiers,
249 use_color, color_type,
250 use_uv,
251 path_mode, copy_set)
253 file.close()
255 # copy all collected files.
256 bpy_extras.io_utils.path_reference_copy(copy_set)
258 return {'FINISHED'}