Skip to content
Snippets Groups Projects
render.py 278 KiB
Newer Older
  • Learn to ignore specific revisions
  •                                         '                        [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
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                                        # pSys.set_resolution(scene, ob, 'PREVIEW') #DEPRECATED
    
                                        # When you render, the entire dependency graph will be
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                                        # evaluated at render resolution, including the particles.
    
                                        # In the viewport it will be at viewport resolution.
                                        # So there is no need fo render engines to use this function anymore,
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                                        # it's automatic now.
    
                                        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:
    
                            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
    
                            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
    
                        #############################################
    
                            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)
    
    
                        ############################################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
                                )
    
                                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))
    
                            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)
    
                            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")
    
                            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")
    
                            continue  # Don't render proxy mesh, skip to next object
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                        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")
    
                            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")
    
                            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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                        if ob.pov.object_as == 'SPHERE':
    
                            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")
    
                            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 == '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(<polyg_inner_r,0,0>,<cycle_r,0,h>,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")
    
                            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)
                            )
    
                            continue  # Don't render proxy mesh, skip to next object
    
                        ############################################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
                                )
    
                            # 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()
    
                            # XXX Here? identify the specific exception for mesh object with no data
                            # XXX So that we can write something for the dataname !
    
                                # also happens when curves cant be made into meshes because of no-data
                                continue
    
                            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 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
    
                                # vcol_layer = me.vertex_colors.active.data
    
                                vcol_layer = me.vertex_colors.active.data
                            except AttributeError:
                                vcol_layer = None
    
                            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]
    
                            # 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
    
                                    file.write(
                                        "<%.6f, %.6f, %.6f>" % v.co[:]
                                    )  # vert count
                                # tabWrite("<%.6f, %.6f, %.6f>" % v.co[:])  # vert count
    
                            file.write("\n")
                            tabWrite("}\n")
    
                            # 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
    
                                    file.write(", ")
    
                                    file.write(
                                        "<%.6f, %.6f, %.6f>" % no
                                    )  # vert count
    
                                index[0] = idx
                                idx += 1
                            file.write("\n")
                            tabWrite("}\n")
    
                            # Vertex colors
                            vertCols = {}  # Use for material colors also.
    
                            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]
    
                                    for uv in uvs:
                                        uniqueUVs[uv[:]] = [-1]
    
                                tabWrite("uv_vectors {\n")
    
                                tabWrite("%d" % len(uniqueUVs))  # vert count
                                idx = 0
                                tabStr = tab * tabLevel
                                for uv, index in uniqueUVs.items():
    
                                    if linebreaksinlists:
                                        file.write(",\n")
    
                                        file.write(tabStr + "<%.6f, %.6f>" % uv)
    
                                    else:
                                        file.write(", ")
    
                                        file.write("<%.6f, %.6f>" % uv)
                                    index[0] = idx
                                    idx += 1
                                '''
    
                                    # 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")
    
                            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
    
                                    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
                                        ]
    
                                            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])
                                                )
    
                                                tabWrite(
                                                    "texture {pigment{ color srgb <%6f,%6f,%6f> }}"
                                                    % (col[0], col[1], col[2])
                                                )
    
                                                tabStr = tab * tabLevel
    
                                        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
    
                                for fi, f in enumerate(me_faces):
                                    fv = faces_verts[fi]
                                    material_index = f.material_index
    
                                        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
    
                                        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]
    
                                            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[:],
                                                    )
                                                ]
    
                                                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 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
    
                                        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")
    
                                if uv_layer:
                                    tabWrite("uv_indices {\n")
                                    tabWrite("%d" % (len(me_faces)))  # faces count
                                    tabStr = tab * tabLevel
                                    for f in me_faces:
                                        uvs = [uv_layer[l].uv[:] for l in f.loops]
    
                                        if linebreaksinlists:
                                            file.write(",\n")
    
                                            file.write(
                                                tabStr
                                                + "<%d,%d,%d>"
                                                % (
                                                    uniqueUVs[uvs[0]][0],
                                                    uniqueUVs[uvs[1]][0],
                                                    uniqueUVs[uvs[2]][0],
                                                )
                                            )
    
                                        else:
                                            file.write(", ")
    
                                            file.write(
                                                "<%d,%d,%d>"
                                                % (
                                                    uniqueUVs[uvs[0]][0],
                                                    uniqueUVs[uvs[1]][0],
                                                    uniqueUVs[uvs[2]][0],
                                                )
                                            )