Newer
Older
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
Maurice Raybaud
committed
else:
idx = uniqueNormals[faces_normals[fi]][0]
if linebreaksinlists:
file.write(",\n")
file.write(
tabStr
+ "<%d,%d,%d>" % (idx, idx, idx)
) # vert count
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],
)
)
Maurice Raybaud
committed
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")
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
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
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 (
): # risk to write several sky_spheres but maybe ok.
if t:
tex = bpy.data.textures[t.texture]
if tex.type is not None:
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
# XXX No enable checkbox for world textures yet (report it?)
# if t and tex.type == 'IMAGE' and t.use:
if tex.type == 'IMAGE':
image_filename = path_image(tex.image)
if tex.image.filepath != image_filename:
tex.image.filepath = image_filename
if image_filename != "" and t.use_map_blend:
texturesBlend = image_filename
# colvalue = t.default_value
t_blend = t
# 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/
# Replace 4/3 by the ratio of each image found by some custom or existing
# function
# mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees" \
# "(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 = ""
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
# Further Scale by 2 and translate by -1 are
# 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,
)
)
# 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))
# 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" % (tex.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")
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
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") #Switch below as soon as 3.8 beta gets easy linked
#file.write("#version 3.8;\n")
file.write(
"#declare Default_texture = texture{pigment {rgb 0.8} "
"finish {brilliance 3.8} }\n\n"
)
file.write("\n//--Global settings--\n\n")