# SPDX-License-Identifier: GPL-2.0-or-later """Translate Blender meta balls to POV blobs.""" import bpy from .shading import write_object_material_interior def export_meta(file, metas, tab_write, DEF_MAT_NAME): """write all POV blob primitives and Blender Metas to exported file """ # TODO - blenders 'motherball' naming is not supported. from .render import ( safety, global_matrix, write_matrix, comments, ) if comments and len(metas) >= 1: file.write("//--Blob objects--\n\n") # Get groups of metaballs by blender name prefix. meta_group = {} meta_elems = {} for meta_ob in metas: prefix = meta_ob.name.split(".")[0] if prefix not in meta_group: meta_group[prefix] = meta_ob # .data.threshold elems = [ (elem, meta_ob) for elem in meta_ob.data.elements if elem.type in {'BALL', 'ELLIPSOID', 'CAPSULE', 'CUBE', 'PLANE'} ] if prefix in meta_elems: meta_elems[prefix].extend(elems) else: meta_elems[prefix] = elems # empty metaball if not elems: tab_write(file, "\n//dummy sphere to represent empty meta location\n") tab_write(file, "sphere {<%.6g, %.6g, %.6g>,0 pigment{rgbt 1} " "no_image no_reflection no_radiosity " "photons{pass_through collect off} hollow}\n\n" % (meta_ob.location.x, meta_ob.location.y, meta_ob.location.z) ) # meta_ob.name > povdataname) return # other metaballs for mg, mob in meta_group.items(): if len(meta_elems[mg]) != 0: tab_write(file, "blob{threshold %.4g // %s \n" % (mob.data.threshold, mg)) for elems in meta_elems[mg]: elem = elems[0] loc = elem.co stiffness = elem.stiffness if elem.use_negative: stiffness = -stiffness if elem.type == 'BALL': tab_write(file, "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g " % (loc.x, loc.y, loc.z, elem.radius, stiffness) ) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") elif elem.type == 'ELLIPSOID': tab_write(file, "sphere{ <%.6g, %.6g, %.6g>,%.4g,%.4g " % ( loc.x / elem.size_x, loc.y / elem.size_y, loc.z / elem.size_z, elem.radius, stiffness, ) ) tab_write(file, "scale <%.6g, %.6g, %.6g>" % (elem.size_x, elem.size_y, elem.size_z) ) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") elif elem.type == 'CAPSULE': tab_write(file, "cylinder{ <%.6g, %.6g, %.6g>,<%.6g, %.6g, %.6g>,%.4g,%.4g " % ( (loc.x - elem.size_x), loc.y, loc.z, (loc.x + elem.size_x), loc.y, loc.z, elem.radius, stiffness, ) ) # tab_write(file, "scale <%.6g, %.6g, %.6g>" % (elem.size_x, elem.size_y, elem.size_z)) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") elif elem.type == 'CUBE': tab_write(file, "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n" % ( elem.radius * 2.0, stiffness / 4.0, loc.x, loc.y, loc.z, elem.size_x, elem.size_y, elem.size_z, ) ) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") tab_write(file, "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n" % ( elem.radius * 2.0, stiffness / 4.0, loc.x, loc.y, loc.z, elem.size_x, elem.size_y, elem.size_z, ) ) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") tab_write(file, "cylinder { -z*8, +z*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1,1/4> scale <%.6g, %.6g, %.6g>\n" % ( elem.radius * 2.0, stiffness / 4.0, loc.x, loc.y, loc.z, elem.size_x, elem.size_y, elem.size_z, ) ) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") elif elem.type == 'PLANE': tab_write(file, "cylinder { -x*8, +x*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1/4,1,1> scale <%.6g, %.6g, %.6g>\n" % ( elem.radius * 2.0, stiffness / 4.0, loc.x, loc.y, loc.z, elem.size_x, elem.size_y, elem.size_z, ) ) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") tab_write(file, "cylinder { -y*8, +y*8,%.4g,%.4g translate<%.6g,%.6g,%.6g> scale <1,1/4,1> scale <%.6g, %.6g, %.6g>\n" % ( elem.radius * 2.0, stiffness / 4.0, loc.x, loc.y, loc.z, elem.size_x, elem.size_y, elem.size_z, ) ) write_matrix(file, global_matrix @ elems[1].matrix_world) tab_write(file, "}\n") try: one_material = elems[1].data.materials[ 0 ] # lame! - blender cant do enything else. except BaseException as e: print(e.__doc__) print('An exception occurred: {}'.format(e)) one_material = None if one_material: diffuse_color = one_material.diffuse_color trans = 1.0 - one_material.pov.alpha if ( one_material.pov.use_transparency and one_material.pov.transparency_method == 'RAYTRACE' ): pov_filter = one_material.pov_raytrace_transparency.filter * ( 1.0 - one_material.pov.alpha ) trans = (1.0 - one_material.pov.alpha) - pov_filter else: pov_filter = 0.0 material_finish = material_names_dictionary[one_material.name] tab_write(file, "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" % ( diffuse_color[0], diffuse_color[1], diffuse_color[2], pov_filter, trans, ) ) tab_write(file, "finish{%s} " % safety(material_finish, ref_level_bound=2)) else: material_finish = DEF_MAT_NAME trans = 0.0 tab_write(file, "pigment{srgbt<1,1,1,%.3g>} finish{%s} " % (trans, safety(material_finish, ref_level_bound=2)) ) write_object_material_interior(file, one_material, mob, tab_write) # write_object_material_interior(file, one_material, elems[1]) tab_write(file, "radiosity{importance %3g}\n" % mob.pov.importance_value) tab_write(file, "}\n\n") # End of Metaball block ''' meta = ob.data # important because no elements will break parsing. elements = [elem for elem in meta.elements if elem.type in {'BALL', 'ELLIPSOID'}] if elements: tab_write(file, "blob {\n") tab_write(file, "threshold %.4g\n" % meta.threshold) importance = ob.pov.importance_value try: material = meta.materials[0] # lame! - blender cant do enything else. except: material = None for elem in elements: loc = elem.co stiffness = elem.stiffness if elem.use_negative: stiffness = - stiffness if elem.type == 'BALL': tab_write(file, "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" % (loc.x, loc.y, loc.z, elem.radius, stiffness)) # After this wecould do something simple like... # "pigment {Blue} }" # except we'll write the color elif elem.type == 'ELLIPSOID': # location is modified by scale tab_write(file, "sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n" % (loc.x / elem.size_x, loc.y / elem.size_y, loc.z / elem.size_z, elem.radius, stiffness)) tab_write(file, "scale <%.6g, %.6g, %.6g> \n" % (elem.size_x, elem.size_y, elem.size_z)) if material: diffuse_color = material.diffuse_color trans = 1.0 - material.pov.alpha if material.pov.use_transparency and material.pov.transparency_method == 'RAYTRACE': pov_filter = material.pov_raytrace_transparency.filter * (1.0 - material.pov.alpha) trans = (1.0 - material.pov.alpha) - pov_filter else: pov_filter = 0.0 material_finish = material_names_dictionary[material.name] tab_write(file, "pigment {srgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" % (diffuse_color[0], diffuse_color[1], diffuse_color[2], pov_filter, trans)) tab_write(file, "finish {%s}\n" % safety(material_finish, ref_level_bound=2)) else: tab_write(file, "pigment {srgb 1} \n") # Write the finish last. tab_write(file, "finish {%s}\n" % (safety(DEF_MAT_NAME, ref_level_bound=2))) write_object_material_interior(file, material, elems[1], tab_write) write_matrix(file, global_matrix @ ob.matrix_world) # Importance for radiosity sampling added here tab_write(file, "radiosity { \n") # importance > ob.pov.importance_value tab_write(file, "importance %3g \n" % importance) tab_write(file, "}\n") tab_write(file, "}\n") # End of Metaball block if comments and len(metas) >= 1: file.write("\n") '''