Newer
Older
# 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")
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:
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)
Maurice Raybaud
committed
else:
# 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Face indices
tabWrite("face_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, f in enumerate(me_faces):
fv = faces_verts[fi]
material_index = f.material_index
indices = (0, 1, 2), (0, 2, 3)
Maurice Raybaud
committed
else:
indices = ((0, 1, 2),)
if vcol_layer:
col = vcol_layer[fi]
if len(fv) == 4:
cols = col.color1, col.color2, col.color3, col.color4
cols = col.color1, col.color2, col.color3
if not me_materials or me_materials[material_index] is None: # No materials
for i1, i2, i3 in indices:
if linebreaksinlists:
file.write(",\n")
# vert count
file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3]))
file.write(", ")
file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count
Maurice Raybaud
committed
else:
material = me_materials[material_index]
for i1, i2, i3 in indices:
ci1 = ci2 = ci3 = f.material_index
if me.vertex_colors: #and material.use_vertex_color_paint:
# Color per vertex - vertex color
col1 = cols[i1]
col2 = cols[i2]
col3 = cols[i3]
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.subsurface_scattering.use:
diffuse_color = [i * j for i, j in
zip(material.subsurface_scattering.color[:],
material.diffuse_color[:])]
else:
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[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>, %d,%d,%d" % \
(fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
Maurice Raybaud
committed
file.write("\n")
tabWrite("}\n")
Maurice Raybaud
committed
# normal_indices indices
tabWrite("normal_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
Maurice Raybaud
committed
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
for i1, i2, i3 in indices:
if me_faces[fi].use_smooth:
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[i1]]][0],\
uniqueNormals[verts_normals[fv[i2]]][0],\
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[i1]]][0],\
uniqueNormals[verts_normals[fv[i2]]][0],\
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
idx = uniqueNormals[faces_normals[fi]][0]
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vertcount
else:
file.write(", ")
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) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
uv = uv_layer[fi]
if len(faces_verts[fi]) == 4:
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:], uv.uv[3][:]
else:
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:]
for i1, i2, i3 in indices:
if linebreaksinlists:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (
uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
uniqueUVs[uvs[i3]][0]))
else:
file.write(", ")
file.write("<%d,%d,%d>" % (
uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
uniqueUVs[uvs[i3]][0]))
file.write("\n")
tabWrite("}\n")
if me.materials:
try:
material = me.materials[0] # dodgy
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#Importance for radiosity sampling added here:
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
tabWrite("}\n") # End of mesh block
bpy.data.meshes.remove(me)
Maurice Raybaud
committed
duplidata_ref = []
for ob in sel:
#matrix = global_matrix * ob.matrix_world
if ob.is_duplicator:
tabWrite("\n//--DupliObjects in %s--\n\n"% ob.name)
ob.dupli_list_create(scene)
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)))
Maurice Raybaud
committed
else:
dup = "#declare DATA%s = union{\n" %(string_strip_hyphen(bpy.path.clean_name(ob.name)))
for eachduplicate in ob.dupli_list:
duplidataname = "OB"+string_strip_hyphen(bpy.path.clean_name(bpy.data.objects[eachduplicate.object.name].data.name))
dup += ("\tobject {\n\t\tDATA%s\n\t\t%s\t}\n" %(string_strip_hyphen(bpy.path.clean_name(bpy.data.objects[eachduplicate.object.name].data.name)), MatrixAsPovString(ob.matrix_world.inverted() * eachduplicate.matrix)))
#add object to a list so that it is not rendered for some dupli_types
if ob.dupli_type not in {'GROUP'} and duplidataname not in duplidata_ref:
duplidata_ref.append(duplidataname) #older key [string_strip_hyphen(bpy.path.clean_name("OB"+ob.name))]
dup += "}\n"
ob.dupli_list_clear()
tabWrite(dup)
else:
continue
print(duplidata_ref)
Bastien Montagne
committed
for data_name, inst in data_ref.items():
for ob_name, matrix_str in inst:
Maurice Raybaud
committed
if ob_name not in duplidata_ref: #.items() for a dictionary
tabWrite("\n//----Blender Object Name:%s----\n" % ob_name)
tabWrite("object { \n")
tabWrite("%s\n" % data_name)
tabWrite("%s\n" % matrix_str)
tabWrite("}\n")
Bastien Montagne
committed
render = scene.render
matrix = global_matrix * camera.matrix_world
#############Maurice####################################
#These lines added to get sky gradient (visible with PNG output)
if world:
#For simple flat background:
if not world.use_sky_blend:
Bastien Montagne
committed
# Non fully transparent background could premultiply alpha and avoid anti-aliasing
# display issue:
if render.alpha_mode == 'TRANSPARENT':
Bastien Montagne
committed
tabWrite("background {rgbt<%.3g, %.3g, %.3g, 0.75>}\n" % \
(world.horizon_color[:]))
#Currently using no alpha with Sky option:
elif render.alpha_mode == 'SKY':
tabWrite("background {rgbt<%.3g, %.3g, %.3g, 0>}\n" % (world.horizon_color[:]))
# XXX Does not exists anymore
#else:
#tabWrite("background {rgbt<%.3g, %.3g, %.3g, 1>}\n" % (world.horizon_color[:]))
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:
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:
texturesBlend = image_filename
#colvalue = t.default_value
t_blend = t
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" \
# "(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.y),
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")
Bastien Montagne
committed
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
Maurice Raybaud
committed
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.horizon_color[:]))
#tabWrite("[1.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.zenith_color[:]))
if render.alpha_mode == 'TRANSPARENT':
tabWrite("[0.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n" % (world.horizon_color[:]))
Bastien Montagne
committed
# aa premult not solved with transmit 1
tabWrite("[1.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n" % (world.zenith_color[:]))
tabWrite("[0.0 rgbt<%.3g, %.3g, %.3g, 0>]\n" % (world.horizon_color[:]))
tabWrite("[1.0 rgbt<%.3g, %.3g, %.3g, 0>]\n" % (world.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'
Maurice Raybaud
committed
#if world.light_settings.use_indirect_light:
Bastien Montagne
committed
# scene.pov.radio_enable=1
Bastien Montagne
committed
# Maybe change the above to a funtion copyInternalRenderer settings when
# user pushes a button, then:
#scene.pov.radio_enable = world.light_settings.use_indirect_light
# and other such translations but maybe this would not be allowed either?
###############################################################
tabWrite("fog {\n")
tabWrite("distance %.6f\n" % mist.depth)
Bastien Montagne
committed
tabWrite("color rgbt<%.3g, %.3g, %.3g, %.3g>\n" % \
(*world.horizon_color, 1.0 - mist.intensity))
#tabWrite("fog_offset %.6f\n" % mist.start)
#tabWrite("fog_alt 5\n")
#tabWrite("turbulence 0.2\n")
#tabWrite("turb_depth 0.3\n")
tabWrite("fog_type 1\n")
tabWrite("}\n")
Bastien Montagne
committed
if scene.pov.media_enable:
tabWrite("media {\n")
Bastien Montagne
committed
tabWrite("scattering { 1, rgb <%.4g, %.4g, %.4g>}\n" % scene.pov.media_color[:])
tabWrite("samples %.d\n" % scene.pov.media_samples)
tabWrite("}\n")
tabWrite("global_settings {\n")
tabWrite("assumed_gamma 1.0\n")
Bastien Montagne
committed
tabWrite("max_trace_level %d\n" % scene.pov.max_trace_level)
Maurice Raybaud
committed
if scene.pov.charset != 'ascii':
file.write(" charset %s\n"%scene.pov.charset)
if scene.pov.global_settings_advanced:
if scene.pov.adc_bailout_enable and scene.pov.radio_enable == False:
file.write(" adc_bailout %.6f\n"%scene.pov.adc_bailout)
if scene.pov.ambient_light_enable:
file.write(" ambient_light <%.6f,%.6f,%.6f>\n"%scene.pov.ambient_light[:])
if scene.pov.irid_wavelength_enable:
file.write(" irid_wavelength <%.6f,%.6f,%.6f>\n"%scene.pov.irid_wavelength[:])
if scene.pov.max_intersections_enable:
file.write(" max_intersections %s\n"%scene.pov.max_intersections)
if scene.pov.number_of_waves_enable:
file.write(" number_of_waves %s\n"%scene.pov.number_of_waves)
if scene.pov.noise_generator_enable:
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.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.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.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.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)):
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))
tabWrite("}\n")
oncePhotons = 0
tabWrite("}\n")
Maurice Raybaud
committed
def exportCustomCode():
# 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)
Bastien Montagne
committed
file.write("//----------------------------------------------\n" \
"//--Exported with POV-Ray exporter for Blender--\n" \
"//----------------------------------------------\n\n")
file.write("#version 3.7;\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?
if texture.users > 0:
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?
Maurice Raybaud
committed
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")
exportLamps([L for L in sel if (L.type == 'LAMP' and L.pov.object_as != 'RAINBOW')])
if comments:
file.write("\n//--Rainbows--\n\n")
exportRainbows([L for L in sel if (L.type == 'LAMP' 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'}):
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.
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))
else:
shading.write_nodes(scene,povMatName,ntree,file)
for node in ntree.nodes:
if node:
if node.bl_idname == "PovrayOutputNode":
if node.inputs["Texture"].is_linked:
for link in ntree.links:
if link.to_node.bl_idname == "PovrayOutputNode":
povMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName
else:
file.write('#declare %s = texture {%s}\n'%(povMatName,color))
else:
shading.writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material)
# attributes are all the variables needed by the other python file...
file.write("\n")
exportMeta([m for m in sel if m.type == 'META'])
file.write("//--Mesh objects--\n")
Bastien Montagne
committed
exportMeshes(scene, sel)
#What follow used to happen here:
#exportCamera()
#exportWorld(scene.world)
#exportGlobalSettings(scene)
# MR:..and the order was important for implementing pov 3.7 baking
Bastien Montagne
committed
# (mesh camera) comment for the record
Constantin Rahn
committed
# CR: Baking should be a special case than. If "baking", than we could change the order.
#print("pov file closed %s" % file.closed)
#print("pov file closed %s" % file.closed)
def write_pov_ini(scene, filename_ini, filename_log, filename_pov, filename_image):
feature_set = bpy.context.user_preferences.addons[__package__].preferences.branch_feature_set_povray
using_uberpov = (feature_set=='uberpov')
#scene = bpy.data.scenes[0]
x = int(render.resolution_x * render.resolution_percentage * 0.01)
y = int(render.resolution_y * render.resolution_percentage * 0.01)
file.write("Version=3.7\n")
#write povray text stream to temporary file of same name with _log suffix
#file.write("All_File='%s'\n" % filename_log)
# DEBUG.OUT log if none specified:
file.write("All_File=1\n")
file.write("Input_File_Name='%s'\n" % filename_pov)
file.write("Output_File_Name='%s'\n" % filename_image)
file.write("Width=%d\n" % x)
file.write("Height=%d\n" % y)
# Border render.
if render.use_border:
file.write("Start_Column=%4g\n" % render.border_min_x)
file.write("End_Column=%4g\n" % (render.border_max_x))
file.write("Start_Row=%4g\n" % (1.0 - render.border_max_y))
file.write("End_Row=%4g\n" % (1.0 - render.border_min_y))
file.write("Bounding_Method=2\n") # The new automatic BSP is faster in most scenes
Bastien Montagne
committed
# Activated (turn this back off when better live exchange is done between the two programs
# (see next comment)
file.write("Display=1\n")
file.write("Pause_When_Done=0\n")
Bastien Montagne
committed
# PNG, with POV-Ray 3.7, can show background color with alpha. In the long run using the
# POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
file.write("Output_File_Type=N\n")
#file.write("Output_File_Type=T\n") # TGA, best progressive loading
file.write("Output_Alpha=1\n")
Bastien Montagne
committed
if scene.pov.antialias_enable:
# method 2 (recursive) with higher max subdiv forced because no mipmapping in POV-Ray
# needs higher sampling.
# aa_mapping = {"5": 2, "8": 3, "11": 4, "16": 5}
if using_uberpov:
method = {"0": 1, "1": 2, "2": 3}
else:
method = {"0": 1, "1": 2, "2": 2}
file.write("Antialias=on\n")
Bastien Montagne
committed
file.write("Antialias_Depth=%d\n" % scene.pov.antialias_depth)
file.write("Antialias_Threshold=%.3g\n" % scene.pov.antialias_threshold)
if using_uberpov and scene.pov.antialias_method == '2':
file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
file.write("Antialias_Confidence=%.3g\n" % scene.pov.antialias_confidence)
else:
file.write("Sampling_Method=%s\n" % method[scene.pov.antialias_method])
Bastien Montagne
committed
file.write("Antialias_Gamma=%.3g\n" % scene.pov.antialias_gamma)
if scene.pov.jitter_enable:
file.write("Jitter=on\n")
Bastien Montagne
committed
file.write("Jitter_Amount=%3g\n" % scene.pov.jitter_amount)
file.write("Jitter=off\n") # prevent animation flicker
file.write("Antialias=off\n")
#print("ini file closed %s" % file.closed)
#print("ini file closed %s" % file.closed)
bl_label = "POV-Ray 3.7"
Campbell Barton
committed
@staticmethod
def _locate_binary():
addon_prefs = bpy.context.user_preferences.addons[__package__].preferences
# Use the system preference if its set.
pov_binary = addon_prefs.filepath_povray
if pov_binary:
if os.path.exists(pov_binary):
return pov_binary
else:
print("User Preferences path to povray %r NOT FOUND, checking $PATH" % pov_binary)
Campbell Barton
committed
# Windows Only
# assume if there is a 64bit binary that the user has a 64bit capable OS
if sys.platform[:3] == "win":
import winreg
win_reg_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
"Software\\POV-Ray\\v3.7\\Windows")
Campbell Barton
committed
win_home = winreg.QueryValueEx(win_reg_key, "Home")[0]
# First try 64bits UberPOV
pov_binary = os.path.join(win_home, "bin", "uberpov64.exe")
if os.path.exists(pov_binary):
return pov_binary
# Then try 64bits POV
Campbell Barton
committed
pov_binary = os.path.join(win_home, "bin", "pvengine64.exe")
if os.path.exists(pov_binary):
return pov_binary
# Then try 32bits UberPOV
pov_binary = os.path.join(win_home, "bin", "uberpov32.exe")
if os.path.exists(pov_binary):
# Then try 32bits POV
Campbell Barton
committed
pov_binary = os.path.join(win_home, "bin", "pvengine.exe")
if os.path.exists(pov_binary):
return pov_binary
# search the path all os's
pov_binary_default = "povray"
os_path_ls = os.getenv("PATH").split(':') + [""]
for dir_name in os_path_ls:
pov_binary = os.path.join(dir_name, pov_binary_default)
if os.path.exists(pov_binary):
return pov_binary
return ""
def _export(self, scene, povPath, renderImagePath):
Bastien Montagne
committed
if scene.pov.tempfiles_enable:
self._temp_file_in = tempfile.NamedTemporaryFile(suffix=".pov", delete=False).name
Bastien Montagne
committed
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
# POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".png", delete=False).name
#self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".tga", delete=False).name
self._temp_file_ini = tempfile.NamedTemporaryFile(suffix=".ini", delete=False).name
self._temp_file_log = os.path.join(tempfile.gettempdir(), "alltext.out")
else:
self._temp_file_in = povPath + ".pov"
Bastien Montagne
committed
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
# POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
self._temp_file_out = renderImagePath + ".png"
#self._temp_file_out = renderImagePath + ".tga"
self._temp_file_ini = povPath + ".ini"
logPath = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/')
self._temp_file_log = os.path.join(logPath, "alltext.out")
'''
self._temp_file_in = "/test.pov"
Bastien Montagne
committed
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
# POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
self._temp_file_out = "/test.png"
#self._temp_file_out = "/test.tga"
self._temp_file_ini = "/test.ini"
'''
Maurice Raybaud
committed
if scene.pov.text_block == "":
def info_callback(txt):
self.update_stats("", "POV-Ray 3.7: " + txt)
Maurice Raybaud
committed
# os.makedirs(user_dir, exist_ok=True) # handled with previews
os.makedirs(preview_dir, exist_ok=True)
Maurice Raybaud
committed
write_pov(self._temp_file_in, scene, info_callback)
else:
pass
Constantin Rahn
committed
def _render(self, scene):
os.remove(self._temp_file_out) # so as not to load the old file
Campbell Barton
committed
pov_binary = PovrayRender._locate_binary()
if not pov_binary:
print("POV-Ray 3.7: could not execute povray, possibly POV-Ray isn't installed")
return False
write_pov_ini(scene, self._temp_file_ini, self._temp_file_log, self._temp_file_in, self._temp_file_out)
print ("***-STARTING-***")
Doug Hammond
committed
extra_args = []
Bastien Montagne
committed
if scene.pov.command_line_switches != "":
for newArg in scene.pov.command_line_switches.split(" "):
Constantin Rahn
committed
extra_args.append(newArg)
self._is_windows = False
self._is_windows = True
if"/EXIT" not in extra_args and not scene.pov.pov_editor:
extra_args.append("/EXIT")
Doug Hammond
committed
else:
Campbell Barton
committed
# added -d option to prevent render window popup which leads to segfault on linux
extra_args.append("-d")
Campbell Barton
committed
# Start Rendering!
try:
self._process = subprocess.Popen([pov_binary, self._temp_file_ini] + extra_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
# TODO, report api
print("POV-Ray 3.7: could not execute '%s'" % pov_binary)
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
Campbell Barton
committed
else:
print("Engine ready!...")
Campbell Barton
committed
print("Command line arguments passed: " + str(extra_args))
return True
# Now that we have a valid process
def _cleanup(self):
for f in (self._temp_file_in, self._temp_file_ini, self._temp_file_out):
for i in range(5):
try:
os.unlink(f)
break
except OSError:
# Wait a bit before retrying file might be still in use by Blender,
# and Windows does not know how to delete a file in use!
time.sleep(self.DELAY)
for i in unpacked_images:
for c in range(5):
try:
os.unlink(i)
break
except OSError:
# Wait a bit before retrying file might be still in use by Blender,
# and Windows does not know how to delete a file in use!
time.sleep(self.DELAY)
x = int(r.resolution_x * r.resolution_percentage * 0.01)
y = int(r.resolution_y * r.resolution_percentage * 0.01)
Maurice Raybaud
committed
print("***INITIALIZING***")
# This makes some tests on the render, returning True if all goes good, and False if
# it was finished one way or the other.
# It also pauses the script (time.sleep())
def _test_wait():
time.sleep(self.DELAY)
# User interrupts the rendering
print("***POV INTERRUPTED***")
return False
Doug Hammond
committed
poll_result = self._process.poll()
# POV process is finisehd, one way or the other
if poll_result < 0:
print("***POV PROCESS FAILED : %s ***" % poll_result)
self.update_stats("", "POV-Ray 3.7: Failed")
return False
return True
Maurice Raybaud
committed
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
if scene.pov.text_block !="":
if scene.pov.tempfiles_enable:
self._temp_file_in = tempfile.NamedTemporaryFile(suffix=".pov", delete=False).name
self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".png", delete=False).name
#self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".tga", delete=False).name
self._temp_file_ini = tempfile.NamedTemporaryFile(suffix=".ini", delete=False).name
self._temp_file_log = os.path.join(tempfile.gettempdir(), "alltext.out")
else:
povPath = scene.pov.text_block
renderImagePath = os.path.splitext(povPath)[0]
self._temp_file_out =os.path.join(preview_dir, renderImagePath )
self._temp_file_in = os.path.join(preview_dir, povPath)
self._temp_file_ini = os.path.join(preview_dir, (os.path.splitext(self._temp_file_in)[0]+".INI"))
self._temp_file_log = os.path.join(preview_dir, "alltext.out")
'''
try:
os.remove(self._temp_file_in) # so as not to load the old file
except OSError:
pass
'''
print(scene.pov.text_block)
text = bpy.data.texts[scene.pov.text_block]
file=open("%s"%self._temp_file_in,"w")
# Why are the newlines needed?
file.write("\n")
file.write(text.as_string())
file.write("\n")
file.close()
# has to be called to update the frame on exporting animations
scene.frame_set(scene.frame_current)
pov_binary = PovrayRender._locate_binary()
if not pov_binary:
print("POV-Ray 3.7: could not execute povray, possibly POV-Ray isn't installed")
return False
# start ini UI options export
self.update_stats("", "POV-Ray 3.7: Exporting ini options from Blender")
write_pov_ini(scene, self._temp_file_ini, self._temp_file_log, self._temp_file_in, self._temp_file_out)
print ("***-STARTING-***")
extra_args = []
Maurice Raybaud
committed
if scene.pov.command_line_switches != "":
for newArg in scene.pov.command_line_switches.split(" "):
extra_args.append(newArg)
if sys.platform[:3] == "win":
if"/EXIT" not in extra_args and not scene.pov.pov_editor:
extra_args.append("/EXIT")
else:
Maurice Raybaud
committed
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
# added -d option to prevent render window popup which leads to segfault on linux
extra_args.append("-d")
# Start Rendering!
try:
_process = subprocess.Popen([pov_binary, self._temp_file_ini] + extra_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
# TODO, report api
print("POV-Ray 3.7: could not execute '%s'" % pov_binary)
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
else:
print("Engine ready!...")
print("Command line arguments passed: " + str(extra_args))
#return True
self.update_stats("", "POV-Ray 3.7: Parsing File")
# Indented in main function now so repeated here but still not working
# to bring back render result to its buffer
if os.path.exists(self._temp_file_out):
xmin = int(r.border_min_x * x)
ymin = int(r.border_min_y * y)
xmax = int(r.border_max_x * x)
ymax = int(r.border_max_y * y)
result = self.begin_result(0, 0, x, y)
lay = result.layers[0]
time.sleep(self.DELAY)
try:
lay.load_from_file(self._temp_file_out)
except RuntimeError:
print("***POV ERROR WHILE READING OUTPUT FILE***")
self.end_result(result)
#print(self._temp_file_log) #bring the pov log to blender console with proper path?
with open(self._temp_file_log) as f: # The with keyword automatically closes the file when you are done
print(f.read())
self.update_stats("", "")
if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable:
self._cleanup()
else:
Maurice Raybaud
committed
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
##WIP output format
## if r.image_settings.file_format == 'OPENEXR':
## fformat = 'EXR'
## render.image_settings.color_mode = 'RGBA'
## else:
## fformat = 'TGA'
## r.image_settings.file_format = 'TARGA'
## r.image_settings.color_mode = 'RGBA'
blendSceneName = bpy.data.filepath.split(os.path.sep)[-1].split(".")[0]
povSceneName = ""
povPath = ""
renderImagePath = ""
# has to be called to update the frame on exporting animations
scene.frame_set(scene.frame_current)
if not scene.pov.tempfiles_enable:
# check paths
povPath = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/')
if povPath == "":
if bpy.data.is_saved:
povPath = bpy.path.abspath("//")
else:
Maurice Raybaud
committed
povPath = tempfile.gettempdir()
elif povPath.endswith("/"):
if povPath == "/":
povPath = bpy.path.abspath("//")
else:
povPath = bpy.path.abspath(scene.pov.scene_path)
if not os.path.exists(povPath):
try:
os.makedirs(povPath)
except:
import traceback
traceback.print_exc()
print("POV-Ray 3.7: Cannot create scenes directory: %r" % povPath)
self.update_stats("", "POV-Ray 3.7: Cannot create scenes directory %r" % \
povPath)
time.sleep(2.0)
#return