# ***** 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 #**** # """Translate complex shaders to exported POV textures.""" import bpy def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material): """Translate Blender material POV texture{} block and write to exported file.""" # Assumes only called once on each material if material: name_orig = material.name name = materialNames[name_orig] = uniqueName(bpy.path.clean_name(name_orig), materialNames) else: name = name_orig = DEF_MAT_NAME if material: # If saturation(.s) is not zero, then color is not grey, and has a tint colored_specular_found = ((material.pov.specular_color.s > 0.0) and (material.pov.diffuse_shader != 'MINNAERT')) ################## # Several versions of the finish: Level conditions are variations for specular/Mirror # texture channel map with alternative finish of 0 specular and no mirror reflection. # Level=1 Means No specular nor Mirror reflection # Level=2 Means translation of spec and mir levels for when no map influences them # Level=3 Means Maximum Spec and Mirror def povHasnoSpecularMaps(Level): """Translate Blender specular map influence to POV finish map trick and write to file.""" if Level == 1: if comments: tabWrite("//--No specular nor Mirror reflection--\n") else: tabWrite("\n") tabWrite("#declare %s = finish {\n" % safety(name, Level=1)) elif Level == 2: if comments: tabWrite("//--translation of spec and mir levels for when no map " \ "influences them--\n") else: tabWrite("\n") tabWrite("#declare %s = finish {\n" % safety(name, Level=2)) elif Level == 3: if comments: tabWrite("//--Maximum Spec and Mirror--\n") else: tabWrite("\n") tabWrite("#declare %s = finish {\n" % safety(name, Level=3)) if material: # POV-Ray 3.7 now uses two diffuse values respectively for front and back shading # (the back diffuse is like blender translucency) frontDiffuse = material.pov.diffuse_intensity backDiffuse = material.pov.translucency if material.pov.conserve_energy: #Total should not go above one if (frontDiffuse + backDiffuse) <= 1.0: pass elif frontDiffuse == backDiffuse: # Try to respect the user's 'intention' by comparing the two values but # bringing the total back to one. frontDiffuse = backDiffuse = 0.5 # Let the highest value stay the highest value. elif frontDiffuse > backDiffuse: # clamps the sum below 1 backDiffuse = min(backDiffuse, (1.0 - frontDiffuse)) else: frontDiffuse = min(frontDiffuse, (1.0 - backDiffuse)) # map hardness between 0.0 and 1.0 roughness = ((1.0 - ((material.pov.specular_hardness - 1.0) / 510.0))) ## scale from 0.0 to 0.1 roughness *= 0.1 # add a small value because 0.0 is invalid. roughness += (1.0 / 511.0) ################################Diffuse Shader###################################### # Not used for Full spec (Level=3) of the shader. if material.pov.diffuse_shader == 'OREN_NAYAR' and Level != 3: # Blender roughness is what is generally called oren nayar Sigma, # and brilliance in POV-Ray. tabWrite("brilliance %.3g\n" % (0.9 + material.roughness)) if material.pov.diffuse_shader == 'TOON' and Level != 3: tabWrite("brilliance %.3g\n" % (0.01 + material.diffuse_toon_smooth * 0.25)) # Lower diffuse and increase specular for toon effect seems to look better # in POV-Ray. frontDiffuse *= 0.5 if material.pov.diffuse_shader == 'MINNAERT' and Level != 3: #tabWrite("aoi %.3g\n" % material.darkness) pass # let's keep things simple for now if material.pov.diffuse_shader == 'FRESNEL' and Level != 3: #tabWrite("aoi %.3g\n" % material.diffuse_fresnel_factor) pass # let's keep things simple for now if material.pov.diffuse_shader == 'LAMBERT' and Level != 3: # trying to best match lambert attenuation by that constant brilliance value tabWrite("brilliance 1\n") if Level == 2: ###########################Specular Shader###################################### # No difference between phong and cook torrence in blender HaHa! if (material.pov.specular_shader == 'COOKTORR' or material.pov.specular_shader == 'PHONG'): tabWrite("phong %.3g\n" % (material.pov.specular_intensity)) tabWrite("phong_size %.3g\n" % (material.pov.specular_hardness /3.14)) # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior. elif material.pov.specular_shader == 'BLINN': # Use blender Blinn's IOR just as some factor for spec intensity tabWrite("specular %.3g\n" % (material.pov.specular_intensity * (material.pov.specular_ior / 4.0))) tabWrite("roughness %.3g\n" % roughness) #Could use brilliance 2(or varying around 2 depending on ior or factor) too. elif material.pov.specular_shader == 'TOON': tabWrite("phong %.3g\n" % (material.pov.specular_intensity * 2.0)) # use extreme phong_size tabWrite("phong_size %.3g\n" % (0.1 + material.pov.specular_toon_smooth / 2.0)) elif material.pov.specular_shader == 'WARDISO': # find best suited default constant for brilliance Use both phong and # specular for some values. tabWrite("specular %.3g\n" % (material.pov.specular_intensity / (material.pov.specular_slope + 0.0005))) # find best suited default constant for brilliance Use both phong and # specular for some values. tabWrite("roughness %.4g\n" % (0.0005 + material.pov.specular_slope / 10.0)) # find best suited default constant for brilliance Use both phong and # specular for some values. tabWrite("brilliance %.4g\n" % (1.8 - material.pov.specular_slope * 1.8)) #################################################################################### elif Level == 1: if (material.pov.specular_shader == 'COOKTORR' or material.pov.specular_shader == 'PHONG'): tabWrite("phong 0\n")#%.3g\n" % (material.pov.specular_intensity/5)) tabWrite("phong_size %.3g\n" % (material.pov.specular_hardness /3.14)) # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior. elif material.pov.specular_shader == 'BLINN': # Use blender Blinn's IOR just as some factor for spec intensity tabWrite("specular %.3g\n" % (material.pov.specular_intensity * (material.pov.specular_ior / 4.0))) tabWrite("roughness %.3g\n" % roughness) #Could use brilliance 2(or varying around 2 depending on ior or factor) too. elif material.pov.specular_shader == 'TOON': tabWrite("phong %.3g\n" % (material.pov.specular_intensity * 2.0)) # use extreme phong_size tabWrite("phong_size %.3g\n" % (0.1 + material.pov.specular_toon_smooth / 2.0)) elif material.pov.specular_shader == 'WARDISO': # find best suited default constant for brilliance Use both phong and # specular for some values. tabWrite("specular %.3g\n" % (material.pov.specular_intensity / (material.pov.specular_slope + 0.0005))) # find best suited default constant for brilliance Use both phong and # specular for some values. tabWrite("roughness %.4g\n" % (0.0005 + material.pov.specular_slope / 10.0)) # find best suited default constant for brilliance Use both phong and # specular for some values. tabWrite("brilliance %.4g\n" % (1.8 - material.pov.specular_slope * 1.8)) elif Level == 3: # Spec must be Max at Level 3 so that white of mixing texture always shows specularity # That's why it's multiplied by 255. maybe replace by texture's brightest pixel value? tabWrite("specular %.3g\n" % ((material.pov.specular_intensity*material.pov.specular_color.v)*(255* slot.specular_factor))) tabWrite("roughness %.3g\n" % (1/material.pov.specular_hardness)) tabWrite("diffuse %.3g %.3g\n" % (frontDiffuse, backDiffuse)) tabWrite("ambient %.3g\n" % material.pov.ambient) # POV-Ray blends the global value #tabWrite("ambient rgb <%.3g, %.3g, %.3g>\n" % \ # tuple([c*material.pov.ambient for c in world.ambient_color])) tabWrite("emission %.3g\n" % material.pov.emit) # New in POV-Ray 3.7 #POV-Ray just ignores roughness if there's no specular keyword #tabWrite("roughness %.3g\n" % roughness) if material.pov.conserve_energy: # added for more realistic shading. Needs some checking to see if it # really works. --Maurice. tabWrite("conserve_energy\n") if colored_specular_found == True: tabWrite("metallic\n") # 'phong 70.0 ' if Level != 1: if material.pov_raytrace_mirror.use: raytrace_mirror = material.pov_raytrace_mirror if raytrace_mirror.reflect_factor: tabWrite("reflection {\n") tabWrite("rgb <%.3g, %.3g, %.3g>\n" % material.pov.mirror_color[:]) if material.pov.mirror_metallic: tabWrite("metallic %.3g\n" % (raytrace_mirror.reflect_factor)) # Blurry reflections for UberPOV if using_uberpov and raytrace_mirror.gloss_factor < 1.0: #tabWrite("#ifdef(unofficial) #if(unofficial = \"patch\") #if(patch(\"upov-reflection-roughness\") > 0)\n") tabWrite("roughness %.6f\n" % \ (0.000001/raytrace_mirror.gloss_factor)) #tabWrite("#end #end #end\n") # This and previous comment for backward compatibility, messier pov code if material.pov.mirror_use_IOR: # WORKING ? # Removed from the line below: gives a more physically correct # material but needs proper IOR. --Maurice tabWrite("fresnel 1 ") tabWrite("falloff %.3g exponent %.3g} " % \ (raytrace_mirror.fresnel, raytrace_mirror.fresnel_factor)) if material.pov_subsurface_scattering.use: subsurface_scattering = material.pov_subsurface_scattering tabWrite("subsurface { translucency <%.3g, %.3g, %.3g> }\n" % ( (subsurface_scattering.radius[0]), (subsurface_scattering.radius[1]), (subsurface_scattering.radius[2]), ) ) if material.pov.irid_enable: tabWrite("irid { %.4g thickness %.4g turbulence %.4g }" % \ (material.pov.irid_amount, material.pov.irid_thickness, material.pov.irid_turbulence)) else: tabWrite("diffuse 0.8\n") tabWrite("phong 70.0\n") #tabWrite("specular 0.2\n") # This is written into the object ''' if material and material.pov.transparency_method=='RAYTRACE': 'interior { ior %.3g} ' % material.raytrace_transparency.ior ''' #tabWrite("crand 1.0\n") # Sand granyness #tabWrite("metallic %.6f\n" % material.spec) #tabWrite("phong %.6f\n" % material.spec) #tabWrite("phong_size %.6f\n" % material.spec) #tabWrite("brilliance %.6f " % (material.pov.specular_hardness/256.0) # Like hardness tabWrite("}\n\n") # Level=2 Means translation of spec and mir levels for when no map influences them povHasnoSpecularMaps(Level=2) if material: special_texture_found = False tmpidx = -1 for t in material.pov_texture_slots: tmpidx += 1 # index = material.pov.active_texture_index slot = material.pov_texture_slots[tmpidx] # [index] povtex = slot.texture # slot.name tex = bpy.data.textures[povtex] if t and t.use and tex is not None: if (tex.type == 'IMAGE' and tex.image) or tex.type != 'IMAGE': #validPath if(t and t.use and (t.use_map_specular or t.use_map_raymir or t.use_map_normal or t.use_map_alpha)): special_texture_found = True continue # Some texture found if special_texture_found or colored_specular_found: # Level=1 Means No specular nor Mirror reflection povHasnoSpecularMaps(Level=1) # Level=3 Means Maximum Spec and Mirror povHasnoSpecularMaps(Level=3) def exportPattern(texture, string_strip_hyphen): """Translate Blender procedural textures to POV patterns and write to pov file. Function Patterns can be used to better access sub components of a pattern like grey values for influence mapping""" tex=texture pat = tex.pov PATname = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(tex.name)) mappingDif = ("translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % \ (pat.tex_mov_x, pat.tex_mov_y, pat.tex_mov_z, 1.0 / pat.tex_scale_x, 1.0 / pat.tex_scale_y, 1.0 / pat.tex_scale_z)) texStrg="" def exportColorRamp(texture): tex=texture pat = tex.pov colRampStrg="color_map {\n" numColor=0 for el in tex.color_ramp.elements: numColor+=1 pos = el.position col=el.color colR,colG,colB,colA = col[0],col[1],col[2],1-col[3] if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} : colRampStrg+="[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n"%(pos,colR,colG,colB,colA) if pat.tex_pattern_type in {'brick','checker'} and numColor < 3: colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) if pat.tex_pattern_type == 'hexagon' and numColor < 4 : colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) if pat.tex_pattern_type == 'square' and numColor < 5 : colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) if pat.tex_pattern_type == 'triangular' and numColor < 7 : colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) colRampStrg+="} \n" #end color map return colRampStrg #much work to be done here only defaults translated for now: #pov noise_generator 3 means perlin noise if tex.type not in {'NONE', 'IMAGE'} and pat.tex_pattern_type == 'emulator': texStrg+="pigment {\n" ####################### EMULATE BLENDER VORONOI TEXTURE #################### if tex.type == 'VORONOI': texStrg+="crackle\n" texStrg+=" offset %.4g\n"%tex.nabla texStrg+=" form <%.4g,%.4g,%.4g>\n"%(tex.weight_1, tex.weight_2, tex.weight_3) if tex.distance_metric == 'DISTANCE': texStrg+=" metric 2.5\n" if tex.distance_metric == 'DISTANCE_SQUARED': texStrg+=" metric 2.5\n" texStrg+=" poly_wave 2\n" if tex.distance_metric == 'MINKOVSKY': texStrg+=" metric %s\n"%tex.minkovsky_exponent if tex.distance_metric == 'MINKOVSKY_FOUR': texStrg+=" metric 4\n" if tex.distance_metric == 'MINKOVSKY_HALF': texStrg+=" metric 0.5\n" if tex.distance_metric == 'CHEBYCHEV': texStrg+=" metric 10\n" if tex.distance_metric == 'MANHATTAN': texStrg+=" metric 1\n" if tex.color_mode == 'POSITION': texStrg+="solid\n" texStrg+="scale 0.25\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<0,0,0,1>]\n" texStrg+="[1 color rgbt<1,1,1,0>]\n" texStrg+="}\n" ####################### EMULATE BLENDER CLOUDS TEXTURE #################### if tex.type == 'CLOUDS': if tex.noise_type == 'SOFT_NOISE': texStrg+="wrinkles\n" texStrg+="scale 0.25\n" else: texStrg+="granite\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<0,0,0,1>]\n" texStrg+="[1 color rgbt<1,1,1,0>]\n" texStrg+="}\n" ####################### EMULATE BLENDER WOOD TEXTURE #################### if tex.type == 'WOOD': if tex.wood_type == 'RINGS': texStrg+="wood\n" texStrg+="scale 0.25\n" if tex.wood_type == 'RINGNOISE': texStrg+="wood\n" texStrg+="scale 0.25\n" texStrg+="turbulence %.4g\n"%(tex.turbulence/100) if tex.wood_type == 'BANDS': texStrg+="marble\n" texStrg+="scale 0.25\n" texStrg+="rotate <45,-45,45>\n" if tex.wood_type == 'BANDNOISE': texStrg+="marble\n" texStrg+="scale 0.25\n" texStrg+="rotate <45,-45,45>\n" texStrg+="turbulence %.4g\n"%(tex.turbulence/10) if tex.noise_basis_2 == 'SIN': texStrg+="sine_wave\n" if tex.noise_basis_2 == 'TRI': texStrg+="triangle_wave\n" if tex.noise_basis_2 == 'SAW': texStrg+="ramp_wave\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<0,0,0,0>]\n" texStrg+="[1 color rgbt<1,1,1,0>]\n" texStrg+="}\n" ####################### EMULATE BLENDER STUCCI TEXTURE #################### if tex.type == 'STUCCI': texStrg+="bozo\n" texStrg+="scale 0.25\n" if tex.noise_type == 'HARD_NOISE': texStrg+="triangle_wave\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbf<1,1,1,0>]\n" texStrg+="[1 color rgbt<0,0,0,1>]\n" texStrg+="}\n" else: if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbf<0,0,0,1>]\n" texStrg+="[1 color rgbt<1,1,1,0>]\n" texStrg+="}\n" ####################### EMULATE BLENDER MAGIC TEXTURE #################### if tex.type == 'MAGIC': texStrg+="leopard\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<1,1,1,0.5>]\n" texStrg+="[0.25 color rgbf<0,1,0,0.75>]\n" texStrg+="[0.5 color rgbf<0,0,1,0.75>]\n" texStrg+="[0.75 color rgbf<1,0,1,0.75>]\n" texStrg+="[1 color rgbf<0,1,0,0.75>]\n" texStrg+="}\n" texStrg+="scale 0.1\n" ####################### EMULATE BLENDER MARBLE TEXTURE #################### if tex.type == 'MARBLE': texStrg+="marble\n" texStrg+="turbulence 0.5\n" texStrg+="noise_generator 3\n" texStrg+="scale 0.75\n" texStrg+="rotate <45,-45,45>\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: if tex.marble_type == 'SOFT': texStrg+="color_map {\n" texStrg+="[0 color rgbt<0,0,0,0>]\n" texStrg+="[0.05 color rgbt<0,0,0,0>]\n" texStrg+="[1 color rgbt<0.9,0.9,0.9,0>]\n" texStrg+="}\n" elif tex.marble_type == 'SHARP': texStrg+="color_map {\n" texStrg+="[0 color rgbt<0,0,0,0>]\n" texStrg+="[0.025 color rgbt<0,0,0,0>]\n" texStrg+="[1 color rgbt<0.9,0.9,0.9,0>]\n" texStrg+="}\n" else: texStrg+="[0 color rgbt<0,0,0,0>]\n" texStrg+="[1 color rgbt<1,1,1,0>]\n" texStrg+="}\n" if tex.noise_basis_2 == 'SIN': texStrg+="sine_wave\n" if tex.noise_basis_2 == 'TRI': texStrg+="triangle_wave\n" if tex.noise_basis_2 == 'SAW': texStrg+="ramp_wave\n" ####################### EMULATE BLENDER BLEND TEXTURE #################### if tex.type == 'BLEND': if tex.progression=='RADIAL': texStrg+="radial\n" if tex.use_flip_axis=='HORIZONTAL': texStrg+="rotate x*90\n" else: texStrg+="rotate <-90,0,90>\n" texStrg+="ramp_wave\n" elif tex.progression=='SPHERICAL': texStrg+="spherical\n" texStrg+="scale 3\n" texStrg+="poly_wave 1\n" elif tex.progression=='QUADRATIC_SPHERE': texStrg+="spherical\n" texStrg+="scale 3\n" texStrg+=" poly_wave 2\n" elif tex.progression=='DIAGONAL': texStrg+="gradient <1,1,0>\n" texStrg+="scale 3\n" elif tex.use_flip_axis=='HORIZONTAL': texStrg+="gradient x\n" texStrg+="scale 2.01\n" elif tex.use_flip_axis=='VERTICAL': texStrg+="gradient y\n" texStrg+="scale 2.01\n" #texStrg+="ramp_wave\n" #texStrg+="frequency 0.5\n" texStrg+="phase 0.5\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<1,1,1,0>]\n" texStrg+="[1 color rgbf<0,0,0,1>]\n" texStrg+="}\n" if tex.progression == 'LINEAR': texStrg+=" poly_wave 1\n" if tex.progression == 'QUADRATIC': texStrg+=" poly_wave 2\n" if tex.progression == 'EASING': texStrg+=" poly_wave 1.5\n" ####################### EMULATE BLENDER MUSGRAVE TEXTURE #################### # if tex.type == 'MUSGRAVE': # texStrg+="function{ f_ridged_mf( x, y, 0, 1, 2, 9, -0.5, 3,3 )*0.5}\n" # texStrg+="color_map {\n" # texStrg+="[0 color rgbf<0,0,0,1>]\n" # texStrg+="[1 color rgbf<1,1,1,0>]\n" # texStrg+="}\n" # simplified for now: if tex.type == 'MUSGRAVE': texStrg+="bozo scale 0.25 \n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {[0.5 color rgbf<0,0,0,1>][1 color rgbt<1,1,1,0>]}ramp_wave \n" ####################### EMULATE BLENDER DISTORTED NOISE TEXTURE #################### if tex.type == 'DISTORTED_NOISE': texStrg+="average\n" texStrg+=" pigment_map {\n" texStrg+=" [1 bozo scale 0.25 turbulence %.4g\n" %tex.distortion if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<1,1,1,0>]\n" texStrg+="[1 color rgbf<0,0,0,1>]\n" texStrg+="}\n" texStrg+="]\n" if tex.noise_distortion == 'CELL_NOISE': texStrg+=" [1 cells scale 0.1\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<1,1,1,0>]\n" texStrg+="[1 color rgbf<0,0,0,1>]\n" texStrg+="}\n" texStrg+="]\n" if tex.noise_distortion=='VORONOI_CRACKLE': texStrg+=" [1 crackle scale 0.25\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<1,1,1,0>]\n" texStrg+="[1 color rgbf<0,0,0,1>]\n" texStrg+="}\n" texStrg+="]\n" if tex.noise_distortion in ['VORONOI_F1','VORONOI_F2','VORONOI_F3','VORONOI_F4','VORONOI_F2_F1']: texStrg+=" [1 crackle metric 2.5 scale 0.25 turbulence %.4g\n" %(tex.distortion/2) if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<1,1,1,0>]\n" texStrg+="[1 color rgbf<0,0,0,1>]\n" texStrg+="}\n" texStrg+="]\n" else: texStrg+=" [1 wrinkles scale 0.25\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0 color rgbt<1,1,1,0>]\n" texStrg+="[1 color rgbf<0,0,0,1>]\n" texStrg+="}\n" texStrg+="]\n" texStrg+=" }\n" ####################### EMULATE BLENDER NOISE TEXTURE #################### if tex.type == 'NOISE': texStrg+="cells\n" texStrg+="turbulence 3\n" texStrg+="omega 3\n" if tex.use_color_ramp == True: texStrg+=exportColorRamp(tex) else: texStrg+="color_map {\n" texStrg+="[0.75 color rgb<0,0,0,>]\n" texStrg+="[1 color rgb<1,1,1,>]\n" texStrg+="}\n" ####################### IGNORE OTHER BLENDER TEXTURE #################### else: #non translated textures pass texStrg+="}\n\n" texStrg+="#declare f%s=\n"%PATname texStrg+="function{pigment{%s}}\n"%PATname texStrg+="\n" elif pat.tex_pattern_type != 'emulator': texStrg+="pigment {\n" texStrg+="%s\n"%pat.tex_pattern_type if pat.tex_pattern_type == 'agate': texStrg+="agate_turb %.4g\n"%pat.modifier_turbulence if pat.tex_pattern_type in {'spiral1', 'spiral2', 'tiling'}: texStrg+="%s\n"%pat.modifier_numbers if pat.tex_pattern_type == 'quilted': texStrg+="control0 %s control1 %s\n"%(pat.modifier_control0, pat.modifier_control1) if pat.tex_pattern_type == 'mandel': texStrg+="%s exponent %s \n"%(pat.f_iter, pat.f_exponent) if pat.tex_pattern_type == 'julia': texStrg+="<%.4g, %.4g> %s exponent %s \n"%(pat.julia_complex_1, pat.julia_complex_2, pat.f_iter, pat.f_exponent) if pat.tex_pattern_type == 'magnet' and pat.magnet_style == 'mandel': texStrg+="%s mandel %s \n"%(pat.magnet_type, pat.f_iter) if pat.tex_pattern_type == 'magnet' and pat.magnet_style == 'julia': texStrg+="%s julia <%.4g, %.4g> %s\n"%(pat.magnet_type, pat.julia_complex_1, pat.julia_complex_2, pat.f_iter) if pat.tex_pattern_type in {'mandel', 'julia', 'magnet'}: texStrg+="interior %s, %.4g\n"%(pat.f_ior, pat.f_ior_fac) texStrg+="exterior %s, %.4g\n"%(pat.f_eor, pat.f_eor_fac) if pat.tex_pattern_type == 'gradient': texStrg+="<%s, %s, %s> \n"%(pat.grad_orient_x, pat.grad_orient_y, pat.grad_orient_z) if pat.tex_pattern_type == 'pavement': numTiles=pat.pave_tiles numPattern=1 if pat.pave_sides == '4' and pat.pave_tiles == 3: numPattern = pat.pave_pat_2 if pat.pave_sides == '6' and pat.pave_tiles == 3: numPattern = pat.pave_pat_3 if pat.pave_sides == '3' and pat.pave_tiles == 4: numPattern = pat.pave_pat_3 if pat.pave_sides == '3' and pat.pave_tiles == 5: numPattern = pat.pave_pat_4 if pat.pave_sides == '4' and pat.pave_tiles == 4: numPattern = pat.pave_pat_5 if pat.pave_sides == '6' and pat.pave_tiles == 4: numPattern = pat.pave_pat_7 if pat.pave_sides == '4' and pat.pave_tiles == 5: numPattern = pat.pave_pat_12 if pat.pave_sides == '3' and pat.pave_tiles == 6: numPattern = pat.pave_pat_12 if pat.pave_sides == '6' and pat.pave_tiles == 5: numPattern = pat.pave_pat_22 if pat.pave_sides == '4' and pat.pave_tiles == 6: numPattern = pat.pave_pat_35 if pat.pave_sides == '6' and pat.pave_tiles == 6: numTiles = 5 texStrg+="number_of_sides %s number_of_tiles %s pattern %s form %s \n"%(pat.pave_sides, numTiles, numPattern, pat.pave_form) ################ functions ##################################################################################################### if pat.tex_pattern_type == 'function': texStrg+="{ %s"%pat.func_list texStrg+="(x" if pat.func_plus_x != "NONE": if pat.func_plus_x =='increase': texStrg+="*" if pat.func_plus_x =='plus': texStrg+="+" texStrg+="%.4g"%pat.func_x texStrg+=",y" if pat.func_plus_y != "NONE": if pat.func_plus_y =='increase': texStrg+="*" if pat.func_plus_y =='plus': texStrg+="+" texStrg+="%.4g"%pat.func_y texStrg+=",z" if pat.func_plus_z != "NONE": if pat.func_plus_z =='increase': texStrg+="*" if pat.func_plus_z =='plus': texStrg+="+" texStrg+="%.4g"%pat.func_z sort = -1 if pat.func_list in {"f_comma","f_crossed_trough","f_cubic_saddle","f_cushion","f_devils_curve", "f_enneper","f_glob","f_heart","f_hex_x","f_hex_y","f_hunt_surface", "f_klein_bottle","f_kummer_surface_v1","f_lemniscate_of_gerono","f_mitre", "f_nodal_cubic","f_noise_generator","f_odd","f_paraboloid","f_pillow", "f_piriform","f_quantum","f_quartic_paraboloid","f_quartic_saddle", "f_sphere","f_steiners_roman","f_torus_gumdrop","f_umbrella"}: sort = 0 if pat.func_list in {"f_bicorn","f_bifolia","f_boy_surface","f_superellipsoid","f_torus"}: sort = 1 if pat.func_list in {"f_ellipsoid","f_folium_surface","f_hyperbolic_torus", "f_kampyle_of_eudoxus","f_parabolic_torus","f_quartic_cylinder","f_torus2"}: sort = 2 if pat.func_list in {"f_blob2","f_cross_ellipsoids","f_flange_cover","f_isect_ellipsoids", "f_kummer_surface_v2","f_ovals_of_cassini","f_rounded_box","f_spikes_2d","f_strophoid"}: sort = 3 if pat.func_list in {"f_algbr_cyl1","f_algbr_cyl2","f_algbr_cyl3","f_algbr_cyl4","f_blob","f_mesh1","f_poly4","f_spikes"}: sort = 4 if pat.func_list in {"f_devils_curve_2d","f_dupin_cyclid","f_folium_surface_2d","f_hetero_mf","f_kampyle_of_eudoxus_2d", "f_lemniscate_of_gerono_2d","f_polytubes","f_ridge","f_ridged_mf","f_spiral","f_witch_of_agnesi"}: sort = 5 if pat.func_list in {"f_helix1","f_helix2","f_piriform_2d","f_strophoid_2d"}: sort = 6 if pat.func_list == "f_helical_torus": sort = 7 if sort > -1: texStrg+=",%.4g"%pat.func_P0 if sort > 0: texStrg+=",%.4g"%pat.func_P1 if sort > 1: texStrg+=",%.4g"%pat.func_P2 if sort > 2: texStrg+=",%.4g"%pat.func_P3 if sort > 3: texStrg+=",%.4g"%pat.func_P4 if sort > 4: texStrg+=",%.4g"%pat.func_P5 if sort > 5: texStrg+=",%.4g"%pat.func_P6 if sort > 6: texStrg+=",%.4g"%pat.func_P7 texStrg+=",%.4g"%pat.func_P8 texStrg+=",%.4g"%pat.func_P9 texStrg+=")}\n" ############## end functions ############################################################### if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: texStrg+="color_map {\n" numColor=0 if tex.use_color_ramp == True: for el in tex.color_ramp.elements: numColor+=1 pos = el.position col=el.color colR,colG,colB,colA = col[0],col[1],col[2],1-col[3] if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} : texStrg+="[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n"%(pos,colR,colG,colB,colA) if pat.tex_pattern_type in {'brick','checker'} and numColor < 3: texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) if pat.tex_pattern_type == 'hexagon' and numColor < 4 : texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) if pat.tex_pattern_type == 'square' and numColor < 5 : texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) if pat.tex_pattern_type == 'triangular' and numColor < 7 : texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) else: texStrg+="[0 color rgbf<0,0,0,1>]\n" texStrg+="[1 color rgbf<1,1,1,0>]\n" if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} : texStrg+="} \n" if pat.tex_pattern_type == 'brick': texStrg+="brick_size <%.4g, %.4g, %.4g> mortar %.4g \n"%(pat.brick_size_x, pat.brick_size_y, pat.brick_size_z, pat.brick_mortar) texStrg+="%s \n"%mappingDif texStrg+="rotate <%.4g,%.4g,%.4g> \n"%(pat.tex_rot_x, pat.tex_rot_y, pat.tex_rot_z) texStrg+="turbulence <%.4g,%.4g,%.4g> \n"%(pat.warp_turbulence_x, pat.warp_turbulence_y, pat.warp_turbulence_z) texStrg+="octaves %s \n"%pat.modifier_octaves texStrg+="lambda %.4g \n"%pat.modifier_lambda texStrg+="omega %.4g \n"%pat.modifier_omega texStrg+="frequency %.4g \n"%pat.modifier_frequency texStrg+="phase %.4g \n"%pat.modifier_phase texStrg+="}\n\n" texStrg+="#declare f%s=\n"%PATname texStrg+="function{pigment{%s}}\n"%PATname texStrg+="\n" return(texStrg) def writeTextureInfluence(using_uberpov, mater, materialNames, LocalMaterialNames, path_image, lampCount, imageFormat, imgMap, imgMapTransforms, tabWrite, comments, string_strip_hyphen, safety, col, os, preview_dir, unpacked_images): """Translate Blender texture influences to various POV texture tricks and write to pov file.""" material_finish = materialNames[mater.name] if mater.pov.use_transparency: trans = 1.0 - mater.pov.alpha else: trans = 0.0 if ((mater.pov.specular_color.s == 0.0) or (mater.pov.diffuse_shader == 'MINNAERT')): # No layered texture because of aoi pattern used for minnaert and pov can't layer patterned colored_specular_found = False else: colored_specular_found = True if mater.pov.use_transparency and mater.pov.transparency_method == 'RAYTRACE': povFilter = mater.pov_raytrace_transparency.filter * (1.0 - mater.pov.alpha) trans = (1.0 - mater.pov.alpha) - povFilter else: povFilter = 0.0 ##############SF texturesDif = "" texturesSpec = "" texturesNorm = "" texturesAlpha = "" #proceduralFlag=False tmpidx = -1 for t in mater.pov_texture_slots: tmpidx += 1 # index = mater.pov.active_texture_index slot = mater.pov_texture_slots[tmpidx] # [index] povtex = slot.texture # slot.name tex = bpy.data.textures[povtex] if t and (t.use and (tex is not None)): # 'NONE' ('NONE' type texture is different from no texture covered above) if (tex.type == 'NONE' and tex.pov.tex_pattern_type == 'emulator'): continue # move to next slot # PROCEDURAL elif (tex.type != 'IMAGE' and tex.type != 'NONE'): proceduralFlag=True image_filename = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(tex.name)) if image_filename: if t.use_map_color_diffuse: texturesDif = image_filename # colvalue = t.default_value # UNUSED t_dif = t if t_dif.texture.pov.tex_gamma_enable: imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) if t.use_map_specular or t.use_map_raymir: texturesSpec = image_filename # colvalue = t.default_value # UNUSED t_spec = t if t.use_map_normal: texturesNorm = image_filename # colvalue = t.normal_factor/10 # UNUSED #textNormName=tex.image.name + ".normal" #was the above used? --MR t_nor = t if t.use_map_alpha: texturesAlpha = image_filename # colvalue = t.alpha_factor * 10.0 # UNUSED #textDispName=tex.image.name + ".displ" #was the above used? --MR t_alpha = t # RASTER IMAGE elif (tex.type == 'IMAGE' and tex.image and tex.pov.tex_pattern_type == 'emulator'): proceduralFlag=False #PACKED if tex.image.packed_file: orig_image_filename=tex.image.filepath_raw unpackedfilename= os.path.join(preview_dir,("unpacked_img_"+(string_strip_hyphen(bpy.path.clean_name(tex.name))))) if not os.path.exists(unpackedfilename): # record which images that were newly copied and can be safely # cleaned up unpacked_images.append(unpackedfilename) tex.image.filepath_raw=unpackedfilename tex.image.save() image_filename = unpackedfilename.replace("\\","/") # .replace("\\","/") to get only forward slashes as it's what POV prefers, # even on windows tex.image.filepath_raw=orig_image_filename #FILE else: image_filename = path_image(tex.image) # IMAGE SEQUENCE BEGINS if image_filename: if bpy.data.images[tex.image.name].source == 'SEQUENCE': korvaa = "." + str(tex.image_user.frame_offset + 1).zfill(3) + "." image_filename = image_filename.replace(".001.", korvaa) print(" seq debug ") print(image_filename) # IMAGE SEQUENCE ENDS imgGamma = "" if image_filename: texdata = bpy.data.textures[t.texture] if t.use_map_color_diffuse: texturesDif = image_filename # colvalue = t.default_value # UNUSED t_dif = t print (texdata) if texdata.pov.tex_gamma_enable: imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) if t.use_map_specular or t.use_map_raymir: texturesSpec = image_filename # colvalue = t.default_value # UNUSED t_spec = t if t.use_map_normal: texturesNorm = image_filename # colvalue = t.normal_factor/10 # UNUSED #textNormName=tex.image.name + ".normal" #was the above used? --MR t_nor = t if t.use_map_alpha: texturesAlpha = image_filename # colvalue = t.alpha_factor * 10.0 # UNUSED #textDispName=tex.image.name + ".displ" #was the above used? --MR t_alpha = t #################################################################################### tabWrite("\n") # THIS AREA NEEDS TO LEAVE THE TEXTURE OPEN UNTIL ALL MAPS ARE WRITTEN DOWN. # --MR currentMatName = string_strip_hyphen(materialNames[mater.name]) LocalMaterialNames.append(currentMatName) tabWrite("\n#declare MAT_%s = \ntexture{\n" % currentMatName) ################################################################################ if mater.pov.replacement_text != "": tabWrite("%s\n" % mater.pov.replacement_text) ################################################################################# # XXX TODO: replace by new POV MINNAERT rather than aoi if mater.pov.diffuse_shader == 'MINNAERT': tabWrite("\n") tabWrite("aoi\n") tabWrite("texture_map {\n") tabWrite("[%.3g finish {diffuse %.3g}]\n" % \ (mater.darkness / 2.0, 2.0 - mater.darkness)) tabWrite("[%.3g\n" % (1.0 - (mater.darkness / 2.0))) if mater.pov.diffuse_shader == 'FRESNEL': # For FRESNEL diffuse in POV, we'll layer slope patterned textures # with lamp vector as the slope vector and nest one slope per lamp # into each texture map's entry. c = 1 while (c <= lampCount): tabWrite("slope { lampTarget%s }\n" % (c)) tabWrite("texture_map {\n") # Diffuse Fresnel value and factor go up to five, # other kind of values needed: used the number 5 below to remap tabWrite("[%.3g finish {diffuse %.3g}]\n" % \ ((5.0 - mater.diffuse_fresnel) / 5, (mater.diffuse_intensity * ((5.0 - mater.diffuse_fresnel_factor) / 5)))) tabWrite("[%.3g\n" % ((mater.diffuse_fresnel_factor / 5) * (mater.diffuse_fresnel / 5.0))) c += 1 # if shader is a 'FRESNEL' or 'MINNAERT': slope pigment pattern or aoi # and texture map above, the rest below as one of its entry if texturesSpec != "" or texturesAlpha != "": if texturesSpec != "": # tabWrite("\n") tabWrite("pigment_pattern {\n") mappingSpec =imgMapTransforms(t_spec) if texturesSpec and texturesSpec.startswith("PAT_"): tabWrite("function{f%s(x,y,z).grey}\n" %texturesSpec) tabWrite("%s\n" % mappingSpec) else: tabWrite("uv_mapping image_map{%s \"%s\" %s}\n" % \ (imageFormat(texturesSpec), texturesSpec, imgMap(t_spec))) tabWrite("%s\n" % mappingSpec) tabWrite("}\n") tabWrite("texture_map {\n") tabWrite("[0 \n") if texturesDif == "": if texturesAlpha != "": tabWrite("\n") mappingAlpha = imgMapTransforms(t_alpha) if texturesAlpha and texturesAlpha.startswith("PAT_"): tabWrite("function{f%s(x,y,z).transmit}%s\n" %(texturesAlpha, mappingAlpha)) else: tabWrite("pigment {pigment_pattern {uv_mapping image_map" \ "{%s \"%s\" %s}%s" % \ (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), mappingAlpha)) tabWrite("}\n") tabWrite("pigment_map {\n") tabWrite("[0 color rgbft<0,0,0,1,1>]\n") tabWrite("[1 color rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>]\n" % \ (col[0], col[1], col[2], povFilter, trans)) tabWrite("}\n") tabWrite("}\n") else: tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n" % \ (col[0], col[1], col[2], povFilter, trans)) if texturesSpec != "": # Level 1 is no specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) else: # Level 2 is translated spec tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) else: mappingDif = imgMapTransforms(t_dif) if texturesAlpha != "": mappingAlpha = imgMapTransforms(t_alpha) tabWrite("pigment {\n") tabWrite("pigment_pattern {\n") if texturesAlpha and texturesAlpha.startswith("PAT_"): tabWrite("function{f%s(x,y,z).transmit}%s\n" %(texturesAlpha, mappingAlpha)) else: tabWrite("uv_mapping image_map{%s \"%s\" %s}%s}\n" % \ (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), mappingAlpha)) tabWrite("pigment_map {\n") tabWrite("[0 color rgbft<0,0,0,1,1>]\n") #if texturesAlpha and texturesAlpha.startswith("PAT_"): #tabWrite("[1 pigment{%s}]\n" %texturesDif) if texturesDif and not texturesDif.startswith("PAT_"): tabWrite("[1 uv_mapping image_map {%s \"%s\" %s} %s]\n" % \ (imageFormat(texturesDif), texturesDif, (imgGamma + imgMap(t_dif)), mappingDif)) elif texturesDif and texturesDif.startswith("PAT_"): tabWrite("[1 %s]\n" %texturesDif) tabWrite("}\n") tabWrite("}\n") if texturesAlpha and texturesAlpha.startswith("PAT_"): tabWrite("}\n") else: if texturesDif and texturesDif.startswith("PAT_"): tabWrite("pigment{%s}\n" %texturesDif) else: tabWrite("pigment {uv_mapping image_map {%s \"%s\" %s}%s}\n" % \ (imageFormat(texturesDif), texturesDif, (imgGamma + imgMap(t_dif)), mappingDif)) if texturesSpec != "": # Level 1 is no specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) else: # Level 2 is translated specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) ## scale 1 rotate y*0 #imageMap = ("{image_map {%s \"%s\" %s }\n" % \ # (imageFormat(textures),textures,imgMap(t_dif))) #tabWrite("uv_mapping pigment %s} %s finish {%s}\n" % \ # (imageMap,mapping,safety(material_finish))) #tabWrite("pigment {uv_mapping image_map {%s \"%s\" %s}%s} " \ # "finish {%s}\n" % \ # (imageFormat(texturesDif), texturesDif, imgMap(t_dif), # mappingDif, safety(material_finish))) if texturesNorm != "": ## scale 1 rotate y*0 mappingNor =imgMapTransforms(t_nor) if texturesNorm and texturesNorm.startswith("PAT_"): tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, ( - t_nor.normal_factor * 9.5), mappingNor)) else: tabWrite("normal {\n") # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials if (mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov): tabWrite("average\n") tabWrite("normal_map{\n") # 0.5 for entries below means a 50 percent mix # between the micro normal and user bump map # order seems indifferent as commutative tabWrite("[0.025 bumps %.4g scale 0.1*%.4g]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(10/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.1]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.15]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.2]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.25]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.3]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.35]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.4]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.45]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.5]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[1.0 ") # Proceed with user bump... tabWrite("uv_mapping bump_map " \ "{%s \"%s\" %s bump_size %.4g }%s" % \ (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor), ( - t_nor.normal_factor * 9.5), mappingNor)) # ...Then close its last entry and the the normal_map itself if (mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov): tabWrite("]}}\n") else: tabWrite("]}\n") if texturesSpec != "": tabWrite("]\n") ##################Second index for mapping specular max value############### tabWrite("[1 \n") if texturesDif == "" and mater.pov.replacement_text == "": if texturesAlpha != "": mappingAlpha = imgMapTransforms(t_alpha) if texturesAlpha and texturesAlpha.startswith("PAT_"): tabWrite("function{f%s(x,y,z).transmit %s}\n" %(texturesAlpha, mappingAlpha)) else: tabWrite("pigment {pigment_pattern {uv_mapping image_map" \ "{%s \"%s\" %s}%s}\n" % \ (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), mappingAlpha)) tabWrite("pigment_map {\n") tabWrite("[0 color rgbft<0,0,0,1,1>]\n") tabWrite("[1 color rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>]\n" % \ (col[0], col[1], col[2], povFilter, trans)) tabWrite("}\n") tabWrite("}\n") else: tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n" % \ (col[0], col[1], col[2], povFilter, trans)) if texturesSpec != "": # Level 3 is full specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=3))) if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: tabWrite("normal {\n") tabWrite("average\n") tabWrite("normal_map{\n") # 0.5 for entries below means a 50 percent mix # between the micro normal and user bump map # order seems indifferent as commutative tabWrite("[0.025 bumps %.4g scale 0.1*%.4g]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(10/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.1]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.15]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.2]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.25]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.3]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.35]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.4]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.45]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.5]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring #XXX IF USER BUMP_MAP if texturesNorm != "": tabWrite("[1.0 ") # Blurry reflection or not Proceed with user bump in either case... tabWrite("uv_mapping bump_map " \ "{%s \"%s\" %s bump_size %.4g }%s]\n" % \ (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor), ( - t_nor.normal_factor * 9.5), mappingNor)) # ...Then close the normal_map itself if blurry reflection if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: tabWrite("}}\n") else: tabWrite("}\n") elif colored_specular_found: # Level 1 is no specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) else: # Level 2 is translated specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) elif mater.pov.replacement_text == "": mappingDif = imgMapTransforms(t_dif) if texturesAlpha != "": mappingAlpha = imgMapTransforms(t_alpha) if texturesAlpha and texturesAlpha.startswith("PAT_"): tabWrite("pigment{pigment_pattern {function{f%s(x,y,z).transmit}%s}\n" %(texturesAlpha, mappingAlpha)) else: tabWrite("pigment {pigment_pattern {uv_mapping image_map" \ "{%s \"%s\" %s}%s}\n" % \ (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), mappingAlpha)) tabWrite("pigment_map {\n") tabWrite("[0 color rgbft<0,0,0,1,1>]\n") if texturesAlpha and texturesAlpha.startswith("PAT_"): tabWrite("[1 function{f%s(x,y,z).transmit}%s]\n" %(texturesAlpha, mappingAlpha)) elif texturesDif and not texturesDif.startswith("PAT_"): tabWrite("[1 uv_mapping image_map {%s \"%s\" %s} %s]\n" % \ (imageFormat(texturesDif), texturesDif, (imgMap(t_dif) + imgGamma), mappingDif)) elif texturesDif and texturesDif.startswith("PAT_"): tabWrite("[1 %s %s]\n" %(texturesDif, mappingDif)) tabWrite("}\n") tabWrite("}\n") else: if texturesDif and texturesDif.startswith("PAT_"): tabWrite("pigment{%s %s}\n" %(texturesDif, mappingDif)) else: tabWrite("pigment {\n") tabWrite("uv_mapping image_map {\n") #tabWrite("%s \"%s\" %s}%s\n" % \ # (imageFormat(texturesDif), texturesDif, # (imgGamma + imgMap(t_dif)),mappingDif)) tabWrite("%s \"%s\" \n" % (imageFormat(texturesDif), texturesDif)) tabWrite("%s\n" % (imgGamma + imgMap(t_dif))) tabWrite("}\n") tabWrite("%s\n" % mappingDif) tabWrite("}\n") if texturesSpec != "": # Level 3 is full specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=3))) else: # Level 2 is translated specular tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) ## scale 1 rotate y*0 #imageMap = ("{image_map {%s \"%s\" %s }" % \ # (imageFormat(textures), textures,imgMap(t_dif))) #tabWrite("\n\t\t\tuv_mapping pigment %s} %s finish {%s}" % \ # (imageMap, mapping, safety(material_finish))) #tabWrite("\n\t\t\tpigment {uv_mapping image_map " \ # "{%s \"%s\" %s}%s} finish {%s}" % \ # (imageFormat(texturesDif), texturesDif,imgMap(t_dif), # mappingDif, safety(material_finish))) if texturesNorm != "" and mater.pov.replacement_text == "": mappingNor =imgMapTransforms(t_nor) if texturesNorm and texturesNorm.startswith("PAT_"): tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, ( - t_nor.normal_factor * 9.5), mappingNor)) else: tabWrite("normal {\n") # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: tabWrite("average\n") tabWrite("normal_map{\n") # 0.5 for entries below means a 50 percent mix # between the micro normal and user bump map # order seems indifferent as commutative tabWrite("[0.025 bumps %.4g scale 0.1*%.4g]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(10/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.1]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.15]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.2]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.25]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.3]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.35]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.4]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.45]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[0.025 bumps %.4g scale 0.1*%.4g phase 0.5]\n" %((10/(mater.pov_raytrace_mirror.gloss_factor+0.01)),(1/(mater.pov_raytrace_mirror.gloss_samples+0.001)))) # micronormals blurring tabWrite("[1.0 ") # Blurry reflection or not Proceed with user bump in either case... tabWrite("uv_mapping bump_map " \ "{%s \"%s\" %s bump_size %.4g }%s]\n" % \ (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor), ( - t_nor.normal_factor * 9.5), mappingNor)) # ...Then close the normal_map itself if blurry reflection if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: tabWrite("}}\n") else: tabWrite("}\n") if texturesSpec != "" and mater.pov.replacement_text == "": tabWrite("]\n") tabWrite("}\n") #End of slope/ior texture_map if mater.pov.diffuse_shader == 'MINNAERT' and mater.pov.replacement_text == "": tabWrite("]\n") tabWrite("}\n") if mater.pov.diffuse_shader == 'FRESNEL' and mater.pov.replacement_text == "": c = 1 while (c <= lampCount): tabWrite("]\n") tabWrite("}\n") c += 1 # Close first layer of POV "texture" (Blender material) tabWrite("}\n") if ((mater.pov.specular_color.s > 0.0) and (mater.pov.diffuse_shader != 'MINNAERT')): colored_specular_found = True else: colored_specular_found = False # Write another layered texture using invisible diffuse and metallic trick # to emulate colored specular highlights special_texture_found = False tmpidx = -1 for t in mater.pov_texture_slots: tmpidx += 1 # index = mater.pov.active_texture_index slot = mater.pov_texture_slots[tmpidx] # [index] povtex = slot.texture # slot.name tex = bpy.data.textures[povtex] if(t and t.use and ((tex.type == 'IMAGE' and tex.image) or tex.type != 'IMAGE') and (t.use_map_specular or t.use_map_raymir)): # Specular mapped textures would conflict with colored specular # because POV can't layer over or under pigment patterned textures special_texture_found = True if colored_specular_found and not special_texture_found: if comments: tabWrite(" // colored highlights with a stransparent metallic layer\n") else: tabWrite("\n") tabWrite("texture {\n") tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, 0, 1>}\n" % \ (mater.pov.specular_color[0], mater.pov.specular_color[1], mater.pov.specular_color[2])) tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) # Level 2 is translated spec texturesNorm = "" for t in mater.pov_texture_slots: if t and tex.pov.tex_pattern_type != 'emulator': proceduralFlag=True image_filename = string_strip_hyphen(bpy.path.clean_name(tex.name)) if (t and tex.type == 'IMAGE' and t.use and tex.image and tex.pov.tex_pattern_type == 'emulator'): proceduralFlag=False image_filename = path_image(tex.image) imgGamma = "" if image_filename: if t.use_map_normal: texturesNorm = image_filename # colvalue = t.normal_factor/10 # UNUSED XXX *-9.5 ! #textNormName=tex.image.name + ".normal" #was the above used? --MR t_nor = t if proceduralFlag: tabWrite("normal{function" \ "{f%s(x,y,z).grey} bump_size %.4g}\n" % \ (texturesNorm, ( - t_nor.normal_factor * 9.5))) else: tabWrite("normal {uv_mapping bump_map " \ "{%s \"%s\" %s bump_size %.4g }%s}\n" % \ (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor), ( - t_nor.normal_factor * 9.5), mappingNor)) tabWrite("}\n") # THEN IT CAN CLOSE LAST LAYER OF TEXTURE def string_strip_hyphen(name): return name.replace("-", "") # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! def write_nodes(scene,povMatName,ntree,file): """translate Blender node trees to pov and write them to file""" declareNodes=[] scene=bpy.context.scene for node in ntree.nodes: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName if node.bl_idname == "PovrayFinishNode" and node.outputs["Finish"].is_linked: file.write('#declare %s = finish {\n'%povNodeName) emission=node.inputs["Emission"].default_value if node.inputs["Emission"].is_linked: pass file.write(' emission %.4g\n'%emission) for link in ntree.links: if link.to_node == node: if link.from_node.bl_idname == 'PovrayDiffuseNode': intensity=0 albedo="" brilliance=0 crand=0 if link.from_node.inputs["Intensity"].is_linked: pass else: intensity=link.from_node.inputs["Intensity"].default_value if link.from_node.inputs["Albedo"].is_linked: pass else: if link.from_node.inputs["Albedo"].default_value == True: albedo = "albedo" file.write(' diffuse %s %.4g\n'%(albedo,intensity)) if link.from_node.inputs["Brilliance"].is_linked: pass else: brilliance=link.from_node.inputs["Brilliance"].default_value file.write(' brilliance %.4g\n'%brilliance) if link.from_node.inputs["Crand"].is_linked: pass else: crand=link.from_node.inputs["Crand"].default_value if crand > 0: file.write(' crand %.4g\n'%crand) if link.from_node.bl_idname == 'PovraySubsurfaceNode': if scene.povray.sslt_enable: energy = 0 r = g = b = 0 if link.from_node.inputs["Translucency"].is_linked: pass else: r,g,b,a=link.from_node.inputs["Translucency"].default_value[:] if link.from_node.inputs["Energy"].is_linked: pass else: energy=link.from_node.inputs["Energy"].default_value file.write(' subsurface { translucency <%.4g,%.4g,%.4g>*%s }\n'%(r,g,b,energy)) if link.from_node.bl_idname in {'PovraySpecularNode','PovrayPhongNode'}: intensity=0 albedo="" roughness=0 metallic=0 phong_size=0 highlight="specular" if link.from_node.inputs["Intensity"].is_linked: pass else: intensity=link.from_node.inputs["Intensity"].default_value if link.from_node.inputs["Albedo"].is_linked: pass else: if link.from_node.inputs["Albedo"].default_value == True: albedo = "albedo" if link.from_node.bl_idname in {'PovrayPhongNode'}: highlight="phong" file.write(' %s %s %.4g\n'%(highlight,albedo,intensity)) if link.from_node.bl_idname in {'PovraySpecularNode'}: if link.from_node.inputs["Roughness"].is_linked: pass else: roughness=link.from_node.inputs["Roughness"].default_value file.write(' roughness %.6g\n'%roughness) if link.from_node.bl_idname in {'PovrayPhongNode'}: if link.from_node.inputs["Size"].is_linked: pass else: phong_size=link.from_node.inputs["Size"].default_value file.write(' phong_size %s\n'%phong_size) if link.from_node.inputs["Metallic"].is_linked: pass else: metallic=link.from_node.inputs["Metallic"].default_value file.write(' metallic %.4g\n'%metallic) if link.from_node.bl_idname in {'PovrayMirrorNode'}: file.write(' reflection {\n') color=None exponent=0 metallic=0 falloff=0 fresnel="" conserve="" if link.from_node.inputs["Color"].is_linked: pass else: color=link.from_node.inputs["Color"].default_value[:] file.write(' <%.4g,%.4g,%.4g>\n'%color) if link.from_node.inputs["Exponent"].is_linked: pass else: exponent=link.from_node.inputs["Exponent"].default_value file.write(' exponent %.4g\n'%exponent) if link.from_node.inputs["Falloff"].is_linked: pass else: falloff=link.from_node.inputs["Falloff"].default_value file.write(' falloff %.4g\n'%falloff) if link.from_node.inputs["Metallic"].is_linked: pass else: metallic=link.from_node.inputs["Metallic"].default_value file.write(' metallic %.4g'%metallic) if link.from_node.inputs["Fresnel"].is_linked: pass else: if link.from_node.inputs["Fresnel"].default_value==True: fresnel="fresnel" if link.from_node.inputs["Conserve energy"].is_linked: pass else: if link.from_node.inputs["Conserve energy"].default_value==True: conserve="conserve_energy" file.write(' %s}\n %s\n'%(fresnel,conserve)) if link.from_node.bl_idname == 'PovrayAmbientNode': ambient=(0,0,0) if link.from_node.inputs["Ambient"].is_linked: pass else: ambient=link.from_node.inputs["Ambient"].default_value[:] file.write(' ambient <%.4g,%.4g,%.4g>\n'%ambient) if link.from_node.bl_idname in {'PovrayIridescenceNode'}: file.write(' irid {\n') amount=0 thickness=0 turbulence=0 if link.from_node.inputs["Amount"].is_linked: pass else: amount=link.from_node.inputs["Amount"].default_value file.write(' %.4g\n'%amount) if link.from_node.inputs["Thickness"].is_linked: pass else: exponent=link.from_node.inputs["Thickness"].default_value file.write(' thickness %.4g\n'%thickness) if link.from_node.inputs["Turbulence"].is_linked: pass else: falloff=link.from_node.inputs["Turbulence"].default_value file.write(' turbulence %.4g}\n'%turbulence) file.write('}\n') for node in ntree.nodes: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName if node.bl_idname == "PovrayTransformNode" and node.outputs["Transform"].is_linked: tx=node.inputs["Translate x"].default_value ty=node.inputs["Translate y"].default_value tz=node.inputs["Translate z"].default_value rx=node.inputs["Rotate x"].default_value ry=node.inputs["Rotate y"].default_value rz=node.inputs["Rotate z"].default_value sx=node.inputs["Scale x"].default_value sy=node.inputs["Scale y"].default_value sz=node.inputs["Scale z"].default_value file.write('#declare %s = transform {\n translate<%.4g,%.4g,%.4g>\n rotate<%.4g,%.4g,%.4g>\n scale<%.4g,%.4g,%.4g>}\n'%(povNodeName,tx,ty,tz,rx,ry,rz,sx,sy,sz)) for node in ntree.nodes: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName if node.bl_idname == "PovrayColorImageNode" and node.outputs["Pigment"].is_linked: declareNodes.append(node.name) if node.image == "": file.write('#declare %s = pigment { color rgb 0.8}\n'%(povNodeName)) else: im=bpy.data.images[node.image] if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)): transform = "" for link in ntree.links: if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node: povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName transform="transform {%s}"%povTransName uv="" if node.map_type=="uv_mapping": uv="uv_mapping" filepath=bpy.path.abspath(im.filepath) file.write('#declare %s = pigment {%s image_map {\n'%(povNodeName,uv)) premul="off" if node.premultiplied: premul="on" once="" if node.once: once="once" file.write(' "%s"\n gamma %.6g\n premultiplied %s\n'%(filepath,node.inputs["Gamma"].default_value,premul)) file.write(' %s\n'%once) if node.map_type!="uv_mapping": file.write(' map_type %s\n'%(node.map_type)) file.write(' interpolate %s\n filter all %.4g\n transmit all %.4g\n'% (node.interpolate,node.inputs["Filter"].default_value,node.inputs["Transmit"].default_value)) file.write(' }\n') file.write(' %s\n'%transform) file.write(' }\n') for node in ntree.nodes: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName if node.bl_idname == "PovrayImagePatternNode" and node.outputs["Pattern"].is_linked: declareNodes.append(node.name) if node.image != "": im=bpy.data.images[node.image] if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)): transform = "" for link in ntree.links: if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node: povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName transform="transform {%s}"%povTransName uv="" if node.map_type=="uv_mapping": uv="uv_mapping" filepath=bpy.path.abspath(im.filepath) file.write('#macro %s() %s image_pattern {\n'%(povNodeName,uv)) premul="off" if node.premultiplied: premul="on" once="" if node.once: once="once" file.write(' "%s"\n gamma %.6g\n premultiplied %s\n'%(filepath,node.inputs["Gamma"].default_value,premul)) file.write(' %s\n'%once) if node.map_type!="uv_mapping": file.write(' map_type %s\n'%(node.map_type)) file.write(' interpolate %s\n'%node.interpolate) file.write(' }\n') file.write(' %s\n'%transform) file.write('#end\n') for node in ntree.nodes: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName if node.bl_idname == "PovrayBumpMapNode" and node.outputs["Normal"].is_linked: if node.image != "": im=bpy.data.images[node.image] if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)): transform = "" for link in ntree.links: if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node: povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName transform="transform {%s}"%povTransName uv="" if node.map_type=="uv_mapping": uv="uv_mapping" filepath=bpy.path.abspath(im.filepath) file.write('#declare %s = normal {%s bump_map {\n'%(povNodeName,uv)) once="" if node.once: once="once" file.write(' "%s"\n'%filepath) file.write(' %s\n'%once) if node.map_type!="uv_mapping": file.write(' map_type %s\n'%(node.map_type)) bump_size=node.inputs["Normal"].default_value if node.inputs["Normal"].is_linked: pass file.write(' interpolate %s\n bump_size %.4g\n'%(node.interpolate,bump_size)) file.write(' }\n') file.write(' %s\n'%transform) file.write(' }\n') declareNodes.append(node.name) for node in ntree.nodes: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName if node.bl_idname == "PovrayPigmentNode" and node.outputs["Pigment"].is_linked: declareNodes.append(node.name) r,g,b=node.inputs["Color"].default_value[:] f=node.inputs["Filter"].default_value t=node.inputs["Transmit"].default_value if node.inputs["Color"].is_linked: pass file.write('#declare %s = pigment{color srgbft <%.4g,%.4g,%.4g,%.4g,%.4g>}\n'%(povNodeName,r,g,b,f,t)) for node in ntree.nodes: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName if node.bl_idname == "PovrayTextureNode" and node.outputs["Texture"].is_linked: declareNodes.append(node.name) r,g,b=node.inputs["Pigment"].default_value[:] povColName="color rgb <%.4g,%.4g,%.4g>"%(r,g,b) if node.inputs["Pigment"].is_linked: for link in ntree.links: if link.to_node==node and link.to_socket.name=="Pigment": povColName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName file.write('#declare %s = texture{\n pigment{%s}\n'%(povNodeName,povColName)) if node.inputs["Normal"].is_linked: for link in ntree.links: if link.to_node==node and link.to_socket.name=="Normal" and link.from_node.name in declareNodes: povNorName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName file.write(' normal{%s}\n'%povNorName) if node.inputs["Finish"].is_linked: for link in ntree.links: if link.to_node==node and link.to_socket.name=="Finish": povFinName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName file.write(' finish{%s}\n'%povFinName) file.write('}\n') declareNodes.append(node.name) for i in range(0,len(ntree.nodes)): for node in ntree.nodes: if node.bl_idname in {"ShaderNodeGroup","ShaderTextureMapNode"}: for output in node.outputs: if output.name=="Texture" and output.is_linked and (node.name not in declareNodes): declare=True for link in ntree.links: if link.to_node==node and link.to_socket.name not in {"","Color ramp","Mapping","Transform","Modifier"}: if link.from_node.name not in declareNodes: declare=False if declare: povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName uv="" warp="" for link in ntree.links: if link.to_node==node and link.from_node.bl_idname=='PovrayMappingNode' and link.from_node.warp_type!="NONE": w_type = link.from_node.warp_type if w_type=="uv_mapping": uv="uv_mapping" else: tor="" if w_type=="toroidal": tor="major_radius %.4g"%link.from_node.warp_tor_major_radius orient=link.from_node.warp_orientation exp=link.from_node.warp_dist_exp warp="warp{%s orientation %s dist_exp %.4g %s}"%(w_type,orient,exp,tor) if link.from_node.warp_type=="planar": warp="warp{%s %s %.4g}"%(w_type,orient,exp) if link.from_node.warp_type=="cubic": warp="warp{%s}"%w_type file.write('#declare %s = texture {%s\n'%(povNodeName,uv)) pattern=node.inputs[0].default_value advanced="" if node.inputs[0].is_linked: for link in ntree.links: if link.to_node==node and link.from_node.bl_idname=='ShaderPatternNode': ########### advanced ############################################### lfn=link.from_node pattern=lfn.pattern if pattern == 'agate': advanced = 'agate_turb %.4g'%lfn.agate_turb if pattern == 'crackle': advanced="form <%.4g,%.4g,%.4g>"%(lfn.crackle_form_x,lfn.crackle_form_y,lfn.crackle_form_z) advanced+=" metric %.4g"%lfn.crackle_metric if lfn.crackle_solid: advanced+=" solid" if pattern in {'spiral1', 'spiral2'}: advanced='%.4g'%lfn.spiral_arms if pattern in {'tiling'}: advanced='%.4g'%lfn.tiling_number if pattern in {'gradient'}: advanced='%s'%lfn.gradient_orient if link.to_node==node and link.from_node.bl_idname=='PovrayImagePatternNode': povMacroName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName pattern = "%s()"%povMacroName file.write(' %s %s %s\n'%(pattern,advanced,warp)) repeat="" for link in ntree.links: if link.to_node==node and link.from_node.bl_idname=='PovrayMultiplyNode': if link.from_node.amount_x > 1: repeat+="warp{repeat %.4g * x}"%link.from_node.amount_x if link.from_node.amount_y > 1: repeat+=" warp{repeat %.4g * y}"%link.from_node.amount_y if link.from_node.amount_z > 1: repeat+=" warp{repeat %.4g * z}"%link.from_node.amount_z transform="" for link in ntree.links: if link.to_node==node and link.from_node.bl_idname=='PovrayTransformNode': povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName transform="transform {%s}"%povTransName x=0 y=0 z=0 d=0 e=0 f=0 g=0 h=0 modifier=False for link in ntree.links: if link.to_node==node and link.from_node.bl_idname=='PovrayModifierNode': modifier=True if link.from_node.inputs["Turb X"].is_linked: pass else: x = link.from_node.inputs["Turb X"].default_value if link.from_node.inputs["Turb Y"].is_linked: pass else: y = link.from_node.inputs["Turb Y"].default_value if link.from_node.inputs["Turb Z"].is_linked: pass else: z = link.from_node.inputs["Turb Z"].default_value if link.from_node.inputs["Octaves"].is_linked: pass else: d = link.from_node.inputs["Octaves"].default_value if link.from_node.inputs["Lambda"].is_linked: pass else: e = link.from_node.inputs["Lambda"].default_value if link.from_node.inputs["Omega"].is_linked: pass else: f = link.from_node.inputs["Omega"].default_value if link.from_node.inputs["Frequency"].is_linked: pass else: g = link.from_node.inputs["Frequency"].default_value if link.from_node.inputs["Phase"].is_linked: pass else: h = link.from_node.inputs["Phase"].default_value turb = "turbulence <%.4g,%.4g,%.4g>"%(x,y,z) octv = "octaves %s"%d lmbd = "lambda %.4g"%e omg = "omega %.4g"%f freq = "frequency %.4g"%g pha = "phase %.4g"%h file.write('\n') if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: file.write(' texture_map {\n') if node.inputs["Color ramp"].is_linked: for link in ntree.links: if link.to_node==node and link.from_node.bl_idname=="ShaderNodeValToRGB": els = link.from_node.color_ramp.elements n=-1 for el in els: n+=1 povInMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s_%s"%(n,povMatName) default=True for ilink in ntree.links: if ilink.to_node==node and ilink.to_socket.name == str(n): default=False povInMatName=string_strip_hyphen(bpy.path.clean_name(ilink.from_node.name))+"_%s"%povMatName if default: r,g,b,a=el.color[:] file.write(' #declare %s = texture{pigment{color srgbt <%.4g,%.4g,%.4g,%.4g>}};\n'%(povInMatName,r,g,b,1-a)) file.write(' [%s %s]\n'%(el.position,povInMatName)) else: els=[[0,0,0,0],[1,1,1,1]] for i in range(0,2): povInMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s_%s"%(i,povMatName) default=True for ilink in ntree.links: if ilink.to_node==node and ilink.to_socket.name == str(i): default=False povInMatName=string_strip_hyphen(bpy.path.clean_name(ilink.from_node.name))+"_%s"%povMatName if default: r,g,b=els[i][1],els[i][2],els[i][3] if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: file.write(' #declare %s = texture{pigment{color rgb <%.4g,%.4g,%.4g>}};\n'%(povInMatName,r,g,b)) else: file.write(' texture{pigment{color rgb <%.4g,%.4g,%.4g>}}\n'%(r,g,b)) if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: file.write(' [%s %s]\n'%(els[i][0],povInMatName)) else: if default==False: file.write(' texture{%s}\n'%povInMatName) if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: file.write('}\n') if pattern == 'brick': file.write("brick_size <%.4g, %.4g, %.4g> mortar %.4g \n"%(node.brick_size_x, node.brick_size_y, node.brick_size_z, node.brick_mortar)) file.write(' %s %s'%(repeat,transform)) if modifier: file.write(' %s %s %s %s %s %s'%(turb,octv,lmbd,omg,freq,pha)) file.write('}\n') declareNodes.append(node.name) for link in ntree.links: if link.to_node.bl_idname == "PovrayOutputNode" and link.from_node.name in declareNodes: povMatNodeName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName file.write('#declare %s = %s\n'%(povMatName,povMatNodeName))