Skip to content
Snippets Groups Projects
render.py 75.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Maurice Raybaud's avatar
    Maurice Raybaud committed
                    if texturesNorm !='':
                        ## scale 1 rotate y*0
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        mappingNor = (' translate <%.4g-0.75,%.4g-0.75,%.4g-0.75> scale <%.4g,%.4g,%.4g>\n' % (t_nor.offset.x / 10 ,t_nor.offset.y / 10 ,t_nor.offset.z / 10, t_nor.scale.x / 2.25, t_nor.scale.y / 2.25, t_nor.scale.z / 2.25))
                        #imageMapNor = ('{bump_map {%s \"%s\" %s mapping}' % (imageFormat(texturesNorm),texturesNorm,imgMap(t_nor)))
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        #We were not using the above maybe we should?
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(4, 'normal {uv_mapping bump_map {%s \"%s\" %s  bump_size %.4g }%s}\n' % (imageFormat(texturesNorm),texturesNorm,imgMap(t_nor),(t_nor.normal_factor * 10),mappingNor))
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    if texturesSpec !='':                
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(7, ']\n')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(4, '}\n') 
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
                    #End of slope/ior texture_map
                    if material.diffuse_shader == 'MINNAERT' or material.diffuse_shader == 'FRESNEL':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(4, ']\n')
                        fileWriteTab(3, '}\n')                          
                    fileWriteTab(2, '}\n') #THEN IT CAN CLOSE IT   --MR
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    
    
                    ############################################################################################################
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                    index[0] = idx
                    idx += 1
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                file.write('\n')
                fileWriteTab(1, '}\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                # Face indicies
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(1, 'face_indices {\n')
                fileWriteTab(2, '%d' % (len(me.faces) + quadCount)) # faces count
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                for fi, f in enumerate(me.faces):
                    fv = faces_verts[fi]
                    material_index = f.material_index
                    if len(fv) == 4:
                        indicies = (0, 1, 2), (0, 2, 3)
                    else:
                        indicies = ((0, 1, 2),)
    
                    if vcol_layer:
                        col = vcol_layer[fi]
    
                        if len(fv) == 4:
                            cols = col.color1, col.color2, col.color3, col.color4
                        else:
                            cols = col.color1, col.color2, col.color3
    
    
    
                    if not me_materials or me_materials[material_index] is None: # No materials
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                        for i1, i2, i3 in indicies:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(0, ',\n')
                            fileWriteTab(2, '<%d,%d,%d>' % (fv[i1], fv[i2], fv[i3])) # vert count
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    else:
                        material = me_materials[material_index]
                        for i1, i2, i3 in indicies:
    
                            if me.vertex_colors and material.use_vertex_color_paint:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                                # Colour per vertex - vertex colour
    
                                col1 = cols[i1]
                                col2 = cols[i2]
                                col3 = cols[i3]
    
                                ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
                                ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
                                ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
                            else:
                                # Colour per material - flat material colour
                                diffuse_color = material.diffuse_color
                                ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], diffuse_color[2], f.material_index][0]
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(0, ',\n')
                            fileWriteTab(2, '<%d,%d,%d>, %d,%d,%d' % (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                file.write('\n')
                fileWriteTab(1, '}\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                # normal_indices indicies
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(1, 'normal_indices {\n')
                fileWriteTab(2, '%d' % (len(me.faces) + quadCount)) # faces count
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                for fi, fv in enumerate(faces_verts):
    
                    if len(fv) == 4:
                        indicies = (0, 1, 2), (0, 2, 3)
                    else:
                        indicies = ((0, 1, 2),)
    
                    for i1, i2, i3 in indicies:
    
                        if f.use_smooth:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(0, ',\n')
                            fileWriteTab(2, '<%d,%d,%d>' %\
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                            (uniqueNormals[verts_normals[fv[i1]]][0],\
                             uniqueNormals[verts_normals[fv[i2]]][0],\
                             uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
                        else:
                            idx = uniqueNormals[faces_normals[fi]][0]
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(0, ',\n')
                            fileWriteTab(2, '<%d,%d,%d>' % (idx, idx, idx)) # vert count
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                file.write('\n')
                fileWriteTab(1, '}\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                if uv_layer:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    fileWriteTab(1, 'uv_indices {\n')
                    fileWriteTab(2, '%d' % (len(me.faces) + quadCount)) # faces count
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    for fi, fv in enumerate(faces_verts):
    
                        if len(fv) == 4:
                            indicies = (0, 1, 2), (0, 2, 3)
                        else:
                            indicies = ((0, 1, 2),)
    
                        uv = uv_layer[fi]
                        if len(faces_verts[fi]) == 4:
                            uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3), tuple(uv.uv4)
                        else:
                            uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3)
    
                        for i1, i2, i3 in indicies:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(0, ',\n')
                            fileWriteTab(2, '<%d,%d,%d>' %\
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                            (uniqueUVs[uvs[i1]][0],\
                             uniqueUVs[uvs[i2]][0],\
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                             uniqueUVs[uvs[i3]][0]))
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    file.write('\n')
                    fileWriteTab(1,'}\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                if me.materials:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    try:
                        material = me.materials[0] # dodgy
                        writeObjectMaterial(material)
                    except IndexError:
                        print(me)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                writeMatrix(matrix)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                
                #Importance for radiosity sampling added here: 
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(1, 'radiosity { \n')
                fileWriteTab(2, 'importance %3g \n' % importance)
                fileWriteTab(1, '}\n') 
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(0, '}\n') # End of mesh block
                fileWriteTab(0, '%s\n' % name) # Use named declaration to allow reference e.g. for baking. MR
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                bpy.data.meshes.remove(me)
    
        def exportWorld(world):
    
            render = scene.render
    
    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 Raybaud's avatar
    Maurice Raybaud committed
            #############Maurice#################################### 
            #These lines added to get sky gradient (visible with PNG output)
            if world:
                #For simple flat background:
                if not world.use_sky_blend:
    
                    #Non fully transparent background could premultiply alpha and avoid anti-aliasing display issue: 
                    if render.alpha_mode == 'PREMUL' or render.alpha_mode == 'PREMUL' :
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(0, 'background {rgbt<%.3g, %.3g, %.3g, 0.75>}\n' % (tuple(world.horizon_color)))
    
                    #Currently using no alpha with Sky option:
                    elif render.alpha_mode == 'SKY':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(0, 'background {rgbt<%.3g, %.3g, %.3g, 0>}\n' % (tuple(world.horizon_color)))
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(0, 'background {rgbt<%.3g, %.3g, %.3g, 1>}\n' % (tuple(world.horizon_color)))
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                worldTexCount=0
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                #For Background image textures
                for t in world.texture_slots: #risk to write several sky_spheres but maybe ok.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    worldTexCount+=1
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    if t and t.texture.type == 'IMAGE': #and t.use: #No enable checkbox for world textures yet (report it?)
                        image_filename  = path_image(t.texture.image.filepath)
                        if t.texture.image.filepath != image_filename: t.texture.image.filepath = image_filename
                        if image_filename != '' and t.use_map_blend: 
                            texturesBlend = image_filename
                            #colvalue = t.default_value
                            t_blend = t
                        #commented below was an idea to make the Background image oriented as camera taken here: http://news.povray.org/povray.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.povray.org%3E/
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        #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))#replace 4/3 by the ratio of each image found by some custom or existing function
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        #using camera rotation valuesdirectly from blender seems much easier
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            mappingBlend = ('')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            mappingBlend = (' translate <%.4g-0.5,%.4g-0.5,%.4g-0.5> rotate<0,0,0>  scale <%.4g,%.4g,%.4g>' % (t_blend.offset.x / 10 ,t_blend.offset.y / 10 ,t_blend.offset.z / 10, t_blend.scale.x*0.85 , t_blend.scale.y*0.85 , t_blend.scale.z*0.85 ))
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            #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. 
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        #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.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(0, 'sky_sphere {\n')            
                        fileWriteTab(1, 'pigment {\n')
                        fileWriteTab(2, 'image_map{%s \"%s\" %s}\n' % (imageFormat(texturesBlend),texturesBlend,imgMapBG(t_blend)))
                        fileWriteTab(1, '}\n')
                        fileWriteTab(1, '%s\n' % (mappingBlend))
                        fileWriteTab(0, '}\n')  
                        #fileWriteTab(2, 'scale 2\n')
                        #fileWriteTab(2, 'translate -1\n')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
          
                #For only Background gradient        
            
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                if worldTexCount==0:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    if world.use_sky_blend:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        fileWriteTab(0, 'sky_sphere {\n')            
                        fileWriteTab(1, 'pigment {\n')
                        fileWriteTab(2, 'gradient y\n')#maybe Should follow the advice of POV doc about replacing gradient for skysphere..5.5
                        fileWriteTab(2, 'color_map {\n')
    
                        if render.alpha_mode == 'STRAIGHT':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(3, '[0.0 rgbt<%.3g, %.3g, %.3g, 1>]\n' % (tuple(world.horizon_color)))
                            fileWriteTab(3, '[1.0 rgbt<%.3g, %.3g, %.3g, 1>]\n' % (tuple(world.zenith_color)))
    
                        elif render.alpha_mode == 'PREMUL':
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(3, '[0.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n' % (tuple(world.horizon_color)))
                            fileWriteTab(3, '[1.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n' % (tuple(world.zenith_color))) #aa premult not solved with transmit 1
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            fileWriteTab(3, '[0.0 rgbt<%.3g, %.3g, %.3g, 0>]\n' % (tuple(world.horizon_color)))
                            fileWriteTab(3, '[1.0 rgbt<%.3g, %.3g, %.3g, 0>]\n' % (tuple(world.zenith_color)))
                        fileWriteTab(2, '}\n')
                        fileWriteTab(1, '}\n')
                        fileWriteTab(0, '}\n')
                        #sky_sphere alpha (transmit) is not translating into image alpha the same way as 'background'
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
                if world.light_settings.use_indirect_light:
    
                    scene.pov_radio_enable=1 
    
                #Maybe change the above to scene.pov_radio_enable = world.light_settings.use_indirect_light ?
    
    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:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(0, 'fog {\n')
                fileWriteTab(1, 'distance %.6f\n' % mist.depth)
                fileWriteTab(1, 'color rgbt<%.3g, %.3g, %.3g, %.3g>\n' % (tuple(world.horizon_color) + (1 - mist.intensity,)))
                #fileWriteTab(1, 'fog_offset %.6f\n' % mist.start)
                #fileWriteTab(1, 'fog_alt 5\n')
                #fileWriteTab(1, 'turbulence 0.2\n')
                #fileWriteTab(1, 'turb_depth 0.3\n')
                fileWriteTab(1, 'fog_type 1\n')
                fileWriteTab(0, '}\n')
    
            if scene.pov_media_enable:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(0, 'media {\n')
                fileWriteTab(1, 'scattering { 1, rgb %.3g}\n' % scene.pov_media_color)
                fileWriteTab(1, 'samples %.d\n' % scene.pov_media_samples)
                fileWriteTab(0, '}\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        def exportGlobalSettings(scene):
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            fileWriteTab(0, 'global_settings {\n')
            fileWriteTab(1, 'assumed_gamma 1.0\n')
            fileWriteTab(1, 'max_trace_level %d\n' % scene.pov_max_trace_level)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            if scene.pov_radio_enable:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(1, 'radiosity {\n')
                fileWriteTab(2, 'adc_bailout %.4g\n' % scene.pov_radio_adc_bailout)
                fileWriteTab(2, 'always_sample %d\n' % scene.pov_radio_always_sample)
                fileWriteTab(2, 'brightness %.4g\n' % scene.pov_radio_brightness)
                fileWriteTab(2, 'count %d\n' % scene.pov_radio_count)
                fileWriteTab(2, 'error_bound %.4g\n' % scene.pov_radio_error_bound)
                fileWriteTab(2, 'gray_threshold %.4g\n' % scene.pov_radio_gray_threshold)
                fileWriteTab(2, 'low_error_factor %.4g\n' % scene.pov_radio_low_error_factor)
                fileWriteTab(2, 'media %d\n' % scene.pov_radio_media)
                fileWriteTab(2, 'minimum_reuse %.4g\n' % scene.pov_radio_minimum_reuse)
                fileWriteTab(2, 'nearest_count %d\n' % scene.pov_radio_nearest_count)
                fileWriteTab(2, 'normal %d\n' % scene.pov_radio_normal)
                fileWriteTab(2, 'pretrace_start %.3g\n' % scene.pov_radio_pretrace_start)
                fileWriteTab(2, 'pretrace_end %.3g\n' % scene.pov_radio_pretrace_end)
                fileWriteTab(2, 'recursion_limit %d\n' % scene.pov_radio_recursion_limit)
                fileWriteTab(1, '}\n')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            once=1
            for material in bpy.data.materials:
                if material.subsurface_scattering.use and once:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    fileWriteTab(1, 'mm_per_unit %.6f\n' % (material.subsurface_scattering.scale * (-100) + 15))#In pov, the scale has reversed influence compared to blender. these number should correct that
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    once=0 #In povray, the scale factor for all subsurface shaders needs to be the same
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            if world: 
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(1, 'ambient_light rgb<%.3g, %.3g, %.3g>\n' % tuple(world.ambient_color))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            if material.pov_photons_refraction or material.pov_photons_reflection:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                fileWriteTab(1, 'photons {\n')
                fileWriteTab(2, 'spacing 0.003\n')
                fileWriteTab(2, 'max_trace_level 5\n')
                fileWriteTab(2, 'adc_bailout 0.1\n')
                fileWriteTab(2, 'gather 30, 150\n')
                fileWriteTab(1, '}\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            fileWriteTab(0, '}\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            
        sel = scene.objects
        comments = scene.pov_comments_enable
        if comments: file.write('//---------------------------------------------\n//--Exported with Povray exporter for Blender--\n//---------------------------------------------\n')
        if comments: file.write('\n//--Global settings and background--\n\n')
        
        exportGlobalSettings(scene)
        
        if comments: file.write('\n')
        
        exportWorld(scene.world)
        
        if comments: file.write('\n//--Cameras--\n\n')
        
        exportCamera()
        
        if comments: file.write('\n//--Lamps--\n\n')
        
        exportLamps([l for l in sel if l.type == 'LAMP'])
        
        if comments: file.write('\n//--Material Definitions--\n\n')
        
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        # Convert all materials to strings we can access directly per vertex.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #exportMaterials()
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        writeMaterial(None) # default material
        for material in bpy.data.materials:
            writeMaterial(material)
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        if comments: file.write('\n')
        if comments: file.write('//--Meta objects--\n\n')  # <- How can this be written only if the scene contains META? Activating a boolean just before meta export and testing it here?
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        exportMeta([l for l in sel if l.type == 'META'])
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        
        if comments: file.write('\n')  # <- How can this be written only if the scene contains META?
        if comments: file.write('//--Mesh objecs--\n\n')
        
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        exportMeshs(scene, sel)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #What follow used to happen here:
        #exportCamera()
        #exportWorld(scene.world)
        #exportGlobalSettings(scene)
        #...and the order was important for an attempt to implement pov 3.7 baking (mesh camera) comment for the record
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #print('pov file closed %s' % file.closed)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        file.close()
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #print('pov file closed %s' % file.closed)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        
    
    
    def write_pov_ini(filename_ini, filename_pov, filename_image):
        scene = bpy.data.scenes[0]
        render = scene.render
    
        x = int(render.resolution_x * render.resolution_percentage * 0.01)
        y = int(render.resolution_y * render.resolution_percentage * 0.01)
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        file = open(filename_ini.name, 'w')
        file.write("Input_File_Name='%s'\n" % filename_pov.name)
        file.write("Output_File_Name='%s'\n" % filename_image.name)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        file.write('Width=%d\n' % x)
        file.write('Height=%d\n' % y)
    
        # Needed for border render.
        '''
        file.write('Start_Column=%d\n' % part.x)
        file.write('End_Column=%d\n' % (part.x+part.w))
    
        file.write('Start_Row=%d\n' % (part.y))
        file.write('End_Row=%d\n' % (part.y+part.h))
        '''
    
    
        file.write('Bounding_Method=2\n')#The new automatic BSP is faster in most scenes
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    
        file.write('Display=1\n')#Activated (turn this back off when better live exchange is done between the two programs (see next comment)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        file.write('Pause_When_Done=0\n')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        file.write('Output_File_Type=N\n') # PNG, with POV 3.7, can show background color with alpha. In the long run using the Povray interactive preview like bishop 3D could solve the preview for all formats. 
        #file.write('Output_File_Type=T\n') # TGA, best progressive loading
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        file.write('Output_Alpha=1\n')
    
    
        if render.use_antialiasing:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            aa_mapping = {'5': 2, '8': 3, '11': 4, '16': 5} # method 2 (recursive) with higher max subdiv forced because no mipmapping in povray needs higher sampling.
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            file.write('Antialias=on\n')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            file.write('Antialias_Depth=%d\n' % aa_mapping[render.antialiasing_samples])
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            file.write('Antialias_Threshold=0.1\n')#rather high settings but necessary.
            file.write('Jitter=off\n')#prevent animation flicker
     
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        else:
            file.write('Antialias=0\n')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #print('ini file closed %s' % file.closed)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        file.close()
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        #print('ini file closed %s' % file.closed)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    class PovrayRender(bpy.types.RenderEngine):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        bl_idname = 'POVRAY_RENDER'
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
        bl_label = 'Povray 3.7'
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
        def _export(self, scene):
            import tempfile
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            
            # mktemp is Deprecated since version 2.3, replaced with NamedTemporaryFile() #CR
            self._temp_file_in = tempfile.NamedTemporaryFile(suffix='.pov', delete=False)
            self._temp_file_out = tempfile.NamedTemporaryFile(suffix='.png', delete=False)#PNG with POV 3.7, can show the background color with alpha. In the long run using the Povray interactive preview like bishop 3D could solve the preview for all formats.
            #self._temp_file_out = tempfile.NamedTemporaryFile(suffix='.tga', delete=False)
            self._temp_file_ini = tempfile.NamedTemporaryFile(suffix='.ini', delete=False)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            '''
            self._temp_file_in = '/test.pov'
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            self._temp_file_out = '/test.png'#PNG with POV 3.7, can show the background color with alpha. In the long run using the Povray interactive preview like bishop 3D could solve the preview for all formats.
            #self._temp_file_out = '/test.tga'
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            self._temp_file_ini = '/test.ini'
            '''
    
            def info_callback(txt):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                self.update_stats('', 'POVRAY 3.7: ' + txt)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            write_pov(self._temp_file_in, scene, info_callback)
    
        def _render(self):
    
            try:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                os.remove(self._temp_file_out.name) # so as not to load the old file
    
    Campbell Barton's avatar
    Campbell Barton committed
            except OSError:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                pass
    
            write_pov_ini(self._temp_file_ini, self._temp_file_in, self._temp_file_out)
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            print ('***-STARTING-***')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            pov_binary = 'povray'
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            if sys.platform == 'win32':
                import winreg
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                regKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\POV-Ray\\v3.7\\Windows')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                if bitness == 64:
                    pov_binary = winreg.QueryValueEx(regKey, 'Home')[0] + '\\bin\\pvengine64'
                else:
                    pov_binary = winreg.QueryValueEx(regKey, 'Home')[0] + '\\bin\\pvengine'
    
            else:
                # DH - added -d option to prevent render window popup which leads to segfault on linux
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                extra_args.append('-d')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            if 1:
                # TODO, when povray isnt found this gives a cryptic error, would be nice to be able to detect if it exists
                try:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    self._process = subprocess.Popen([pov_binary, self._temp_file_ini.name] + extra_args) # stdout=subprocess.PIPE, stderr=subprocess.PIPE
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                except OSError:
                    # TODO, report api
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    print("POVRAY 3.7: could not execute '%s', possibly povray isn't installed" % pov_binary)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    import traceback
                    traceback.print_exc()
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    print ('***-DONE-***')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    return False
    
            else:
                # This works too but means we have to wait until its done
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                os.system('%s %s' % (pov_binary, self._temp_file_ini.name))
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            # print ('***-DONE-***')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            return True
    
        def _cleanup(self):
            for f in (self._temp_file_in, self._temp_file_ini, self._temp_file_out):
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                #print('Name: %s' % f.name)
                #print('File closed %s' % f.closed)
                f.close() # Why do I have to close them again? Without closeing the pov and ini files are not deletable. PNG is not closable!
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                try:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    os.unlink(f.name)
                    #os.remove(f.name)
    
                except OSError:  #was that the proper error type?
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    #print('Couldn't remove/unlink TEMP file %s' % f.name)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    pass
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                print('')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            self.update_stats('', '')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def render(self, scene):
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            self.update_stats('', 'POVRAY 3.7: Exporting data from Blender')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            self._export(scene)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            self.update_stats('', 'POVRAY 3.7: Parsing File')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            if not self._render():
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                self.update_stats('', 'POVRAY 3.7: Not found')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                return
    
            r = scene.render
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    ##WIP output format 
    ##        if r.file_format == 'OPENEXR':
    ##            fformat = 'EXR'
    ##            render.color_mode = 'RGBA'
    ##        else:
    ##            fformat = 'TGA'
    ##            r.file_format = 'TARGA'            
    ##            r.color_mode = 'RGBA'
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
            # compute resolution
            x = int(r.resolution_x * r.resolution_percentage * 0.01)
            y = int(r.resolution_y * r.resolution_percentage * 0.01)
    
            # Wait for the file to be created
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            while not os.path.exists(self._temp_file_out.name):
                # print('***POV WAITING FOR FILE***')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                if self.test_break():
                    try:
    
    Campbell Barton's avatar
    Campbell Barton committed
                        self._process.terminate()
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        print('***POV INTERRUPTED***')
    
    Campbell Barton's avatar
    Campbell Barton committed
                    except OSError:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                        pass
                    break
    
    Campbell Barton's avatar
    Campbell Barton committed
                if poll_result is not None:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    print('***POV PROCESS FAILED : %s ***' % poll_result)
                    self.update_stats('', 'POVRAY 3.7: Failed')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    break
    
                time.sleep(self.DELAY)
    
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            if os.path.exists(self._temp_file_out.name):
                # print('***POV FILE OK***')
                self.update_stats('', 'POVRAY 3.7: Rendering')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                prev_size = -1
    
                def update_image():
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    # print('***POV UPDATING IMAGE***')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                    result = self.begin_result(0, 0, x, y)
                    lay = result.layers[0]
                    # possible the image wont load early on.
                    try:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        lay.load_from_file(self._temp_file_out.name)
    
    Campbell Barton's avatar
    Campbell Barton committed
                    except SystemError:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                        pass
                    self.end_result(result)
    
                # Update while povray renders
                while True:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    # print('***POV RENDER LOOP***')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                    # test if povray exists
    
    Campbell Barton's avatar
    Campbell Barton committed
                    if self._process.poll() is not None:
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                        print('***POV PROCESS FINISHED***')
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                        update_image()
                        break
    
                    # user exit
                    if self.test_break():
                        try:
    
    Campbell Barton's avatar
    Campbell Barton committed
                            self._process.terminate()
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                            print('***POV PROCESS INTERRUPTED***')
    
    Campbell Barton's avatar
    Campbell Barton committed
                        except OSError:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                            pass
    
                        break
    
                    # Would be nice to redirect the output
                    # stdout_value, stderr_value = self._process.communicate() # locks
    
    
                    # check if the file updated
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                    new_size = os.path.getsize(self._temp_file_out.name)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
                    if new_size != prev_size:
                        update_image()
                        prev_size = new_size
    
                    time.sleep(self.DELAY)
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
                print('***POV FILE NOT FOUND***')
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
            print('***POV FINISHED***')
            #time.sleep(self.DELAY)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            self._cleanup()