1 # SPDX-FileCopyrightText: 2022-2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 """Translate Blender meta balls to POV blobs."""
8 from .shading
import write_object_material_interior
10 def export_meta(file, metas
, material_names_dictionary
, tab_write
, DEF_MAT_NAME
):
11 """write all POV blob primitives and Blender Metas to exported file """
12 # TODO - blenders 'motherball' naming is not supported.
20 if comments
and len(metas
) >= 1:
21 file.write("//--Blob objects--\n\n")
22 # Get groups of metaballs by blender name prefix.
26 prefix
= meta_ob
.name
.split(".")[0]
27 if prefix
not in meta_group
:
28 meta_group
[prefix
] = meta_ob
# .data.threshold
31 for elem
in meta_ob
.data
.elements
32 if elem
.type in {'BALL', 'ELLIPSOID', 'CAPSULE', 'CUBE', 'PLANE'}
34 if prefix
in meta_elems
:
35 meta_elems
[prefix
].extend(elems
)
37 meta_elems
[prefix
] = elems
41 tab_write(file, "\n//dummy sphere to represent empty meta location\n")
43 "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} "
44 "no_image no_reflection no_radiosity "
45 "photons{pass_through collect off} hollow}\n\n"
46 % (meta_ob
.location
.x
, meta_ob
.location
.y
, meta_ob
.location
.z
)
47 ) # meta_ob.name > povdataname)
52 for mg
, mob
in meta_group
.items():
53 if len(meta_elems
[mg
]) != 0:
54 tab_write(file, "blob{threshold %.4g // %s \n" % (mob
.data
.threshold
, mg
))
55 for elems
in meta_elems
[mg
]:
58 stiffness
= elem
.stiffness
60 stiffness
= -stiffness
61 if elem
.type == 'BALL':
63 "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g "
64 % (loc
.x
, loc
.y
, loc
.z
, elem
.radius
, stiffness
)
66 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
67 tab_write(file, "}\n")
68 elif elem
.type == 'ELLIPSOID':
70 "sphere{ <%.6g, %.6g, %.6g>,%.4g,%.4g "
80 "scale <%.6g, %.6g, %.6g>"
81 % (elem
.size_x
, elem
.size_y
, elem
.size_z
)
83 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
84 tab_write(file, "}\n")
85 elif elem
.type == 'CAPSULE':
87 "cylinder{ <%.6g, %.6g, %.6g>,<%.6g, %.6g, %.6g>,%.4g,%.4g "
89 (loc
.x
- elem
.size_x
),
92 (loc
.x
+ elem
.size_x
),
99 # tab_write(file, "scale <%.6g, %.6g, %.6g>" % (elem.size_x, elem.size_y, elem.size_z))
100 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
101 tab_write(file, "}\n")
103 elif elem
.type == 'CUBE':
105 "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
117 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
118 tab_write(file, "}\n")
120 "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
132 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
133 tab_write(file, "}\n")
135 "cylinder { -z*8, +z*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1,1/4> scale <%.6g, %.6g, %.6g>\n"
147 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
148 tab_write(file, "}\n")
150 elif elem
.type == 'PLANE':
152 "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
164 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
165 tab_write(file, "}\n")
167 "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
179 write_matrix(file, global_matrix
@ elems
[1].matrix_world
)
180 tab_write(file, "}\n")
183 one_material
= elems
[1].data
.materials
[
185 ] # lame! - blender can't do anything else.
186 except BaseException
as e
:
188 print('An exception occurred: {}'.format(e
))
191 diffuse_color
= one_material
.diffuse_color
192 trans
= 1.0 - one_material
.pov
.alpha
194 one_material
.pov
.use_transparency
195 and one_material
.pov
.transparency_method
== 'RAYTRACE'
197 pov_filter
= one_material
.pov_raytrace_transparency
.filter * (
198 1.0 - one_material
.pov
.alpha
200 trans
= (1.0 - one_material
.pov
.alpha
) - pov_filter
203 material_finish
= material_names_dictionary
[one_material
.name
]
205 "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n"
214 tab_write(file, "finish{%s} " % safety(material_finish
, ref_level_bound
=2))
216 material_finish
= DEF_MAT_NAME
219 "pigment{srgbt<1,1,1,%.3g>} finish{%s} "
220 % (trans
, safety(material_finish
, ref_level_bound
=2))
223 write_object_material_interior(file, one_material
, mob
, tab_write
)
224 # write_object_material_interior(file, one_material, elems[1])
225 tab_write(file, "radiosity{importance %3g}\n" % mob
.pov
.importance_value
)
227 tab_write(file, "}\n\n") # End of Metaball block
233 # important because no elements will break parsing.
234 elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}]
237 tab_write(file, "blob {\n")
238 tab_write(file, "threshold %.4g\n" % meta.threshold)
239 importance = ob.pov.importance_value
242 material = meta.materials[0] # lame! - blender can't do anything else.
246 for elem in elements:
249 stiffness = elem.stiffness
250 if elem.use_negative:
251 stiffness = - stiffness
253 if elem.type == 'BALL':
255 tab_write(file, "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
256 (loc.x, loc.y, loc.z, elem.radius, stiffness))
258 # After this wecould do something simple like...
260 # except we'll write the color
262 elif elem.type == 'ELLIPSOID':
263 # location is modified by scale
264 tab_write(file, "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" %
265 (loc.x / elem.size_x,
268 elem.radius, stiffness))
269 tab_write(file, "scale <%.6g, %.6g, %.6g> \n" %
270 (elem.size_x, elem.size_y, elem.size_z))
273 diffuse_color = material.diffuse_color
274 trans = 1.0 - material.pov.alpha
275 if material.pov.use_transparency and material.pov.transparency_method == 'RAYTRACE':
276 pov_filter = material.pov_raytrace_transparency.filter * (1.0 -
278 trans = (1.0 - material.pov.alpha) - pov_filter
282 material_finish = material_names_dictionary[material.name]
284 tab_write(file, "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" %
285 (diffuse_color[0], diffuse_color[1], diffuse_color[2],
287 tab_write(file, "finish {%s}\n" % safety(material_finish, ref_level_bound=2))
290 tab_write(file, "pigment {srgb 1} \n")
291 # Write the finish last.
292 tab_write(file, "finish {%s}\n" % (safety(DEF_MAT_NAME, ref_level_bound=2)))
294 write_object_material_interior(file, material, elems[1], tab_write)
296 write_matrix(file, global_matrix @ ob.matrix_world)
297 # Importance for radiosity sampling added here
298 tab_write(file, "radiosity { \n")
299 # importance > ob.pov.importance_value
300 tab_write(file, "importance %3g \n" % importance)
301 tab_write(file, "}\n")
303 tab_write(file, "}\n") # End of Metaball block
305 if comments and len(metas) >= 1: