From d20975b80900f4e2a13d792274b989cf5cc4880f Mon Sep 17 00:00:00 2001 From: Maurice Raybaud Date: Tue, 23 Aug 2016 19:39:13 +0200 Subject: *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 --- render_povray/primitives.py | 68 +++++++++--- render_povray/render.py | 264 ++++++++++++++++++++++++++++++++++---------- render_povray/shading.py | 181 +++++++++++++++--------------- 3 files changed, 351 insertions(+), 162 deletions(-) (limited to 'render_povray') diff --git a/render_povray/primitives.py b/render_povray/primitives.py index 27010baa..dcb920dd 100644 --- a/render_povray/primitives.py +++ b/render_povray/primitives.py @@ -52,7 +52,7 @@ class POVRAY_OT_lathe_add(bpy.types.Operator): ob.name = ob.data.name = "PovLathe" ob.pov.object_as='LATHE' bpy.ops.object.mode_set(mode='EDIT') - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") bpy.ops.transform.rotate(value=-pi/2, axis=(0, 0, 1)) bpy.ops.object.mode_set(mode='OBJECT') @@ -228,7 +228,7 @@ class POVRAY_OT_superellipsoid_add(bpy.types.Operator): def execute(self,context): pov_superellipsoid_define(context, self, None) - self.report({'WARNING'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") + self.report({'INFO'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") return {'FINISHED'} @@ -423,7 +423,7 @@ class POVRAY_OT_supertorus_add(bpy.types.Operator): def execute(self, context): pov_supertorus_define(context, self, None) - self.report({'WARNING'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") + self.report({'INFO'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") return {'FINISHED'} class POVRAY_OT_supertorus_update(bpy.types.Operator): @@ -577,7 +577,7 @@ class POVRAY_OT_plane_add(bpy.types.Operator): ob = context.object ob.name = ob.data.name = 'PovInfinitePlane' bpy.ops.object.mode_set(mode="EDIT") - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") bpy.ops.mesh.hide(unselected=False) bpy.ops.object.mode_set(mode="OBJECT") @@ -598,7 +598,7 @@ class POVRAY_OT_box_add(bpy.types.Operator): ob = context.object ob.name = ob.data.name = 'PovBox' bpy.ops.object.mode_set(mode="EDIT") - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") bpy.ops.mesh.hide(unselected=False) bpy.ops.object.mode_set(mode="OBJECT") @@ -677,7 +677,7 @@ class POVRAY_OT_cylinder_add(bpy.types.Operator): else: LOC = props.imported_cyl_loc LOC_CAP = props.imported_cyl_loc_cap - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") pov_cylinder_define(context, self, None, self.R, LOC, LOC_CAP) @@ -778,7 +778,7 @@ class POVRAY_OT_sphere_add(bpy.types.Operator): else: LOC = props.imported_loc - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") pov_sphere_define(context, self, None, LOC) @@ -791,7 +791,7 @@ class POVRAY_OT_sphere_add(bpy.types.Operator): # bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4, radius=ob.pov.sphere_radius, layers=layers) # ob = context.object # bpy.ops.object.mode_set(mode="EDIT") - # self.report({'WARNING'}, "This native POV-Ray primitive " + # self.report({'INFO'}, "This native POV-Ray primitive " # "won't have any vertex to show in edit mode") # bpy.ops.mesh.hide(unselected=False) # bpy.ops.object.mode_set(mode="OBJECT") @@ -910,7 +910,7 @@ class POVRAY_OT_cone_add(bpy.types.Operator): def execute(self, context): pov_cone_define(context, self, None) - self.report({'WARNING'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") + self.report({'INFO'}, "This native POV-Ray primitive won't have any vertex to show in edit mode") return {'FINISHED'} @@ -952,7 +952,7 @@ class POVRAY_OT_isosurface_box_add(bpy.types.Operator): bpy.ops.mesh.primitive_cube_add(layers = layers) ob = context.object bpy.ops.object.mode_set(mode="EDIT") - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") bpy.ops.mesh.hide(unselected=False) bpy.ops.object.mode_set(mode="OBJECT") @@ -974,7 +974,7 @@ class POVRAY_OT_isosurface_sphere_add(bpy.types.Operator): bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=4,layers=layers) ob = context.object bpy.ops.object.mode_set(mode="EDIT") - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") bpy.ops.mesh.hide(unselected=False) bpy.ops.object.mode_set(mode="OBJECT") @@ -1203,7 +1203,7 @@ class POVRAY_OT_torus_add(bpy.types.Operator): mas = props.mas mis = props.mis pov_torus_define(context, self, None) - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") return {'FINISHED'} @@ -1373,7 +1373,7 @@ class POVRAY_OT_parametric_add(bpy.types.Operator): z_eq = props.z_eq pov_parametric_define(context, self, None) - self.report({'WARNING'}, "This native POV-Ray primitive " + self.report({'INFO'}, "This native POV-Ray primitive " "won't have any vertex to show in edit mode") return {'FINISHED'} @@ -1480,6 +1480,8 @@ class ImportPOV(bpy.types.Operator, ImportHelper): verts = [] faces = [] materials = [] + blendMats = [] ############## + povMats = [] ############## colors = [] matNames = [] lenverts = None @@ -1494,6 +1496,7 @@ class ImportPOV(bpy.types.Operator, ImportHelper): cylinder_search = False sphere_search = False cone_search = False + tex_search = False ################## cache = [] matrixes = {} writematrix = False @@ -1716,8 +1719,16 @@ class ImportPOV(bpy.types.Operator, ImportHelper): z=(i*3)+2 verts.append((float(cache[x]),float(cache[y]),float(cache[z]))) cache = [] + #if word == 'face_indices': + #faces_search = True + if word == 'texture_list': ######## + tex_search = True ####### + if tex_search: ######### + if word not in {'texture_list','texture','{','}','face_indices'} and word.isdigit() == False: ############## + povMats.append(word) ################# if word == 'face_indices': - faces_search = True + tex_search = False ################ + faces_search = True if faces_search: cache.append(word) if word == '}': @@ -1751,9 +1762,32 @@ class ImportPOV(bpy.types.Operator, ImportHelper): m2=i*6+5 materials.append((int(cache[m0]),int(cache[m1]),int(cache[m2]))) faces.append((int(cache[v0]),int(cache[v1]),int(cache[v2]))) - mesh = pov_define_mesh(None, verts, [], faces, name, hide_geometry=False) - ob_base = object_utils.object_data_add(context, mesh, operator=None) - ob = ob_base.object + #mesh = pov_define_mesh(None, verts, [], faces, name, hide_geometry=False) + #ob_base = object_utils.object_data_add(context, mesh, operator=None) + #ob = ob_base.object + + me = bpy.data.meshes.new(name) ######## + ob = bpy.data.objects.new(name, me) ########## + bpy.context.scene.objects.link(ob) ######### + me.from_pydata(verts, [], faces) ############ + + for mat in bpy.data.materials: ############## + blendMats.append(mat.name) ############# + for mName in povMats: ##################### + if mName not in blendMats: ########### + povMat = bpy.data.materials.new(mName) ################# + mat_search(cache) + ob.data.materials.append(bpy.data.materials[mName]) ################### + if materials: ################## + for i,val in enumerate(materials): #################### + try: ################### + ob.data.polygons[i].material_index = val #################### + except TypeError: ################### + ob.data.polygons[i].material_index = int(val[0]) ################## + + blendMats = [] ######################### + povMats = [] ######################### + materials = [] ######################### cache = [] name_search = True if name in matrixes and self.import_at_cur==False: 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: 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: diff --git a/render_povray/shading.py b/render_povray/shading.py index 750711a5..d6245a16 100644 --- a/render_povray/shading.py +++ b/render_povray/shading.py @@ -12,7 +12,7 @@ def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments if material: # If saturation(.s) is not zero, then color is not grey, and has a tint - colored_specular_found = (material.specular_color.s > 0.0) + colored_specular_found = ((material.specular_color.s > 0.0) and (material.diffuse_shader != 'MINNAERT')) ################## # Several versions of the finish: Level conditions are variations for specular/Mirror @@ -214,7 +214,7 @@ def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments if material: special_texture_found = False for t in material.texture_slots: - if t and t.use: + if t and t.use and t.texture is not None: if (t.texture.type == 'IMAGE' and t.texture.image) or t.texture.type != 'IMAGE': validPath=True else: @@ -713,15 +713,16 @@ def exportPattern(texture, string_strip_hyphen): return(texStrg) -def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image, - imageFormat, imgMap, imgMapTransforms, tabWrite, +def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image, lampCount, + imageFormat, imgMap, imgMapTransforms, tabWrite, comments, string_strip_hyphen, safety, col, os, preview_dir, unpacked_images): material_finish = materialNames[mater.name] if mater.use_transparency: trans = 1.0 - mater.alpha else: trans = 0.0 - if (mater.specular_color.s == 0.0): + if ((mater.specular_color.s == 0.0) or (mater.diffuse_shader == 'MINNAERT')): + # No layered texture because of aoi pattern used for minnaert and pov can't layer patterned colored_specular_found = False else: colored_specular_found = True @@ -739,86 +740,92 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image, texturesAlpha = "" #proceduralFlag=False for t in mater.texture_slots: - # PROCEDURAL - if t and t.use and t.texture.type != 'IMAGE' and t.texture.type != 'NONE': - proceduralFlag=True - image_filename = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(t.texture.name)) - if image_filename: - if t.use_map_color_diffuse: - texturesDif = image_filename - # colvalue = t.default_value # UNUSED - t_dif = t - if t_dif.texture.pov.tex_gamma_enable: - imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) - if t.use_map_specular or t.use_map_raymir: - texturesSpec = image_filename - # colvalue = t.default_value # UNUSED - t_spec = t - if t.use_map_normal: - texturesNorm = image_filename - # colvalue = t.normal_factor * 10.0 # UNUSED - #textNormName=t.texture.image.name + ".normal" - #was the above used? --MR - t_nor = t - if t.use_map_alpha: - texturesAlpha = image_filename - # colvalue = t.alpha_factor * 10.0 # UNUSED - #textDispName=t.texture.image.name + ".displ" - #was the above used? --MR - t_alpha = t - - # RASTER IMAGE - if t and t.texture.type == 'IMAGE' and t.use and t.texture.image and t.texture.pov.tex_pattern_type == 'emulator': - proceduralFlag=False - #PACKED - if t.texture.image.packed_file: - orig_image_filename=t.texture.image.filepath_raw - unpackedfilename= os.path.join(preview_dir,("unpacked_img_"+(string_strip_hyphen(bpy.path.clean_name(t.texture.name))))) - if not os.path.exists(unpackedfilename): - # record which images that were newly copied and can be safely - # cleaned up - unpacked_images.append(unpackedfilename) - t.texture.image.filepath_raw=unpackedfilename - t.texture.image.save() - image_filename = unpackedfilename.replace("\\","/") - # .replace("\\","/") to get only forward slashes as it's what POV prefers, - # even on windows - t.texture.image.filepath_raw=orig_image_filename - #FILE - else: - image_filename = path_image(t.texture.image) - # IMAGE SEQUENCE BEGINS - if image_filename: - if bpy.data.images[t.texture.image.name].source == 'SEQUENCE': - korvaa = "." + str(bpy.data.textures[t.texture.name].image_user.frame_offset + 1).zfill(3) + "." - image_filename = image_filename.replace(".001.", korvaa) - print(" seq debug ") - print(image_filename) - # IMAGE SEQUENCE ENDS - imgGamma = "" - if image_filename: - if t.use_map_color_diffuse: - texturesDif = image_filename - # colvalue = t.default_value # UNUSED - t_dif = t - if t_dif.texture.pov.tex_gamma_enable: - imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) - if t.use_map_specular or t.use_map_raymir: - texturesSpec = image_filename - # colvalue = t.default_value # UNUSED - t_spec = t - if t.use_map_normal: - texturesNorm = image_filename - # colvalue = t.normal_factor * 10.0 # UNUSED - #textNormName=t.texture.image.name + ".normal" - #was the above used? --MR - t_nor = t - if t.use_map_alpha: - texturesAlpha = image_filename - # colvalue = t.alpha_factor * 10.0 # UNUSED - #textDispName=t.texture.image.name + ".displ" - #was the above used? --MR - t_alpha = t + if t and (t.use and (t.texture is not None)): + # 'NONE' ('NONE' type texture is different from no texture covered above) + if (t.texture.type == 'NONE' and t.texture.pov.tex_pattern_type == 'emulator'): + print('RESHAITE') + continue # move to next slot + # PROCEDURAL + elif (t.texture.type != 'IMAGE' and t.texture.type != 'NONE'): + proceduralFlag=True + print('XXXSHHHAAIIIITE') + image_filename = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(t.texture.name)) + if image_filename: + if t.use_map_color_diffuse: + texturesDif = image_filename + # colvalue = t.default_value # UNUSED + t_dif = t + if t_dif.texture.pov.tex_gamma_enable: + imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) + if t.use_map_specular or t.use_map_raymir: + texturesSpec = image_filename + # colvalue = t.default_value # UNUSED + t_spec = t + if t.use_map_normal: + texturesNorm = image_filename + # colvalue = t.normal_factor * 10.0 # UNUSED + #textNormName=t.texture.image.name + ".normal" + #was the above used? --MR + t_nor = t + if t.use_map_alpha: + texturesAlpha = image_filename + # colvalue = t.alpha_factor * 10.0 # UNUSED + #textDispName=t.texture.image.name + ".displ" + #was the above used? --MR + t_alpha = t + + # RASTER IMAGE + elif (t.texture.type == 'IMAGE' and t.texture.image and t.texture.pov.tex_pattern_type == 'emulator'): + proceduralFlag=False + #PACKED + if t.texture.image.packed_file: + orig_image_filename=t.texture.image.filepath_raw + unpackedfilename= os.path.join(preview_dir,("unpacked_img_"+(string_strip_hyphen(bpy.path.clean_name(t.texture.name))))) + if not os.path.exists(unpackedfilename): + # record which images that were newly copied and can be safely + # cleaned up + unpacked_images.append(unpackedfilename) + t.texture.image.filepath_raw=unpackedfilename + t.texture.image.save() + image_filename = unpackedfilename.replace("\\","/") + # .replace("\\","/") to get only forward slashes as it's what POV prefers, + # even on windows + t.texture.image.filepath_raw=orig_image_filename + #FILE + else: + image_filename = path_image(t.texture.image) + # IMAGE SEQUENCE BEGINS + if image_filename: + if bpy.data.images[t.texture.image.name].source == 'SEQUENCE': + korvaa = "." + str(bpy.data.textures[t.texture.name].image_user.frame_offset + 1).zfill(3) + "." + image_filename = image_filename.replace(".001.", korvaa) + print(" seq debug ") + print(image_filename) + # IMAGE SEQUENCE ENDS + imgGamma = "" + if image_filename: + if t.use_map_color_diffuse: + texturesDif = image_filename + # colvalue = t.default_value # UNUSED + t_dif = t + if t_dif.texture.pov.tex_gamma_enable: + imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) + if t.use_map_specular or t.use_map_raymir: + texturesSpec = image_filename + # colvalue = t.default_value # UNUSED + t_spec = t + if t.use_map_normal: + texturesNorm = image_filename + # colvalue = t.normal_factor * 10.0 # UNUSED + #textNormName=t.texture.image.name + ".normal" + #was the above used? --MR + t_nor = t + if t.use_map_alpha: + texturesAlpha = image_filename + # colvalue = t.alpha_factor * 10.0 # UNUSED + #textDispName=t.texture.image.name + ".displ" + #was the above used? --MR + t_alpha = t #################################################################################### @@ -1053,6 +1060,7 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image, else: if texturesDif and texturesDif.startswith("PAT_"): tabWrite("pigment{%s %s}\n" %(texturesDif, mappingDif)) + print('XXXMEEEERDE!') else: tabWrite("pigment {\n") tabWrite("uv_mapping image_map {\n") @@ -1113,7 +1121,8 @@ def writeTextureInfluence(mater, materialNames, LocalMaterialNames, path_image, # Close first layer of POV "texture" (Blender material) tabWrite("}\n") - if (mater.specular_color.s > 0.0): + if ((mater.specular_color.s > 0.0) and (mater.diffuse_shader != 'MINNAERT')): + colored_specular_found = True else: colored_specular_found = False -- cgit v1.2.3