From 9152da178b89a8e7cbcca870acd63cfa8857935e Mon Sep 17 00:00:00 2001 From: Maurice Raybaud Date: Wed, 21 Aug 2019 08:38:27 +0200 Subject: Some instantiation 2.8 API update fixing --- render_povray/render.py | 2105 ++++++++++++++++++++++++----------------------- 1 file changed, 1056 insertions(+), 1049 deletions(-) diff --git a/render_povray/render.py b/render_povray/render.py index 62cd2426..828141ce 100644 --- a/render_povray/render.py +++ b/render_povray/render.py @@ -2064,1159 +2064,1163 @@ def write_pov(filename, scene=None, info_callback=None): ob_num = 0 for ob in sel: - ob_num += 1 - - # XXX I moved all those checks here, as there is no need to compute names - # for object we won't export here! - if (ob.type in {'LIGHT', 'CAMERA', #'EMPTY', #empties can bear dupligroups - 'META', 'ARMATURE', 'LATTICE'}): - continue - smokeFlag=False - for mod in ob.modifiers: - if mod and hasattr(mod, 'smoke_type'): - smokeFlag=True - if (mod.smoke_type == 'DOMAIN'): - exportSmoke(ob.name) - break # don't render domain mesh or flow emitter mesh, skip to next object. - if not smokeFlag: - # Export Hair - renderEmitter = True - if hasattr(ob, 'particle_systems'): - renderEmitter = False - for pSys in ob.particle_systems: - if pSys.settings.use_render_emitter: - renderEmitter = True - for mod in [m for m in ob.modifiers if (m is not None) and (m.type == 'PARTICLE_SYSTEM')]: - if (pSys.settings.render_type == 'PATH') and mod.show_render and (pSys.name == mod.particle_system.name): - tstart = time.time() - texturedHair=0 - 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: - if (th.texture.type == 'IMAGE' and th.texture.image) or th.texture.type != 'IMAGE': - if th.use_map_color_diffuse: - texturedHair=1 - if pmaterial.strand.use_blender_units: - strandStart = pmaterial.strand.root_size - strandEnd = pmaterial.strand.tip_size - strandShape = pmaterial.strand.shape - else: # Blender unit conversion - strandStart = pmaterial.strand.root_size / 200.0 - strandEnd = pmaterial.strand.tip_size / 200.0 - strandShape = pmaterial.strand.shape - else: - pmaterial = "default" # No material assigned in blender, use default one - strandStart = 0.01 - strandEnd = 0.01 - strandShape = 0.0 - # Set the number of particles to render count rather than 3d view display - pSys.set_resolution(scene, ob, 'RENDER') - steps = pSys.settings.display_step - steps = 3 ** steps # or (power of 2 rather than 3) + 1 # Formerly : len(particle.hair_keys) - - totalNumberOfHairs = ( len(pSys.particles) + len(pSys.child_particles) ) - #hairCounter = 0 - file.write('#declare HairArray = array[%i] {\n' % totalNumberOfHairs) - for pindex in range(0, totalNumberOfHairs): - - #if particle.is_exist and particle.is_visible: - #hairCounter += 1 - #controlPointCounter = 0 - # Each hair is represented as a separate sphere_sweep in POV-Ray. - - file.write('sphere_sweep{') - if pSys.settings.use_hair_bspline: - file.write('b_spline ') - file.write('%i,\n' % (steps + 2)) # +2 because the first point needs tripling to be more than a handle in POV - else: - file.write('linear_spline ') - 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.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 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] - image_pixels = image.pixels[:] - uv_co = pSys.uv_on_emitter(mod, pSys.particles[pindex], pindex, 0) - x_co = round(uv_co[0] * (image_width - 1)) - y_co = round(uv_co[1] * (image_height - 1)) - pixelnumber = (image_width * y_co) + x_co - r = image_pixels[pixelnumber*4] - g = image_pixels[pixelnumber*4+1] - b = image_pixels[pixelnumber*4+2] - a = image_pixels[pixelnumber*4+3] - initColor=(r,g,b,a) - else: - #only overwrite variable for each competing texture for now - initColor=th.texture.evaluate((initCo[0],initCo[1],initCo[2])) - for step in range(0, steps): - co = ob.matrix_world.inverted()*(pSys.co_hair(ob, pindex, step)) - #for controlPoint in particle.hair_keys: - if pSys.settings.clump_factor != 0: - hDiameter = pSys.settings.clump_factor / 200.0 * random.uniform(0.5, 1) - elif step == 0: - hDiameter = strandStart + #subtract original from the count of their instances as were not counted before 2.8 + if not (ob.is_instancer and ob.original != ob): + ob_num += 1 + + # XXX I moved all those checks here, as there is no need to compute names + # for object we won't export here! + if (ob.type in {'LIGHT', 'CAMERA', #'EMPTY', #empties can bear dupligroups + 'META', 'ARMATURE', 'LATTICE'}): + continue + smokeFlag=False + for mod in ob.modifiers: + if mod and hasattr(mod, 'smoke_type'): + smokeFlag=True + if (mod.smoke_type == 'DOMAIN'): + exportSmoke(ob.name) + break # don't render domain mesh or flow emitter mesh, skip to next object. + if not smokeFlag: + # Export Hair + renderEmitter = True + if hasattr(ob, 'particle_systems'): + renderEmitter = False + for pSys in ob.particle_systems: + if pSys.settings.use_render_emitter: + renderEmitter = True + for mod in [m for m in ob.modifiers if (m is not None) and (m.type == 'PARTICLE_SYSTEM')]: + if (pSys.settings.render_type == 'PATH') and mod.show_render and (pSys.name == mod.particle_system.name): + tstart = time.time() + texturedHair=0 + 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: + if (th.texture.type == 'IMAGE' and th.texture.image) or th.texture.type != 'IMAGE': + if th.use_map_color_diffuse: + texturedHair=1 + if pmaterial.strand.use_blender_units: + strandStart = pmaterial.strand.root_size + strandEnd = pmaterial.strand.tip_size + strandShape = pmaterial.strand.shape + else: # Blender unit conversion + strandStart = pmaterial.strand.root_size / 200.0 + strandEnd = pmaterial.strand.tip_size / 200.0 + strandShape = pmaterial.strand.shape + else: + pmaterial = "default" # No material assigned in blender, use default one + strandStart = 0.01 + strandEnd = 0.01 + strandShape = 0.0 + # Set the number of particles to render count rather than 3d view display + pSys.set_resolution(scene, ob, 'RENDER') + steps = pSys.settings.display_step + steps = 3 ** steps # or (power of 2 rather than 3) + 1 # Formerly : len(particle.hair_keys) + + totalNumberOfHairs = ( len(pSys.particles) + len(pSys.child_particles) ) + #hairCounter = 0 + file.write('#declare HairArray = array[%i] {\n' % totalNumberOfHairs) + for pindex in range(0, totalNumberOfHairs): + + #if particle.is_exist and particle.is_visible: + #hairCounter += 1 + #controlPointCounter = 0 + # Each hair is represented as a separate sphere_sweep in POV-Ray. + + file.write('sphere_sweep{') + if pSys.settings.use_hair_bspline: + file.write('b_spline ') + file.write('%i,\n' % (steps + 2)) # +2 because the first point needs tripling to be more than a handle in POV else: - hDiameter += (strandEnd-strandStart)/(pSys.settings.display_step+1) #XXX +1 or not? - if step == 0 and pSys.settings.use_hair_bspline: - # Write three times the first point to compensate pov Bezier handling - file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter))) - file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter))) - #file.write('<%.6g,%.6g,%.6g>,%.7g' % (particle.location[0], particle.location[1], particle.location[2], abs(hDiameter))) # Useless because particle location is the tip, not the root. - #file.write(',\n') - #controlPointCounter += 1 - #totalNumberOfHairs += len(pSys.particles)# len(particle.hair_keys) - - # Each control point is written out, along with the radius of the - # hair at that point. - file.write('<%.6g,%.6g,%.6g>,%.7g' % (co[0], co[1], co[2], abs(hDiameter))) - - # All coordinates except the last need a following comma. - - if step != steps - 1: + file.write('linear_spline ') + 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.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 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] + image_pixels = image.pixels[:] + uv_co = pSys.uv_on_emitter(mod, pSys.particles[pindex], pindex, 0) + x_co = round(uv_co[0] * (image_width - 1)) + y_co = round(uv_co[1] * (image_height - 1)) + pixelnumber = (image_width * y_co) + x_co + r = image_pixels[pixelnumber*4] + g = image_pixels[pixelnumber*4+1] + b = image_pixels[pixelnumber*4+2] + a = image_pixels[pixelnumber*4+3] + initColor=(r,g,b,a) + else: + #only overwrite variable for each competing texture for now + initColor=th.texture.evaluate((initCo[0],initCo[1],initCo[2])) + for step in range(0, steps): + co = ob.matrix_world.inverted()*(pSys.co_hair(ob, pindex, step)) + #for controlPoint in particle.hair_keys: + if pSys.settings.clump_factor != 0: + hDiameter = pSys.settings.clump_factor / 200.0 * random.uniform(0.5, 1) + elif step == 0: + hDiameter = strandStart + else: + hDiameter += (strandEnd-strandStart)/(pSys.settings.display_step+1) #XXX +1 or not? + if step == 0 and pSys.settings.use_hair_bspline: + # Write three times the first point to compensate pov Bezier handling + file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter))) + file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter))) + #file.write('<%.6g,%.6g,%.6g>,%.7g' % (particle.location[0], particle.location[1], particle.location[2], abs(hDiameter))) # Useless because particle location is the tip, not the root. + #file.write(',\n') + #controlPointCounter += 1 + #totalNumberOfHairs += len(pSys.particles)# len(particle.hair_keys) + + # Each control point is written out, along with the radius of the + # hair at that point. + file.write('<%.6g,%.6g,%.6g>,%.7g' % (co[0], co[1], co[2], abs(hDiameter))) + + # All coordinates except the last need a following comma. + + if step != steps - 1: + file.write(',\n') + else: + if texturedHair: + # Write pigment and alpha (between Pov and Blender alpha 0 and 1 are reversed) + file.write('\npigment{ color srgbf < %.3g, %.3g, %.3g, %.3g> }\n' %(initColor[0], initColor[1], initColor[2], 1.0-initColor[3])) + # End the sphere_sweep declaration for this hair + file.write('}\n') + + # All but the final sphere_sweep (each array element) needs a terminating comma. + if pindex != totalNumberOfHairs: file.write(',\n') else: - if texturedHair: - # Write pigment and alpha (between Pov and Blender alpha 0 and 1 are reversed) - file.write('\npigment{ color srgbf < %.3g, %.3g, %.3g, %.3g> }\n' %(initColor[0], initColor[1], initColor[2], 1.0-initColor[3])) - # End the sphere_sweep declaration for this hair - file.write('}\n') - - # All but the final sphere_sweep (each array element) needs a terminating comma. - if pindex != totalNumberOfHairs: - file.write(',\n') - else: - file.write('\n') + file.write('\n') - # End the array declaration. + # End the array declaration. - file.write('}\n') - file.write('\n') - - if not texturedHair: - # Pick up the hair material diffuse color and create a default POV-Ray hair texture. - - file.write('#ifndef (HairTexture)\n') - file.write(' #declare HairTexture = texture {\n') - file.write(' pigment {srgbt <%s,%s,%s,%s>}\n' % (pmaterial.diffuse_color[0], pmaterial.diffuse_color[1], pmaterial.diffuse_color[2], (pmaterial.strand.width_fade + 0.05))) - file.write(' }\n') - file.write('#end\n') + file.write('}\n') file.write('\n') - # Dynamically create a union of the hairstrands (or a subset of them). - # By default use every hairstrand, commented line is for hand tweaking test renders. - file.write('//Increasing HairStep divides the amount of hair for test renders.\n') - file.write('#ifndef(HairStep) #declare HairStep = 1; #end\n') - file.write('union{\n') - file.write(' #local I = 0;\n') - file.write(' #while (I < %i)\n' % totalNumberOfHairs) - file.write(' object {HairArray[I]') - if not texturedHair: - file.write(' texture{HairTexture}\n') - else: - file.write('\n') - # Translucency of the hair: - file.write(' hollow\n') - file.write(' double_illuminate\n') - file.write(' interior {\n') - file.write(' ior 1.45\n') - file.write(' media {\n') - file.write(' scattering { 1, 10*<0.73, 0.35, 0.15> /*extinction 0*/ }\n') - file.write(' absorption 10/<0.83, 0.75, 0.15>\n') - file.write(' samples 1\n') - file.write(' method 2\n') - file.write(' density {cylindrical\n') - file.write(' color_map {\n') - file.write(' [0.0 rgb <0.83, 0.45, 0.35>]\n') - file.write(' [0.5 rgb <0.8, 0.8, 0.4>]\n') - file.write(' [1.0 rgb <1,1,1>]\n') - file.write(' }\n') - file.write(' }\n') - file.write(' }\n') - file.write(' }\n') - file.write(' }\n') - - file.write(' #local I = I + HairStep;\n') - file.write(' #end\n') - - writeMatrix(global_matrix @ ob.matrix_world) - - - file.write('}') - print('Totals hairstrands written: %i' % totalNumberOfHairs) - print('Number of tufts (particle systems)', len(ob.particle_systems)) - - # Set back the displayed number of particles to preview count - pSys.set_resolution(scene, ob, 'PREVIEW') - - if renderEmitter == False: - continue #don't render mesh, skip to next object. - - ############################################# - # 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, - # so this condition is always True, IMO -- mont29 - if ob.data: - name_orig = "OB" + ob.name - dataname_orig = "DATA" + ob.data.name - elif ob.is_instancer: - if ob.instance_type == 'COLLECTION': + if not texturedHair: + # Pick up the hair material diffuse color and create a default POV-Ray hair texture. + + file.write('#ifndef (HairTexture)\n') + file.write(' #declare HairTexture = texture {\n') + file.write(' pigment {srgbt <%s,%s,%s,%s>}\n' % (pmaterial.diffuse_color[0], pmaterial.diffuse_color[1], pmaterial.diffuse_color[2], (pmaterial.strand.width_fade + 0.05))) + file.write(' }\n') + file.write('#end\n') + file.write('\n') + + # Dynamically create a union of the hairstrands (or a subset of them). + # By default use every hairstrand, commented line is for hand tweaking test renders. + file.write('//Increasing HairStep divides the amount of hair for test renders.\n') + file.write('#ifndef(HairStep) #declare HairStep = 1; #end\n') + file.write('union{\n') + file.write(' #local I = 0;\n') + file.write(' #while (I < %i)\n' % totalNumberOfHairs) + file.write(' object {HairArray[I]') + if not texturedHair: + file.write(' texture{HairTexture}\n') + else: + file.write('\n') + # Translucency of the hair: + file.write(' hollow\n') + file.write(' double_illuminate\n') + file.write(' interior {\n') + file.write(' ior 1.45\n') + file.write(' media {\n') + file.write(' scattering { 1, 10*<0.73, 0.35, 0.15> /*extinction 0*/ }\n') + file.write(' absorption 10/<0.83, 0.75, 0.15>\n') + file.write(' samples 1\n') + file.write(' method 2\n') + file.write(' density {cylindrical\n') + file.write(' color_map {\n') + file.write(' [0.0 rgb <0.83, 0.45, 0.35>]\n') + file.write(' [0.5 rgb <0.8, 0.8, 0.4>]\n') + file.write(' [1.0 rgb <1,1,1>]\n') + file.write(' }\n') + file.write(' }\n') + file.write(' }\n') + file.write(' }\n') + file.write(' }\n') + + file.write(' #local I = I + HairStep;\n') + file.write(' #end\n') + + writeMatrix(global_matrix @ ob.matrix_world) + + + file.write('}') + print('Totals hairstrands written: %i' % totalNumberOfHairs) + print('Number of tufts (particle systems)', len(ob.particle_systems)) + + # Set back the displayed number of particles to preview count + pSys.set_resolution(scene, ob, 'PREVIEW') + + if renderEmitter == False: + continue #don't render mesh, skip to next object. + + ############################################# + # 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, + # so this condition is always True, IMO -- mont29 + if ob.data: name_orig = "OB" + ob.name - dataname_orig = "DATA" + ob.instance_collection.name + dataname_orig = "DATA" + ob.data.name + elif ob.is_instancer: + if ob.instance_type == 'COLLECTION': + name_orig = "OB" + ob.name + dataname_orig = "DATA" + ob.instance_collection.name + else: + #hoping only dupligroups have several source datablocks + #ob_dupli_list_create(scene) #deprecated in 2.8 + depsgraph = bpy.context.evaluated_depsgraph_get() + for eachduplicate in depsgraph.object_instances: + if eachduplicate.is_instance: # Real dupli instance filtered because original included in list since 2.8 + dataname_orig = "DATA" + eachduplicate.object.name + #ob.dupli_list_clear() #just don't store any reference to instance since 2.8 + elif ob.type == 'EMPTY': + name_orig = "OB" + ob.name + dataname_orig = "DATA" + ob.name else: - #hoping only dupligroups have several source datablocks - ob.dupli_list_create(scene) - for eachduplicate in ob.dupli_list: - dataname_orig = "DATA" + eachduplicate.object.name - ob.dupli_list_clear() - elif ob.type == 'EMPTY': - name_orig = "OB" + ob.name - dataname_orig = "DATA" + ob.name - else: - name_orig = DEF_OBJ_NAME - dataname_orig = DEF_OBJ_NAME - name = string_strip_hyphen(bpy.path.clean_name(name_orig)) - dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig)) - ## for slot in ob.material_slots: - ## if slot.material is not None and slot.link == 'OBJECT': - ## obmaterial = slot.material - - ############################################# - - if info_callback: - info_callback("Object %2.d of %2.d (%s)" % (ob_num, len(sel), ob.name)) - - #if ob.type != 'MESH': - # continue - # me = ob.data - - matrix = global_matrix @ ob.matrix_world - povdataname = store(scene, ob, name, dataname, matrix) - if povdataname is None: - print("This is an instance of " + name) - continue + name_orig = DEF_OBJ_NAME + dataname_orig = DEF_OBJ_NAME + name = string_strip_hyphen(bpy.path.clean_name(name_orig)) + dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig)) + ## for slot in ob.material_slots: + ## if slot.material is not None and slot.link == 'OBJECT': + ## obmaterial = slot.material + + ############################################# + + if info_callback: + info_callback("Object %2.d of %2.d (%s)" % (ob_num, len(sel), ob.name)) + + #if ob.type != 'MESH': + # continue + # me = ob.data + + matrix = global_matrix @ ob.matrix_world + povdataname = store(scene, ob, name, dataname, matrix) + if povdataname is None: + print("This is an instance of " + name) + continue - print("Writing Down First Occurrence of " + name) + print("Writing Down First Occurrence of " + name) + + ############################################Povray Primitives + # special exportCurves() function takes care of writing + # 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) + tabWrite("function{ \n") + textName = ob.pov.iso_function_text + if textName: + node_tree = bpy.context.scene.node_tree + for node in node_tree.nodes: + if node.bl_idname == "IsoPropsNode" and node.label == ob.name: + for inp in node.inputs: + if inp: + tabWrite("#declare %s = %.6g;\n"%(inp.name,inp.default_value)) + + text = bpy.data.texts[textName] + for line in text.lines: + split = line.body.split() + if split[0] != "#declare": + tabWrite("%s\n"%line.body) + else: + tabWrite("abs(x) - 2 + y") + tabWrite("}\n") + tabWrite("threshold %.6g\n"%ob.pov.threshold) + tabWrite("max_gradient %.6g\n"%ob.pov.max_gradient) + tabWrite("accuracy %.6g\n"%ob.pov.accuracy) + tabWrite("contained_by { ") + if ob.pov.contained_by == "sphere": + tabWrite("sphere {0,%.6g}}\n"%ob.pov.container_scale) + else: + tabWrite("box {-%.6g,%.6g}}\n"%(ob.pov.container_scale,ob.pov.container_scale)) + if ob.pov.all_intersections: + tabWrite("all_intersections\n") + else: + if ob.pov.max_trace > 1: + tabWrite("max_trace %.6g\n"%ob.pov.max_trace) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + tabWrite("scale %.6g\n"%(1/ob.pov.container_scale)) + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object -############################################Povray Primitives - # special exportCurves() function takes care of writing - # 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'}): + if ob.pov.object_as == 'SUPERELLIPSOID': + tabWrite("#declare %s = superellipsoid{ <%.4f,%.4f>\n"%(povdataname,ob.pov.se_n2,ob.pov.se_n1)) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + tabWrite("}\n") continue #Don't render proxy mesh, skip to next object - if ob.pov.object_as == 'ISOSURFACE': - tabWrite("#declare %s = isosurface{ \n"% povdataname) - tabWrite("function{ \n") - textName = ob.pov.iso_function_text - if textName: - node_tree = bpy.context.scene.node_tree - for node in node_tree.nodes: - if node.bl_idname == "IsoPropsNode" and node.label == ob.name: - for inp in node.inputs: - if inp: - tabWrite("#declare %s = %.6g;\n"%(inp.name,inp.default_value)) - - text = bpy.data.texts[textName] - for line in text.lines: - split = line.body.split() - if split[0] != "#declare": - tabWrite("%s\n"%line.body) - else: - tabWrite("abs(x) - 2 + y") - tabWrite("}\n") - tabWrite("threshold %.6g\n"%ob.pov.threshold) - tabWrite("max_gradient %.6g\n"%ob.pov.max_gradient) - tabWrite("accuracy %.6g\n"%ob.pov.accuracy) - tabWrite("contained_by { ") - if ob.pov.contained_by == "sphere": - tabWrite("sphere {0,%.6g}}\n"%ob.pov.container_scale) - else: - tabWrite("box {-%.6g,%.6g}}\n"%(ob.pov.container_scale,ob.pov.container_scale)) - if ob.pov.all_intersections: - tabWrite("all_intersections\n") - else: - if ob.pov.max_trace > 1: - tabWrite("max_trace %.6g\n"%ob.pov.max_trace) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - tabWrite("scale %.6g\n"%(1/ob.pov.container_scale)) - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object - if ob.pov.object_as == 'SUPERELLIPSOID': - tabWrite("#declare %s = superellipsoid{ <%.4f,%.4f>\n"%(povdataname,ob.pov.se_n2,ob.pov.se_n1)) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object - - - if ob.pov.object_as == 'SUPERTORUS': - rMajor = ob.pov.st_major_radius - rMinor = ob.pov.st_minor_radius - ring = ob.pov.st_ring - cross = ob.pov.st_cross - accuracy=ob.pov.st_accuracy - gradient=ob.pov.st_max_gradient - ############Inline Supertorus macro - file.write("#macro Supertorus(RMj, RMn, MajorControl, MinorControl, Accuracy, MaxGradient)\n") - file.write(" #local CP = 2/MinorControl;\n") - file.write(" #local RP = 2/MajorControl;\n") - file.write(" isosurface {\n") - file.write(" function { pow( pow(abs(pow(pow(abs(x),RP) + pow(abs(z),RP), 1/RP) - RMj),CP) + pow(abs(y),CP) ,1/CP) - RMn }\n") - file.write(" threshold 0\n") - file.write(" contained_by {box {<-RMj-RMn,-RMn,-RMj-RMn>, < RMj+RMn, RMn, RMj+RMn>}}\n") - file.write(" #if(MaxGradient >= 1)\n") - file.write(" max_gradient MaxGradient\n") - file.write(" #else\n") - file.write(" evaluate 1, 10, 0.1\n") - file.write(" #end\n") - file.write(" accuracy Accuracy\n") - file.write(" }\n") - file.write("#end\n") - ############ - tabWrite("#declare %s = object{ Supertorus( %.4g,%.4g,%.4g,%.4g,%.4g,%.4g)\n"%(povdataname,rMajor,rMinor,ring,cross,accuracy,gradient)) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - tabWrite("rotate x*90\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object + if ob.pov.object_as == 'SUPERTORUS': + rMajor = ob.pov.st_major_radius + rMinor = ob.pov.st_minor_radius + ring = ob.pov.st_ring + cross = ob.pov.st_cross + accuracy=ob.pov.st_accuracy + gradient=ob.pov.st_max_gradient + ############Inline Supertorus macro + file.write("#macro Supertorus(RMj, RMn, MajorControl, MinorControl, Accuracy, MaxGradient)\n") + file.write(" #local CP = 2/MinorControl;\n") + file.write(" #local RP = 2/MajorControl;\n") + file.write(" isosurface {\n") + file.write(" function { pow( pow(abs(pow(pow(abs(x),RP) + pow(abs(z),RP), 1/RP) - RMj),CP) + pow(abs(y),CP) ,1/CP) - RMn }\n") + file.write(" threshold 0\n") + file.write(" contained_by {box {<-RMj-RMn,-RMn,-RMj-RMn>, < RMj+RMn, RMn, RMj+RMn>}}\n") + file.write(" #if(MaxGradient >= 1)\n") + file.write(" max_gradient MaxGradient\n") + file.write(" #else\n") + file.write(" evaluate 1, 10, 0.1\n") + file.write(" #end\n") + file.write(" accuracy Accuracy\n") + file.write(" }\n") + file.write("#end\n") + ############ + tabWrite("#declare %s = object{ Supertorus( %.4g,%.4g,%.4g,%.4g,%.4g,%.4g)\n"%(povdataname,rMajor,rMinor,ring,cross,accuracy,gradient)) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + tabWrite("rotate x*90\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - if ob.pov.object_as == 'PLANE': - tabWrite("#declare %s = plane{ <0,0,1>,1\n"%povdataname) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - #tabWrite("rotate x*90\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object + if ob.pov.object_as == 'PLANE': + tabWrite("#declare %s = plane{ <0,0,1>,1\n"%povdataname) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + #tabWrite("rotate x*90\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - if ob.pov.object_as == 'BOX': - tabWrite("#declare %s = box { -1,1\n"%povdataname) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - #tabWrite("rotate x*90\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object - - - if ob.pov.object_as == 'CONE': - br = ob.pov.cone_base_radius - cr = ob.pov.cone_cap_radius - bz = ob.pov.cone_base_z - cz = ob.pov.cone_cap_z - tabWrite("#declare %s = cone { <0,0,%.4f>,%.4f,<0,0,%.4f>,%.4f\n"%(povdataname,bz,br,cz,cr)) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - #tabWrite("rotate x*90\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object - - if ob.pov.object_as == 'CYLINDER': - r = ob.pov.cylinder_radius - x2 = ob.pov.cylinder_location_cap[0] - y2 = ob.pov.cylinder_location_cap[1] - z2 = ob.pov.cylinder_location_cap[2] - tabWrite("#declare %s = cylinder { <0,0,0>,<%6f,%6f,%6f>,%6f\n"%( - povdataname, - x2, - y2, - z2, - r)) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - #cylinders written at origin, translated below - write_object_modifiers(scene,ob,file) - #tabWrite("rotate x*90\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object - - - if ob.pov.object_as == 'HEIGHT_FIELD': - data = "" - filename = ob.pov.hf_filename - data += '"%s"'%filename - gamma = ' gamma %.4f'%ob.pov.hf_gamma - data += gamma - if ob.pov.hf_premultiplied: - data += ' premultiplied on' - if ob.pov.hf_smooth: - data += ' smooth' - if ob.pov.hf_water > 0: - data += ' water_level %.4f'%ob.pov.hf_water - #hierarchy = ob.pov.hf_hierarchy - tabWrite('#declare %s = height_field { %s\n'%(povdataname,data)) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - tabWrite("rotate x*90\n") - tabWrite("translate <-0.5,0.5,0>\n") - tabWrite("scale <0,-1,0>\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object + if ob.pov.object_as == 'BOX': + tabWrite("#declare %s = box { -1,1\n"%povdataname) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + #tabWrite("rotate x*90\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - if ob.pov.object_as == 'SPHERE': + if ob.pov.object_as == 'CONE': + br = ob.pov.cone_base_radius + cr = ob.pov.cone_cap_radius + bz = ob.pov.cone_base_z + cz = ob.pov.cone_cap_z + tabWrite("#declare %s = cone { <0,0,%.4f>,%.4f,<0,0,%.4f>,%.4f\n"%(povdataname,bz,br,cz,cr)) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + #tabWrite("rotate x*90\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - tabWrite("#declare %s = sphere { 0,%6f\n"%(povdataname,ob.pov.sphere_radius)) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - #tabWrite("rotate x*90\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object + if ob.pov.object_as == 'CYLINDER': + r = ob.pov.cylinder_radius + x2 = ob.pov.cylinder_location_cap[0] + y2 = ob.pov.cylinder_location_cap[1] + z2 = ob.pov.cylinder_location_cap[2] + tabWrite("#declare %s = cylinder { <0,0,0>,<%6f,%6f,%6f>,%6f\n"%( + povdataname, + x2, + y2, + z2, + r)) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + #cylinders written at origin, translated below + write_object_modifiers(scene,ob,file) + #tabWrite("rotate x*90\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - if ob.pov.object_as == 'TORUS': - tabWrite("#declare %s = torus { %.4f,%.4f\n"%(povdataname,ob.pov.torus_major_radius,ob.pov.torus_minor_radius)) - povMatName = "Default_texture" - if ob.active_material: - #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) - try: - material = ob.active_material - writeObjectMaterial(material, ob) - except IndexError: - print(me) - #tabWrite("texture {%s}\n"%povMatName) - write_object_modifiers(scene,ob,file) - tabWrite("rotate x*90\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object + if ob.pov.object_as == 'HEIGHT_FIELD': + data = "" + filename = ob.pov.hf_filename + data += '"%s"'%filename + gamma = ' gamma %.4f'%ob.pov.hf_gamma + data += gamma + if ob.pov.hf_premultiplied: + data += ' premultiplied on' + if ob.pov.hf_smooth: + data += ' smooth' + if ob.pov.hf_water > 0: + data += ' water_level %.4f'%ob.pov.hf_water + #hierarchy = ob.pov.hf_hierarchy + tabWrite('#declare %s = height_field { %s\n'%(povdataname,data)) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + tabWrite("rotate x*90\n") + tabWrite("translate <-0.5,0.5,0>\n") + tabWrite("scale <0,-1,0>\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - if ob.pov.object_as == 'PARAMETRIC': - tabWrite("#declare %s = parametric {\n"%povdataname) - tabWrite("function { %s }\n"%ob.pov.x_eq) - tabWrite("function { %s }\n"%ob.pov.y_eq) - tabWrite("function { %s }\n"%ob.pov.z_eq) - tabWrite("<%.4f,%.4f>, <%.4f,%.4f>\n"%(ob.pov.u_min,ob.pov.v_min,ob.pov.u_max,ob.pov.v_max)) - if ob.pov.contained_by == "sphere": - tabWrite("contained_by { sphere{0, 2} }\n") - else: - tabWrite("contained_by { box{-2, 2} }\n") - tabWrite("max_gradient %.6f\n"%ob.pov.max_gradient) - tabWrite("accuracy %.6f\n"%ob.pov.accuracy) - tabWrite("precompute 10 x,y,z\n") - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object - - if ob.pov.object_as == 'POLYCIRCLE': - #TODO write below macro Once: - #if write_polytocircle_macro_once == 0: - file.write("/****************************\n") - file.write("This macro was written by 'And'.\n") - file.write("Link:(http://news.povray.org/povray.binaries.scene-files/)\n") - file.write("****************************/\n") - file.write("//from math.inc:\n") - file.write("#macro VPerp_Adjust(V, Axis)\n") - file.write(" vnormalize(vcross(vcross(Axis, V), Axis))\n") - file.write("#end\n") - file.write("//Then for the actual macro\n") - file.write("#macro Shape_Slice_Plane_2P_1V(point1, point2, clip_direct)\n") - file.write("#local p1 = point1 + <0,0,0>;\n") - file.write("#local p2 = point2 + <0,0,0>;\n") - file.write("#local clip_v = vnormalize(clip_direct + <0,0,0>);\n") - file.write("#local direct_v1 = vnormalize(p2 - p1);\n") - file.write("#if(vdot(direct_v1, clip_v) = 1)\n") - file.write(' #error "Shape_Slice_Plane_2P_1V error: Can\'t decide plane"\n') - file.write("#end\n\n") - file.write("#local norm = -vnormalize(clip_v - direct_v1*vdot(direct_v1,clip_v));\n") - file.write("#local d = vdot(norm, p1);\n") - file.write("plane{\n") - file.write("norm, d\n") - file.write("}\n") - file.write("#end\n\n") - file.write("//polygon to circle\n") - file.write("#macro Shape_Polygon_To_Circle_Blending(_polygon_n, _side_face, _polygon_circumscribed_radius, _circle_radius, _height)\n") - file.write("#local n = int(_polygon_n);\n") - file.write("#if(n < 3)\n") - file.write(" #error ""\n") - file.write("#end\n\n") - file.write("#local front_v = VPerp_Adjust(_side_face, z);\n") - file.write("#if(vdot(front_v, x) >= 0)\n") - file.write(" #local face_ang = acos(vdot(-y, front_v));\n") - file.write("#else\n") - file.write(" #local face_ang = -acos(vdot(-y, front_v));\n") - file.write("#end\n") - file.write("#local polyg_ext_ang = 2*pi/n;\n") - file.write("#local polyg_outer_r = _polygon_circumscribed_radius;\n") - file.write("#local polyg_inner_r = polyg_outer_r*cos(polyg_ext_ang/2);\n") - file.write("#local cycle_r = _circle_radius;\n") - file.write("#local h = _height;\n") - file.write("#if(polyg_outer_r < 0 | cycle_r < 0 | h <= 0)\n") - file.write(' #error "error: each side length must be positive"\n') - file.write("#end\n\n") - file.write("#local multi = 1000;\n") - file.write("#local poly_obj =\n") - file.write("polynomial{\n") - file.write("4,\n") - file.write("xyz(0,2,2): multi*1,\n") - file.write("xyz(2,0,1): multi*2*h,\n") - file.write("xyz(1,0,2): multi*2*(polyg_inner_r-cycle_r),\n") - file.write("xyz(2,0,0): multi*(-h*h),\n") - file.write("xyz(0,0,2): multi*(-pow(cycle_r - polyg_inner_r, 2)),\n") - file.write("xyz(1,0,1): multi*2*h*(-2*polyg_inner_r + cycle_r),\n") - file.write("xyz(1,0,0): multi*2*h*h*polyg_inner_r,\n") - file.write("xyz(0,0,1): multi*2*h*polyg_inner_r*(polyg_inner_r - cycle_r),\n") - file.write("xyz(0,0,0): multi*(-pow(polyg_inner_r*h, 2))\n") - file.write("sturm\n") - file.write("}\n\n") - file.write("#local mockup1 =\n") - file.write("difference{\n") - file.write(" cylinder{\n") - file.write(" <0,0,0.0>,<0,0,h>, max(polyg_outer_r, cycle_r)\n") - file.write(" }\n\n") - file.write(" #for(i, 0, n-1)\n") - file.write(" object{\n") - file.write(" poly_obj\n") - file.write(" inverse\n") - file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n") - file.write(" }\n") - file.write(" object{\n") - file.write(" Shape_Slice_Plane_2P_1V(,,x)\n") - file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n") - file.write(" }\n") - file.write(" #end\n") - file.write("}\n\n") - file.write("object{\n") - file.write("mockup1\n") - file.write("rotate <0, 0, degrees(face_ang)>\n") - file.write("}\n") - file.write("#end\n") - #Use the macro - ngon = ob.pov.polytocircle_ngon - ngonR = ob.pov.polytocircle_ngonR - circleR = ob.pov.polytocircle_circleR - tabWrite("#declare %s = object { Shape_Polygon_To_Circle_Blending(%s, z, %.4f, %.4f, 2) rotate x*180 translate z*1\n"%(povdataname,ngon,ngonR,circleR)) - tabWrite("}\n") - continue #Don't render proxy mesh, skip to next object + if ob.pov.object_as == 'SPHERE': -############################################else try to export mesh - elif ob.is_instancer == False: #except duplis which should be instances groups for now but all duplis later - if ob.type == 'EMPTY': - tabWrite("\n//dummy sphere to represent Empty 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) + tabWrite("#declare %s = sphere { 0,%6f\n"%(povdataname,ob.pov.sphere_radius)) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + #tabWrite("rotate x*90\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - # TODO(sergey): PovRay is a render engine, so should be using dependency graph - # which was given to it via render engine API. - depsgraph = bpy.context.evaluated_depsgraph_get() - ob_eval = ob.evaluated_get(depsgraph) - try: - me = ob_eval.to_mesh() + if ob.pov.object_as == 'TORUS': + tabWrite("#declare %s = torus { %.4f,%.4f\n"%(povdataname,ob.pov.torus_major_radius,ob.pov.torus_minor_radius)) + povMatName = "Default_texture" + if ob.active_material: + #povMatName = string_strip_hyphen(bpy.path.clean_name(ob.active_material.name)) + try: + material = ob.active_material + writeObjectMaterial(material, ob) + except IndexError: + print(me) + #tabWrite("texture {%s}\n"%povMatName) + write_object_modifiers(scene,ob,file) + tabWrite("rotate x*90\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - #XXX Here? identify the specific exception for mesh object with no data - #XXX So that we can write something for the dataname ! - except: - # also happens when curves cant be made into meshes because of no-data - continue + if ob.pov.object_as == 'PARAMETRIC': + tabWrite("#declare %s = parametric {\n"%povdataname) + tabWrite("function { %s }\n"%ob.pov.x_eq) + tabWrite("function { %s }\n"%ob.pov.y_eq) + tabWrite("function { %s }\n"%ob.pov.z_eq) + tabWrite("<%.4f,%.4f>, <%.4f,%.4f>\n"%(ob.pov.u_min,ob.pov.v_min,ob.pov.u_max,ob.pov.v_max)) + if ob.pov.contained_by == "sphere": + tabWrite("contained_by { sphere{0, 2} }\n") + else: + tabWrite("contained_by { box{-2, 2} }\n") + tabWrite("max_gradient %.6f\n"%ob.pov.max_gradient) + tabWrite("accuracy %.6f\n"%ob.pov.accuracy) + tabWrite("precompute 10 x,y,z\n") + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - importance = ob.pov.importance_value - if me: - me.calc_loop_triangles() - me_materials = me.materials - me_faces = me.loop_triangles[:] - #if len(me_faces)==0: - #tabWrite("\n//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 ob.pov.object_as == 'POLYCIRCLE': + #TODO write below macro Once: + #if write_polytocircle_macro_once == 0: + file.write("/****************************\n") + file.write("This macro was written by 'And'.\n") + file.write("Link:(http://news.povray.org/povray.binaries.scene-files/)\n") + file.write("****************************/\n") + file.write("//from math.inc:\n") + file.write("#macro VPerp_Adjust(V, Axis)\n") + file.write(" vnormalize(vcross(vcross(Axis, V), Axis))\n") + file.write("#end\n") + file.write("//Then for the actual macro\n") + file.write("#macro Shape_Slice_Plane_2P_1V(point1, point2, clip_direct)\n") + file.write("#local p1 = point1 + <0,0,0>;\n") + file.write("#local p2 = point2 + <0,0,0>;\n") + file.write("#local clip_v = vnormalize(clip_direct + <0,0,0>);\n") + file.write("#local direct_v1 = vnormalize(p2 - p1);\n") + file.write("#if(vdot(direct_v1, clip_v) = 1)\n") + file.write(' #error "Shape_Slice_Plane_2P_1V error: Can\'t decide plane"\n') + file.write("#end\n\n") + file.write("#local norm = -vnormalize(clip_v - direct_v1*vdot(direct_v1,clip_v));\n") + file.write("#local d = vdot(norm, p1);\n") + file.write("plane{\n") + file.write("norm, d\n") + file.write("}\n") + file.write("#end\n\n") + file.write("//polygon to circle\n") + file.write("#macro Shape_Polygon_To_Circle_Blending(_polygon_n, _side_face, _polygon_circumscribed_radius, _circle_radius, _height)\n") + file.write("#local n = int(_polygon_n);\n") + file.write("#if(n < 3)\n") + file.write(" #error ""\n") + file.write("#end\n\n") + file.write("#local front_v = VPerp_Adjust(_side_face, z);\n") + file.write("#if(vdot(front_v, x) >= 0)\n") + file.write(" #local face_ang = acos(vdot(-y, front_v));\n") + file.write("#else\n") + file.write(" #local face_ang = -acos(vdot(-y, front_v));\n") + file.write("#end\n") + file.write("#local polyg_ext_ang = 2*pi/n;\n") + file.write("#local polyg_outer_r = _polygon_circumscribed_radius;\n") + file.write("#local polyg_inner_r = polyg_outer_r*cos(polyg_ext_ang/2);\n") + file.write("#local cycle_r = _circle_radius;\n") + file.write("#local h = _height;\n") + file.write("#if(polyg_outer_r < 0 | cycle_r < 0 | h <= 0)\n") + file.write(' #error "error: each side length must be positive"\n') + file.write("#end\n\n") + file.write("#local multi = 1000;\n") + file.write("#local poly_obj =\n") + file.write("polynomial{\n") + file.write("4,\n") + file.write("xyz(0,2,2): multi*1,\n") + file.write("xyz(2,0,1): multi*2*h,\n") + file.write("xyz(1,0,2): multi*2*(polyg_inner_r-cycle_r),\n") + file.write("xyz(2,0,0): multi*(-h*h),\n") + file.write("xyz(0,0,2): multi*(-pow(cycle_r - polyg_inner_r, 2)),\n") + file.write("xyz(1,0,1): multi*2*h*(-2*polyg_inner_r + cycle_r),\n") + file.write("xyz(1,0,0): multi*2*h*h*polyg_inner_r,\n") + file.write("xyz(0,0,1): multi*2*h*polyg_inner_r*(polyg_inner_r - cycle_r),\n") + file.write("xyz(0,0,0): multi*(-pow(polyg_inner_r*h, 2))\n") + file.write("sturm\n") + file.write("}\n\n") + file.write("#local mockup1 =\n") + file.write("difference{\n") + file.write(" cylinder{\n") + file.write(" <0,0,0.0>,<0,0,h>, max(polyg_outer_r, cycle_r)\n") + file.write(" }\n\n") + file.write(" #for(i, 0, n-1)\n") + file.write(" object{\n") + file.write(" poly_obj\n") + file.write(" inverse\n") + file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n") + file.write(" }\n") + file.write(" object{\n") + file.write(" Shape_Slice_Plane_2P_1V(,,x)\n") + file.write(" rotate <0, 0, -90 + degrees(polyg_ext_ang*i)>\n") + file.write(" }\n") + file.write(" #end\n") + file.write("}\n\n") + file.write("object{\n") + file.write("mockup1\n") + file.write("rotate <0, 0, degrees(face_ang)>\n") + file.write("}\n") + file.write("#end\n") + #Use the macro + ngon = ob.pov.polytocircle_ngon + ngonR = ob.pov.polytocircle_ngonR + circleR = ob.pov.polytocircle_circleR + tabWrite("#declare %s = object { Shape_Polygon_To_Circle_Blending(%s, z, %.4f, %.4f, 2) rotate x*180 translate z*1\n"%(povdataname,ngon,ngonR,circleR)) + tabWrite("}\n") + continue #Don't render proxy mesh, skip to next object - if not me or not me_faces: - tabWrite("\n//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) - continue + ############################################else try to export mesh + elif ob.is_instancer == False: #except duplis which should be instances groups for now but all duplis later + if ob.type == 'EMPTY': + tabWrite("\n//dummy sphere to represent Empty 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) - uv_layers = me.uv_layers - if len(uv_layers) > 0: - if me.uv_layers.active and uv_layers.active.data: - uv_layer = uv_layers.active.data - else: - uv_layer = None + # TODO(sergey): PovRay is a render engine, so should be using dependency graph + # which was given to it via render engine API. + depsgraph = bpy.context.evaluated_depsgraph_get() + ob_eval = ob.evaluated_get(depsgraph) + try: + me = ob_eval.to_mesh() - try: - #vcol_layer = me.vertex_colors.active.data - vcol_layer = me.vertex_colors.active.data - except AttributeError: - vcol_layer = None + #XXX Here? identify the specific exception for mesh object with no data + #XXX So that we can write something for the dataname ! + except: - faces_verts = [f.vertices[:] for f in me_faces] - faces_normals = [f.normal[:] for f in me_faces] - verts_normals = [v.normal[:] for v in me.vertices] + # also happens when curves cant be made into meshes because of no-data + continue - # Use named declaration to allow reference e.g. for baking. MR - file.write("\n") - tabWrite("#declare %s =\n" % povdataname) - tabWrite("mesh2 {\n") - tabWrite("vertex_vectors {\n") - tabWrite("%d" % len(me.vertices)) # vert count - - tabStr = tab * tabLevel - for v in me.vertices: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%.6f, %.6f, %.6f>" % v.co[:]) # vert count - else: - file.write(", ") - file.write("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count - #tabWrite("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count - file.write("\n") - tabWrite("}\n") + importance = ob.pov.importance_value + if me: + me.calc_loop_triangles() + me_materials = me.materials + me_faces = me.loop_triangles[:] + #if len(me_faces)==0: + #tabWrite("\n//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) - # Build unique Normal list - uniqueNormals = {} - for fi, f in enumerate(me_faces): - fv = faces_verts[fi] - # [-1] is a dummy index, use a list so we can modify in place - if f.use_smooth: # Use vertex normals - for v in fv: - key = verts_normals[v] - uniqueNormals[key] = [-1] - else: # Use face normal - key = faces_normals[fi] - uniqueNormals[key] = [-1] - - tabWrite("normal_vectors {\n") - tabWrite("%d" % len(uniqueNormals)) # vert count - idx = 0 - tabStr = tab * tabLevel - for no, index in uniqueNormals.items(): - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%.6f, %.6f, %.6f>" % no) # vert count + + if not me or not me_faces: + tabWrite("\n//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) + continue + + uv_layers = me.uv_layers + if len(uv_layers) > 0: + if me.uv_layers.active and uv_layers.active.data: + uv_layer = uv_layers.active.data else: - file.write(", ") - file.write("<%.6f, %.6f, %.6f>" % no) # vert count - index[0] = idx - idx += 1 - file.write("\n") - tabWrite("}\n") + uv_layer = None - # Vertex colors - vertCols = {} # Use for material colors also. + try: + #vcol_layer = me.vertex_colors.active.data + vcol_layer = me.vertex_colors.active.data + except AttributeError: + vcol_layer = None - if uv_layer: - # Generate unique UV's - uniqueUVs = {} - #n = 0 - for f in me_faces: # me.faces in 2.7 - uvs = [uv_layer[l].uv[:] for l in f.loops] + faces_verts = [f.vertices[:] for f in me_faces] + faces_normals = [f.normal[:] for f in me_faces] + verts_normals = [v.normal[:] for v in me.vertices] - for uv in uvs: - uniqueUVs[uv[:]] = [-1] + # Use named declaration to allow reference e.g. for baking. MR + file.write("\n") + tabWrite("#declare %s =\n" % povdataname) + tabWrite("mesh2 {\n") + tabWrite("vertex_vectors {\n") + tabWrite("%d" % len(me.vertices)) # vert count - tabWrite("uv_vectors {\n") - #print unique_uvs - tabWrite("%d" % len(uniqueUVs)) # vert count - idx = 0 tabStr = tab * tabLevel - for uv, index in uniqueUVs.items(): + for v in me.vertices: if linebreaksinlists: file.write(",\n") - file.write(tabStr + "<%.6f, %.6f>" % uv) + file.write(tabStr + "<%.6f, %.6f, %.6f>" % v.co[:]) # vert count else: file.write(", ") - file.write("<%.6f, %.6f>" % uv) - index[0] = idx - idx += 1 - ''' - else: - # Just add 1 dummy vector, no real UV's - tabWrite('1') # vert count - file.write(',\n\t\t<0.0, 0.0>') - ''' + file.write("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count + #tabWrite("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count file.write("\n") tabWrite("}\n") - if me.vertex_colors: - #Write down vertex colors as a texture for each vertex - tabWrite("texture_list {\n") - tabWrite("%d\n" % (len(me_faces) * 3)) # assumes we have only triangles - VcolIdx=0 - if comments: - file.write("\n //Vertex colors: one simple pigment texture per vertex\n") + # Build unique Normal list + uniqueNormals = {} for fi, f in enumerate(me_faces): - # annoying, index may be invalid - material_index = f.material_index - try: - material = me_materials[material_index] - except: - material = None - if material: #and material.use_vertex_color_paint: #Always use vertex color when there is some for now - - cols = [vcol_layer[l].color[:] for l in f.loops] + fv = faces_verts[fi] + # [-1] is a dummy index, use a list so we can modify in place + if f.use_smooth: # Use vertex normals + for v in fv: + key = verts_normals[v] + uniqueNormals[key] = [-1] + else: # Use face normal + key = faces_normals[fi] + uniqueNormals[key] = [-1] - for col in cols: - key = col[0], col[1], col[2], material_index # Material index! - VcolIdx+=1 - vertCols[key] = [VcolIdx] - if linebreaksinlists: - tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}\n" % (col[0], col[1], col[2])) - else: - tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}" % (col[0], col[1], col[2])) - tabStr = tab * tabLevel + tabWrite("normal_vectors {\n") + tabWrite("%d" % len(uniqueNormals)) # vert count + idx = 0 + tabStr = tab * tabLevel + for no, index in uniqueNormals.items(): + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%.6f, %.6f, %.6f>" % no) # vert count else: - if material: - # Multiply diffuse with SSS Color - if material.pov_subsurface_scattering.use: - diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])] - key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \ - material_index - vertCols[key] = [-1] - else: - diffuse_color = material.diffuse_color[:] - key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \ - material_index - vertCols[key] = [-1] + file.write(", ") + file.write("<%.6f, %.6f, %.6f>" % no) # vert count + index[0] = idx + idx += 1 + file.write("\n") + tabWrite("}\n") - tabWrite("\n}\n") - # Face indices - tabWrite("\nface_indices {\n") - tabWrite("%d" % (len(me_faces))) # faces count - tabStr = tab * tabLevel + # Vertex colors + vertCols = {} # Use for material colors also. - for fi, f in enumerate(me_faces): - fv = faces_verts[fi] - material_index = f.material_index + if uv_layer: + # Generate unique UV's + uniqueUVs = {} + #n = 0 + for f in me_faces: # me.faces in 2.7 + uvs = [uv_layer[l].uv[:] for l in f.loops] - if vcol_layer: - cols = [vcol_layer[l].color[:] for l in f.loops] + for uv in uvs: + uniqueUVs[uv[:]] = [-1] - if not me_materials or me_materials[material_index] is None: # No materials + tabWrite("uv_vectors {\n") + #print unique_uvs + tabWrite("%d" % len(uniqueUVs)) # vert count + idx = 0 + tabStr = tab * tabLevel + for uv, index in uniqueUVs.items(): if linebreaksinlists: file.write(",\n") - # vert count - file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2])) + file.write(tabStr + "<%.6f, %.6f>" % uv) else: file.write(", ") - file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count + file.write("<%.6f, %.6f>" % uv) + index[0] = idx + idx += 1 + ''' else: - material = me_materials[material_index] - if me.vertex_colors: #and material.use_vertex_color_paint: - # Color per vertex - vertex color - - col1 = cols[0] - col2 = cols[1] - col3 = cols[2] + # Just add 1 dummy vector, no real UV's + tabWrite('1') # vert count + file.write(',\n\t\t<0.0, 0.0>') + ''' + file.write("\n") + tabWrite("}\n") - 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] - else: - # Color per material - flat material color - if material.pov_subsurface_scattering.use: - diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])] - else: - diffuse_color = material.diffuse_color[:] - ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ - diffuse_color[2], f.material_index][0] - # ci are zero based index so we'll subtract 1 from them - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ - (fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count + if me.vertex_colors: + #Write down vertex colors as a texture for each vertex + tabWrite("texture_list {\n") + tabWrite("%d\n" % (len(me_faces) * 3)) # assumes we have only triangles + VcolIdx=0 + if comments: + file.write("\n //Vertex colors: one simple pigment texture per vertex\n") + for fi, f in enumerate(me_faces): + # annoying, index may be invalid + material_index = f.material_index + try: + material = me_materials[material_index] + except: + material = None + if material: #and material.use_vertex_color_paint: #Always use vertex color when there is some for now + + cols = [vcol_layer[l].color[:] for l in f.loops] + + for col in cols: + key = col[0], col[1], col[2], material_index # Material index! + VcolIdx+=1 + vertCols[key] = [VcolIdx] + if linebreaksinlists: + tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}\n" % (col[0], col[1], col[2])) + else: + tabWrite("texture {pigment{ color srgb <%6f,%6f,%6f> }}" % (col[0], col[1], col[2])) + tabStr = tab * tabLevel else: - file.write(", ") - file.write("<%d,%d,%d>, %d,%d,%d" % \ - (fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count + if material: + # Multiply diffuse with SSS Color + if material.pov_subsurface_scattering.use: + diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])] + key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \ + material_index + vertCols[key] = [-1] + else: + diffuse_color = material.diffuse_color[:] + key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \ + material_index + vertCols[key] = [-1] + + tabWrite("\n}\n") + # Face indices + tabWrite("\nface_indices {\n") + tabWrite("%d" % (len(me_faces))) # faces count + tabStr = tab * tabLevel - file.write("\n") - tabWrite("}\n") + for fi, f in enumerate(me_faces): + fv = faces_verts[fi] + material_index = f.material_index - # normal_indices indices - tabWrite("normal_indices {\n") - tabWrite("%d" % (len(me_faces))) # faces count - tabStr = tab * tabLevel - for fi, fv in enumerate(faces_verts): + if vcol_layer: + cols = [vcol_layer[l].color[:] for l in f.loops] - if me_faces[fi].use_smooth: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[0]]][0],\ - uniqueNormals[verts_normals[fv[1]]][0],\ - uniqueNormals[verts_normals[fv[2]]][0])) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[0]]][0],\ - uniqueNormals[verts_normals[fv[1]]][0],\ - uniqueNormals[verts_normals[fv[2]]][0])) # vert count - else: - idx = uniqueNormals[faces_normals[fi]][0] - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count + if not me_materials or me_materials[material_index] is None: # No materials + if linebreaksinlists: + file.write(",\n") + # vert count + file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2])) + else: + file.write(", ") + file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count else: - file.write(", ") - file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count + material = me_materials[material_index] + if me.vertex_colors: #and material.use_vertex_color_paint: + # Color per vertex - vertex color - file.write("\n") - tabWrite("}\n") + col1 = cols[0] + col2 = cols[1] + col3 = cols[2] - if uv_layer: - tabWrite("uv_indices {\n") + 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] + else: + # Color per material - flat material color + if material.pov_subsurface_scattering.use: + diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])] + else: + diffuse_color = material.diffuse_color[:] + ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ + diffuse_color[2], f.material_index][0] + # ci are zero based index so we'll subtract 1 from them + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1-1, ci2-1, ci3-1)) # vert count + + file.write("\n") + tabWrite("}\n") + + # normal_indices indices + tabWrite("normal_indices {\n") tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel - for f in me_faces: - uvs = [uv_layer[l].uv[:] for l in f.loops] + for fi, fv in enumerate(faces_verts): - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % ( - uniqueUVs[uvs[0]][0],\ - uniqueUVs[uvs[1]][0],\ - uniqueUVs[uvs[2]][0])) + if me_faces[fi].use_smooth: + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count else: - file.write(", ") - file.write("<%d,%d,%d>" % ( - uniqueUVs[uvs[0]][0],\ - uniqueUVs[uvs[1]][0],\ - uniqueUVs[uvs[2]][0])) + idx = uniqueNormals[faces_normals[fi]][0] + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count file.write("\n") tabWrite("}\n") - #XXX BOOLEAN - onceCSG = 0 - for mod in ob.modifiers: - if onceCSG == 0: - if mod : - if mod.type == 'BOOLEAN': - if ob.pov.boolean_mod == "POV": - file.write("\tinside_vector <%.6g, %.6g, %.6g>\n" % - (ob.pov.inside_vector[0], - ob.pov.inside_vector[1], - ob.pov.inside_vector[2])) - onceCSG = 1 - - if me.materials: - try: - material = me.materials[0] # dodgy - writeObjectMaterial(material, ob) - except IndexError: - print(me) + if uv_layer: + tabWrite("uv_indices {\n") + tabWrite("%d" % (len(me_faces))) # faces count + tabStr = tab * tabLevel + for f in me_faces: + uvs = [uv_layer[l].uv[:] for l in f.loops] - # POV object modifiers such as - # hollow / sturm / double_illuminate etc. - write_object_modifiers(scene,ob,file) + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) + else: + file.write(", ") + file.write("<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) - #Importance for radiosity sampling added here: - tabWrite("radiosity { \n") - tabWrite("importance %3g \n" % importance) - tabWrite("}\n") + file.write("\n") + tabWrite("}\n") - tabWrite("}\n") # End of mesh block - else: - facesMaterials = [] # WARNING!!!!!!!!!!!!!!!!!!!!!! - if me_materials: - for f in me_faces: - if f.material_index not in facesMaterials: - facesMaterials.append(f.material_index) - # No vertex colors, so write material colors as vertex colors - for i, material in enumerate(me_materials): - - if material and material.pov.material_use_nodes == False: # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # Multiply diffuse with SSS Color - if material.pov_subsurface_scattering.use: - diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])] - key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat - vertCols[key] = [-1] - else: - diffuse_color = material.diffuse_color[:] - key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat - vertCols[key] = [-1] - - idx = 0 - LocalMaterialNames = [] - for col, index in vertCols.items(): - #if me_materials: - mater = me_materials[col[3]] - if me_materials is None: #XXX working? - material_finish = DEF_MAT_NAME # not working properly, - trans = 0.0 + #XXX BOOLEAN + onceCSG = 0 + for mod in ob.modifiers: + if onceCSG == 0: + if mod : + if mod.type == 'BOOLEAN': + if ob.pov.boolean_mod == "POV": + file.write("\tinside_vector <%.6g, %.6g, %.6g>\n" % + (ob.pov.inside_vector[0], + ob.pov.inside_vector[1], + ob.pov.inside_vector[2])) + onceCSG = 1 + + if me.materials: + try: + material = me.materials[0] # dodgy + writeObjectMaterial(material, ob) + except IndexError: + print(me) + + # POV object modifiers such as + # hollow / sturm / double_illuminate etc. + write_object_modifiers(scene,ob,file) + + #Importance for radiosity sampling added here: + tabWrite("radiosity { \n") + tabWrite("importance %3g \n" % importance) + tabWrite("}\n") - else: - shading.writeTextureInfluence(mater, materialNames, - LocalMaterialNames, - path_image, lampCount, - imageFormat, imgMap, - imgMapTransforms, - tabWrite, comments, - string_strip_hyphen, - safety, col, os, preview_dir, unpacked_images) - ################################################################### - index[0] = idx - idx += 1 - - - - # Vert Colors - tabWrite("texture_list {\n") - # In case there's is no material slot, give at least one texture - #(an empty one so it uses pov default) - if len(vertCols)==0: - file.write(tabStr + "1") + tabWrite("}\n") # End of mesh block else: - file.write(tabStr + "%s" % (len(vertCols))) # vert count + facesMaterials = [] # WARNING!!!!!!!!!!!!!!!!!!!!!! + if me_materials: + for f in me_faces: + if f.material_index not in facesMaterials: + facesMaterials.append(f.material_index) + # No vertex colors, so write material colors as vertex colors + for i, material in enumerate(me_materials): + + if material and material.pov.material_use_nodes == False: # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # Multiply diffuse with SSS Color + if material.pov_subsurface_scattering.use: + diffuse_color = [i * j for i, j in zip(material.pov_subsurface_scattering.color[:], material.diffuse_color[:])] + key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat + vertCols[key] = [-1] + else: + diffuse_color = material.diffuse_color[:] + key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat + vertCols[key] = [-1] + idx = 0 + LocalMaterialNames = [] + for col, index in vertCols.items(): + #if me_materials: + mater = me_materials[col[3]] + if me_materials is None: #XXX working? + material_finish = DEF_MAT_NAME # not working properly, + trans = 0.0 + else: + shading.writeTextureInfluence(mater, materialNames, + LocalMaterialNames, + path_image, lampCount, + imageFormat, imgMap, + imgMapTransforms, + tabWrite, comments, + string_strip_hyphen, + safety, col, os, preview_dir, unpacked_images) + ################################################################### + index[0] = idx + idx += 1 + + + + # Vert Colors + tabWrite("texture_list {\n") + # In case there's is no material slot, give at least one texture + #(an empty one so it uses pov default) + if len(vertCols)==0: + file.write(tabStr + "1") + else: + file.write(tabStr + "%s" % (len(vertCols))) # vert count - # below "material" alias, added check ob.active_material - # to avoid variable referenced before assignment error - try: - material = ob.active_material - except IndexError: - #when no material slot exists, - material=None - - # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - if material and ob.active_material is not None and material.pov.material_use_nodes == False: - if material.pov.replacement_text != "": - file.write("\n") - file.write(" texture{%s}\n" % material.pov.replacement_text) - 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - else: - file.write(" texture{}\n") - tabWrite("}\n") - - # Face indices - tabWrite("face_indices {\n") - tabWrite("%d" % (len(me_faces))) # faces count - tabStr = tab * tabLevel - for fi, f in enumerate(me_faces): - fv = faces_verts[fi] - material_index = f.material_index + # 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 vcol_layer: - cols = [vcol_layer[l].color[:] for l in f.loops] + # 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) - if not me_materials or me_materials[material_index] is None: # No materials - if linebreaksinlists: - file.write(",\n") - # vert count - file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2])) else: - file.write(", ") - file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count + # 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! else: - material = me_materials[material_index] - ci1 = ci2 = ci3 = f.material_index - if me.vertex_colors: #and material.use_vertex_color_paint: - # Color per vertex - vertex color - - col1 = cols[0] - col2 = cols[1] - col3 = cols[2] - - ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0] - ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0] - ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0] - elif material.pov.material_use_nodes: - ci1 = ci2 = ci3 = 0 - else: - # Color per material - flat material color - if material.pov_subsurface_scattering.use: - diffuse_color = [i * j for i, j in - zip(material.pov_subsurface_scattering.color[:], - material.diffuse_color[:])] - else: - diffuse_color = material.diffuse_color[:] - ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ - diffuse_color[2], f.material_index][0] + file.write(" texture{}\n") + tabWrite("}\n") - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ - (fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>, %d,%d,%d" % \ - (fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count + # Face indices + tabWrite("face_indices {\n") + tabWrite("%d" % (len(me_faces))) # faces count + tabStr = tab * tabLevel - file.write("\n") - tabWrite("}\n") + for fi, f in enumerate(me_faces): + fv = faces_verts[fi] + material_index = f.material_index - # normal_indices indices - tabWrite("normal_indices {\n") - tabWrite("%d" % (len(me_faces))) # faces count - tabStr = tab * tabLevel - for fi, fv in enumerate(faces_verts): - if me_faces[fi].use_smooth: - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[0]]][0],\ - uniqueNormals[verts_normals[fv[1]]][0],\ - uniqueNormals[verts_normals[fv[2]]][0])) # vert count - else: - file.write(", ") - file.write("<%d,%d,%d>" %\ - (uniqueNormals[verts_normals[fv[0]]][0],\ - uniqueNormals[verts_normals[fv[1]]][0],\ - uniqueNormals[verts_normals[fv[2]]][0])) # vert count - else: - idx = uniqueNormals[faces_normals[fi]][0] - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vertcount + if vcol_layer: + cols = [vcol_layer[l].color[:] for l in f.loops] + + if not me_materials or me_materials[material_index] is None: # No materials + if linebreaksinlists: + file.write(",\n") + # vert count + file.write(tabStr + "<%d,%d,%d>" % (fv[0], fv[1], fv[2])) + else: + file.write(", ") + file.write("<%d,%d,%d>" % (fv[0], fv[1], fv[2])) # vert count else: - file.write(", ") - file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count + material = me_materials[material_index] + ci1 = ci2 = ci3 = f.material_index + if me.vertex_colors: #and material.use_vertex_color_paint: + # Color per vertex - vertex color + + col1 = cols[0] + col2 = cols[1] + col3 = cols[2] + + ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0] + ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0] + ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0] + elif material.pov.material_use_nodes: + ci1 = ci2 = ci3 = 0 + else: + # Color per material - flat material color + if material.pov_subsurface_scattering.use: + diffuse_color = [i * j for i, j in + zip(material.pov_subsurface_scattering.color[:], + material.diffuse_color[:])] + else: + diffuse_color = material.diffuse_color[:] + ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \ + diffuse_color[2], f.material_index][0] - file.write("\n") - tabWrite("}\n") + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>, %d,%d,%d" % \ + (fv[0], fv[1], fv[2], ci1, ci2, ci3)) # vert count - if uv_layer: - tabWrite("uv_indices {\n") + file.write("\n") + tabWrite("}\n") + + # normal_indices indices + tabWrite("normal_indices {\n") tabWrite("%d" % (len(me_faces))) # faces count tabStr = tab * tabLevel - for f in me_faces: - uvs = [uv_layer[l].uv[:] for l in f.loops] - - if linebreaksinlists: - file.write(",\n") - file.write(tabStr + "<%d,%d,%d>" % ( - uniqueUVs[uvs[0]][0],\ - uniqueUVs[uvs[1]][0],\ - uniqueUVs[uvs[2]][0])) + for fi, fv in enumerate(faces_verts): + if me_faces[fi].use_smooth: + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count + else: + file.write(", ") + file.write("<%d,%d,%d>" %\ + (uniqueNormals[verts_normals[fv[0]]][0],\ + uniqueNormals[verts_normals[fv[1]]][0],\ + uniqueNormals[verts_normals[fv[2]]][0])) # vert count else: - file.write(", ") - file.write("<%d,%d,%d>" % ( - uniqueUVs[uvs[0]][0],\ - uniqueUVs[uvs[1]][0],\ - uniqueUVs[uvs[2]][0])) + 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") - #XXX BOOLEAN - onceCSG = 0 - for mod in ob.modifiers: - if onceCSG == 0: - if mod : - if mod.type == 'BOOLEAN': - if ob.pov.boolean_mod == "POV": - file.write("\tinside_vector <%.6g, %.6g, %.6g>\n" % - (ob.pov.inside_vector[0], - ob.pov.inside_vector[1], - ob.pov.inside_vector[2])) - onceCSG = 1 - - if me.materials: - try: - material = me.materials[0] # dodgy - writeObjectMaterial(material, ob) - except IndexError: - print(me) + if uv_layer: + tabWrite("uv_indices {\n") + tabWrite("%d" % (len(me_faces))) # faces count + tabStr = tab * tabLevel + for f in me_faces: + uvs = [uv_layer[l].uv[:] for l in f.loops] - # POV object modifiers such as - # hollow / sturm / double_illuminate etc. - write_object_modifiers(scene,ob,file) + if linebreaksinlists: + file.write(",\n") + file.write(tabStr + "<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) + else: + file.write(", ") + file.write("<%d,%d,%d>" % ( + uniqueUVs[uvs[0]][0],\ + uniqueUVs[uvs[1]][0],\ + uniqueUVs[uvs[2]][0])) - #Importance for radiosity sampling added here: - tabWrite("radiosity { \n") - tabWrite("importance %3g \n" % importance) - tabWrite("}\n") + file.write("\n") + tabWrite("}\n") - tabWrite("}\n") # End of mesh block + #XXX BOOLEAN + onceCSG = 0 + for mod in ob.modifiers: + if onceCSG == 0: + if mod : + if mod.type == 'BOOLEAN': + if ob.pov.boolean_mod == "POV": + file.write("\tinside_vector <%.6g, %.6g, %.6g>\n" % + (ob.pov.inside_vector[0], + ob.pov.inside_vector[1], + ob.pov.inside_vector[2])) + onceCSG = 1 + + if me.materials: + try: + material = me.materials[0] # dodgy + writeObjectMaterial(material, ob) + except IndexError: + print(me) + + # POV object modifiers such as + # hollow / sturm / double_illuminate etc. + write_object_modifiers(scene,ob,file) + + #Importance for radiosity sampling added here: + tabWrite("radiosity { \n") + tabWrite("importance %3g \n" % importance) + tabWrite("}\n") + tabWrite("}\n") # End of mesh block - ob_eval.to_mesh_clear() + + ob_eval.to_mesh_clear() if csg: duplidata_ref = [] @@ -3224,21 +3228,24 @@ def write_pov(filename, scene=None, info_callback=None): #matrix = global_matrix @ ob.matrix_world if ob.is_instancer: tabWrite("\n//--DupliObjects in %s--\n\n"% ob.name) - ob.dupli_list_create(scene) + #ob.dupli_list_create(scene) #deprecated in 2.8 + depsgraph = bpy.context.evaluated_depsgraph_get() dup = "" if ob.is_modified(scene, 'RENDER'): #modified object always unique so using object name rather than data name dup = "#declare OB%s = union{\n" %(string_strip_hyphen(bpy.path.clean_name(ob.name))) 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 instance_types - if ob.instance_type not in {'COLLECTION'} and duplidataname not in duplidata_ref: - duplidata_ref.append(duplidataname) #older key [string_strip_hyphen(bpy.path.clean_name("OB"+ob.name))] + for eachduplicate in depsgraph.object_instances: + if eachduplicate.is_instance: # Real dupli instance filtered because original included in list since 2.8 + duplidataname = "OB"+string_strip_hyphen(bpy.path.clean_name(bpy.data.objects[eachduplicate.object.name].data.name)) + dupmatrix = eachduplicate.matrix_world.copy() #has to be copied to not store instance since 2.8 + dup += ("\tobject {\n\t\tDATA%s\n\t\t%s\t}\n" %(string_strip_hyphen(bpy.path.clean_name(bpy.data.objects[eachduplicate.object.name].data.name)), MatrixAsPovString(ob.matrix_world.inverted() @ dupmatrix))) + #add object to a list so that it is not rendered for some instance_types + if ob.instance_type not in {'COLLECTION'} and duplidataname not in duplidata_ref: + duplidata_ref.append(duplidataname) #older key [string_strip_hyphen(bpy.path.clean_name("OB"+ob.name))] dup += "}\n" - ob.dupli_list_clear() + #ob.dupli_list_clear()# just do not store any reference to instance since 2.8 tabWrite(dup) else: continue -- cgit v1.2.3