Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Raybaud <mauriceraybaud@hotmail.fr>2016-08-23 20:39:13 +0300
committerMaurice Raybaud <mauriceraybaud@hotmail.fr>2016-08-23 20:39:13 +0300
commitd20975b80900f4e2a13d792274b989cf5cc4880f (patch)
tree99a43dadad733ffe5e3ffaef03a89f312400bf4d /render_povray/render.py
parent8b21e5df055d68aa3666e283ac224992ee0eeec5 (diff)
*added: write pov console to a log read by Blender console
*fix: area_illumination syntax updated to fix bug in area lights *fix:sphere sweep was buggy (bezier curve would'nt export) *several curves in one blender object can now export Thanks Lanuhum *fix:hair with no material slot would'nt export *fixemodifier like subsurf or mirror over curves wouldn't export, now trying to convert to mesh *fix:meshes with 0 vertices wrote a bad file, now create a dummy 0 radius sphere *fix: export visible layer only was broken
Diffstat (limited to 'render_povray/render.py')
-rw-r--r--render_povray/render.py264
1 files changed, 205 insertions, 59 deletions
diff --git a/render_povray/render.py b/render_povray/render.py
index 4d6d7e6b..74f720f3 100644
--- a/render_povray/render.py
+++ b/render_povray/render.py
@@ -29,7 +29,7 @@ import random
import platform#
import subprocess#
from bpy.types import(Operator)
-
+from imghdr import what #imghdr is a python lib to identify image file types
from . import df3 # for smoke rendering
from . import shading # for BI POV haders emulation
@@ -52,9 +52,11 @@ def imageFormat(imgF):
'HDR': "hdr",
}.get(os.path.splitext(imgF)[-1].upper(), "")
- #if not ext:
- #print(" WARNING: texture image has no extension") #too verbose
-
+ if not ext:
+ #maybe add a check for if path exists here?
+ print(" WARNING: texture image has no extension") #too verbose
+
+ ext = what(imgF) #imghdr is a python lib to identify image file types
return ext
@@ -182,12 +184,12 @@ def safety(name, Level):
##############end safety string name material
##############################EndSF###########################
-def is_renderable(ob):
- return (ob.hide_render==False)
+def is_renderable(scene, ob):
+ return (ob.is_visible(scene) and not ob.hide_render)
-def renderable_objects():
- return [ob for ob in bpy.data.objects if is_renderable(ob)]
+def renderable_objects(scene):
+ return [ob for ob in bpy.data.objects if is_renderable(scene, ob)]
tabLevel = 0
@@ -561,7 +563,6 @@ def write_pov(filename, scene=None, info_callback=None):
tabWrite("point_at <0, 0, -1>\n") # *must* be after 'parallel'
elif lamp.type == 'AREA':
- tabWrite("area_illumination\n")
tabWrite("fade_distance %.6f\n" % (lamp.distance / 2.0))
# Area lights have no falloff type, so always use blenders lamp quad equivalent
# for those?
@@ -577,6 +578,7 @@ def write_pov(filename, scene=None, info_callback=None):
tabWrite("area_light <%.6f,0,0>,<0,%.6f,0> %d, %d\n" % \
(size_x, size_y, samples_x, samples_y))
+ tabWrite("area_illumination\n")
if lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
if lamp.use_jitter:
tabWrite("jitter\n")
@@ -694,6 +696,94 @@ def write_pov(filename, scene=None, info_callback=None):
matrix=global_matrix*ob.matrix_world
bezier_sweep = False
if ob.pov.curveshape == 'sphere_sweep':
+ #inlined spheresweep macro, which itself calls Shapes.inc:
+ file.write(' #include "shapes.inc"\n')
+
+ file.write(' #macro Shape_Bezierpoints_Sphere_Sweep(_merge_shape, _resolution, _points_array, _radius_array)\n')
+ file.write(' //input adjusting and inspection\n')
+ file.write(' #if(_resolution <= 1)\n')
+ file.write(' #local res = 1;\n')
+ file.write(' #else\n')
+ file.write(' #local res = int(_resolution);\n')
+ file.write(' #end\n')
+ file.write(' #if(dimensions(_points_array) != 1 | dimensions(_radius_array) != 1)\n')
+ file.write(' #error ""\n')
+ file.write(' #elseif(div(dimension_size(_points_array,1),4) - dimension_size(_points_array,1)/4 != 0)\n')
+ file.write(' #error ""\n')
+ file.write(' #elseif(dimension_size(_points_array,1) != dimension_size(_radius_array,1))\n')
+ file.write(' #error ""\n')
+ file.write(' #else\n')
+ file.write(' #local n_of_seg = div(dimension_size(_points_array,1), 4);\n')
+ file.write(' #local ctrl_pts_array = array[n_of_seg]\n')
+ file.write(' #local ctrl_rs_array = array[n_of_seg]\n')
+ file.write(' #for(i, 0, n_of_seg-1)\n')
+ file.write(' #local ctrl_pts_array[i] = array[4] {_points_array[4*i], _points_array[4*i+1], _points_array[4*i+2], _points_array[4*i+3]}\n')
+ file.write(' #local ctrl_rs_array[i] = array[4] {abs(_radius_array[4*i]), abs(_radius_array[4*i+1]), abs(_radius_array[4*i+2]), abs(_radius_array[4*i+3])}\n')
+ file.write(' #end\n')
+ file.write(' #end\n')
+
+ file.write(' //drawing\n')
+ file.write(' #local mockup1 =\n')
+ file.write(' #if(_merge_shape) merge{ #else union{ #end\n')
+ file.write(' #for(i, 0, n_of_seg-1)\n')
+ file.write(' #local has_head = true;\n')
+ file.write(' #if(i = 0)\n')
+ file.write(' #if(vlength(ctrl_pts_array[i][0]-ctrl_pts_array[n_of_seg-1][3]) = 0 & ctrl_rs_array[i][0]-ctrl_rs_array[n_of_seg-1][3] <= 0)\n')
+ file.write(' #local has_head = false;\n')
+ file.write(' #end\n')
+ file.write(' #else\n')
+ file.write(' #if(vlength(ctrl_pts_array[i][0]-ctrl_pts_array[i-1][3]) = 0 & ctrl_rs_array[i][0]-ctrl_rs_array[i-1][3] <= 0)\n')
+ file.write(' #local has_head = false;\n')
+ file.write(' #end\n')
+ file.write(' #end\n')
+ file.write(' #if(has_head = true)\n')
+ file.write(' sphere{\n')
+ file.write(' ctrl_pts_array[i][0], ctrl_rs_array[i][0]\n')
+ file.write(' }\n')
+ file.write(' #end\n')
+ file.write(' #local para_t = (1/2)/res;\n')
+ file.write(' #local this_point = ctrl_pts_array[i][0]*pow(1-para_t,3) + ctrl_pts_array[i][1]*3*pow(1-para_t,2)*para_t + ctrl_pts_array[i][2]*3*(1-para_t)*pow(para_t,2) + ctrl_pts_array[i][3]*pow(para_t,3);\n')
+ file.write(' #local this_radius = ctrl_rs_array[i][0]*pow(1-para_t,3) + ctrl_rs_array[i][1]*3*pow(1-para_t,2)*para_t + ctrl_rs_array[i][2]*3*(1-para_t)*pow(para_t,2) + ctrl_rs_array[i][3]*pow(para_t,3);\n')
+ file.write(' #if(vlength(this_point-ctrl_pts_array[i][0]) > abs(this_radius-ctrl_rs_array[i][0]))\n')
+ file.write(' object{\n')
+ file.write(' Connect_Spheres(ctrl_pts_array[i][0], ctrl_rs_array[i][0], this_point, this_radius)\n')
+ file.write(' }\n')
+ file.write(' #end\n')
+ file.write(' sphere{\n')
+ file.write(' this_point, this_radius\n')
+ file.write(' }\n')
+ file.write(' #for(j, 1, res-1)\n')
+ file.write(' #local last_point = this_point;\n')
+ file.write(' #local last_radius = this_radius;\n')
+ file.write(' #local para_t = (1/2+j)/res;\n')
+ file.write(' #local this_point = ctrl_pts_array[i][0]*pow(1-para_t,3) + ctrl_pts_array[i][1]*3*pow(1-para_t,2)*para_t + ctrl_pts_array[i][2]*3*(1-para_t)*pow(para_t,2) + ctrl_pts_array[i][3]*pow(para_t,3);\n')
+ file.write(' #local this_radius = ctrl_rs_array[i][0]*pow(1-para_t,3) + ctrl_rs_array[i][1]*3*pow(1-para_t,2)*para_t + ctrl_rs_array[i][2]*3*(1-para_t)*pow(para_t,2) + ctrl_rs_array[i][3]*pow(para_t,3);\n')
+ file.write(' #if(vlength(this_point-last_point) > abs(this_radius-last_radius))\n')
+ file.write(' object{\n')
+ file.write(' Connect_Spheres(last_point, last_radius, this_point, this_radius)\n')
+ file.write(' }\n')
+ file.write(' #end\n')
+ file.write(' sphere{\n')
+ file.write(' this_point, this_radius\n')
+ file.write(' }\n')
+ file.write(' #end\n')
+ file.write(' #local last_point = this_point;\n')
+ file.write(' #local last_radius = this_radius;\n')
+ file.write(' #local this_point = ctrl_pts_array[i][3];\n')
+ file.write(' #local this_radius = ctrl_rs_array[i][3];\n')
+ file.write(' #if(vlength(this_point-last_point) > abs(this_radius-last_radius))\n')
+ file.write(' object{\n')
+ file.write(' Connect_Spheres(last_point, last_radius, this_point, this_radius)\n')
+ file.write(' }\n')
+ file.write(' #end\n')
+ file.write(' sphere{\n')
+ file.write(' this_point, this_radius\n')
+ file.write(' }\n')
+ file.write(' #end\n')
+ file.write(' }\n')
+ file.write(' mockup1\n')
+ file.write(' #end\n')
+
for spl in ob.data.splines:
if spl.type == "BEZIER":
bezier_sweep = True
@@ -1387,30 +1477,49 @@ def write_pov(filename, scene=None, info_callback=None):
wpt = pt.co
tabWrite("<%.4g,%.4g>\n" %(wpt[0], wpt[1]))
if bezier_sweep:
- spl = ob.data.splines[0]
- points=spl.bezier_points
- lenCur = len(points)-1
- numPoints = lenCur*4
- if spl.use_cyclic_u:
- lenCur += 1
- numPoints += 4
- tabWrite("#declare %s_bezier_points = array[%s]{\n"%(dataname,numPoints))
- for i in range(lenCur):
- p1=points[i].co
- pR=points[i].handle_right
- end = i+1
- if spl.use_cyclic_u and i == (lenCur - 1):
- end = 0
- pL=points[end].handle_left
- p2=points[end].co
- line="<%.4g,%.4g,%.4f>"%(p1[0],p1[1],p1[2])
- line+="<%.4g,%.4g,%.4f>"%(pR[0],pR[1],pR[2])
- line+="<%.4g,%.4g,%.4f>"%(pL[0],pL[1],pL[2])
- line+="<%.4g,%.4g,%.4f>"%(p2[0],p2[1],p2[2])
- tabWrite("%s\n" %line)
- tabWrite("}\n")
- #tabWrite('#include "bezier_spheresweep.inc"\n') #now inlined
- tabWrite('#declare %s = object{Shape_Bezierpoints_Sphere_Sweep(%s, %s_bezier_points, %.4f) \n'%(dataname,ob.data.resolution_u,dataname,ob.data.bevel_depth))
+ for p in range(len(ob.data.splines)):
+ br = []
+ depth = ob.data.bevel_depth
+ spl = ob.data.splines[p]
+ points=spl.bezier_points
+ lenCur = len(points)-1
+ numPoints = lenCur*4
+ if spl.use_cyclic_u:
+ lenCur += 1
+ numPoints += 4
+ tabWrite("#declare %s_points_%s = array[%s]{\n"%(dataname,p,numPoints))
+ for i in range(lenCur):
+ p1=points[i].co
+ pR=points[i].handle_right
+ end = i+1
+ if spl.use_cyclic_u and i == (lenCur - 1):
+ end = 0
+ pL=points[end].handle_left
+ p2=points[end].co
+ r3 = points[end].radius * depth
+ r0 = points[i].radius * depth
+ r1 = 2/3*r0 + 1/3*r3
+ r2 = 1/3*r0 + 2/3*r3
+ br.append((r0,r1,r2,r3))
+ line="<%.4g,%.4g,%.4f>"%(p1[0],p1[1],p1[2])
+ line+="<%.4g,%.4g,%.4f>"%(pR[0],pR[1],pR[2])
+ line+="<%.4g,%.4g,%.4f>"%(pL[0],pL[1],pL[2])
+ line+="<%.4g,%.4g,%.4f>"%(p2[0],p2[1],p2[2])
+ tabWrite("%s\n" %line)
+ tabWrite("}\n")
+ tabWrite("#declare %s_radii_%s = array[%s]{\n"%(dataname,p,len(br)*4))
+ for Tuple in br:
+ tabWrite('%.4f,%.4f,%.4f,%.4f\n'%(Tuple[0],Tuple[1],Tuple[2],Tuple[3]))
+ tabWrite("}\n")
+ if len(ob.data.splines)== 1:
+ tabWrite('#declare %s = object{\n'%dataname)
+ tabWrite(' Shape_Bezierpoints_Sphere_Sweep(yes,%s, %s_points_%s, %s_radii_%s) \n'%(ob.data.resolution_u,dataname,p,dataname,p))
+ else:
+ tabWrite('#declare %s = union{\n'%dataname)
+ for p in range(len(ob.data.splines)):
+ tabWrite(' object{Shape_Bezierpoints_Sphere_Sweep(yes,%s, %s_points_%s, %s_radii_%s)} \n'%(ob.data.resolution_u,dataname,p,dataname,p))
+ #tabWrite('#include "bezier_spheresweep.inc"\n') #now inlined
+ # tabWrite('#declare %s = object{Shape_Bezierpoints_Sphere_Sweep(yes,%s, %s_bezier_points, %.4f) \n'%(dataname,ob.data.resolution_u,dataname,ob.data.bevel_depth))
if ob.pov.curveshape in {'loft'}:
tabWrite('object {MSM(%s,%s,"c",%s,"")\n'%(dataname,ob.pov.res_u,ob.pov.res_v))
if ob.pov.curveshape in {'birail'}:
@@ -1809,7 +1918,7 @@ def write_pov(filename, scene=None, info_callback=None):
if (pSys.settings.render_type == 'PATH') and mod.show_render and (pSys.name == mod.particle_system.name):
tstart = time.time()
texturedHair=0
- if ob.active_material is not None:
+ if ob.material_slots[pSys.settings.material - 1].material and ob.active_material is not None:
pmaterial = ob.material_slots[pSys.settings.material - 1].material
for th in pmaterial.texture_slots:
if th and th.use:
@@ -1853,12 +1962,12 @@ def write_pov(filename, scene=None, info_callback=None):
file.write('%i,\n' % (steps))
#changing world coordinates to object local coordinates by multiplying with inverted matrix
initCo = ob.matrix_world.inverted()*(pSys.co_hair(ob, pindex, 0))
- if ob.active_material is not None:
+ if ob.material_slots[pSys.settings.material - 1].material and ob.active_material is not None:
pmaterial = ob.material_slots[pSys.settings.material-1].material
for th in pmaterial.texture_slots:
if th and th.use and th.use_map_color_diffuse:
#treat POV textures as bitmaps
- if (th.texture.type == 'IMAGE' and th.texture.image and th.texture_coords == 'UV' and ob.data.uv_textures != None): # or (th.texture.pov.tex_pattern_type != 'emulator' and th.texture_coords == 'UV' and ob.data.uv_textures != None):
+ if (th.texture.type == 'IMAGE' and th.texture.image and th.texture_coords == 'UV' and ob.data.uv_textures is not None): # or (th.texture.pov.tex_pattern_type != 'emulator' and th.texture_coords == 'UV' and ob.data.uv_textures is not None):
image=th.texture.image
image_width = image.size[0]
image_height = image.size[1]
@@ -1909,7 +2018,6 @@ def write_pov(filename, scene=None, info_callback=None):
file.write('}\n')
# All but the final sphere_sweep (each array element) needs a terminating comma.
-
if pindex != totalNumberOfHairs:
file.write(',\n')
else:
@@ -1982,7 +2090,7 @@ def write_pov(filename, scene=None, info_callback=None):
#############################################
# Generating a name for object just like materials to be able to use it
# (baking for now or anything else).
- # XXX I don't understand that:&nbsp;if we are here, sel if a non-empty iterable,
+ # XXX I don't understand that if we are here, sel if a non-empty iterable,
# so this condition is always True, IMO -- mont29
if sel:
name_orig = "OB" + ob.name
@@ -2008,17 +2116,19 @@ def write_pov(filename, scene=None, info_callback=None):
matrix = global_matrix * ob.matrix_world
povdataname = store(scene, ob, name, dataname, matrix)
if povdataname is None:
- print("This is an instance")
+ print("This is an instance of " + name)
continue
- print("Writing Down First Occurence")
+ print("Writing Down First Occurence of " + name)
############################################Povray Primitives
# special exportCurves() function takes care of writing
- # lathe, sphere_sweep, birail, and loft
- if ob.type == 'CURVE' and (ob.pov.curveshape in
- {'lathe', 'sphere_sweep', 'loft'}):
- continue #Don't render proxy mesh, skip to next object
+ # lathe, sphere_sweep, birail, and loft except with modifiers
+ # converted to mesh
+ if not ob.is_modified(scene, 'RENDER'):
+ if ob.type == 'CURVE' and (ob.pov.curveshape in
+ {'lathe', 'sphere_sweep', 'loft'}):
+ continue #Don't render proxy mesh, skip to next object
if ob.pov.object_as == 'ISOSURFACE':
tabWrite("#declare %s = isosurface{ \n"% povdataname)
@@ -2380,13 +2490,23 @@ def write_pov(filename, scene=None, info_callback=None):
else:
try:
me = ob.to_mesh(scene, True, 'RENDER')
+
+ #XXX Here? identify the specific exception for mesh object with no data
+ #XXX So that we can write something for the dataname !
except:
- # happens when curves cant be made into meshes because of no-data
- continue
+ # also happens when curves cant be made into meshes because of no-data
+ continue
+
importance = ob.pov.importance_value
- me_materials = me.materials
- me_faces = me.tessfaces[:]
+ if me:
+ me_materials = me.materials
+ me_faces = me.tessfaces[:]
+ if len(me_faces)==0:
+ file.write("\n")
+ tabWrite("//dummy sphere to represent empty mesh location\n")
+ tabWrite("#declare %s =sphere {<0, 0, 0>,0 pigment{rgbt 1} no_image no_reflection no_radiosity photons{pass_through collect off} hollow}\n" % povdataname)
+
if not me or not me_faces:
continue
@@ -2721,9 +2841,10 @@ def write_pov(filename, scene=None, info_callback=None):
else:
shading.writeTextureInfluence(mater, materialNames,
LocalMaterialNames,
- path_image, imageFormat,
- imgMap, imgMapTransforms,
- tabWrite,
+ path_image, lampCount,
+ imageFormat, imgMap,
+ imgMapTransforms,
+ tabWrite, comments,
string_strip_hyphen,
safety, col, os, preview_dir, unpacked_images)
###################################################################
@@ -2740,10 +2861,20 @@ def write_pov(filename, scene=None, info_callback=None):
file.write(tabStr + "1")
else:
file.write(tabStr + "%s" % (len(vertCols))) # vert count
+
+
+
- # below "material" alias, changed to ob.active_material
- # because variable referenced before assignment
- if ob.active_material is not None:
+ # 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
+
+
+ if material and ob.active_material is not None:
if material.pov.replacement_text != "":
file.write("\n")
file.write(" texture{%s}\n" % material.pov.replacement_text)
@@ -3141,7 +3272,7 @@ def write_pov(filename, scene=None, info_callback=None):
file.write(txt.as_string())
file.write("\n")
- sel = renderable_objects()
+ sel = renderable_objects(scene)
if comments:
file.write("//----------------------------------------------\n" \
"//--Exported with POV-Ray exporter for Blender--\n" \
@@ -3169,7 +3300,7 @@ def write_pov(filename, scene=None, info_callback=None):
#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'):
file.write("\n#declare PAT_%s = \n" % currentPatName)
- file.write(shading.exportPattern(texture, string_strip_hyphen))
+ file.write(shading.exportPattern(texture, string_strip_hyphen))
file.write("\n")
if comments:
file.write("\n//--Background--\n\n")
@@ -3194,7 +3325,9 @@ def write_pov(filename, scene=None, info_callback=None):
if comments:
file.write("\n//--Special Curves--\n\n")
for c in sel:
- if c.type == 'CURVE' and (c.pov.curveshape in {'lathe','sphere_sweep','loft','birail'}):
+ 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)
@@ -3232,7 +3365,7 @@ def write_pov(filename, scene=None, info_callback=None):
#print("pov file closed %s" % file.closed)
-def write_pov_ini(scene, filename_ini, filename_pov, filename_image):
+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]
@@ -3243,6 +3376,12 @@ def write_pov_ini(scene, filename_ini, filename_pov, filename_image):
file = open(filename_ini, "w")
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)
@@ -3365,6 +3504,7 @@ class PovrayRender(bpy.types.RenderEngine):
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"
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
@@ -3372,6 +3512,8 @@ class PovrayRender(bpy.types.RenderEngine):
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"
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
@@ -3400,7 +3542,7 @@ class PovrayRender(bpy.types.RenderEngine):
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_in, self._temp_file_out)
+ write_pov_ini(scene, self._temp_file_ini, self._temp_file_log, self._temp_file_in, self._temp_file_out)
print ("***-STARTING-***")
@@ -3718,6 +3860,10 @@ class PovrayRender(bpy.types.RenderEngine):
print("***POV FINISHED***")
+ #print(filename_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: