Skip to content
Snippets Groups Projects
render.py 277 KiB
Newer Older
  • Learn to ignore specific revisions
  •                                     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
    
                                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():
    
                                            mater = me_materials[col[3]]
    
                                            if me_materials is None:  # XXX working?
                                                material_finish = (
                                                    DEF_MAT_NAME
                                                )  # not working properly,
    
                                                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
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                                # 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
                                        )
    
                                        # 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
                                    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
    
                                        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]
                                        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[:],
                                                    )
                                                ]
    
                                                diffuse_color = material.diffuse_color[
                                                    :
                                                ]
                                            ci1 = ci2 = ci3 = vertCols[
                                                diffuse_color[0],
                                                diffuse_color[1],
                                                diffuse_color[2],
                                                f.material_index,
                                            ][0]
    
                                        if linebreaksinlists:
                                            file.write(",\n")
    
                                            file.write(
                                                tabStr
                                                + "<%d,%d,%d>, %d,%d,%d"
                                                % (
                                                    fv[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
    
                                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)
                                            )  # vertcount
    
                                        else:
                                            file.write(", ")
    
                                            file.write(
                                                "<%d,%d,%d>" % (idx, idx, idx)
                                            )  # vert count
    
    
                                file.write("\n")
                                tabWrite("}\n")
    
                                if uv_layer:
                                    tabWrite("uv_indices {\n")
                                    tabWrite("%d" % (len(me_faces)))  # 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],
                                                )
                                            )
    
                                    file.write("\n")
                                    tabWrite("}\n")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
    
                                onceCSG = 0
                                for mod in ob.modifiers:
                                    if onceCSG == 0:
    
                                            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")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                                tabWrite("}\n")  # End of mesh block
    
                            ob_eval.to_mesh_clear()
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            if csg:
                duplidata_ref = []
    
                _dupnames_seen = (
                    dict()
                )  # avoid duplicate output during introspection
    
                    # matrix = global_matrix @ ob.matrix_world
    
                        tabWrite("\n//--DupliObjects in %s--\n\n" % ob.name)
                        # 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))
                            )
    
                            dup = "#declare DATA%s = union{\n" % (
                                string_strip_hyphen(bpy.path.clean_name(ob.name))
                            )
    
                        for eachduplicate in depsgraph.object_instances:
    
                            if (
                                eachduplicate.is_instance
                            ):  # Real dupli instance filtered because original included in list since 2.8
    
                                _dupname = eachduplicate.object.name
                                _dupobj = bpy.data.objects[_dupname]
                                # BEGIN introspection for troubleshooting purposes
                                if not "name" in dir(_dupobj.data):
                                    if _dupname not in _dupnames_seen:
    
                                        print(
                                            "WARNING: bpy.data.objects[%s].data (of type %s) has no 'name' attribute"
                                            % (_dupname, type(_dupobj.data))
                                        )
    
                                        for _thing in dir(_dupobj):
    
                                            print(
                                                "||  %s.%s = %s"
                                                % (
                                                    _dupname,
                                                    _thing,
                                                    getattr(_dupobj, _thing),
                                                )
                                            )
    
                                        _dupnames_seen[_dupname] = 1
    
                                        print(
                                            "''=>  Unparseable objects so far: %s"
                                            % (_dupnames_seen)
                                        )
    
                                    else:
                                        _dupnames_seen[_dupname] += 1
                                    continue  # don't try to parse data objects with no name attribute
                                # END introspection for troubleshooting purposes
    
                                duplidataname = "OB" + string_strip_hyphen(
                                    bpy.path.clean_name(_dupobj.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(_dupobj.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))]
    
                        # ob.dupli_list_clear()# just do not store any reference to instance since 2.8
    
                print(
                    "WARNING: Unparseable objects in current .blend file:\n''=> %s"
                    % (_dupnames_seen)
                )
    
                print("duplidata_ref = %s" % (duplidata_ref))
    
                for data_name, inst in data_ref.items():
                    for ob_name, matrix_str in inst:
    
                        if (
                            ob_name not in duplidata_ref
                        ):  # .items() for a dictionary
                            tabWrite(
                                "\n//----Blender Object Name:%s----\n" % ob_name
                            )
    
                            if ob.pov.object_as == '':
                                tabWrite("object { \n")
                                tabWrite("%s\n" % data_name)
                                tabWrite("%s\n" % matrix_str)
                                tabWrite("}\n")
                            else:
                                no_boolean = True
                                for mod in ob.modifiers:
                                    if mod.type == 'BOOLEAN':
                                        operation = None
                                        no_boolean = False
                                        if mod.operation == 'INTERSECT':
                                            operation = 'intersection'
                                        else:
                                            operation = mod.operation.lower()
    
                                        mod_ob_name = string_strip_hyphen(
                                            bpy.path.clean_name(mod.object.name)
                                        )
                                        mod_matrix = (
                                            global_matrix @ mod.object.matrix_world
                                        )
                                        mod_ob_matrix = MatrixAsPovString(
                                            mod_matrix
                                        )
                                        tabWrite("%s { \n" % operation)
    
                                        tabWrite("object { \n")
                                        tabWrite("%s\n" % data_name)
                                        tabWrite("%s\n" % matrix_str)
                                        tabWrite("}\n")
                                        tabWrite("object { \n")
    
                                        tabWrite("%s\n" % ('DATA' + mod_ob_name))
    
                                        tabWrite("%s\n" % mod_ob_matrix)
                                        tabWrite("}\n")
                                        tabWrite("}\n")
                                        break
                                if no_boolean:
                                    tabWrite("object { \n")
                                    tabWrite("%s\n" % data_name)
                                    tabWrite("%s\n" % matrix_str)
                                    tabWrite("}\n")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def exportWorld(world):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            """write world as POV backgrounbd and sky_sphere to exported file """
    
            render = scene.pov
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            camera = scene.camera
    
            matrix = global_matrix @ camera.matrix_world
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            if not world:
                return
    
            #############Maurice####################################
    
            # These lines added to get sky gradient (visible with PNG output)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            if world:
    
                # For simple flat background:
    
                if not world.pov.use_sky_blend:
    
                    # Non fully transparent background could premultiply alpha and avoid anti-aliasing
                    # display issue:
    
                    if render.alpha_mode == 'TRANSPARENT':
    
                        tabWrite(
                            "background {rgbt<%.3g, %.3g, %.3g, 0.75>}\n"
                            % (world.pov.horizon_color[:])
                        )
                    # Currently using no alpha with Sky option:
    
                    elif render.alpha_mode == 'SKY':
    
                        tabWrite(
                            "background {rgbt<%.3g, %.3g, %.3g, 0>}\n"
                            % (world.pov.horizon_color[:])
                        )
                    # StraightAlpha:
    
                    # XXX Does not exists anymore
    
                    # else:
                    # tabWrite("background {rgbt<%.3g, %.3g, %.3g, 1>}\n" % (world.pov.horizon_color[:]))
    
                worldTexCount = 0
    
                # For Background image textures
                for (
                    t
                ) in (
                    world.texture_slots
                ):  # risk to write several sky_spheres but maybe ok.
    
                    if t and t.texture.type is not None:
    
                        worldTexCount += 1
    
                    # XXX No enable checkbox for world textures yet (report it?)
    
                    # if t and t.texture.type == 'IMAGE' and t.use:
    
    Campbell Barton's avatar
    Campbell Barton committed
                        image_filename = path_image(t.texture.image)
    
                        if t.texture.image.filepath != image_filename:
                            t.texture.image.filepath = image_filename
    
                        if image_filename != "" and t.use_map_blend:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            texturesBlend = image_filename
    
                            # colvalue = t.default_value
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            t_blend = t
    
                        # Commented below was an idea to make the Background image oriented as camera
                        # taken here:
    
                        # http://news.pov.org/pov.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.pov.org%3E/
    
                        # Replace 4/3 by the ratio of each image found by some custom or existing
                        # function
    
                        # mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees" \
    
                        #                "(atan((camLocation - camLookAt).x/(camLocation - " \
                        #                "camLookAt).y)) rotate x*degrees(atan((camLocation - " \
                        #                "camLookAt).y/(camLocation - camLookAt).z)) rotate y*" \
                        #                "degrees(atan((camLocation - camLookAt).z/(camLocation - " \
                        #                "camLookAt).x)) scale <%.4g,%.4g,%.4g>b" % \
                        #                (t_blend.offset.x / 10 , t_blend.offset.y / 10 ,
                        #                 t_blend.offset.z / 10, t_blend.scale.x ,
                        #                 t_blend.scale.y , t_blend.scale.z))
    
                        # using camera rotation valuesdirectly from blender seems much easier
    
                        if t_blend.texture_coords == 'ANGMAP':
                            mappingBlend = ""
    
                            # POV-Ray "scale" is not a number of repetitions factor, but its
                            # inverse, a standard scale factor.
                            # 0.5 Offset is needed relatively to scale because center of the
                            # UV scale is 0.5,0.5 in blender and 0,0 in POV
    
                            # Further Scale by 2 and translate by -1 are
    
                            # required for the sky_sphere not to repeat
    
                            mappingBlend = (
                                "scale 2 scale <%.4g,%.4g,%.4g> translate -1 "
                                "translate <%.4g,%.4g,%.4g> rotate<0,0,0> "
                                % (
                                    (1.0 / t_blend.scale.x),
                                    (1.0 / t_blend.scale.y),
                                    (1.0 / t_blend.scale.z),
                                    0.5
                                    - (0.5 / t_blend.scale.x)
                                    - t_blend.offset.x,
                                    0.5
                                    - (0.5 / t_blend.scale.y)
                                    - t_blend.offset.y,
                                    t_blend.offset.z,
                                )
                            )
    
    
                            # The initial position and rotation of the pov camera is probably creating
                            # the rotation offset should look into it someday but at least background
                            # won't rotate with the camera now.
                        # Putting the map on a plane would not introduce the skysphere distortion and
                        # allow for better image scale matching but also some waay to chose depth and
                        # size of the plane relative to camera.
    
                        tabWrite("sky_sphere {\n")
                        tabWrite("pigment {\n")
    
                        tabWrite(
                            "image_map{%s \"%s\" %s}\n"
                            % (
                                imageFormat(texturesBlend),
                                texturesBlend,
                                imgMapBG(t_blend),
                            )
                        )
    
                        tabWrite("}\n")
                        tabWrite("%s\n" % (mappingBlend))
    
                        # The following layered pigment opacifies to black over the texture for
                        # transmit below 1 or otherwise adds to itself
    
                        tabWrite(
                            "pigment {rgb 0 transmit %s}\n" % (t.texture.intensity)
                        )
    
                        # tabWrite("scale 2\n")
                        # tabWrite("translate -1\n")
    
                # For only Background gradient
    
    
                if worldTexCount == 0:
    
                    if world.pov.use_sky_blend:
    
                        tabWrite("sky_sphere {\n")
                        tabWrite("pigment {\n")
    
                        # maybe Should follow the advice of POV doc about replacing gradient
                        # for skysphere..5.5
                        tabWrite("gradient y\n")
    
                        # XXX Does not exists anymore
    
                        # if render.alpha_mode == 'STRAIGHT':
                        # tabWrite("[0.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.horizon_color[:]))
                        # tabWrite("[1.0 rgbt<%.3g, %.3g, %.3g, 1>]\n" % (world.pov.zenith_color[:]))
    
                        if render.alpha_mode == 'TRANSPARENT':
    
                            tabWrite(
                                "[0.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n"
                                % (world.pov.horizon_color[:])
                            )
    
                            tabWrite(
                                "[1.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n"
                                % (world.pov.zenith_color[:])
                            )
    
                            tabWrite(
                                "[0.0 rgbt<%.3g, %.3g, %.3g, 0>]\n"
                                % (world.pov.horizon_color[:])
                            )
                            tabWrite(
                                "[1.0 rgbt<%.3g, %.3g, %.3g, 0>]\n"
                                % (world.pov.zenith_color[:])
                            )
    
                        tabWrite("}\n")
                        tabWrite("}\n")
                        tabWrite("}\n")
    
                        # Sky_sphere alpha (transmit) is not translating into image alpha the same
                        # way as 'background'
    
                # if world.pov.light_settings.use_indirect_light:
    
                # Maybe change the above to a function copyInternalRenderer settings when
    
                # scene.pov.radio_enable = world.pov.light_settings.use_indirect_light
    
                # and other such translations but maybe this would not be allowed either?
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
            ###############################################################
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Campbell Barton's avatar
    Campbell Barton committed
            mist = world.mist_settings
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            if mist.use_mist:
    
                if mist.falloff == 'LINEAR':
                    tabWrite(
                        "distance %.6f\n" % ((mist.start + mist.depth) * 0.368)
                    )
                elif mist.falloff == 'QUADRATIC':  # n**2 or squrt(n)?
                    tabWrite(
                        "distance %.6f\n" % ((mist.start + mist.depth) ** 2 * 0.368)
                    )
                elif mist.falloff == 'INVERSE_QUADRATIC':  # n**2 or squrt(n)?
                    tabWrite(
                        "distance %.6f\n" % ((mist.start + mist.depth) ** 2 * 0.368)
                    )
                tabWrite(
                    "color rgbt<%.3g, %.3g, %.3g, %.3g>\n"
                    % (*world.pov.horizon_color, 1.0 - mist.intensity)
                )
                # tabWrite("fog_offset %.6f\n" % mist.start) #create a pov property to prepend
                # tabWrite("fog_alt %.6f\n" % mist.height) #XXX right?
                # tabWrite("turbulence 0.2\n")
                # tabWrite("turb_depth 0.3\n")
                tabWrite("fog_type 1\n")  # type2 for height
    
                tabWrite(
                    "scattering { %d, rgb %.12f*<%.4g, %.4g, %.4g>\n"
                    % (
                        int(scene.pov.media_scattering_type),
                        (scene.pov.media_diffusion_scale),
                        *(scene.pov.media_diffusion_color[:]),
                    )
                )
    
                if scene.pov.media_scattering_type == '5':
    
                    tabWrite("eccentricity %.3g\n" % scene.pov.media_eccentricity)
                tabWrite("}\n")
    
                tabWrite(
                    "absorption %.12f*<%.4g, %.4g, %.4g>\n"
                    % (
                        scene.pov.media_absorption_scale,
                        *(scene.pov.media_absorption_color[:]),
                    )
                )
    
                tabWrite("\n")
    
                tabWrite("samples %.d\n" % scene.pov.media_samples)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        def exportGlobalSettings(scene):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            """write all POV global settings to exported file """
    
            tabWrite("global_settings {\n")
            tabWrite("assumed_gamma 1.0\n")
    
            tabWrite("max_trace_level %d\n" % scene.pov.max_trace_level)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            # Deprecated (autodetected in pov3.8):
            # if scene.pov.charset != 'ascii':
                # file.write("    charset %s\n" % scene.pov.charset)
    
                if scene.pov.radio_enable == False:
    
                    file.write("    adc_bailout %.6f\n" % scene.pov.adc_bailout)
                file.write(
                    "    ambient_light <%.6f,%.6f,%.6f>\n"
                    % scene.pov.ambient_light[:]
                )
                file.write(
                    "    irid_wavelength <%.6f,%.6f,%.6f>\n"
                    % scene.pov.irid_wavelength[:]
                )
                file.write(
                    "    max_intersections %s\n" % scene.pov.max_intersections
                )
                file.write("    number_of_waves %s\n" % scene.pov.number_of_waves)
                file.write("    noise_generator %s\n" % scene.pov.noise_generator)
    
                tabWrite("adc_bailout %.4g\n" % scene.pov.radio_adc_bailout)
                tabWrite("brightness %.4g\n" % scene.pov.radio_brightness)
                tabWrite("count %d\n" % scene.pov.radio_count)
                tabWrite("error_bound %.4g\n" % scene.pov.radio_error_bound)
                tabWrite("gray_threshold %.4g\n" % scene.pov.radio_gray_threshold)
    
                tabWrite(
                    "low_error_factor %.4g\n" % scene.pov.radio_low_error_factor
                )
    
                tabWrite("maximum_reuse %.4g\n" % scene.pov.radio_maximum_reuse)
    
                tabWrite("minimum_reuse %.4g\n" % scene.pov.radio_minimum_reuse)
                tabWrite("nearest_count %d\n" % scene.pov.radio_nearest_count)
                tabWrite("pretrace_start %.3g\n" % scene.pov.radio_pretrace_start)
                tabWrite("pretrace_end %.3g\n" % scene.pov.radio_pretrace_end)
                tabWrite("recursion_limit %d\n" % scene.pov.radio_recursion_limit)
    
                tabWrite("always_sample %d\n" % scene.pov.radio_always_sample)
                tabWrite("normal %d\n" % scene.pov.radio_normal)
                tabWrite("media %d\n" % scene.pov.radio_media)
                tabWrite("subsurface %d\n" % scene.pov.radio_subsurface)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            for material in bpy.data.materials:
    
                if material.pov_subsurface_scattering.use and onceSss:
    
                    # In pov, the scale has reversed influence compared to blender. these number
                    # should correct that
    
                    tabWrite(
                        "mm_per_unit %.6f\n"
                        % (material.pov_subsurface_scattering.scale * 1000.0)
                    )
                    # 1000 rather than scale * (-100.0) + 15.0))
    
                    # In POV-Ray, the scale factor for all subsurface shaders needs to be the same
    
                    # formerly sslt_samples were multiplied by 100 instead of 10
    
                    sslt_samples = (
                        11 - material.pov_subsurface_scattering.error_threshold
                    ) * 10
    
                    tabWrite(
                        "subsurface { samples %d, %d }\n"
                        % (sslt_samples, sslt_samples / 10)
                    )
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                    tabWrite(
                        "ambient_light rgb<%.3g, %.3g, %.3g>\n"
                        % world.pov.ambient_color[:]
                    )
    
                    if oncePhotons and (
                        material.pov.refraction_type == "2"
                        or material.pov.photons_reflection == True
                    ):
    
                        tabWrite("photons {\n")
                        tabWrite("spacing %.6f\n" % scene.pov.photon_spacing)
    
                        tabWrite(
                            "max_trace_level %d\n"
                            % scene.pov.photon_max_trace_level
                        )
                        tabWrite(
                            "adc_bailout %.3g\n" % scene.pov.photon_adc_bailout
                        )
                        tabWrite(
                            "gather %d, %d\n"
                            % (
                                scene.pov.photon_gather_min,
                                scene.pov.photon_gather_max,
                            )
                        )
    
                        if scene.pov.photon_map_file_save_load in {'save'}:
                            filePhName = 'Photon_map_file.ph'
                            if scene.pov.photon_map_file != '':
    
                                filePhName = scene.pov.photon_map_file + '.ph'
    
                            filePhDir = tempfile.gettempdir()
                            path = bpy.path.abspath(scene.pov.photon_map_dir)
                            if os.path.exists(path):
                                filePhDir = path
    
                            fullFileName = os.path.join(filePhDir, filePhName)
                            tabWrite('save_file "%s"\n' % fullFileName)
    
                            scene.pov.photon_map_file = fullFileName
                        if scene.pov.photon_map_file_save_load in {'load'}:
    
                            fullFileName = bpy.path.abspath(
                                scene.pov.photon_map_file
                            )
    
                            if os.path.exists(fullFileName):
    
                                tabWrite('load_file "%s"\n' % fullFileName)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            """write all POV user defined custom code to exported file """
    
            # Write CurrentAnimation Frame for use in Custom POV Code
    
            file.write(
                "#declare CURFRAMENUM = %d;\n" % bpy.context.scene.frame_current
            )
            # Change path and uncomment to add an animated include file by hand:
            file.write(
                "//#include \"/home/user/directory/animation_include_file.inc\"\n"
            )
    
                    # Why are the newlines needed?
                    file.write("\n")
                    file.write(txt.as_string())
                    file.write("\n")
    
        # sel = renderable_objects(scene) #removed for booleans
    
            file.write(
                "//----------------------------------------------\n"
                "//--Exported with POV-Ray exporter for Blender--\n"
                "//----------------------------------------------\n\n"
            )
    
        file.write(
            "#declare Default_texture = texture{pigment {rgb 0.8} "
            "finish {brilliance 3.8} }\n\n"
        )
    
            file.write("\n//--Global settings--\n\n")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        exportGlobalSettings(scene)
    
            file.write("\n//--Custom Code--\n\n")
        exportCustomCode()
    
    
        if comments:
            file.write("\n//--Patterns Definitions--\n\n")
        LocalPatternNames = []
    
        for texture in bpy.data.textures:  # ok?
    
            if texture.users > 0:
    
                currentPatName = string_strip_hyphen(
                    bpy.path.clean_name(texture.name)
                )
                # string_strip_hyphen(patternNames[texture.name]) #maybe instead of the above
    
                LocalPatternNames.append(currentPatName)
    
                # use above list to prevent writing texture instances several times and assign in mats?
                if (
                    texture.type not in {'NONE', 'IMAGE'}
                    and texture.pov.tex_pattern_type == 'emulator'
                ) or (
                    texture.type in {'NONE', 'IMAGE'}
                    and texture.pov.tex_pattern_type != 'emulator'
                ):
    
                    file.write("\n#declare PAT_%s = \n" % currentPatName)
    
                    file.write(shading.exportPattern(texture, string_strip_hyphen))
    
                file.write("\n")
    
            file.write("\n//--Background--\n\n")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        exportWorld(scene.world)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        exportCamera()
    
        for ob in bpy.data.objects:
            if ob.type == 'MESH':
                for mod in ob.modifiers:
                    if mod.type == 'BOOLEAN':
                        if mod.object not in csg_list:
                            csg_list.append(mod.object)
        if csg_list != []:
            csg = False
            sel = no_renderable_objects(scene)
            exportMeshes(scene, sel, csg)
    
        csg = True
        sel = renderable_objects(scene)
    
    
        exportLamps(
            [L for L in sel if (L.type == 'LIGHT' and L.pov.object_as != 'RAINBOW')]
        )
    
        if comments:
            file.write("\n//--Rainbows--\n\n")
    
        exportRainbows(
            [L for L in sel if (L.type == 'LIGHT' and L.pov.object_as == 'RAINBOW')]
        )
    
        if comments:
            file.write("\n//--Special Curves--\n\n")
        for c in sel:
    
            if c.is_modified(scene, 'RENDER'):
    
                continue  # don't export as pov curves objects with modifiers, but as mesh
            elif c.type == 'CURVE' and (
                c.pov.curveshape in {'lathe', 'sphere_sweep', 'loft', 'birail'}
            ):
                exportCurves(scene, c)
    
            file.write("\n//--Material Definitions--\n\n")
    
        # write a default pigment for objects with no material (comment out to show black)
    
        file.write("#default{ pigment{ color srgb 0.8 }}\n")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        # Convert all materials to strings we can access directly per vertex.
    
        # exportMaterials()
        shading.writeMaterial(
            using_uberpov,
            DEF_MAT_NAME,
            scene,
            tabWrite,
            safety,
            comments,
            uniqueName,
            materialNames,
            None,
        )  # default material
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        for material in bpy.data.materials:
    
            if material.users > 0:
    
                if material.pov.material_use_nodes:
                    ntree = material.node_tree
    
                    povMatName = string_strip_hyphen(
                        bpy.path.clean_name(material.name)
                    )
                    if len(ntree.nodes) == 0:
                        file.write(
                            '#declare %s = texture {%s}\n' % (povMatName, color)
                        )