Newer
Older
material = me.materials[0] # dodgy
writeObjectMaterial(material, ob)
except IndexError:
print(me)
# POV object modifiers such as
# hollow / sturm / double_illuminate etc.
write_object_modifiers(scene, ob, file)
# Importance for radiosity sampling added here:
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
Maurice Raybaud
committed
tabWrite("}\n") # End of mesh block
facesMaterials = [] # WARNING!!!!!!!!!!!!!!!!!!!!!!
if me_materials:
for f in me_faces:
if f.material_index not in facesMaterials:
facesMaterials.append(f.material_index)
# No vertex colors, so write material colors as vertex colors
for i, material in enumerate(me_materials):
if (
material
and material.pov.material_use_nodes == False
): # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Multiply diffuse with SSS Color
if material.pov_subsurface_scattering.use:
diffuse_color = [
i * j
for i, j in zip(
material.pov_subsurface_scattering.color[
:
],
material.diffuse_color[:],
)
]
key = (
diffuse_color[0],
diffuse_color[1],
diffuse_color[2],
i,
) # i == f.mat
vertCols[key] = [-1]
else:
diffuse_color = material.diffuse_color[
:
]
key = (
diffuse_color[0],
diffuse_color[1],
diffuse_color[2],
i,
) # i == f.mat
idx = 0
LocalMaterialNames = []
for col, index in vertCols.items():
mater = me_materials[col[3]]
if me_materials is None: # XXX working?
material_finish = (
DEF_MAT_NAME
) # not working properly,
shading.writeTextureInfluence(
mater,
materialNames,
LocalMaterialNames,
path_image,
lampCount,
imageFormat,
imgMap,
imgMapTransforms,
tabWrite,
comments,
string_strip_hyphen,
safety,
col,
os,
preview_dir,
unpacked_images,
)
###################################################################
index[0] = idx
idx += 1
# Vert Colors
tabWrite("texture_list {\n")
# In case there's is no material slot, give at least one texture
# (an empty one so it uses pov default)
if len(vertCols) == 0:
file.write(tabStr + "1")
else:
file.write(
tabStr + "%s" % (len(vertCols))
) # vert count
# below "material" alias, added check ob.active_material
# to avoid variable referenced before assignment error
try:
material = ob.active_material
except IndexError:
# when no material slot exists,
material = None
# WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (
material
and ob.active_material is not None
and material.pov.material_use_nodes == False
):
if material.pov.replacement_text != "":
file.write("\n")
file.write(
" texture{%s}\n"
% material.pov.replacement_text
)
# Loop through declared materials list
for cMN in LocalMaterialNames:
if material != "Default":
file.write(
"\n texture{MAT_%s}\n" % cMN
)
# use string_strip_hyphen(materialNames[material]))
# or Something like that to clean up the above?
elif material and material.pov.material_use_nodes:
for index in facesMaterials:
faceMaterial = string_strip_hyphen(
bpy.path.clean_name(
me_materials[index].name
)
)
file.write(
"\n texture{%s}\n" % faceMaterial
)
# END!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Maurice Raybaud
committed
else:
file.write(" texture{}\n")
tabWrite("}\n")
# Face indices
tabWrite("face_indices {\n")
tabWrite("%d" % (len(me_faces))) # faces count
tabStr = tab * tabLevel
Maurice Raybaud
committed
for fi, f in enumerate(me_faces):
fv = faces_verts[fi]
material_index = f.material_index
Maurice Raybaud
committed
cols = [
vcol_layer[l].color[:] for l in f.loops
]
if (
not me_materials
or me_materials[material_index] is None
): # No materials
if linebreaksinlists:
file.write(",\n")
# vert count
file.write(
tabStr
+ "<%d,%d,%d>"
% (fv[0], fv[1], fv[2])
)
file.write(
"<%d,%d,%d>" % (fv[0], fv[1], fv[2])
) # vert count
material = me_materials[material_index]
ci1 = ci2 = ci3 = f.material_index
if (
me.vertex_colors
): # and material.use_vertex_color_paint:
# Color per vertex - vertex color
col1 = cols[0]
col2 = cols[1]
col3 = cols[2]
ci1 = vertCols[
col1[0],
col1[1],
col1[2],
material_index,
][0]
ci2 = vertCols[
col2[0],
col2[1],
col2[2],
material_index,
][0]
ci3 = vertCols[
col3[0],
col3[1],
col3[2],
material_index,
][0]
elif material.pov.material_use_nodes:
ci1 = ci2 = ci3 = 0
else:
# Color per material - flat material color
if (
material.pov_subsurface_scattering.use
):
diffuse_color = [
i * j
for i, j in zip(
material.pov_subsurface_scattering.color[
:
],
material.diffuse_color[:],
)
]
diffuse_color = material.diffuse_color[
:
]
ci1 = ci2 = ci3 = vertCols[
diffuse_color[0],
diffuse_color[1],
diffuse_color[2],
f.material_index,
][0]
if linebreaksinlists:
file.write(",\n")
file.write(
tabStr
+ "<%d,%d,%d>, %d,%d,%d"
% (
fv[0],
fv[1],
fv[2],
ci1,
ci2,
ci3,
)
) # vert count
file.write(
"<%d,%d,%d>, %d,%d,%d"
% (
fv[0],
fv[1],
fv[2],
ci1,
ci2,
ci3,
)
) # vert count
file.write("\n")
tabWrite("}\n")
# normal_indices indices
tabWrite("normal_indices {\n")
tabWrite("%d" % (len(me_faces))) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
if me_faces[fi].use_smooth:
if linebreaksinlists:
file.write(",\n")
file.write(
tabStr
+ "<%d,%d,%d>"
% (
uniqueNormals[
verts_normals[fv[0]]
][0],
uniqueNormals[
verts_normals[fv[1]]
][0],
uniqueNormals[
verts_normals[fv[2]]
][0],
)
) # vert count
file.write(
"<%d,%d,%d>"
% (
uniqueNormals[
verts_normals[fv[0]]
][0],
uniqueNormals[
verts_normals[fv[1]]
][0],
uniqueNormals[
verts_normals[fv[2]]
][0],
)
) # vert count
idx = uniqueNormals[faces_normals[fi]][0]
if linebreaksinlists:
file.write(",\n")
file.write(
tabStr
+ "<%d,%d,%d>" % (idx, idx, idx)
) # vertcount
file.write(
"<%d,%d,%d>" % (idx, idx, idx)
) # vert count
file.write("\n")
tabWrite("}\n")
if uv_layer:
tabWrite("uv_indices {\n")
tabWrite("%d" % (len(me_faces))) # faces count
tabStr = tab * tabLevel
for f in me_faces:
uvs = [uv_layer[l].uv[:] for l in f.loops]
if linebreaksinlists:
file.write(",\n")
file.write(
tabStr
+ "<%d,%d,%d>"
% (
uniqueUVs[uvs[0]][0],
uniqueUVs[uvs[1]][0],
uniqueUVs[uvs[2]][0],
)
)
file.write(
"<%d,%d,%d>"
% (
uniqueUVs[uvs[0]][0],
uniqueUVs[uvs[1]][0],
uniqueUVs[uvs[2]][0],
)
)
file.write("\n")
tabWrite("}\n")
onceCSG = 0
for mod in ob.modifiers:
if onceCSG == 0:
if mod.type == 'BOOLEAN':
if ob.pov.boolean_mod == "POV":
file.write(
"\tinside_vector <%.6g, %.6g, %.6g>\n"
% (
ob.pov.inside_vector[0],
ob.pov.inside_vector[1],
ob.pov.inside_vector[2],
)
)
onceCSG = 1
if me.materials:
try:
material = me.materials[0] # dodgy
writeObjectMaterial(material, ob)
except IndexError:
print(me)
# POV object modifiers such as
# hollow / sturm / double_illuminate etc.
write_object_modifiers(scene, ob, file)
# Importance for radiosity sampling added here:
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
tabWrite("}\n") # End of mesh block
if csg:
duplidata_ref = []
_dupnames_seen = (
dict()
) # avoid duplicate output during introspection
# matrix = global_matrix @ ob.matrix_world
if ob.is_instancer:
tabWrite("\n//--DupliObjects in %s--\n\n" % ob.name)
# ob.dupli_list_create(scene) #deprecated in 2.8
depsgraph = bpy.context.evaluated_depsgraph_get()
dup = ""
if ob.is_modified(scene, 'RENDER'):
# modified object always unique so using object name rather than data name
dup = "#declare OB%s = union{\n" % (
string_strip_hyphen(bpy.path.clean_name(ob.name))
)
dup = "#declare DATA%s = union{\n" % (
string_strip_hyphen(bpy.path.clean_name(ob.name))
)
for eachduplicate in depsgraph.object_instances:
if (
eachduplicate.is_instance
): # Real dupli instance filtered because original included in list since 2.8
_dupname = eachduplicate.object.name
_dupobj = bpy.data.objects[_dupname]
# BEGIN introspection for troubleshooting purposes
if not "name" in dir(_dupobj.data):
if _dupname not in _dupnames_seen:
print(
"WARNING: bpy.data.objects[%s].data (of type %s) has no 'name' attribute"
% (_dupname, type(_dupobj.data))
)
print(
"|| %s.%s = %s"
% (
_dupname,
_thing,
getattr(_dupobj, _thing),
)
)
print(
"''=> Unparseable objects so far: %s"
% (_dupnames_seen)
)
else:
_dupnames_seen[_dupname] += 1
continue # don't try to parse data objects with no name attribute
# END introspection for troubleshooting purposes
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
duplidataname = "OB" + string_strip_hyphen(
bpy.path.clean_name(_dupobj.data.name)
)
dupmatrix = (
eachduplicate.matrix_world.copy()
) # has to be copied to not store instance since 2.8
dup += "\tobject {\n\t\tDATA%s\n\t\t%s\t}\n" % (
string_strip_hyphen(
bpy.path.clean_name(_dupobj.data.name)
),
MatrixAsPovString(
ob.matrix_world.inverted() @ dupmatrix
),
)
# add object to a list so that it is not rendered for some instance_types
if (
ob.instance_type not in {'COLLECTION'}
and duplidataname not in duplidata_ref
):
duplidata_ref.append(
duplidataname
) # older key [string_strip_hyphen(bpy.path.clean_name("OB"+ob.name))]
# ob.dupli_list_clear()# just do not store any reference to instance since 2.8
Maurice Raybaud
committed
else:
print(
"WARNING: Unparseable objects in current .blend file:\n''=> %s"
% (_dupnames_seen)
)
print("duplidata_ref = %s" % (duplidata_ref))
for data_name, inst in data_ref.items():
for ob_name, matrix_str in inst:
if (
ob_name not in duplidata_ref
): # .items() for a dictionary
tabWrite(
"\n//----Blender Object Name:%s----\n" % ob_name
)
if ob.pov.object_as == '':
tabWrite("object { \n")
tabWrite("%s\n" % data_name)
tabWrite("%s\n" % matrix_str)
tabWrite("}\n")
else:
no_boolean = True
for mod in ob.modifiers:
if mod.type == 'BOOLEAN':
operation = None
no_boolean = False
if mod.operation == 'INTERSECT':
operation = 'intersection'
else:
operation = mod.operation.lower()
mod_ob_name = string_strip_hyphen(
bpy.path.clean_name(mod.object.name)
)
mod_matrix = (
global_matrix @ mod.object.matrix_world
)
mod_ob_matrix = MatrixAsPovString(
mod_matrix
)
tabWrite("%s { \n" % operation)
tabWrite("object { \n")
tabWrite("%s\n" % data_name)
tabWrite("%s\n" % matrix_str)
tabWrite("}\n")
tabWrite("object { \n")
tabWrite("%s\n" % ('DATA' + mod_ob_name))
tabWrite("%s\n" % mod_ob_matrix)
tabWrite("}\n")
tabWrite("}\n")
break
if no_boolean:
tabWrite("object { \n")
tabWrite("%s\n" % data_name)
tabWrite("%s\n" % matrix_str)
tabWrite("}\n")
Maurice Raybaud
committed
"""write world as POV backgrounbd and sky_sphere to exported file """
matrix = global_matrix @ camera.matrix_world
#############Maurice####################################
# These lines added to get sky gradient (visible with PNG output)
# For simple flat background:
if not world.pov.use_sky_blend:
Bastien Montagne
committed
# Non fully transparent background could premultiply alpha and avoid anti-aliasing
# display issue:
if render.alpha_mode == 'TRANSPARENT':
tabWrite(
"background {rgbt<%.3g, %.3g, %.3g, 0.75>}\n"
% (world.pov.horizon_color[:])
)
# Currently using no alpha with Sky option:
elif render.alpha_mode == 'SKY':
tabWrite(
"background {rgbt<%.3g, %.3g, %.3g, 0>}\n"
% (world.pov.horizon_color[:])
)
# StraightAlpha:
# XXX Does not exists anymore
# else:
# tabWrite("background {rgbt<%.3g, %.3g, %.3g, 1>}\n" % (world.pov.horizon_color[:]))
# For Background image textures
for (
t
) in (
world.texture_slots
): # risk to write several sky_spheres but maybe ok.
if t and t.texture.type is not None:
Bastien Montagne
committed
# XXX No enable checkbox for world textures yet (report it?)
# if t and t.texture.type == 'IMAGE' and t.use:
Bastien Montagne
committed
if t and t.texture.type == 'IMAGE':
if t.texture.image.filepath != image_filename:
t.texture.image.filepath = image_filename
if image_filename != "" and t.use_map_blend:
# colvalue = t.default_value
Bastien Montagne
committed
Bastien Montagne
committed
# Commented below was an idea to make the Background image oriented as camera
# taken here:
# http://news.pov.org/pov.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.pov.org%3E/
Bastien Montagne
committed
# Replace 4/3 by the ratio of each image found by some custom or existing
# function
# mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees" \
Bastien Montagne
committed
# "(atan((camLocation - camLookAt).x/(camLocation - " \
# "camLookAt).y)) rotate x*degrees(atan((camLocation - " \
# "camLookAt).y/(camLocation - camLookAt).z)) rotate y*" \
# "degrees(atan((camLocation - camLookAt).z/(camLocation - " \
# "camLookAt).x)) scale <%.4g,%.4g,%.4g>b" % \
# (t_blend.offset.x / 10 , t_blend.offset.y / 10 ,
# t_blend.offset.z / 10, t_blend.scale.x ,
# t_blend.scale.y , t_blend.scale.z))
# using camera rotation valuesdirectly from blender seems much easier
if t_blend.texture_coords == 'ANGMAP':
mappingBlend = ""
Maurice Raybaud
committed
else:
# POV-Ray "scale" is not a number of repetitions factor, but its
# inverse, a standard scale factor.
# 0.5 Offset is needed relatively to scale because center of the
# UV scale is 0.5,0.5 in blender and 0,0 in POV
# required for the sky_sphere not to repeat
mappingBlend = (
"scale 2 scale <%.4g,%.4g,%.4g> translate -1 "
"translate <%.4g,%.4g,%.4g> rotate<0,0,0> "
% (
(1.0 / t_blend.scale.x),
(1.0 / t_blend.scale.y),
(1.0 / t_blend.scale.z),
0.5
- (0.5 / t_blend.scale.x)
- t_blend.offset.x,
0.5
- (0.5 / t_blend.scale.y)
- t_blend.offset.y,
t_blend.offset.z,
)
)
Bastien Montagne
committed
# The initial position and rotation of the pov camera is probably creating
# the rotation offset should look into it someday but at least background
# won't rotate with the camera now.
# Putting the map on a plane would not introduce the skysphere distortion and
# allow for better image scale matching but also some waay to chose depth and
# size of the plane relative to camera.
tabWrite("sky_sphere {\n")
tabWrite("pigment {\n")
tabWrite(
"image_map{%s \"%s\" %s}\n"
% (
imageFormat(texturesBlend),
texturesBlend,
imgMapBG(t_blend),
)
)
tabWrite("}\n")
tabWrite("%s\n" % (mappingBlend))
Bastien Montagne
committed
# The following layered pigment opacifies to black over the texture for
# transmit below 1 or otherwise adds to itself
tabWrite(
"pigment {rgb 0 transmit %s}\n" % (t.texture.intensity)
)
tabWrite("}\n")
# tabWrite("scale 2\n")
# tabWrite("translate -1\n")
# For only Background gradient
if worldTexCount == 0:
tabWrite("sky_sphere {\n")
tabWrite("pigment {\n")
Bastien Montagne
committed
# maybe Should follow the advice of POV doc about replacing gradient
# for skysphere..5.5
tabWrite("gradient y\n")
tabWrite("color_map {\n")
# XXX Does not exists anymore
# if render.alpha_mode == 'STRAIGHT':
# tabWrite("[0.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.horizon_color[:]))
# tabWrite("[1.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.zenith_color[:]))
if render.alpha_mode == 'TRANSPARENT':
tabWrite(
"[0.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n"
% (world.pov.horizon_color[:])
)
Bastien Montagne
committed
# aa premult not solved with transmit 1
tabWrite(
"[1.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n"
% (world.pov.zenith_color[:])
)
tabWrite(
"[0.0 rgbt<%.3g, %.3g, %.3g, 0>]\n"
% (world.pov.horizon_color[:])
)
tabWrite(
"[1.0 rgbt<%.3g, %.3g, %.3g, 0>]\n"
% (world.pov.zenith_color[:])
)
tabWrite("}\n")
tabWrite("}\n")
tabWrite("}\n")
Bastien Montagne
committed
# Sky_sphere alpha (transmit) is not translating into image alpha the same
# way as 'background'
# if world.pov.light_settings.use_indirect_light:
Bastien Montagne
committed
# scene.pov.radio_enable=1
# Maybe change the above to a function copyInternalRenderer settings when
Bastien Montagne
committed
# user pushes a button, then:
# scene.pov.radio_enable = world.pov.light_settings.use_indirect_light
Bastien Montagne
committed
# and other such translations but maybe this would not be allowed either?
###############################################################
tabWrite("fog {\n")
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
if mist.falloff == 'LINEAR':
tabWrite(
"distance %.6f\n" % ((mist.start + mist.depth) * 0.368)
)
elif mist.falloff == 'QUADRATIC': # n**2 or squrt(n)?
tabWrite(
"distance %.6f\n" % ((mist.start + mist.depth) ** 2 * 0.368)
)
elif mist.falloff == 'INVERSE_QUADRATIC': # n**2 or squrt(n)?
tabWrite(
"distance %.6f\n" % ((mist.start + mist.depth) ** 2 * 0.368)
)
tabWrite(
"color rgbt<%.3g, %.3g, %.3g, %.3g>\n"
% (*world.pov.horizon_color, 1.0 - mist.intensity)
)
# tabWrite("fog_offset %.6f\n" % mist.start) #create a pov property to prepend
# tabWrite("fog_alt %.6f\n" % mist.height) #XXX right?
# tabWrite("turbulence 0.2\n")
# tabWrite("turb_depth 0.3\n")
tabWrite("fog_type 1\n") # type2 for height
tabWrite("}\n")
Bastien Montagne
committed
if scene.pov.media_enable:
tabWrite("media {\n")
tabWrite(
"scattering { %d, rgb %.12f*<%.4g, %.4g, %.4g>\n"
% (
int(scene.pov.media_scattering_type),
(scene.pov.media_diffusion_scale),
*(scene.pov.media_diffusion_color[:]),
)
)
if scene.pov.media_scattering_type == '5':
tabWrite("eccentricity %.3g\n" % scene.pov.media_eccentricity)
tabWrite("}\n")
tabWrite(
"absorption %.12f*<%.4g, %.4g, %.4g>\n"
% (
scene.pov.media_absorption_scale,
*(scene.pov.media_absorption_color[:]),
)
)
Bastien Montagne
committed
tabWrite("samples %.d\n" % scene.pov.media_samples)
tabWrite("}\n")
"""write all POV global settings to exported file """
tabWrite("global_settings {\n")
tabWrite("assumed_gamma 1.0\n")
Bastien Montagne
committed
tabWrite("max_trace_level %d\n" % scene.pov.max_trace_level)
# Deprecated (autodetected in pov3.8):
# if scene.pov.charset != 'ascii':
# file.write(" charset %s\n" % scene.pov.charset)
Maurice Raybaud
committed
if scene.pov.global_settings_advanced:
if scene.pov.radio_enable == False:
file.write(" adc_bailout %.6f\n" % scene.pov.adc_bailout)
file.write(
" ambient_light <%.6f,%.6f,%.6f>\n"
% scene.pov.ambient_light[:]
)
file.write(
" irid_wavelength <%.6f,%.6f,%.6f>\n"
% scene.pov.irid_wavelength[:]
)
file.write(
" max_intersections %s\n" % scene.pov.max_intersections
)
file.write(" number_of_waves %s\n" % scene.pov.number_of_waves)
file.write(" noise_generator %s\n" % scene.pov.noise_generator)
Bastien Montagne
committed
if scene.pov.radio_enable:
tabWrite("radiosity {\n")
Bastien Montagne
committed
tabWrite("adc_bailout %.4g\n" % scene.pov.radio_adc_bailout)
tabWrite("brightness %.4g\n" % scene.pov.radio_brightness)
tabWrite("count %d\n" % scene.pov.radio_count)
tabWrite("error_bound %.4g\n" % scene.pov.radio_error_bound)
tabWrite("gray_threshold %.4g\n" % scene.pov.radio_gray_threshold)
tabWrite(
"low_error_factor %.4g\n" % scene.pov.radio_low_error_factor
)
tabWrite("maximum_reuse %.4g\n" % scene.pov.radio_maximum_reuse)
Bastien Montagne
committed
tabWrite("minimum_reuse %.4g\n" % scene.pov.radio_minimum_reuse)
tabWrite("nearest_count %d\n" % scene.pov.radio_nearest_count)
tabWrite("pretrace_start %.3g\n" % scene.pov.radio_pretrace_start)
tabWrite("pretrace_end %.3g\n" % scene.pov.radio_pretrace_end)
tabWrite("recursion_limit %d\n" % scene.pov.radio_recursion_limit)
Maurice Raybaud
committed
tabWrite("always_sample %d\n" % scene.pov.radio_always_sample)
tabWrite("normal %d\n" % scene.pov.radio_normal)
tabWrite("media %d\n" % scene.pov.radio_media)
tabWrite("subsurface %d\n" % scene.pov.radio_subsurface)
tabWrite("}\n")
Bastien Montagne
committed
onceSss = 1
onceAmbient = 1
oncePhotons = 1
if material.pov_subsurface_scattering.use and onceSss:
Bastien Montagne
committed
# In pov, the scale has reversed influence compared to blender. these number
# should correct that
tabWrite(
"mm_per_unit %.6f\n"
% (material.pov_subsurface_scattering.scale * 1000.0)
)
# 1000 rather than scale * (-100.0) + 15.0))
Bastien Montagne
committed
# In POV-Ray, the scale factor for all subsurface shaders needs to be the same
# formerly sslt_samples were multiplied by 100 instead of 10
sslt_samples = (
11 - material.pov_subsurface_scattering.error_threshold
) * 10
tabWrite(
"subsurface { samples %d, %d }\n"
% (sslt_samples, sslt_samples / 10)
)
Bastien Montagne
committed
onceSss = 0
Bastien Montagne
committed
if world and onceAmbient:
tabWrite(
"ambient_light rgb<%.3g, %.3g, %.3g>\n"
% world.pov.ambient_color[:]
)
Bastien Montagne
committed
onceAmbient = 0
Maurice Raybaud
committed
Maurice Raybaud
committed
if scene.pov.photon_enable:
if oncePhotons and (
material.pov.refraction_type == "2"
or material.pov.photons_reflection == True
):
Maurice Raybaud
committed
tabWrite("photons {\n")
tabWrite("spacing %.6f\n" % scene.pov.photon_spacing)
tabWrite(
"max_trace_level %d\n"
% scene.pov.photon_max_trace_level
)
tabWrite(
"adc_bailout %.3g\n" % scene.pov.photon_adc_bailout
)
tabWrite(
"gather %d, %d\n"
% (
scene.pov.photon_gather_min,
scene.pov.photon_gather_max,
)
)
if scene.pov.photon_map_file_save_load in {'save'}:
filePhName = 'Photon_map_file.ph'
if scene.pov.photon_map_file != '':
filePhName = scene.pov.photon_map_file + '.ph'
filePhDir = tempfile.gettempdir()
path = bpy.path.abspath(scene.pov.photon_map_dir)
if os.path.exists(path):
filePhDir = path
fullFileName = os.path.join(filePhDir, filePhName)
tabWrite('save_file "%s"\n' % fullFileName)
scene.pov.photon_map_file = fullFileName
if scene.pov.photon_map_file_save_load in {'load'}:
fullFileName = bpy.path.abspath(
scene.pov.photon_map_file
)
if os.path.exists(fullFileName):
tabWrite('load_file "%s"\n' % fullFileName)
Maurice Raybaud
committed
tabWrite("}\n")
oncePhotons = 0
tabWrite("}\n")
Maurice Raybaud
committed
def exportCustomCode():
"""write all POV user defined custom code to exported file """
# Write CurrentAnimation Frame for use in Custom POV Code
file.write(
"#declare CURFRAMENUM = %d;\n" % bpy.context.scene.frame_current
)
# Change path and uncomment to add an animated include file by hand:
file.write(
"//#include \"/home/user/directory/animation_include_file.inc\"\n"
)
Campbell Barton
committed
for txt in bpy.data.texts:
Maurice Raybaud
committed
if txt.pov.custom_code == 'both':
Campbell Barton
committed
# Why are the newlines needed?
file.write("\n")
file.write(txt.as_string())
file.write("\n")
Maurice Raybaud
committed
# sel = renderable_objects(scene) #removed for booleans
file.write(
"//----------------------------------------------\n"
"//--Exported with POV-Ray exporter for Blender--\n"
"//----------------------------------------------\n\n"
)
file.write("#version 3.7;\n")
file.write(
"#declare Default_texture = texture{pigment {rgb 0.8} "
"finish {brilliance 3.8} }\n\n"
)
file.write("\n//--Global settings--\n\n")
file.write("\n//--Custom Code--\n\n")
exportCustomCode()
if comments:
file.write("\n//--Patterns Definitions--\n\n")
LocalPatternNames = []
for texture in bpy.data.textures: # ok?
currentPatName = string_strip_hyphen(
bpy.path.clean_name(texture.name)
)
# string_strip_hyphen(patternNames[texture.name]) #maybe instead of the above
# use above list to prevent writing texture instances several times and assign in mats?
if (
texture.type not in {'NONE', 'IMAGE'}
and texture.pov.tex_pattern_type == 'emulator'
) or (
texture.type in {'NONE', 'IMAGE'}
and texture.pov.tex_pattern_type != 'emulator'
):
Maurice Raybaud
committed
file.write("\n#declare PAT_%s = \n" % currentPatName)
file.write(shading.exportPattern(texture, string_strip_hyphen))
file.write("\n//--Background--\n\n")
file.write("\n//--Cameras--\n\n")
file.write("\n//--Lamps--\n\n")
for ob in bpy.data.objects:
if ob.type == 'MESH':
for mod in ob.modifiers:
if mod.type == 'BOOLEAN':
if mod.object not in csg_list:
csg_list.append(mod.object)
if csg_list != []:
csg = False
sel = no_renderable_objects(scene)
exportMeshes(scene, sel, csg)
csg = True
sel = renderable_objects(scene)
exportLamps(
[L for L in sel if (L.type == 'LIGHT' and L.pov.object_as != 'RAINBOW')]
)
if comments:
file.write("\n//--Rainbows--\n\n")
exportRainbows(
[L for L in sel if (L.type == 'LIGHT' and L.pov.object_as == 'RAINBOW')]
)
if comments:
file.write("\n//--Special Curves--\n\n")
for c in sel:
if c.is_modified(scene, 'RENDER'):
continue # don't export as pov curves objects with modifiers, but as mesh
elif c.type == 'CURVE' and (
c.pov.curveshape in {'lathe', 'sphere_sweep', 'loft', 'birail'}
):
exportCurves(scene, c)
file.write("\n//--Material Definitions--\n\n")
# write a default pigment for objects with no material (comment out to show black)
Maurice Raybaud
committed
file.write("#default{ pigment{ color srgb 0.8 }}\n")
# Convert all materials to strings we can access directly per vertex.
# exportMaterials()
shading.writeMaterial(
using_uberpov,
DEF_MAT_NAME,
scene,
tabWrite,
safety,
comments,
uniqueName,
materialNames,
None,
) # default material
if material.pov.material_use_nodes:
ntree = material.node_tree
povMatName = string_strip_hyphen(
bpy.path.clean_name(material.name)
)
if len(ntree.nodes) == 0:
file.write(
'#declare %s = texture {%s}\n' % (povMatName, color)
)