Skip to content
Snippets Groups Projects
render.py 188 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ***** BEGIN GPL LICENSE BLOCK *****
    #
    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU General Public License
    # as published by the Free Software Foundation; either version 2
    # of the License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software Foundation,
    # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    #
    # #**** END GPL LICENSE BLOCK #****
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    import bpy
    
    import subprocess
    import os
    import sys
    import time
    
    from math import atan, pi, degrees, sqrt, cos, sin
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    import random
    
    import platform#
    import subprocess#
    
    from bpy.types import(Operator)
    
    from . import df3 # for smoke rendering
    
    from . import shading # for BI POV haders emulation
    from . import primitives # for import and export of POV specific primitives
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    ##############################SF###########################
    
    ##############find image texture
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    def imageFormat(imgF):
    
        ext = {
            'JPG': "jpeg",
            'JPEG': "jpeg",
            'GIF': "gif",
            'TGA': "tga",
            'IFF': "iff",
            'PPM': "ppm",
            'PNG': "png",
            'SYS': "sys",
            'TIFF': "tiff",
            'TIF': "tiff",
    
            'EXR': "exr",
            'HDR': "hdr",
    
        }.get(os.path.splitext(imgF)[-1].upper(), "")
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #if not ext:
            #print(" WARNING: texture image has no extension") #too verbose 
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        return ext
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    def imgMap(ts):
    
        image_map = ""
        if ts.mapping == 'FLAT':
            image_map = "map_type 0 "
        elif ts.mapping == 'SPHERE':
    
            image_map = "map_type 1 " 
    
        elif ts.mapping == 'TUBE':
            image_map = "map_type 2 "
    
    
        ## map_type 3 and 4 in development (?)
        ## for POV-Ray, currently they just seem to default back to Flat (type 0)
    
        #    image_map = " map_type 3 "
    
        #    image_map = " map_type 4 "
    
        if ts.texture.use_interpolation:
            image_map += " interpolate 2 "
        if ts.texture.extension == 'CLIP':
            image_map += " once "
        #image_map += "}"
        #if ts.mapping=='CUBE':
    
        #    image_map+= "warp { cubic } rotate <-90,0,180>"
        # no direct cube type mapping. Though this should work in POV 3.7
        # it doesn't give that good results(best suited to environment maps?)
    
        #if image_map == "":
    
        #    print(" No texture image  found ")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        return image_map
    
    
    def imgMapTransforms(ts):
        # XXX TODO: unchecked textures give error of variable referenced before assignment XXX
        # 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
        # scale is 0.5,0.5 in blender and 0,0 in POV
        image_map_transforms = ""
        image_map_transforms = ("scale <%.4g,%.4g,%.4g> translate <%.4g,%.4g,%.4g>" % \
                      ( 1.0 / ts.scale.x,
                      1.0 / ts.scale.y,
                      1.0 / ts.scale.z,
                      0.5-(0.5/ts.scale.x) - (ts.offset.x),
                      0.5-(0.5/ts.scale.y) - (ts.offset.y),
                      ts.offset.z))    
        # image_map_transforms = (" translate <-0.5,-0.5,0.0> scale <%.4g,%.4g,%.4g> translate <%.4g,%.4g,%.4g>" % \
                      # ( 1.0 / ts.scale.x,
                      # 1.0 / ts.scale.y,
                      # 1.0 / ts.scale.z,
                      # (0.5 / ts.scale.x) + ts.offset.x,
                      # (0.5 / ts.scale.y) + ts.offset.y,
                      # ts.offset.z))
        # image_map_transforms = ("translate <-0.5,-0.5,0> scale <-1,-1,1> * <%.4g,%.4g,%.4g> translate <0.5,0.5,0> + <%.4g,%.4g,%.4g>" % \
                      # (1.0 / ts.scale.x, 
                      # 1.0 / ts.scale.y,
                      # 1.0 / ts.scale.z,
                      # ts.offset.x,
                      # ts.offset.y,
                      # ts.offset.z))
        return image_map_transforms
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    def imgMapBG(wts):
    
        image_mapBG = ""
    
        # texture_coords refers to the mapping of world textures:
    
        if wts.texture_coords == 'VIEW' or wts.texture_coords == 'GLOBAL':
    
            image_mapBG = " map_type 0 "
    
        elif wts.texture_coords == 'ANGMAP':
            image_mapBG = " map_type 1 "
        elif wts.texture_coords == 'TUBE':
            image_mapBG = " map_type 2 "
    
        if wts.texture.use_interpolation:
            image_mapBG += " interpolate 2 "
        if wts.texture.extension == 'CLIP':
            image_mapBG += " once "
    
        #image_mapBG += "}"
        #if wts.mapping == 'CUBE':
    
        #   image_mapBG += "warp { cubic } rotate <-90,0,180>"
        # no direct cube type mapping. Though this should work in POV 3.7
        # it doesn't give that good results(best suited to environment maps?)
    
        #if image_mapBG == "":
        #    print(" No background texture image  found ")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        return image_mapBG
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    def path_image(image):
    
        return bpy.path.abspath(image.filepath, library=image.library).replace("\\","/")
        # .replace("\\","/") to get only forward slashes as it's what POV prefers, 
        # even on windows
    
    Campbell Barton's avatar
    Campbell Barton committed
    # end find image texture
    # -----------------------------------------------------------------------------
    
    Campbell Barton's avatar
    Campbell Barton committed
    def string_strip_hyphen(name):
        return name.replace("-", "")
    
    def safety(name, Level):
    
        # safety string name material
        #
    
        # Level=1 is for texture with No specular nor Mirror reflection
    
        # Level=2 is for texture with translation of spec and mir levels
        # for when no map influences them
    
        # Level=3 is for texture with Maximum Spec and Mirror
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        try:
    
    Campbell Barton's avatar
    Campbell Barton committed
            if int(name) > 0:
    
                prefix = "shader"
    
    Campbell Barton's avatar
    Campbell Barton committed
        except:
    
        prefix = "shader_"
    
    Campbell Barton's avatar
    Campbell Barton committed
        name = string_strip_hyphen(name)
    
            return prefix + name
    
            return prefix + name + "0"  # used for 0 of specular map
    
            return prefix + name + "1"  # used for 1 of specular map
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    ##############end safety string name material
    ##############################EndSF###########################
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    def is_renderable(ob):
        return (ob.hide_render==False)
    
    def renderable_objects():
        return [ob for ob in bpy.data.objects if is_renderable(ob)]
    
    user_dir = bpy.utils.resource_path('USER')
    preview_dir = os.path.join(user_dir, "preview")
    
    
    ## Make sure Preview directory exists and is empty
    
    smokePath = os.path.join(preview_dir, "smoke.df3")
    
    
    def write_global_setting(scene,file):
        file.write("global_settings {\n")
        file.write("    assumed_gamma %.6f\n"%scene.pov.assumed_gamma)
        if scene.pov.global_settings_default == False:
            if scene.pov.adc_bailout_enable and scene.pov.radio_enable == False:
                file.write("    adc_bailout %.6f\n"%scene.pov.adc_bailout)
            if scene.pov.ambient_light_enable:
                file.write("    ambient_light <%.6f,%.6f,%.6f>\n"%scene.pov.ambient_light[:])
            if scene.pov.irid_wavelength_enable:
                file.write("    irid_wavelength <%.6f,%.6f,%.6f>\n"%scene.pov.irid_wavelength[:])
            if scene.pov.charset_enable:
                file.write("    charset %s\n"%scene.pov.charset)
            if scene.pov.max_trace_level_enable:
                file.write("    max_trace_level %s\n"%scene.pov.max_trace_level)    
            if scene.pov.max_intersections_enable:
                file.write("    max_intersections %s\n"%scene.pov.max_intersections)
            if scene.pov.number_of_waves_enable:
                file.write("    number_of_waves %s\n"%scene.pov.number_of_waves)
            if scene.pov.noise_generator_enable:
                file.write("    noise_generator %s\n"%scene.pov.noise_generator) 
        if scene.pov.sslt_enable:
            file.write("    mm_per_unit %s\n"%scene.pov.mm_per_unit) 
            file.write("    subsurface {\n")
            file.write("        samples %s, %s\n"%(scene.pov.sslt_samples_max,scene.pov.sslt_samples_min))
            if scene.pov.sslt_radiosity:
                file.write("        radiosity on\n")
            file.write("}\n")
    
        if scene.pov.radio_enable:
            file.write("    radiosity {\n")
            file.write("        pretrace_start %.6f\n"%scene.pov.radio_pretrace_start) 
            file.write("        pretrace_end %.6f\n"%scene.pov.radio_pretrace_end) 
            file.write("        count %s\n"%scene.pov.radio_count) 
            file.write("        nearest_count %s\n"%scene.pov.radio_nearest_count) 
            file.write("        error_bound %.6f\n"%scene.pov.radio_error_bound)         
            file.write("        recursion_limit %s\n"%scene.pov.radio_recursion_limit) 
            file.write("        low_error_factor %.6f\n"%scene.pov.radio_low_error_factor) 
            file.write("        gray_threshold %.6f\n"%scene.pov.radio_gray_threshold) 
            file.write("        maximum_reuse %.6f\n"%scene.pov.radio_maximum_reuse) 
            file.write("        minimum_reuse %.6f\n"%scene.pov.radio_minimum_reuse) 
            file.write("        brightness %.6f\n"%scene.pov.radio_brightness) 
            file.write("        adc_bailout %.6f\n"%scene.pov.radio_adc_bailout)
            if scene.pov.radio_normal:
                file.write("        normal on\n") 
            if scene.pov.radio_always_sample:
                file.write("        always_sample on\n") 
            if scene.pov.radio_media:
                file.write("        media on\n") 
            if scene.pov.radio_subsurface:
                file.write("        subsurface on\n")
            file.write("    }\n")
    
        if scene.pov.photon_enable:
            file.write("    photons {\n")
            if scene.pov.photon_enable_count:
                file.write("        count %s\n"%scene.pov.photon_count)
            else:
                file.write("        spacing %.6g\n"%scene.pov.photon_spacing)
            if scene.pov.photon_gather:
                file.write("        gather %s, %s\n"%(scene.pov.photon_gather_min,scene.pov.photon_gather_max))
            if scene.pov.photon_autostop:
                file.write("        autostop %.4g\n"%scene.pov.photon_autostop_value)
            if scene.pov.photon_jitter_enable:
                file.write("        jitter %.4g\n"%scene.pov.photon_jitter)
            file.write("        max_trace_level %s\n"%scene.pov.photon_max_trace_level)
            if scene.pov.photon_adc:
                file.write("        adc_bailout %.6f\n"%scene.pov.photon_adc_bailout)
            if scene.pov.photon_media_enable:
                file.write("        media %s, %s\n"%(scene.pov.photon_media_steps,scene.pov.photon_media_factor))
            if scene.pov.photon_savefile or scene.pov.photon_loadfile:
                filePh = bpy.path.abspath(scene.pov.photon_map_file)
                if scene.pov.photon_savefile:
                    file.write('save_file "%s"\n'%filePh)
                if scene.pov.photon_loadfile and os.path.exists(filePh):
                    file.write('load_file "%s"\n'%filePh)
            file.write("}\n")
        file.write("}\n")
    
    def write_object_modifiers(scene,ob,File):
        if ob.pov.hollow:
            File.write("hollow\n")
        if ob.pov.double_illuminate:
            File.write("double_illuminate\n")
        if ob.pov.sturm:
            File.write("sturm\n")
        if ob.pov.no_shadow:
            File.write("no_shadow\n")
        if ob.pov.no_image:
            File.write("no_image\n")
        if ob.pov.no_reflection:
            File.write("no_reflection\n")
        if ob.pov.no_radiosity:
            File.write("no_radiosity\n")
        if ob.pov.inverse:
            File.write("inverse\n")
        if ob.pov.hierarchy:
            File.write("hierarchy\n")
        if scene.pov.photon_enable:
            File.write("photons {\n")
            if ob.pov.target:
                File.write("target %.4g\n"%ob.pov.target_value)
            if ob.pov.refraction:
                File.write("refraction on\n")
            if ob.pov.reflection:
                File.write("reflection on\n")
            if ob.pov.pass_through:
                File.write("pass_through\n")
            File.write("}\n")
        # if ob.pov.object_ior > 1:
            # File.write("interior {\n")
            # File.write("ior %.4g\n"%ob.pov.object_ior)
            # if scene.pov.photon_enable and ob.pov.target and ob.pov.refraction and ob.pov.dispersion:
                # File.write("ior %.4g\n"%ob.pov.dispersion_value)
                # File.write("ior %s\n"%ob.pov.dispersion_samples) 
            # if scene.pov.photon_enable == False:
                # File.write("caustics %.4g\n"%ob.pov.fake_caustics_power)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    def write_pov(filename, scene=None, info_callback=None):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #file = filename
    
        file = open(filename, "w")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        # Only for testing
        if not scene:
            scene = bpy.data.scenes[0]
    
        render = scene.render
        world = scene.world
    
        global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X')
    
        comments = scene.pov.comments_enable and not scene.pov.tempfiles_enable
    
        linebreaksinlists = scene.pov.list_lf_enable and not scene.pov.tempfiles_enable
        feature_set = bpy.context.user_preferences.addons[__package__].preferences.branch_feature_set_povray
        using_uberpov = (feature_set=='uberpov')
        pov_binary = PovrayRender._locate_binary()
    
        if using_uberpov:
            print("Unofficial UberPOV feature set chosen in preferences")
        else:
            print("Official POV-Ray 3.7 feature set chosen in preferences")
        if 'uber' in pov_binary: 
    
            print("The name of the binary suggests you are probably rendering with Uber POV engine")
    
            print("The name of the binary suggests you are probably rendering with standard POV engine")
    
        tab = setTab(scene.pov.indentation_character, scene.pov.indentation_spaces)
    
        if not scene.pov.tempfiles_enable:
            def tabWrite(str_o):
    
                global tabLevel
                brackets = str_o.count("{") - str_o.count("}") + str_o.count("[") - str_o.count("]")
                if brackets < 0:
                    tabLevel = tabLevel + brackets
                if tabLevel < 0:
                    print("Indentation Warning: tabLevel = %s" % tabLevel)
                    tabLevel = 0
                if tabLevel >= 1:
                    file.write("%s" % tab * tabLevel)
                file.write(str_o)
                if brackets > 0:
                    tabLevel = tabLevel + brackets
    
        else:
            def tabWrite(str_o):
    
                file.write(str_o)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def uniqueName(name, nameSeq):
    
            if name not in nameSeq:
    
    Campbell Barton's avatar
    Campbell Barton committed
                name = string_strip_hyphen(name)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                return name
    
            name_orig = name
            i = 1
            while name in nameSeq:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                i += 1
    
    Campbell Barton's avatar
    Campbell Barton committed
            name = string_strip_hyphen(name)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            return name
    
        def writeMatrix(matrix):
    
            tabWrite("matrix <%.6f, %.6f, %.6f,  %.6f, %.6f, %.6f,  %.6f, %.6f, %.6f,  %.6f, %.6f, %.6f>\n" %
                     (matrix[0][0], matrix[1][0], matrix[2][0],
                      matrix[0][1], matrix[1][1], matrix[2][1],
                      matrix[0][2], matrix[1][2], matrix[2][2],
                      matrix[0][3], matrix[1][3], matrix[2][3]))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            sMatrix = ("matrix <%.6f, %.6f, %.6f,  %.6f, %.6f, %.6f,  %.6f, %.6f, %.6f,  %.6f, %.6f, %.6f>\n" %
                       (matrix[0][0], matrix[1][0], matrix[2][0],
                        matrix[0][1], matrix[1][1], matrix[2][1],
                        matrix[0][2], matrix[1][2], matrix[2][2],
                        matrix[0][3], matrix[1][3], matrix[2][3]))
    
        def writeObjectMaterial(material, ob):
    
            # DH - modified some variables to be function local, avoiding RNA write
            # this should be checked to see if it is functionally correct
    
            # Commented out: always write IOR to be able to use it for SSS, Fresnel reflections...
            #if material and material.transparency_method == 'RAYTRACE':
            if material:
    
                # But there can be only one!
                if material.subsurface_scattering.use:  # SSS IOR get highest priority
    
                    tabWrite("interior {\n")
                    tabWrite("ior %.6f\n" % material.subsurface_scattering.ior)
    
                # Then the raytrace IOR taken from raytrace transparency properties and used for
                # reflections if IOR Mirror option is checked.
                elif material.pov.mirror_use_IOR:
    
                    tabWrite("interior {\n")
                    tabWrite("ior %.6f\n" % material.raytrace_transparency.ior)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                else:
    
                    tabWrite("interior {\n")
                    tabWrite("ior %.6f\n" % material.raytrace_transparency.ior)
    
                pov_fake_caustics = False
                pov_photons_refraction = False
                pov_photons_reflection = False
    
                    pov_photons_reflection = True
    
                    pov_fake_caustics = False
                    pov_photons_refraction = False
    
                    pov_fake_caustics = True
                    pov_photons_refraction = False
    
                    pov_fake_caustics = False
                    pov_photons_refraction = True
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # If only Raytrace transparency is set, its IOR will be used for refraction, but user
                # can set up 'un-physical' fresnel reflections in raytrace mirror parameters.
                # Last, if none of the above is specified, user can set up 'un-physical' fresnel
                # reflections in raytrace mirror parameters. And pov IOR defaults to 1.
                if material.pov.caustics_enable:
    
                        tabWrite("caustics %.3g\n" % material.pov.fake_caustics_power)
    
                        # Default of 1 means no dispersion
                        tabWrite("dispersion %.6f\n" % material.pov.photons_dispersion)
    
                        tabWrite("dispersion_samples %.d\n" % material.pov.photons_dispersion_samples)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                # Other interior args
    
                if material.use_transparency and material.transparency_method == 'RAYTRACE':
                    # fade_distance
    
                    # In Blender this value has always been reversed compared to what tooltip says.
                    # 100.001 rather than 100 so that it does not get to 0
    
                    # which deactivates the feature in POV
    
                    tabWrite("fade_distance %.3g\n" % \
                             (100.001 - material.raytrace_transparency.depth_max))
    
                    # fade_power
                    tabWrite("fade_power %.3g\n" % material.raytrace_transparency.falloff)
                    # fade_color
    
                    tabWrite("fade_color <%.3g, %.3g, %.3g>\n" % material.pov.interior_fade_color[:])
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                # (variable) dispersion_samples (constant count for now)
    
                if material.pov.photons_reflection or material.pov.refraction_type=="2":
                    tabWrite("photons{")
    
                    tabWrite("target %.3g\n" % ob.pov.spacing_multiplier)
    
                    if not ob.pov.collect_photons:
                        tabWrite("collect off\n")
                    if pov_photons_refraction:
                        tabWrite("refraction on\n")
                    if pov_photons_reflection:
                        tabWrite("reflection on\n")
                    tabWrite("}\n")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        materialNames = {}
    
        DEF_MAT_NAME = "" #or "Default"?
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def exportCamera():
            camera = scene.camera
    
            # DH disabled for now, this isn't the correct context
    
            active_object = None  # bpy.context.active_object # does not always work  MR
    
            matrix = global_matrix * camera.matrix_world
    
            focal_point = camera.data.dof_distance
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            # compute resolution
    
            Qsize = render.resolution_x / render.resolution_y
    
            tabWrite("#declare camLocation  = <%.6f, %.6f, %.6f>;\n" %
                     matrix.translation[:])
            tabWrite("#declare camLookAt = <%.6f, %.6f, %.6f>;\n" %
    
                     tuple([degrees(e) for e in matrix.to_3x3().to_euler()]))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            if scene.pov.baking_enable and active_object and active_object.type == 'MESH':
    
                tabWrite("mesh_camera{ 1 3\n")  # distribution 3 is what we want here
                tabWrite("mesh{%s}\n" % active_object.name)
                tabWrite("}\n")
                tabWrite("location <0,0,.01>")
                tabWrite("direction <0,0,-1>")
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            # Using standard camera otherwise
            else:
    
                tabWrite("location  <0, 0, 0>\n")
                tabWrite("look_at  <0, 0, -1>\n")
                tabWrite("right <%s, 0, 0>\n" % - Qsize)
                tabWrite("up <0, 1, 0>\n")
                tabWrite("angle  %f\n" % (360.0 * atan(16.0 / camera.data.lens) / pi))
    
    
                tabWrite("rotate  <%.6f, %.6f, %.6f>\n" % \
                         tuple([degrees(e) for e in matrix.to_3x3().to_euler()]))
    
                tabWrite("translate <%.6f, %.6f, %.6f>\n" % matrix.translation[:])
    
                if camera.data.pov.dof_enable and focal_point != 0:
                    tabWrite("aperture %.3g\n" % camera.data.pov.dof_aperture)
                    tabWrite("blur_samples %d %d\n" % \
                             (camera.data.pov.dof_samples_min, camera.data.pov.dof_samples_max))
                    tabWrite("variance 1/%d\n" % camera.data.pov.dof_variance)
                    tabWrite("confidence %.3g\n" % camera.data.pov.dof_confidence)
    
                    tabWrite("focal_point <0, 0, %f>\n" % focal_point)
            tabWrite("}\n")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def exportLamps(lamps):
    
            # Incremented after each lamp export to declare its target
            # currently used for Fresnel diffuse shader as their slope vector:
            global lampCount
            lampCount = 0
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            # Get all lamps
            for ob in lamps:
                lamp = ob.data
    
    
                matrix = global_matrix * ob.matrix_world
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # Color is modified by energy #muiltiplie by 2 for a better match --Maurice
    
                color = tuple([c * lamp.energy * 2.0 for c in lamp.color])
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                tabWrite("light_source {\n")
                tabWrite("< 0,0,0 >\n")
                tabWrite("color rgb<%.3g, %.3g, %.3g>\n" % color)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                if lamp.type == 'POINT':
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    pass
    
                elif lamp.type == 'SPOT':
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                    # Falloff is the main radius from the centre line
    
                    tabWrite("falloff %.2f\n" % (degrees(lamp.spot_size) / 2.0))  # 1 TO 179 FOR BOTH
    
                    tabWrite("radius %.6f\n" % \
                             ((degrees(lamp.spot_size) / 2.0) * (1.0 - lamp.spot_blend)))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                    # Blender does not have a tightness equivilent, 0 is most like blender default.
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                elif lamp.type == 'SUN':
    
                    tabWrite("parallel\n")
                    tabWrite("point_at  <0, 0, -1>\n")  # *must* be after 'parallel'
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                elif lamp.type == 'AREA':
    
                    tabWrite("area_illumination\n")
                    tabWrite("fade_distance %.6f\n" % (lamp.distance / 2.0))
    
                    # Area lights have no falloff type, so always use blenders lamp quad equivalent
                    # for those?
                    tabWrite("fade_power %d\n" % 2)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    size_x = lamp.size
                    samples_x = lamp.shadow_ray_samples_x
                    if lamp.shape == 'SQUARE':
                        size_y = size_x
                        samples_y = samples_x
                    else:
                        size_y = lamp.size_y
                        samples_y = lamp.shadow_ray_samples_y
    
    
                    tabWrite("area_light <%.6f,0,0>,<0,%.6f,0> %d, %d\n" % \
    
                             (size_x, size_y, samples_x, samples_y))
    
                    if lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    else:
    
                        tabWrite("adaptive 1\n")
                        tabWrite("jitter\n")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # HEMI never has any shadow_method attribute
                if(not scene.render.use_shadows or lamp.type == 'HEMI' or
                   (lamp.type != 'HEMI' and lamp.shadow_method == 'NOSHADOW')):
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # Sun shouldn't be attenuated. Hemi and area lights have no falloff attribute so they
                # are put to type 2 attenuation a little higher above.
    
                if lamp.type not in {'SUN', 'AREA', 'HEMI'}:
    
                    tabWrite("fade_distance %.6f\n" % (lamp.distance / 2.0))
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    if lamp.falloff_type == 'INVERSE_SQUARE':
    
                        tabWrite("fade_power %d\n" % 2)  # Use blenders lamp quad equivalent
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    elif lamp.falloff_type == 'INVERSE_LINEAR':
    
                        tabWrite("fade_power %d\n" % 1)  # Use blenders lamp linear
    
                    # supposing using no fade power keyword would default to constant, no attenuation.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        pass
    
                    # Using Custom curve for fade power 3 for now.
                    elif lamp.falloff_type == 'CUSTOM_CURVE':
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                writeMatrix(matrix)
    
    
    
                lampCount += 1
    
                # v(A,B) rotates vector A about origin by vector B.
    
                file.write("#declare lampTarget%s= vrotate(<%.4g,%.4g,%.4g>,<%.4g,%.4g,%.4g>);\n" % \
                           (lampCount, -(ob.location.x), -(ob.location.y), -(ob.location.z),
                            ob.rotation_euler.x, ob.rotation_euler.y, ob.rotation_euler.z))
    
    ####################################################################################################
    
    616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
        def exportRainbows(rainbows):
            for ob in rainbows:
                povdataname = ob.data.name #enough?
                angle = degrees(ob.data.spot_size/2.5) #radians in blender (2
                width = ob.data.spot_blend *10
                distance = ob.data.shadow_buffer_clip_start 
                #eps=0.0000001
                #angle = br/(cr+eps) * 10 #eps is small epsilon variable to avoid dividing by zero
                #width = ob.dimensions[2] #now let's say width of rainbow is the actual proxy height
                # formerly:
                #cz-bz # let's say width of the rainbow is height of the cone (interfacing choice
                
                # v(A,B) rotates vector A about origin by vector B.
                # and avoid a 0 length vector by adding 1
                
                # file.write("#declare %s_Target= vrotate(<%.6g,%.6g,%.6g>,<%.4g,%.4g,%.4g>);\n" % \
                           # (povdataname, -(ob.location.x+0.1), -(ob.location.y+0.1), -(ob.location.z+0.1),
                            # ob.rotation_euler.x, ob.rotation_euler.y, ob.rotation_euler.z))                    
                
                direction = (ob.location.x,ob.location.y,ob.location.z) # not taking matrix into account
                rmatrix = global_matrix * ob.matrix_world
                
                #ob.rotation_euler.to_matrix().to_4x4() * mathutils.Vector((0,0,1))
                # XXX Is result of the below offset by 90 degrees?
                up =ob.matrix_world.to_3x3()[1].xyz #* global_matrix 
    
    
                # XXX TO CHANGE: 
                #formerly:
                #tabWrite("#declare %s = rainbow {\n"%povdataname) 
                
                # clumsy for now but remove the rainbow from instancing
                # system because not an object. use lamps later instead of meshes
                
                #del data_ref[dataname]
                tabWrite("rainbow {\n")
    
                tabWrite("angle %.4f\n"%angle)
                tabWrite("width %.4f\n"%width)
                tabWrite("distance %.4f\n"%distance)
                tabWrite("arc_angle %.4f\n"%ob.pov.arc_angle)
                tabWrite("falloff_angle %.4f\n"%ob.pov.falloff_angle)
                tabWrite("direction <%.4f,%.4f,%.4f>\n"%rmatrix.translation[:])
                tabWrite("up <%.4f,%.4f,%.4f>\n"%(up[0],up[1],up[2]))
                tabWrite("color_map {\n")
                tabWrite("[0.000  color rgbt<1.0, 0.5, 1.0, 1.0>]\n")
                tabWrite("[0.130  color rgbt<0.5, 0.5, 1.0, 0.9>]\n")
                tabWrite("[0.298  color rgbt<0.2, 0.2, 1.0, 0.7>]\n")
                tabWrite("[0.412  color rgbt<0.2, 1.0, 1.0, 0.4>]\n")
                tabWrite("[0.526  color rgbt<0.2, 1.0, 0.2, 0.4>]\n")
                tabWrite("[0.640  color rgbt<1.0, 1.0, 0.2, 0.4>]\n")
                tabWrite("[0.754  color rgbt<1.0, 0.5, 0.2, 0.6>]\n")
                tabWrite("[0.900  color rgbt<1.0, 0.2, 0.2, 0.7>]\n")
                tabWrite("[1.000  color rgbt<1.0, 0.2, 0.2, 1.0>]\n")
                tabWrite("}\n")
                
                
                povMatName = "Default_texture"
                #tabWrite("texture {%s}\n"%povMatName)
                write_object_modifiers(scene,ob,file)
                #tabWrite("rotate x*90\n")
                #matrix = global_matrix * ob.matrix_world
                #writeMatrix(matrix)
                tabWrite("}\n")
                #continue #Don't render proxy mesh, skip to next object
                
    ################################XXX LOFT, ETC.
        def exportCurves(scene, ob):
            name_orig = "OB" + ob.name
            dataname_orig = "DATA" + ob.data.name
    
            name = string_strip_hyphen(bpy.path.clean_name(name_orig))
            dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig))
    
            global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X')
            matrix=global_matrix*ob.matrix_world
            bezier_sweep = False
            if ob.pov.curveshape == 'sphere_sweep':
                for spl in ob.data.splines:
                    if spl.type == "BEZIER":
                        bezier_sweep = True
            if ob.pov.curveshape in {'loft','birail'}:
                n=0
                for spline in ob.data.splines:
                    n+=1
                    tabWrite('#declare %s%s=spline {\n'%(dataname,n))
                    tabWrite('cubic_spline\n')
                    lp = len(spline.points)
                    delta = 1/(lp)
                    d=-delta
                    point = spline.points[lp-1]
                    x,y,z,w  = point.co[:]
                    tabWrite('%.6f, <%.6f,%.6f,%.6f>\n'%(d,x,y,z))
                    d+=delta
                    for point in spline.points:
                        x,y,z,w  = point.co[:]
                        tabWrite('%.6f, <%.6f,%.6f,%.6f>\n'%(d,x,y,z))
                        d+=delta
                    for i in range(2):
                        point = spline.points[i]
                        x,y,z,w  = point.co[:]
                        tabWrite('%.6f, <%.6f,%.6f,%.6f>\n'%(d,x,y,z))
                        d+=delta
                    tabWrite('}\n')
                if ob.pov.curveshape in {'loft'}:
                    n = len(ob.data.splines)
                    tabWrite('#declare %s = array[%s]{\n'%(dataname,(n+3)))
                    tabWrite('spline{%s%s},\n'%(dataname,n))
                    for i in range(n):
                        tabWrite('spline{%s%s},\n'%(dataname,(i+1)))
                    tabWrite('spline{%s1},\n'%(dataname))
                    tabWrite('spline{%s2}\n'%(dataname))
                    tabWrite('}\n')
                # Use some of the Meshmaker.inc macro, here inlined
                file.write('#macro CheckFileName(FileName)\n')
                file.write('   #local Len=strlen(FileName);\n')
                file.write('   #if(Len>0)\n')
                file.write('      #if(file_exists(FileName))\n')
                file.write('         #if(Len>=4)\n')
                file.write('            #local Ext=strlwr(substr(FileName,Len-3,4))\n')
                file.write('            #if (strcmp(Ext,".obj")=0 | strcmp(Ext,".pcm")=0 | strcmp(Ext,".arr")=0)\n')
                file.write('               #local Return=99;\n')
                file.write('            #else\n')
                file.write('               #local Return=0;\n')
                file.write('            #end\n')
                file.write('         #else\n')
                file.write('            #local Return=0;\n')
                file.write('         #end\n')
                file.write('      #else\n')
                file.write('         #if(Len>=4)\n')
                file.write('            #local Ext=strlwr(substr(FileName,Len-3,4))\n')
                file.write('            #if (strcmp(Ext,".obj")=0 | strcmp(Ext,".pcm")=0 | strcmp(Ext,".arr")=0)\n')
                file.write('               #if (strcmp(Ext,".obj")=0)\n')
                file.write('                  #local Return=2;\n')
                file.write('               #end\n')
                file.write('               #if (strcmp(Ext,".pcm")=0)\n')
                file.write('                  #local Return=3;\n')
                file.write('               #end\n')
                file.write('               #if (strcmp(Ext,".arr")=0)\n')
                file.write('                  #local Return=4;\n')
                file.write('               #end\n')
                file.write('            #else\n')
                file.write('               #local Return=1;\n')
                file.write('            #end\n')
                file.write('         #else\n')
                file.write('            #local Return=1;\n')
                file.write('         #end\n')
                file.write('      #end\n')
                file.write('   #else\n')
                file.write('      #local Return=1;\n')
                file.write('   #end\n')
                file.write('   (Return)\n')
                file.write('#end\n')
    
                file.write('#macro BuildSpline(Arr, SplType)\n')
                file.write('   #local Ds=dimension_size(Arr,1);\n')
                file.write('   #local Asc=asc(strupr(SplType));\n')
                file.write('   #if(Asc!=67 & Asc!=76 & Asc!=81) \n')
                file.write('      #local Asc=76;\n')
                file.write('      #debug "\nWrong spline type defined (C/c/L/l/N/n/Q/q), using default linear_spline\\n"\n')
                file.write('   #end\n')
                file.write('   spline {\n')
                file.write('      #switch (Asc)\n')
                file.write('         #case (67) //C  cubic_spline\n')
                file.write('            cubic_spline\n')
                file.write('         #break\n')
                file.write('         #case (76) //L  linear_spline\n')
                file.write('            linear_spline\n')
                file.write('         #break\n')
                file.write('         #case (78) //N  linear_spline\n')
                file.write('            natural_spline\n')
                file.write('         #break\n')
                file.write('         #case (81) //Q  Quadratic_spline\n')
                file.write('            quadratic_spline\n')
                file.write('         #break\n')
                file.write('      #end\n')
                file.write('      #local Add=1/((Ds-2)-1);\n')
                file.write('      #local J=0-Add;\n')
                file.write('      #local I=0;\n')
                file.write('      #while (I<Ds)\n')
                file.write('         J\n')
                file.write('         Arr[I]\n')
                file.write('         #local I=I+1;\n')
                file.write('         #local J=J+Add;\n')
                file.write('      #end\n')
                file.write('   }\n')
                file.write('#end\n')
    
    
                file.write('#macro BuildWriteMesh2(VecArr, NormArr, UVArr, U, V, FileName)\n')
                #suppressed some file checking from original macro because no more separate files
                file.write(' #local Write=0;\n')
                file.write(' #debug concat("\\n\\n Building mesh2: \\n   - vertex_vectors\\n")\n')
                file.write('  #local NumVertices=dimension_size(VecArr,1);\n')
                file.write('  #switch (Write)\n')
                file.write('     #case(1)\n')
                file.write('        #write(\n')
                file.write('           MeshFile,\n')
                file.write('           "  vertex_vectors {\\n",\n')
                file.write('           "    ", str(NumVertices,0,0),"\\n    "\n')
                file.write('        )\n')
                file.write('     #break\n')
                file.write('     #case(2)\n')
                file.write('        #write(\n')
                file.write('           MeshFile,\n')
                file.write('           "# Vertices: ",str(NumVertices,0,0),"\\n"\n')
                file.write('        )\n')
                file.write('     #break\n')
                file.write('     #case(3)\n')
                file.write('        #write(\n')
                file.write('           MeshFile,\n')
                file.write('           str(2*NumVertices,0,0),",\\n"\n')
                file.write('        )\n')
                file.write('     #break\n')
                file.write('     #case(4)\n')
                file.write('        #write(\n')
                file.write('           MeshFile,\n')
                file.write('           "#declare VertexVectors= array[",str(NumVertices,0,0),"] {\\n  "\n')
                file.write('        )\n')
                file.write('     #break\n')
                file.write('  #end\n')
                file.write('  mesh2 {\n')
                file.write('     vertex_vectors {\n')
                file.write('        NumVertices\n')
                file.write('        #local I=0;\n')
                file.write('        #while (I<NumVertices)\n')
                file.write('           VecArr[I]\n')
                file.write('           #switch(Write)\n')
                file.write('              #case(1)\n')
                file.write('                 #write(MeshFile, VecArr[I])\n')
                file.write('              #break\n')
                file.write('              #case(2)\n')
                file.write('                 #write(\n')
                file.write('                    MeshFile,\n')
                file.write('                    "v ", VecArr[I].x," ", VecArr[I].y," ", VecArr[I].z,"\\n"\n')
                file.write('                 )\n')
                file.write('              #break\n')
                file.write('              #case(3)\n')
                file.write('                 #write(\n')
                file.write('                    MeshFile,\n')
                file.write('                    VecArr[I].x,",", VecArr[I].y,",", VecArr[I].z,",\\n"\n')
                file.write('                 )\n')
                file.write('              #break\n')
                file.write('              #case(4)\n')
                file.write('                 #write(MeshFile, VecArr[I])\n')
                file.write('              #break\n')
                file.write('           #end\n')
                file.write('           #local I=I+1;\n')
                file.write('           #if(Write=1 | Write=4)\n')
                file.write('              #if(mod(I,3)=0)\n')
                file.write('                 #write(MeshFile,"\\n    ")\n')
                file.write('              #end\n')
                file.write('           #end \n')
                file.write('        #end\n')
                file.write('        #switch(Write)\n')
                file.write('           #case(1)\n')
                file.write('              #write(MeshFile,"\\n  }\\n")\n')
                file.write('           #break\n')
                file.write('           #case(2)\n')
                file.write('              #write(MeshFile,"\\n")\n')
                file.write('           #break\n')
                file.write('           #case(3)\n')
                file.write('              // do nothing\n')
                file.write('           #break\n')
                file.write('           #case(4) \n')
                file.write('              #write(MeshFile,"\\n}\\n")\n')
                file.write('           #break\n')
                file.write('        #end\n')
                file.write('     }\n')
    
                file.write('     #debug concat("   - normal_vectors\\n")    \n')
                file.write('     #local NumVertices=dimension_size(NormArr,1);\n')
                file.write('     #switch(Write)\n')
                file.write('        #case(1)\n')
                file.write('           #write(\n')
                file.write('              MeshFile,\n')
                file.write('              "  normal_vectors {\\n",\n')
                file.write('              "    ", str(NumVertices,0,0),"\\n    "\n')
                file.write('           )\n')
                file.write('        #break\n')
                file.write('        #case(2)\n')
                file.write('           #write(\n')
                file.write('              MeshFile,\n')
                file.write('              "# Normals: ",str(NumVertices,0,0),"\\n"\n')
                file.write('           )\n')
                file.write('        #break\n')
                file.write('        #case(3)\n')
                file.write('           // do nothing\n')
                file.write('        #break\n')
                file.write('        #case(4)\n')
                file.write('           #write(\n')
                file.write('              MeshFile,\n')
                file.write('              "#declare NormalVectors= array[",str(NumVertices,0,0),"] {\\n  "\n')
                file.write('           )\n')
                file.write('        #break\n')
                file.write('     #end\n')
                file.write('     normal_vectors {\n')
                file.write('        NumVertices\n')
                file.write('        #local I=0;\n')
                file.write('        #while (I<NumVertices)\n')
                file.write('           NormArr[I]\n')
                file.write('           #switch(Write)\n')
                file.write('              #case(1)\n')
                file.write('                 #write(MeshFile NormArr[I])\n')
                file.write('              #break\n')
                file.write('              #case(2)\n')
                file.write('                 #write(\n')
                file.write('                    MeshFile,\n')
                file.write('                    "vn ", NormArr[I].x," ", NormArr[I].y," ", NormArr[I].z,"\\n"\n')
                file.write('                 )\n')
                file.write('              #break\n')
                file.write('              #case(3)\n')
                file.write('                 #write(\n')
                file.write('                    MeshFile,\n')
                file.write('                    NormArr[I].x,",", NormArr[I].y,",", NormArr[I].z,",\\n"\n')
                file.write('                 )\n')
                file.write('              #break\n')
                file.write('              #case(4)\n')
                file.write('                 #write(MeshFile NormArr[I])\n')
                file.write('              #break\n')
                file.write('           #end\n')
                file.write('           #local I=I+1;\n')
                file.write('           #if(Write=1 | Write=4) \n')
                file.write('              #if(mod(I,3)=0)\n')
                file.write('                 #write(MeshFile,"\\n    ")\n')
                file.write('              #end\n')
                file.write('           #end\n')
                file.write('        #end\n')
                file.write('        #switch(Write)\n')
                file.write('           #case(1)\n')
                file.write('              #write(MeshFile,"\\n  }\\n")\n')
                file.write('           #break\n')
                file.write('           #case(2)\n')
                file.write('              #write(MeshFile,"\\n")\n')
                file.write('           #break\n')
                file.write('           #case(3)\n')
                file.write('              //do nothing\n')
                file.write('           #break\n')
                file.write('           #case(4)\n')
                file.write('              #write(MeshFile,"\\n}\\n")\n')
                file.write('           #break\n')
                file.write('        #end\n')
                file.write('     }\n')
         
                file.write('     #debug concat("   - uv_vectors\\n")   \n')
                file.write('     #local NumVertices=dimension_size(UVArr,1);\n')
                file.write('     #switch(Write)\n')
                file.write('        #case(1)\n')
                file.write('           #write(\n')
                file.write('              MeshFile, \n')
                file.write('              "  uv_vectors {\\n",\n')
                file.write('              "    ", str(NumVertices,0,0),"\\n    "\n')
                file.write('           )\n')
                file.write('         #break\n')
                file.write('         #case(2)\n')
                file.write('           #write(\n')
                file.write('              MeshFile,\n')
                file.write('              "# UV-vectors: ",str(NumVertices,0,0),"\\n"\n')
                file.write('           )\n')
                file.write('         #break\n')
                file.write('         #case(3)\n')
                file.write('           // do nothing, *.pcm does not support uv-vectors\n')
                file.write('         #break\n')
                file.write('         #case(4)\n')
                file.write('            #write(\n')
                file.write('               MeshFile,\n')
                file.write('               "#declare UVVectors= array[",str(NumVertices,0,0),"] {\\n  "\n')
                file.write('            )\n')
                file.write('         #break\n')
                file.write('     #end\n')
                file.write('     uv_vectors {\n')
                file.write('        NumVertices\n')
                file.write('        #local I=0;\n')
                file.write('        #while (I<NumVertices)\n')
                file.write('           UVArr[I]\n')
                file.write('           #switch(Write)\n')
                file.write('              #case(1)\n')
                file.write('                 #write(MeshFile UVArr[I])\n')
                file.write('              #break\n')
                file.write('              #case(2)\n')
                file.write('                 #write(\n')
                file.write('                    MeshFile,\n')
                file.write('                    "vt ", UVArr[I].u," ", UVArr[I].v,"\\n"\n')
                file.write('                 )\n')
                file.write('              #break\n')