Animall: move to own dir, to add translations later
[blender-addons.git] / render_povray / model_meta_topology.py
blob47e874c52131b2e36ff0141e28ee0ad165892f5b
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 """Translate Blender meta balls to POV blobs."""
5 import bpy
6 from .shading import write_object_material_interior
8 def export_meta(file, metas, tab_write, DEF_MAT_NAME):
9 """write all POV blob primitives and Blender Metas to exported file """
10 # TODO - blenders 'motherball' naming is not supported.
12 from .render import (
13 safety,
14 global_matrix,
15 write_matrix,
16 comments,
18 if comments and len(metas) >= 1:
19 file.write("//--Blob objects--\n\n")
20 # Get groups of metaballs by blender name prefix.
21 meta_group = {}
22 meta_elems = {}
23 for meta_ob in metas:
24 prefix = meta_ob.name.split(".")[0]
25 if prefix not in meta_group:
26 meta_group[prefix] = meta_ob # .data.threshold
27 elems = [
28 (elem, meta_ob)
29 for elem in meta_ob.data.elements
30 if elem.type in {'BALL', 'ELLIPSOID', 'CAPSULE', 'CUBE', 'PLANE'}
32 if prefix in meta_elems:
33 meta_elems[prefix].extend(elems)
34 else:
35 meta_elems[prefix] = elems
37 # empty metaball
38 if not elems:
39 tab_write(file, "\n//dummy sphere to represent empty meta location\n")
40 tab_write(file,
41 "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} "
42 "no_image no_reflection no_radiosity "
43 "photons{pass_through collect off} hollow}\n\n"
44 % (meta_ob.location.x, meta_ob.location.y, meta_ob.location.z)
45 ) # meta_ob.name > povdataname)
46 return
48 # other metaballs
50 for mg, mob in meta_group.items():
51 if len(meta_elems[mg]) != 0:
52 tab_write(file, "blob{threshold %.4g // %s \n" % (mob.data.threshold, mg))
53 for elems in meta_elems[mg]:
54 elem = elems[0]
55 loc = elem.co
56 stiffness = elem.stiffness
57 if elem.use_negative:
58 stiffness = -stiffness
59 if elem.type == 'BALL':
60 tab_write(file,
61 "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g "
62 % (loc.x, loc.y, loc.z, elem.radius, stiffness)
64 write_matrix(file, global_matrix @ elems[1].matrix_world)
65 tab_write(file, "}\n")
66 elif elem.type == 'ELLIPSOID':
67 tab_write(file,
68 "sphere{ <%.6g, %.6g, %.6g>,%.4g,%.4g "
69 % (
70 loc.x / elem.size_x,
71 loc.y / elem.size_y,
72 loc.z / elem.size_z,
73 elem.radius,
74 stiffness,
77 tab_write(file,
78 "scale <%.6g, %.6g, %.6g>"
79 % (elem.size_x, elem.size_y, elem.size_z)
81 write_matrix(file, global_matrix @ elems[1].matrix_world)
82 tab_write(file, "}\n")
83 elif elem.type == 'CAPSULE':
84 tab_write(file,
85 "cylinder{ <%.6g, %.6g, %.6g>,<%.6g, %.6g, %.6g>,%.4g,%.4g "
86 % (
87 (loc.x - elem.size_x),
88 loc.y,
89 loc.z,
90 (loc.x + elem.size_x),
91 loc.y,
92 loc.z,
93 elem.radius,
94 stiffness,
97 # tab_write(file, "scale <%.6g, %.6g, %.6g>" % (elem.size_x, elem.size_y, elem.size_z))
98 write_matrix(file, global_matrix @ elems[1].matrix_world)
99 tab_write(file, "}\n")
101 elif elem.type == 'CUBE':
102 tab_write(file,
103 "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
105 elem.radius * 2.0,
106 stiffness / 4.0,
107 loc.x,
108 loc.y,
109 loc.z,
110 elem.size_x,
111 elem.size_y,
112 elem.size_z,
115 write_matrix(file, global_matrix @ elems[1].matrix_world)
116 tab_write(file, "}\n")
117 tab_write(file,
118 "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
120 elem.radius * 2.0,
121 stiffness / 4.0,
122 loc.x,
123 loc.y,
124 loc.z,
125 elem.size_x,
126 elem.size_y,
127 elem.size_z,
130 write_matrix(file, global_matrix @ elems[1].matrix_world)
131 tab_write(file, "}\n")
132 tab_write(file,
133 "cylinder { -z*8, +z*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1,1/4> scale <%.6g, %.6g, %.6g>\n"
135 elem.radius * 2.0,
136 stiffness / 4.0,
137 loc.x,
138 loc.y,
139 loc.z,
140 elem.size_x,
141 elem.size_y,
142 elem.size_z,
145 write_matrix(file, global_matrix @ elems[1].matrix_world)
146 tab_write(file, "}\n")
148 elif elem.type == 'PLANE':
149 tab_write(file,
150 "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
152 elem.radius * 2.0,
153 stiffness / 4.0,
154 loc.x,
155 loc.y,
156 loc.z,
157 elem.size_x,
158 elem.size_y,
159 elem.size_z,
162 write_matrix(file, global_matrix @ elems[1].matrix_world)
163 tab_write(file, "}\n")
164 tab_write(file,
165 "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
167 elem.radius * 2.0,
168 stiffness / 4.0,
169 loc.x,
170 loc.y,
171 loc.z,
172 elem.size_x,
173 elem.size_y,
174 elem.size_z,
177 write_matrix(file, global_matrix @ elems[1].matrix_world)
178 tab_write(file, "}\n")
180 try:
181 one_material = elems[1].data.materials[
183 ] # lame! - blender can't do enything else.
184 except BaseException as e:
185 print(e.__doc__)
186 print('An exception occurred: {}'.format(e))
187 one_material = None
188 if one_material:
189 diffuse_color = one_material.diffuse_color
190 trans = 1.0 - one_material.pov.alpha
191 if (
192 one_material.pov.use_transparency
193 and one_material.pov.transparency_method == 'RAYTRACE'
195 pov_filter = one_material.pov_raytrace_transparency.filter * (
196 1.0 - one_material.pov.alpha
198 trans = (1.0 - one_material.pov.alpha) - pov_filter
199 else:
200 pov_filter = 0.0
201 material_finish = material_names_dictionary[one_material.name]
202 tab_write(file,
203 "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n"
205 diffuse_color[0],
206 diffuse_color[1],
207 diffuse_color[2],
208 pov_filter,
209 trans,
212 tab_write(file, "finish{%s} " % safety(material_finish, ref_level_bound=2))
213 else:
214 material_finish = DEF_MAT_NAME
215 trans = 0.0
216 tab_write(file,
217 "pigment{srgbt<1,1,1,%.3g>} finish{%s} "
218 % (trans, safety(material_finish, ref_level_bound=2))
221 write_object_material_interior(file, one_material, mob, tab_write)
222 # write_object_material_interior(file, one_material, elems[1])
223 tab_write(file, "radiosity{importance %3g}\n" % mob.pov.importance_value)
224 tab_write(file, "}\n\n") # End of Metaball block
228 meta = ob.data
230 # important because no elements will break parsing.
231 elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}]
233 if elements:
234 tab_write(file, "blob {\n")
235 tab_write(file, "threshold %.4g\n" % meta.threshold)
236 importance = ob.pov.importance_value
238 try:
239 material = meta.materials[0] # lame! - blender can't do anything else.
240 except:
241 material = None
243 for elem in elements:
244 loc = elem.co
246 stiffness = elem.stiffness
247 if elem.use_negative:
248 stiffness = - stiffness
250 if elem.type == 'BALL':
252 tab_write(file, "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
253 (loc.x, loc.y, loc.z, elem.radius, stiffness))
255 # After this wecould do something simple like...
256 # "pigment {Blue} }"
257 # except we'll write the color
259 elif elem.type == 'ELLIPSOID':
260 # location is modified by scale
261 tab_write(file, "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
262 (loc.x / elem.size_x,
263 loc.y / elem.size_y,
264 loc.z / elem.size_z,
265 elem.radius, stiffness))
266 tab_write(file, "scale <%.6g, %.6g, %.6g> \n" %
267 (elem.size_x, elem.size_y, elem.size_z))
269 if material:
270 diffuse_color = material.diffuse_color
271 trans = 1.0 - material.pov.alpha
272 if material.pov.use_transparency and material.pov.transparency_method == 'RAYTRACE':
273 pov_filter = material.pov_raytrace_transparency.filter * (1.0 -
274 material.pov.alpha)
275 trans = (1.0 - material.pov.alpha) - pov_filter
276 else:
277 pov_filter = 0.0
279 material_finish = material_names_dictionary[material.name]
281 tab_write(file, "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" %
282 (diffuse_color[0], diffuse_color[1], diffuse_color[2],
283 pov_filter, trans))
284 tab_write(file, "finish {%s}\n" % safety(material_finish, ref_level_bound=2))
286 else:
287 tab_write(file, "pigment {srgb 1} \n")
288 # Write the finish last.
289 tab_write(file, "finish {%s}\n" % (safety(DEF_MAT_NAME, ref_level_bound=2)))
291 write_object_material_interior(file, material, elems[1], tab_write)
293 write_matrix(file, global_matrix @ ob.matrix_world)
294 # Importance for radiosity sampling added here
295 tab_write(file, "radiosity { \n")
296 # importance > ob.pov.importance_value
297 tab_write(file, "importance %3g \n" % importance)
298 tab_write(file, "}\n")
300 tab_write(file, "}\n") # End of Metaball block
302 if comments and len(metas) >= 1:
303 file.write("\n")