mirror of
https://github.com/blender/blender-addons.git
synced 2025-07-29 12:05:36 +00:00

Move copyright text to SPDX-FileCopyrightText or set to the Blender Foundation so "make check_licenses" now runs without warnings.
308 lines
14 KiB
Python
308 lines
14 KiB
Python
# SPDX-FileCopyrightText: 2022-2023 Blender Foundation
|
|
#
|
|
# 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, material_names_dictionary, 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 can't do anything 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 can't do anything 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")
|
|
'''
|