License Headers: use SPDX-FileCopyrightText for mesh_tissue
[blender-addons.git] / render_povray / model_meta_topology.py
blob99b3ff3cd794a25199daec37991cb9899969d3d8
1 # SPDX-FileCopyrightText: 2022-2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 """Translate Blender meta balls to POV blobs."""
7 import bpy
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.
14 from .render import (
15 safety,
16 global_matrix,
17 write_matrix,
18 comments,
20 if comments and len(metas) >= 1:
21 file.write("//--Blob objects--\n\n")
22 # Get groups of metaballs by blender name prefix.
23 meta_group = {}
24 meta_elems = {}
25 for meta_ob in metas:
26 prefix = meta_ob.name.split(".")[0]
27 if prefix not in meta_group:
28 meta_group[prefix] = meta_ob # .data.threshold
29 elems = [
30 (elem, meta_ob)
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)
36 else:
37 meta_elems[prefix] = elems
39 # empty metaball
40 if not elems:
41 tab_write(file, "\n//dummy sphere to represent empty meta location\n")
42 tab_write(file,
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)
48 return
50 # other metaballs
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]:
56 elem = elems[0]
57 loc = elem.co
58 stiffness = elem.stiffness
59 if elem.use_negative:
60 stiffness = -stiffness
61 if elem.type == 'BALL':
62 tab_write(file,
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':
69 tab_write(file,
70 "sphere{ <%.6g, %.6g, %.6g>,%.4g,%.4g "
71 % (
72 loc.x / elem.size_x,
73 loc.y / elem.size_y,
74 loc.z / elem.size_z,
75 elem.radius,
76 stiffness,
79 tab_write(file,
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':
86 tab_write(file,
87 "cylinder{ <%.6g, %.6g, %.6g>,<%.6g, %.6g, %.6g>,%.4g,%.4g "
88 % (
89 (loc.x - elem.size_x),
90 loc.y,
91 loc.z,
92 (loc.x + elem.size_x),
93 loc.y,
94 loc.z,
95 elem.radius,
96 stiffness,
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':
104 tab_write(file,
105 "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
107 elem.radius * 2.0,
108 stiffness / 4.0,
109 loc.x,
110 loc.y,
111 loc.z,
112 elem.size_x,
113 elem.size_y,
114 elem.size_z,
117 write_matrix(file, global_matrix @ elems[1].matrix_world)
118 tab_write(file, "}\n")
119 tab_write(file,
120 "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
122 elem.radius * 2.0,
123 stiffness / 4.0,
124 loc.x,
125 loc.y,
126 loc.z,
127 elem.size_x,
128 elem.size_y,
129 elem.size_z,
132 write_matrix(file, global_matrix @ elems[1].matrix_world)
133 tab_write(file, "}\n")
134 tab_write(file,
135 "cylinder { -z*8, +z*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1,1/4> scale <%.6g, %.6g, %.6g>\n"
137 elem.radius * 2.0,
138 stiffness / 4.0,
139 loc.x,
140 loc.y,
141 loc.z,
142 elem.size_x,
143 elem.size_y,
144 elem.size_z,
147 write_matrix(file, global_matrix @ elems[1].matrix_world)
148 tab_write(file, "}\n")
150 elif elem.type == 'PLANE':
151 tab_write(file,
152 "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n"
154 elem.radius * 2.0,
155 stiffness / 4.0,
156 loc.x,
157 loc.y,
158 loc.z,
159 elem.size_x,
160 elem.size_y,
161 elem.size_z,
164 write_matrix(file, global_matrix @ elems[1].matrix_world)
165 tab_write(file, "}\n")
166 tab_write(file,
167 "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n"
169 elem.radius * 2.0,
170 stiffness / 4.0,
171 loc.x,
172 loc.y,
173 loc.z,
174 elem.size_x,
175 elem.size_y,
176 elem.size_z,
179 write_matrix(file, global_matrix @ elems[1].matrix_world)
180 tab_write(file, "}\n")
182 try:
183 one_material = elems[1].data.materials[
185 ] # lame! - blender can't do anything else.
186 except BaseException as e:
187 print(e.__doc__)
188 print('An exception occurred: {}'.format(e))
189 one_material = None
190 if one_material:
191 diffuse_color = one_material.diffuse_color
192 trans = 1.0 - one_material.pov.alpha
193 if (
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
201 else:
202 pov_filter = 0.0
203 material_finish = material_names_dictionary[one_material.name]
204 tab_write(file,
205 "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n"
207 diffuse_color[0],
208 diffuse_color[1],
209 diffuse_color[2],
210 pov_filter,
211 trans,
214 tab_write(file, "finish{%s} " % safety(material_finish, ref_level_bound=2))
215 else:
216 material_finish = DEF_MAT_NAME
217 trans = 0.0
218 tab_write(file,
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
231 meta = ob.data
233 # important because no elements will break parsing.
234 elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}]
236 if elements:
237 tab_write(file, "blob {\n")
238 tab_write(file, "threshold %.4g\n" % meta.threshold)
239 importance = ob.pov.importance_value
241 try:
242 material = meta.materials[0] # lame! - blender can't do anything else.
243 except:
244 material = None
246 for elem in elements:
247 loc = elem.co
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...
259 # "pigment {Blue} }"
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,
266 loc.y / elem.size_y,
267 loc.z / elem.size_z,
268 elem.radius, stiffness))
269 tab_write(file, "scale <%.6g, %.6g, %.6g> \n" %
270 (elem.size_x, elem.size_y, elem.size_z))
272 if material:
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 -
277 material.pov.alpha)
278 trans = (1.0 - material.pov.alpha) - pov_filter
279 else:
280 pov_filter = 0.0
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],
286 pov_filter, trans))
287 tab_write(file, "finish {%s}\n" % safety(material_finish, ref_level_bound=2))
289 else:
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:
306 file.write("\n")