1# ***** BEGIN GPL LICENSE BLOCK ***** 2# 3# This program is free software; you can redistribute it and/or 4# modify it under the terms of the GNU General Public License 5# as published by the Free Software Foundation; either version 2 6# of the License, or (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program; if not, write to the Free Software Foundation, 15# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16# 17# #**** END GPL LICENSE BLOCK #**** 18 19# <pep8 compliant> 20 21"""Translate complex shaders to exported POV textures.""" 22 23import bpy 24 25def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material): 26 """Translate Blender material POV texture{} block and write to exported file.""" 27 # Assumes only called once on each material 28 if material: 29 name_orig = material.name 30 name = materialNames[name_orig] = uniqueName(bpy.path.clean_name(name_orig), materialNames) 31 else: 32 name = name_orig = DEF_MAT_NAME 33 34 35 if material: 36 # If saturation(.s) is not zero, then color is not grey, and has a tint 37 colored_specular_found = ((material.pov.specular_color.s > 0.0) and (material.pov.diffuse_shader != 'MINNAERT')) 38 39 ################## 40 # Several versions of the finish: Level conditions are variations for specular/Mirror 41 # texture channel map with alternative finish of 0 specular and no mirror reflection. 42 # Level=1 Means No specular nor Mirror reflection 43 # Level=2 Means translation of spec and mir levels for when no map influences them 44 # Level=3 Means Maximum Spec and Mirror 45 46 def povHasnoSpecularMaps(Level): 47 """Translate Blender specular map influence to POV finish map trick and write to file.""" 48 if Level == 1: 49 if comments: 50 tabWrite("//--No specular nor Mirror reflection--\n") 51 else: 52 tabWrite("\n") 53 tabWrite("#declare %s = finish {\n" % safety(name, Level=1)) 54 55 elif Level == 2: 56 if comments: 57 tabWrite("//--translation of spec and mir levels for when no map " \ 58 "influences them--\n") 59 else: 60 tabWrite("\n") 61 tabWrite("#declare %s = finish {\n" % safety(name, Level=2)) 62 63 elif Level == 3: 64 if comments: 65 tabWrite("//--Maximum Spec and Mirror--\n") 66 else: 67 tabWrite("\n") 68 tabWrite("#declare %s = finish {\n" % safety(name, Level=3)) 69 if material: 70 # POV-Ray 3.7 now uses two diffuse values respectively for front and back shading 71 # (the back diffuse is like blender translucency) 72 frontDiffuse = material.pov.diffuse_intensity 73 backDiffuse = material.pov.translucency 74 75 if material.pov.conserve_energy: 76 77 #Total should not go above one 78 if (frontDiffuse + backDiffuse) <= 1.0: 79 pass 80 elif frontDiffuse == backDiffuse: 81 # Try to respect the user's 'intention' by comparing the two values but 82 # bringing the total back to one. 83 frontDiffuse = backDiffuse = 0.5 84 # Let the highest value stay the highest value. 85 elif frontDiffuse > backDiffuse: 86 # clamps the sum below 1 87 backDiffuse = min(backDiffuse, (1.0 - frontDiffuse)) 88 else: 89 frontDiffuse = min(frontDiffuse, (1.0 - backDiffuse)) 90 91 # map hardness between 0.0 and 1.0 92 roughness = ((1.0 - ((material.pov.specular_hardness - 1.0) / 510.0))) 93 ## scale from 0.0 to 0.1 94 roughness *= 0.1 95 # add a small value because 0.0 is invalid. 96 roughness += (1.0 / 511.0) 97 98 ################################Diffuse Shader###################################### 99 # Not used for Full spec (Level=3) of the shader. 100 if material.pov.diffuse_shader == 'OREN_NAYAR' and Level != 3: 101 # Blender roughness is what is generally called oren nayar Sigma, 102 # and brilliance in POV-Ray. 103 tabWrite("brilliance %.3g\n" % (0.9 + material.roughness)) 104 105 if material.pov.diffuse_shader == 'TOON' and Level != 3: 106 tabWrite("brilliance %.3g\n" % (0.01 + material.diffuse_toon_smooth * 0.25)) 107 # Lower diffuse and increase specular for toon effect seems to look better 108 # in POV-Ray. 109 frontDiffuse *= 0.5 110 111 if material.pov.diffuse_shader == 'MINNAERT' and Level != 3: 112 #tabWrite("aoi %.3g\n" % material.darkness) 113 pass # let's keep things simple for now 114 if material.pov.diffuse_shader == 'FRESNEL' and Level != 3: 115 #tabWrite("aoi %.3g\n" % material.diffuse_fresnel_factor) 116 pass # let's keep things simple for now 117 if material.pov.diffuse_shader == 'LAMBERT' and Level != 3: 118 # trying to best match lambert attenuation by that constant brilliance value 119 tabWrite("brilliance 1\n") 120 121 if Level == 2: 122 ###########################Specular Shader###################################### 123 # No difference between phong and cook torrence in blender HaHa! 124 if (material.pov.specular_shader == 'COOKTORR' or 125 material.pov.specular_shader == 'PHONG'): 126 tabWrite("phong %.3g\n" % (material.pov.specular_intensity)) 127 tabWrite("phong_size %.3g\n" % (material.pov.specular_hardness /3.14)) 128 129 # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior. 130 elif material.pov.specular_shader == 'BLINN': 131 # Use blender Blinn's IOR just as some factor for spec intensity 132 tabWrite("specular %.3g\n" % (material.pov.specular_intensity * 133 (material.pov.specular_ior / 4.0))) 134 tabWrite("roughness %.3g\n" % roughness) 135 #Could use brilliance 2(or varying around 2 depending on ior or factor) too. 136 137 elif material.pov.specular_shader == 'TOON': 138 tabWrite("phong %.3g\n" % (material.pov.specular_intensity * 2.0)) 139 # use extreme phong_size 140 tabWrite("phong_size %.3g\n" % (0.1 + material.pov.specular_toon_smooth / 2.0)) 141 142 elif material.pov.specular_shader == 'WARDISO': 143 # find best suited default constant for brilliance Use both phong and 144 # specular for some values. 145 tabWrite("specular %.3g\n" % (material.pov.specular_intensity / 146 (material.pov.specular_slope + 0.0005))) 147 # find best suited default constant for brilliance Use both phong and 148 # specular for some values. 149 tabWrite("roughness %.4g\n" % (0.0005 + material.pov.specular_slope / 10.0)) 150 # find best suited default constant for brilliance Use both phong and 151 # specular for some values. 152 tabWrite("brilliance %.4g\n" % (1.8 - material.pov.specular_slope * 1.8)) 153 154 #################################################################################### 155 elif Level == 1: 156 if (material.pov.specular_shader == 'COOKTORR' or 157 material.pov.specular_shader == 'PHONG'): 158 tabWrite("phong 0\n")#%.3g\n" % (material.pov.specular_intensity/5)) 159 tabWrite("phong_size %.3g\n" % (material.pov.specular_hardness /3.14)) 160 161 # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior. 162 elif material.pov.specular_shader == 'BLINN': 163 # Use blender Blinn's IOR just as some factor for spec intensity 164 tabWrite("specular %.3g\n" % (material.pov.specular_intensity * 165 (material.pov.specular_ior / 4.0))) 166 tabWrite("roughness %.3g\n" % roughness) 167 #Could use brilliance 2(or varying around 2 depending on ior or factor) too. 168 169 elif material.pov.specular_shader == 'TOON': 170 tabWrite("phong %.3g\n" % (material.pov.specular_intensity * 2.0)) 171 # use extreme phong_size 172 tabWrite("phong_size %.3g\n" % (0.1 + material.pov.specular_toon_smooth / 2.0)) 173 174 elif material.pov.specular_shader == 'WARDISO': 175 # find best suited default constant for brilliance Use both phong and 176 # specular for some values. 177 tabWrite("specular %.3g\n" % (material.pov.specular_intensity / 178 (material.pov.specular_slope + 0.0005))) 179 # find best suited default constant for brilliance Use both phong and 180 # specular for some values. 181 tabWrite("roughness %.4g\n" % (0.0005 + material.pov.specular_slope / 10.0)) 182 # find best suited default constant for brilliance Use both phong and 183 # specular for some values. 184 tabWrite("brilliance %.4g\n" % (1.8 - material.pov.specular_slope * 1.8)) 185 elif Level == 3: 186 # Spec must be Max at Level 3 so that white of mixing texture always shows specularity 187 # That's why it's multiplied by 255. maybe replace by texture's brightest pixel value? 188 tabWrite("specular %.3g\n" % ((material.pov.specular_intensity*material.pov.specular_color.v)*(255* slot.specular_factor))) 189 tabWrite("roughness %.3g\n" % (1/material.pov.specular_hardness)) 190 tabWrite("diffuse %.3g %.3g\n" % (frontDiffuse, backDiffuse)) 191 192 tabWrite("ambient %.3g\n" % material.pov.ambient) 193 # POV-Ray blends the global value 194 #tabWrite("ambient rgb <%.3g, %.3g, %.3g>\n" % \ 195 # tuple([c*material.pov.ambient for c in world.ambient_color])) 196 tabWrite("emission %.3g\n" % material.pov.emit) # New in POV-Ray 3.7 197 198 #POV-Ray just ignores roughness if there's no specular keyword 199 #tabWrite("roughness %.3g\n" % roughness) 200 201 if material.pov.conserve_energy: 202 # added for more realistic shading. Needs some checking to see if it 203 # really works. --Maurice. 204 tabWrite("conserve_energy\n") 205 206 if colored_specular_found == True: 207 tabWrite("metallic\n") 208 209 # 'phong 70.0 ' 210 if Level != 1: 211 if material.pov_raytrace_mirror.use: 212 raytrace_mirror = material.pov_raytrace_mirror 213 if raytrace_mirror.reflect_factor: 214 tabWrite("reflection {\n") 215 tabWrite("rgb <%.3g, %.3g, %.3g>\n" % material.pov.mirror_color[:]) 216 if material.pov.mirror_metallic: 217 tabWrite("metallic %.3g\n" % (raytrace_mirror.reflect_factor)) 218 # Blurry reflections for UberPOV 219 if using_uberpov and raytrace_mirror.gloss_factor < 1.0: 220 #tabWrite("#ifdef(unofficial) #if(unofficial = \"patch\") #if(patch(\"upov-reflection-roughness\") > 0)\n") 221 tabWrite("roughness %.6f\n" % \ 222 (0.000001/raytrace_mirror.gloss_factor)) 223 #tabWrite("#end #end #end\n") # This and previous comment for backward compatibility, messier pov code 224 if material.pov.mirror_use_IOR: # WORKING ? 225 # Removed from the line below: gives a more physically correct 226 # material but needs proper IOR. --Maurice 227 tabWrite("fresnel 1 ") 228 tabWrite("falloff %.3g exponent %.3g} " % \ 229 (raytrace_mirror.fresnel, raytrace_mirror.fresnel_factor)) 230 231 if material.pov_subsurface_scattering.use: 232 subsurface_scattering = material.pov_subsurface_scattering 233 tabWrite("subsurface { translucency <%.3g, %.3g, %.3g> }\n" % ( 234 (subsurface_scattering.radius[0]), 235 (subsurface_scattering.radius[1]), 236 (subsurface_scattering.radius[2]), 237 ) 238 ) 239 240 if material.pov.irid_enable: 241 tabWrite("irid { %.4g thickness %.4g turbulence %.4g }" % \ 242 (material.pov.irid_amount, material.pov.irid_thickness, 243 material.pov.irid_turbulence)) 244 245 else: 246 tabWrite("diffuse 0.8\n") 247 tabWrite("phong 70.0\n") 248 249 #tabWrite("specular 0.2\n") 250 251 # This is written into the object 252 ''' 253 if material and material.pov.transparency_method=='RAYTRACE': 254 'interior { ior %.3g} ' % material.raytrace_transparency.ior 255 ''' 256 257 #tabWrite("crand 1.0\n") # Sand granyness 258 #tabWrite("metallic %.6f\n" % material.spec) 259 #tabWrite("phong %.6f\n" % material.spec) 260 #tabWrite("phong_size %.6f\n" % material.spec) 261 #tabWrite("brilliance %.6f " % (material.pov.specular_hardness/256.0) # Like hardness 262 263 tabWrite("}\n\n") 264 265 # Level=2 Means translation of spec and mir levels for when no map influences them 266 povHasnoSpecularMaps(Level=2) 267 268 if material: 269 special_texture_found = False 270 tmpidx = -1 271 for t in material.pov_texture_slots: 272 tmpidx += 1 273 # index = material.pov.active_texture_index 274 slot = material.pov_texture_slots[tmpidx] # [index] 275 povtex = slot.texture # slot.name 276 tex = bpy.data.textures[povtex] 277 278 if t and t.use and tex is not None: 279 280 281 if (tex.type == 'IMAGE' and tex.image) or tex.type != 'IMAGE': 282 #validPath 283 if(t and t.use and 284 (t.use_map_specular or t.use_map_raymir or t.use_map_normal or t.use_map_alpha)): 285 special_texture_found = True 286 continue # Some texture found 287 288 if special_texture_found or colored_specular_found: 289 # Level=1 Means No specular nor Mirror reflection 290 povHasnoSpecularMaps(Level=1) 291 292 # Level=3 Means Maximum Spec and Mirror 293 povHasnoSpecularMaps(Level=3) 294 295def exportPattern(texture, string_strip_hyphen): 296 """Translate Blender procedural textures to POV patterns and write to pov file. 297 298 Function Patterns can be used to better access sub components of a pattern like 299 grey values for influence mapping""" 300 301 tex=texture 302 pat = tex.pov 303 PATname = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(tex.name)) 304 mappingDif = ("translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % \ 305 (pat.tex_mov_x, pat.tex_mov_y, pat.tex_mov_z, 306 1.0 / pat.tex_scale_x, 1.0 / pat.tex_scale_y, 1.0 / pat.tex_scale_z)) 307 texStrg="" 308 def exportColorRamp(texture): 309 tex=texture 310 pat = tex.pov 311 colRampStrg="color_map {\n" 312 numColor=0 313 for el in tex.color_ramp.elements: 314 numColor+=1 315 pos = el.position 316 col=el.color 317 colR,colG,colB,colA = col[0],col[1],col[2],1-col[3] 318 if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} : 319 colRampStrg+="[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n"%(pos,colR,colG,colB,colA) 320 if pat.tex_pattern_type in {'brick','checker'} and numColor < 3: 321 colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 322 if pat.tex_pattern_type == 'hexagon' and numColor < 4 : 323 colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 324 if pat.tex_pattern_type == 'square' and numColor < 5 : 325 colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 326 if pat.tex_pattern_type == 'triangular' and numColor < 7 : 327 colRampStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 328 329 colRampStrg+="} \n" 330 #end color map 331 return colRampStrg 332 #much work to be done here only defaults translated for now: 333 #pov noise_generator 3 means perlin noise 334 if tex.type not in {'NONE', 'IMAGE'} and pat.tex_pattern_type == 'emulator': 335 texStrg+="pigment {\n" 336 ####################### EMULATE BLENDER VORONOI TEXTURE #################### 337 if tex.type == 'VORONOI': 338 texStrg+="crackle\n" 339 texStrg+=" offset %.4g\n"%tex.nabla 340 texStrg+=" form <%.4g,%.4g,%.4g>\n"%(tex.weight_1, tex.weight_2, tex.weight_3) 341 if tex.distance_metric == 'DISTANCE': 342 texStrg+=" metric 2.5\n" 343 if tex.distance_metric == 'DISTANCE_SQUARED': 344 texStrg+=" metric 2.5\n" 345 texStrg+=" poly_wave 2\n" 346 if tex.distance_metric == 'MINKOVSKY': 347 texStrg+=" metric %s\n"%tex.minkovsky_exponent 348 if tex.distance_metric == 'MINKOVSKY_FOUR': 349 texStrg+=" metric 4\n" 350 if tex.distance_metric == 'MINKOVSKY_HALF': 351 texStrg+=" metric 0.5\n" 352 if tex.distance_metric == 'CHEBYCHEV': 353 texStrg+=" metric 10\n" 354 if tex.distance_metric == 'MANHATTAN': 355 texStrg+=" metric 1\n" 356 357 if tex.color_mode == 'POSITION': 358 texStrg+="solid\n" 359 texStrg+="scale 0.25\n" 360 if tex.use_color_ramp == True: 361 texStrg+=exportColorRamp(tex) 362 else: 363 texStrg+="color_map {\n" 364 texStrg+="[0 color rgbt<0,0,0,1>]\n" 365 texStrg+="[1 color rgbt<1,1,1,0>]\n" 366 texStrg+="}\n" 367 368 ####################### EMULATE BLENDER CLOUDS TEXTURE #################### 369 if tex.type == 'CLOUDS': 370 if tex.noise_type == 'SOFT_NOISE': 371 texStrg+="wrinkles\n" 372 texStrg+="scale 0.25\n" 373 else: 374 texStrg+="granite\n" 375 if tex.use_color_ramp == True: 376 texStrg+=exportColorRamp(tex) 377 else: 378 texStrg+="color_map {\n" 379 texStrg+="[0 color rgbt<0,0,0,1>]\n" 380 texStrg+="[1 color rgbt<1,1,1,0>]\n" 381 texStrg+="}\n" 382 383 ####################### EMULATE BLENDER WOOD TEXTURE #################### 384 if tex.type == 'WOOD': 385 if tex.wood_type == 'RINGS': 386 texStrg+="wood\n" 387 texStrg+="scale 0.25\n" 388 if tex.wood_type == 'RINGNOISE': 389 texStrg+="wood\n" 390 texStrg+="scale 0.25\n" 391 texStrg+="turbulence %.4g\n"%(tex.turbulence/100) 392 if tex.wood_type == 'BANDS': 393 texStrg+="marble\n" 394 texStrg+="scale 0.25\n" 395 texStrg+="rotate <45,-45,45>\n" 396 if tex.wood_type == 'BANDNOISE': 397 texStrg+="marble\n" 398 texStrg+="scale 0.25\n" 399 texStrg+="rotate <45,-45,45>\n" 400 texStrg+="turbulence %.4g\n"%(tex.turbulence/10) 401 402 if tex.noise_basis_2 == 'SIN': 403 texStrg+="sine_wave\n" 404 if tex.noise_basis_2 == 'TRI': 405 texStrg+="triangle_wave\n" 406 if tex.noise_basis_2 == 'SAW': 407 texStrg+="ramp_wave\n" 408 if tex.use_color_ramp == True: 409 texStrg+=exportColorRamp(tex) 410 else: 411 texStrg+="color_map {\n" 412 texStrg+="[0 color rgbt<0,0,0,0>]\n" 413 texStrg+="[1 color rgbt<1,1,1,0>]\n" 414 texStrg+="}\n" 415 416 ####################### EMULATE BLENDER STUCCI TEXTURE #################### 417 if tex.type == 'STUCCI': 418 texStrg+="bozo\n" 419 texStrg+="scale 0.25\n" 420 if tex.noise_type == 'HARD_NOISE': 421 texStrg+="triangle_wave\n" 422 if tex.use_color_ramp == True: 423 texStrg+=exportColorRamp(tex) 424 else: 425 texStrg+="color_map {\n" 426 texStrg+="[0 color rgbf<1,1,1,0>]\n" 427 texStrg+="[1 color rgbt<0,0,0,1>]\n" 428 texStrg+="}\n" 429 else: 430 if tex.use_color_ramp == True: 431 texStrg+=exportColorRamp(tex) 432 else: 433 texStrg+="color_map {\n" 434 texStrg+="[0 color rgbf<0,0,0,1>]\n" 435 texStrg+="[1 color rgbt<1,1,1,0>]\n" 436 texStrg+="}\n" 437 438 ####################### EMULATE BLENDER MAGIC TEXTURE #################### 439 if tex.type == 'MAGIC': 440 texStrg+="leopard\n" 441 if tex.use_color_ramp == True: 442 texStrg+=exportColorRamp(tex) 443 else: 444 texStrg+="color_map {\n" 445 texStrg+="[0 color rgbt<1,1,1,0.5>]\n" 446 texStrg+="[0.25 color rgbf<0,1,0,0.75>]\n" 447 texStrg+="[0.5 color rgbf<0,0,1,0.75>]\n" 448 texStrg+="[0.75 color rgbf<1,0,1,0.75>]\n" 449 texStrg+="[1 color rgbf<0,1,0,0.75>]\n" 450 texStrg+="}\n" 451 texStrg+="scale 0.1\n" 452 453 ####################### EMULATE BLENDER MARBLE TEXTURE #################### 454 if tex.type == 'MARBLE': 455 texStrg+="marble\n" 456 texStrg+="turbulence 0.5\n" 457 texStrg+="noise_generator 3\n" 458 texStrg+="scale 0.75\n" 459 texStrg+="rotate <45,-45,45>\n" 460 if tex.use_color_ramp == True: 461 texStrg+=exportColorRamp(tex) 462 else: 463 if tex.marble_type == 'SOFT': 464 texStrg+="color_map {\n" 465 texStrg+="[0 color rgbt<0,0,0,0>]\n" 466 texStrg+="[0.05 color rgbt<0,0,0,0>]\n" 467 texStrg+="[1 color rgbt<0.9,0.9,0.9,0>]\n" 468 texStrg+="}\n" 469 elif tex.marble_type == 'SHARP': 470 texStrg+="color_map {\n" 471 texStrg+="[0 color rgbt<0,0,0,0>]\n" 472 texStrg+="[0.025 color rgbt<0,0,0,0>]\n" 473 texStrg+="[1 color rgbt<0.9,0.9,0.9,0>]\n" 474 texStrg+="}\n" 475 else: 476 texStrg+="[0 color rgbt<0,0,0,0>]\n" 477 texStrg+="[1 color rgbt<1,1,1,0>]\n" 478 texStrg+="}\n" 479 if tex.noise_basis_2 == 'SIN': 480 texStrg+="sine_wave\n" 481 if tex.noise_basis_2 == 'TRI': 482 texStrg+="triangle_wave\n" 483 if tex.noise_basis_2 == 'SAW': 484 texStrg+="ramp_wave\n" 485 486 ####################### EMULATE BLENDER BLEND TEXTURE #################### 487 if tex.type == 'BLEND': 488 if tex.progression=='RADIAL': 489 texStrg+="radial\n" 490 if tex.use_flip_axis=='HORIZONTAL': 491 texStrg+="rotate x*90\n" 492 else: 493 texStrg+="rotate <-90,0,90>\n" 494 texStrg+="ramp_wave\n" 495 elif tex.progression=='SPHERICAL': 496 texStrg+="spherical\n" 497 texStrg+="scale 3\n" 498 texStrg+="poly_wave 1\n" 499 elif tex.progression=='QUADRATIC_SPHERE': 500 texStrg+="spherical\n" 501 texStrg+="scale 3\n" 502 texStrg+=" poly_wave 2\n" 503 elif tex.progression=='DIAGONAL': 504 texStrg+="gradient <1,1,0>\n" 505 texStrg+="scale 3\n" 506 elif tex.use_flip_axis=='HORIZONTAL': 507 texStrg+="gradient x\n" 508 texStrg+="scale 2.01\n" 509 elif tex.use_flip_axis=='VERTICAL': 510 texStrg+="gradient y\n" 511 texStrg+="scale 2.01\n" 512 #texStrg+="ramp_wave\n" 513 #texStrg+="frequency 0.5\n" 514 texStrg+="phase 0.5\n" 515 if tex.use_color_ramp == True: 516 texStrg+=exportColorRamp(tex) 517 else: 518 texStrg+="color_map {\n" 519 texStrg+="[0 color rgbt<1,1,1,0>]\n" 520 texStrg+="[1 color rgbf<0,0,0,1>]\n" 521 texStrg+="}\n" 522 if tex.progression == 'LINEAR': 523 texStrg+=" poly_wave 1\n" 524 if tex.progression == 'QUADRATIC': 525 texStrg+=" poly_wave 2\n" 526 if tex.progression == 'EASING': 527 texStrg+=" poly_wave 1.5\n" 528 529 530 ####################### EMULATE BLENDER MUSGRAVE TEXTURE #################### 531 # if tex.type == 'MUSGRAVE': 532 # texStrg+="function{ f_ridged_mf( x, y, 0, 1, 2, 9, -0.5, 3,3 )*0.5}\n" 533 # texStrg+="color_map {\n" 534 # texStrg+="[0 color rgbf<0,0,0,1>]\n" 535 # texStrg+="[1 color rgbf<1,1,1,0>]\n" 536 # texStrg+="}\n" 537 # simplified for now: 538 539 if tex.type == 'MUSGRAVE': 540 texStrg+="bozo scale 0.25 \n" 541 if tex.use_color_ramp == True: 542 texStrg+=exportColorRamp(tex) 543 else: 544 texStrg+="color_map {[0.5 color rgbf<0,0,0,1>][1 color rgbt<1,1,1,0>]}ramp_wave \n" 545 546 ####################### EMULATE BLENDER DISTORTED NOISE TEXTURE #################### 547 if tex.type == 'DISTORTED_NOISE': 548 texStrg+="average\n" 549 texStrg+=" pigment_map {\n" 550 texStrg+=" [1 bozo scale 0.25 turbulence %.4g\n" %tex.distortion 551 if tex.use_color_ramp == True: 552 texStrg+=exportColorRamp(tex) 553 else: 554 texStrg+="color_map {\n" 555 texStrg+="[0 color rgbt<1,1,1,0>]\n" 556 texStrg+="[1 color rgbf<0,0,0,1>]\n" 557 texStrg+="}\n" 558 texStrg+="]\n" 559 560 if tex.noise_distortion == 'CELL_NOISE': 561 texStrg+=" [1 cells scale 0.1\n" 562 if tex.use_color_ramp == True: 563 texStrg+=exportColorRamp(tex) 564 else: 565 texStrg+="color_map {\n" 566 texStrg+="[0 color rgbt<1,1,1,0>]\n" 567 texStrg+="[1 color rgbf<0,0,0,1>]\n" 568 texStrg+="}\n" 569 texStrg+="]\n" 570 if tex.noise_distortion=='VORONOI_CRACKLE': 571 texStrg+=" [1 crackle scale 0.25\n" 572 if tex.use_color_ramp == True: 573 texStrg+=exportColorRamp(tex) 574 else: 575 texStrg+="color_map {\n" 576 texStrg+="[0 color rgbt<1,1,1,0>]\n" 577 texStrg+="[1 color rgbf<0,0,0,1>]\n" 578 texStrg+="}\n" 579 texStrg+="]\n" 580 if tex.noise_distortion in ['VORONOI_F1','VORONOI_F2','VORONOI_F3','VORONOI_F4','VORONOI_F2_F1']: 581 texStrg+=" [1 crackle metric 2.5 scale 0.25 turbulence %.4g\n" %(tex.distortion/2) 582 if tex.use_color_ramp == True: 583 texStrg+=exportColorRamp(tex) 584 else: 585 texStrg+="color_map {\n" 586 texStrg+="[0 color rgbt<1,1,1,0>]\n" 587 texStrg+="[1 color rgbf<0,0,0,1>]\n" 588 texStrg+="}\n" 589 texStrg+="]\n" 590 else: 591 texStrg+=" [1 wrinkles scale 0.25\n" 592 if tex.use_color_ramp == True: 593 texStrg+=exportColorRamp(tex) 594 else: 595 texStrg+="color_map {\n" 596 texStrg+="[0 color rgbt<1,1,1,0>]\n" 597 texStrg+="[1 color rgbf<0,0,0,1>]\n" 598 texStrg+="}\n" 599 texStrg+="]\n" 600 texStrg+=" }\n" 601 602 ####################### EMULATE BLENDER NOISE TEXTURE #################### 603 if tex.type == 'NOISE': 604 texStrg+="cells\n" 605 texStrg+="turbulence 3\n" 606 texStrg+="omega 3\n" 607 if tex.use_color_ramp == True: 608 texStrg+=exportColorRamp(tex) 609 else: 610 texStrg+="color_map {\n" 611 texStrg+="[0.75 color rgb<0,0,0,>]\n" 612 texStrg+="[1 color rgb<1,1,1,>]\n" 613 texStrg+="}\n" 614 615 ####################### IGNORE OTHER BLENDER TEXTURE #################### 616 else: #non translated textures 617 pass 618 texStrg+="}\n\n" 619 620 texStrg+="#declare f%s=\n"%PATname 621 texStrg+="function{pigment{%s}}\n"%PATname 622 texStrg+="\n" 623 624 elif pat.tex_pattern_type != 'emulator': 625 texStrg+="pigment {\n" 626 texStrg+="%s\n"%pat.tex_pattern_type 627 if pat.tex_pattern_type == 'agate': 628 texStrg+="agate_turb %.4g\n"%pat.modifier_turbulence 629 if pat.tex_pattern_type in {'spiral1', 'spiral2', 'tiling'}: 630 texStrg+="%s\n"%pat.modifier_numbers 631 if pat.tex_pattern_type == 'quilted': 632 texStrg+="control0 %s control1 %s\n"%(pat.modifier_control0, pat.modifier_control1) 633 if pat.tex_pattern_type == 'mandel': 634 texStrg+="%s exponent %s \n"%(pat.f_iter, pat.f_exponent) 635 if pat.tex_pattern_type == 'julia': 636 texStrg+="<%.4g, %.4g> %s exponent %s \n"%(pat.julia_complex_1, pat.julia_complex_2, pat.f_iter, pat.f_exponent) 637 if pat.tex_pattern_type == 'magnet' and pat.magnet_style == 'mandel': 638 texStrg+="%s mandel %s \n"%(pat.magnet_type, pat.f_iter) 639 if pat.tex_pattern_type == 'magnet' and pat.magnet_style == 'julia': 640 texStrg+="%s julia <%.4g, %.4g> %s\n"%(pat.magnet_type, pat.julia_complex_1, pat.julia_complex_2, pat.f_iter) 641 if pat.tex_pattern_type in {'mandel', 'julia', 'magnet'}: 642 texStrg+="interior %s, %.4g\n"%(pat.f_ior, pat.f_ior_fac) 643 texStrg+="exterior %s, %.4g\n"%(pat.f_eor, pat.f_eor_fac) 644 if pat.tex_pattern_type == 'gradient': 645 texStrg+="<%s, %s, %s> \n"%(pat.grad_orient_x, pat.grad_orient_y, pat.grad_orient_z) 646 if pat.tex_pattern_type == 'pavement': 647 numTiles=pat.pave_tiles 648 numPattern=1 649 if pat.pave_sides == '4' and pat.pave_tiles == 3: 650 numPattern = pat.pave_pat_2 651 if pat.pave_sides == '6' and pat.pave_tiles == 3: 652 numPattern = pat.pave_pat_3 653 if pat.pave_sides == '3' and pat.pave_tiles == 4: 654 numPattern = pat.pave_pat_3 655 if pat.pave_sides == '3' and pat.pave_tiles == 5: 656 numPattern = pat.pave_pat_4 657 if pat.pave_sides == '4' and pat.pave_tiles == 4: 658 numPattern = pat.pave_pat_5 659 if pat.pave_sides == '6' and pat.pave_tiles == 4: 660 numPattern = pat.pave_pat_7 661 if pat.pave_sides == '4' and pat.pave_tiles == 5: 662 numPattern = pat.pave_pat_12 663 if pat.pave_sides == '3' and pat.pave_tiles == 6: 664 numPattern = pat.pave_pat_12 665 if pat.pave_sides == '6' and pat.pave_tiles == 5: 666 numPattern = pat.pave_pat_22 667 if pat.pave_sides == '4' and pat.pave_tiles == 6: 668 numPattern = pat.pave_pat_35 669 if pat.pave_sides == '6' and pat.pave_tiles == 6: 670 numTiles = 5 671 texStrg+="number_of_sides %s number_of_tiles %s pattern %s form %s \n"%(pat.pave_sides, numTiles, numPattern, pat.pave_form) 672 ################ functions ##################################################################################################### 673 if pat.tex_pattern_type == 'function': 674 texStrg+="{ %s"%pat.func_list 675 texStrg+="(x" 676 if pat.func_plus_x != "NONE": 677 if pat.func_plus_x =='increase': 678 texStrg+="*" 679 if pat.func_plus_x =='plus': 680 texStrg+="+" 681 texStrg+="%.4g"%pat.func_x 682 texStrg+=",y" 683 if pat.func_plus_y != "NONE": 684 if pat.func_plus_y =='increase': 685 texStrg+="*" 686 if pat.func_plus_y =='plus': 687 texStrg+="+" 688 texStrg+="%.4g"%pat.func_y 689 texStrg+=",z" 690 if pat.func_plus_z != "NONE": 691 if pat.func_plus_z =='increase': 692 texStrg+="*" 693 if pat.func_plus_z =='plus': 694 texStrg+="+" 695 texStrg+="%.4g"%pat.func_z 696 sort = -1 697 if pat.func_list in {"f_comma","f_crossed_trough","f_cubic_saddle","f_cushion","f_devils_curve", 698 "f_enneper","f_glob","f_heart","f_hex_x","f_hex_y","f_hunt_surface", 699 "f_klein_bottle","f_kummer_surface_v1","f_lemniscate_of_gerono","f_mitre", 700 "f_nodal_cubic","f_noise_generator","f_odd","f_paraboloid","f_pillow", 701 "f_piriform","f_quantum","f_quartic_paraboloid","f_quartic_saddle", 702 "f_sphere","f_steiners_roman","f_torus_gumdrop","f_umbrella"}: 703 sort = 0 704 if pat.func_list in {"f_bicorn","f_bifolia","f_boy_surface","f_superellipsoid","f_torus"}: 705 sort = 1 706 if pat.func_list in {"f_ellipsoid","f_folium_surface","f_hyperbolic_torus", 707 "f_kampyle_of_eudoxus","f_parabolic_torus","f_quartic_cylinder","f_torus2"}: 708 sort = 2 709 if pat.func_list in {"f_blob2","f_cross_ellipsoids","f_flange_cover","f_isect_ellipsoids", 710 "f_kummer_surface_v2","f_ovals_of_cassini","f_rounded_box","f_spikes_2d","f_strophoid"}: 711 sort = 3 712 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"}: 713 sort = 4 714 if pat.func_list in {"f_devils_curve_2d","f_dupin_cyclid","f_folium_surface_2d","f_hetero_mf","f_kampyle_of_eudoxus_2d", 715 "f_lemniscate_of_gerono_2d","f_polytubes","f_ridge","f_ridged_mf","f_spiral","f_witch_of_agnesi"}: 716 sort = 5 717 if pat.func_list in {"f_helix1","f_helix2","f_piriform_2d","f_strophoid_2d"}: 718 sort = 6 719 if pat.func_list == "f_helical_torus": 720 sort = 7 721 if sort > -1: 722 texStrg+=",%.4g"%pat.func_P0 723 if sort > 0: 724 texStrg+=",%.4g"%pat.func_P1 725 if sort > 1: 726 texStrg+=",%.4g"%pat.func_P2 727 if sort > 2: 728 texStrg+=",%.4g"%pat.func_P3 729 if sort > 3: 730 texStrg+=",%.4g"%pat.func_P4 731 if sort > 4: 732 texStrg+=",%.4g"%pat.func_P5 733 if sort > 5: 734 texStrg+=",%.4g"%pat.func_P6 735 if sort > 6: 736 texStrg+=",%.4g"%pat.func_P7 737 texStrg+=",%.4g"%pat.func_P8 738 texStrg+=",%.4g"%pat.func_P9 739 texStrg+=")}\n" 740 ############## end functions ############################################################### 741 if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: 742 texStrg+="color_map {\n" 743 numColor=0 744 if tex.use_color_ramp == True: 745 for el in tex.color_ramp.elements: 746 numColor+=1 747 pos = el.position 748 col=el.color 749 colR,colG,colB,colA = col[0],col[1],col[2],1-col[3] 750 if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} : 751 texStrg+="[%.4g color rgbf<%.4g,%.4g,%.4g,%.4g>] \n"%(pos,colR,colG,colB,colA) 752 if pat.tex_pattern_type in {'brick','checker'} and numColor < 3: 753 texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 754 if pat.tex_pattern_type == 'hexagon' and numColor < 4 : 755 texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 756 if pat.tex_pattern_type == 'square' and numColor < 5 : 757 texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 758 if pat.tex_pattern_type == 'triangular' and numColor < 7 : 759 texStrg+="color rgbf<%.4g,%.4g,%.4g,%.4g> \n"%(colR,colG,colB,colA) 760 else: 761 texStrg+="[0 color rgbf<0,0,0,1>]\n" 762 texStrg+="[1 color rgbf<1,1,1,0>]\n" 763 if pat.tex_pattern_type not in {'checker', 'hexagon', 'square', 'triangular', 'brick'} : 764 texStrg+="} \n" 765 if pat.tex_pattern_type == 'brick': 766 texStrg+="brick_size <%.4g, %.4g, %.4g> mortar %.4g \n"%(pat.brick_size_x, pat.brick_size_y, pat.brick_size_z, pat.brick_mortar) 767 texStrg+="%s \n"%mappingDif 768 texStrg+="rotate <%.4g,%.4g,%.4g> \n"%(pat.tex_rot_x, pat.tex_rot_y, pat.tex_rot_z) 769 texStrg+="turbulence <%.4g,%.4g,%.4g> \n"%(pat.warp_turbulence_x, pat.warp_turbulence_y, pat.warp_turbulence_z) 770 texStrg+="octaves %s \n"%pat.modifier_octaves 771 texStrg+="lambda %.4g \n"%pat.modifier_lambda 772 texStrg+="omega %.4g \n"%pat.modifier_omega 773 texStrg+="frequency %.4g \n"%pat.modifier_frequency 774 texStrg+="phase %.4g \n"%pat.modifier_phase 775 texStrg+="}\n\n" 776 texStrg+="#declare f%s=\n"%PATname 777 texStrg+="function{pigment{%s}}\n"%PATname 778 texStrg+="\n" 779 return(texStrg) 780 781 782def writeTextureInfluence(using_uberpov, mater, materialNames, LocalMaterialNames, path_image, lampCount, 783 imageFormat, imgMap, imgMapTransforms, tabWrite, comments, 784 string_strip_hyphen, safety, col, os, preview_dir, unpacked_images): 785 """Translate Blender texture influences to various POV texture tricks and write to pov file.""" 786 787 material_finish = materialNames[mater.name] 788 if mater.pov.use_transparency: 789 trans = 1.0 - mater.pov.alpha 790 else: 791 trans = 0.0 792 if ((mater.pov.specular_color.s == 0.0) or (mater.pov.diffuse_shader == 'MINNAERT')): 793 # No layered texture because of aoi pattern used for minnaert and pov can't layer patterned 794 colored_specular_found = False 795 else: 796 colored_specular_found = True 797 798 if mater.pov.use_transparency and mater.pov.transparency_method == 'RAYTRACE': 799 povFilter = mater.pov_raytrace_transparency.filter * (1.0 - mater.pov.alpha) 800 trans = (1.0 - mater.pov.alpha) - povFilter 801 else: 802 povFilter = 0.0 803 804 ##############SF 805 texturesDif = "" 806 texturesSpec = "" 807 texturesNorm = "" 808 texturesAlpha = "" 809 #proceduralFlag=False 810 tmpidx = -1 811 for t in mater.pov_texture_slots: 812 813 814 tmpidx += 1 815 # index = mater.pov.active_texture_index 816 slot = mater.pov_texture_slots[tmpidx] # [index] 817 povtex = slot.texture # slot.name 818 tex = bpy.data.textures[povtex] 819 820 if t and (t.use and (tex is not None)): 821 # 'NONE' ('NONE' type texture is different from no texture covered above) 822 if (tex.type == 'NONE' and tex.pov.tex_pattern_type == 'emulator'): 823 continue # move to next slot 824 # PROCEDURAL 825 elif (tex.type != 'IMAGE' and tex.type != 'NONE'): 826 proceduralFlag=True 827 image_filename = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(tex.name)) 828 if image_filename: 829 if t.use_map_color_diffuse: 830 texturesDif = image_filename 831 # colvalue = t.default_value # UNUSED 832 t_dif = t 833 if t_dif.texture.pov.tex_gamma_enable: 834 imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) 835 if t.use_map_specular or t.use_map_raymir: 836 texturesSpec = image_filename 837 # colvalue = t.default_value # UNUSED 838 t_spec = t 839 if t.use_map_normal: 840 texturesNorm = image_filename 841 # colvalue = t.normal_factor/10 # UNUSED 842 #textNormName=tex.image.name + ".normal" 843 #was the above used? --MR 844 t_nor = t 845 if t.use_map_alpha: 846 texturesAlpha = image_filename 847 # colvalue = t.alpha_factor * 10.0 # UNUSED 848 #textDispName=tex.image.name + ".displ" 849 #was the above used? --MR 850 t_alpha = t 851 852 # RASTER IMAGE 853 elif (tex.type == 'IMAGE' and tex.image and tex.pov.tex_pattern_type == 'emulator'): 854 proceduralFlag=False 855 #PACKED 856 if tex.image.packed_file: 857 orig_image_filename=tex.image.filepath_raw 858 unpackedfilename= os.path.join(preview_dir,("unpacked_img_"+(string_strip_hyphen(bpy.path.clean_name(tex.name))))) 859 if not os.path.exists(unpackedfilename): 860 # record which images that were newly copied and can be safely 861 # cleaned up 862 unpacked_images.append(unpackedfilename) 863 tex.image.filepath_raw=unpackedfilename 864 tex.image.save() 865 image_filename = unpackedfilename.replace("\\","/") 866 # .replace("\\","/") to get only forward slashes as it's what POV prefers, 867 # even on windows 868 tex.image.filepath_raw=orig_image_filename 869 #FILE 870 else: 871 image_filename = path_image(tex.image) 872 # IMAGE SEQUENCE BEGINS 873 if image_filename: 874 if bpy.data.images[tex.image.name].source == 'SEQUENCE': 875 korvaa = "." + str(tex.image_user.frame_offset + 1).zfill(3) + "." 876 image_filename = image_filename.replace(".001.", korvaa) 877 print(" seq debug ") 878 print(image_filename) 879 # IMAGE SEQUENCE ENDS 880 imgGamma = "" 881 if image_filename: 882 texdata = bpy.data.textures[t.texture] 883 if t.use_map_color_diffuse: 884 texturesDif = image_filename 885 # colvalue = t.default_value # UNUSED 886 t_dif = t 887 print (texdata) 888 if texdata.pov.tex_gamma_enable: 889 imgGamma = (" gamma %.3g " % t_dif.texture.pov.tex_gamma_value) 890 if t.use_map_specular or t.use_map_raymir: 891 texturesSpec = image_filename 892 # colvalue = t.default_value # UNUSED 893 t_spec = t 894 if t.use_map_normal: 895 texturesNorm = image_filename 896 # colvalue = t.normal_factor/10 # UNUSED 897 #textNormName=tex.image.name + ".normal" 898 #was the above used? --MR 899 t_nor = t 900 if t.use_map_alpha: 901 texturesAlpha = image_filename 902 # colvalue = t.alpha_factor * 10.0 # UNUSED 903 #textDispName=tex.image.name + ".displ" 904 #was the above used? --MR 905 t_alpha = t 906 907 #################################################################################### 908 909 910 tabWrite("\n") 911 # THIS AREA NEEDS TO LEAVE THE TEXTURE OPEN UNTIL ALL MAPS ARE WRITTEN DOWN. 912 # --MR 913 currentMatName = string_strip_hyphen(materialNames[mater.name]) 914 LocalMaterialNames.append(currentMatName) 915 tabWrite("\n#declare MAT_%s = \ntexture{\n" % currentMatName) 916 ################################################################################ 917 918 if mater.pov.replacement_text != "": 919 tabWrite("%s\n" % mater.pov.replacement_text) 920 ################################################################################# 921 # XXX TODO: replace by new POV MINNAERT rather than aoi 922 if mater.pov.diffuse_shader == 'MINNAERT': 923 tabWrite("\n") 924 tabWrite("aoi\n") 925 tabWrite("texture_map {\n") 926 tabWrite("[%.3g finish {diffuse %.3g}]\n" % \ 927 (mater.darkness / 2.0, 2.0 - mater.darkness)) 928 tabWrite("[%.3g\n" % (1.0 - (mater.darkness / 2.0))) 929 930 if mater.pov.diffuse_shader == 'FRESNEL': 931 # For FRESNEL diffuse in POV, we'll layer slope patterned textures 932 # with lamp vector as the slope vector and nest one slope per lamp 933 # into each texture map's entry. 934 935 c = 1 936 while (c <= lampCount): 937 tabWrite("slope { lampTarget%s }\n" % (c)) 938 tabWrite("texture_map {\n") 939 # Diffuse Fresnel value and factor go up to five, 940 # other kind of values needed: used the number 5 below to remap 941 tabWrite("[%.3g finish {diffuse %.3g}]\n" % \ 942 ((5.0 - mater.diffuse_fresnel) / 5, 943 (mater.diffuse_intensity * 944 ((5.0 - mater.diffuse_fresnel_factor) / 5)))) 945 tabWrite("[%.3g\n" % ((mater.diffuse_fresnel_factor / 5) * 946 (mater.diffuse_fresnel / 5.0))) 947 c += 1 948 949 # if shader is a 'FRESNEL' or 'MINNAERT': slope pigment pattern or aoi 950 # and texture map above, the rest below as one of its entry 951 952 if texturesSpec != "" or texturesAlpha != "": 953 if texturesSpec != "": 954 # tabWrite("\n") 955 tabWrite("pigment_pattern {\n") 956 957 mappingSpec =imgMapTransforms(t_spec) 958 if texturesSpec and texturesSpec.startswith("PAT_"): 959 tabWrite("function{f%s(x,y,z).grey}\n" %texturesSpec) 960 tabWrite("%s\n" % mappingSpec) 961 else: 962 963 tabWrite("uv_mapping image_map{%s \"%s\" %s}\n" % \ 964 (imageFormat(texturesSpec), texturesSpec, imgMap(t_spec))) 965 tabWrite("%s\n" % mappingSpec) 966 tabWrite("}\n") 967 tabWrite("texture_map {\n") 968 tabWrite("[0 \n") 969 970 if texturesDif == "": 971 if texturesAlpha != "": 972 tabWrite("\n") 973 974 mappingAlpha = imgMapTransforms(t_alpha) 975 976 if texturesAlpha and texturesAlpha.startswith("PAT_"): 977 tabWrite("function{f%s(x,y,z).transmit}%s\n" %(texturesAlpha, mappingAlpha)) 978 else: 979 980 tabWrite("pigment {pigment_pattern {uv_mapping image_map" \ 981 "{%s \"%s\" %s}%s" % \ 982 (imageFormat(texturesAlpha), texturesAlpha, 983 imgMap(t_alpha), mappingAlpha)) 984 tabWrite("}\n") 985 tabWrite("pigment_map {\n") 986 tabWrite("[0 color rgbft<0,0,0,1,1>]\n") 987 tabWrite("[1 color rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>]\n" % \ 988 (col[0], col[1], col[2], povFilter, trans)) 989 tabWrite("}\n") 990 tabWrite("}\n") 991 992 else: 993 994 tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n" % \ 995 (col[0], col[1], col[2], povFilter, trans)) 996 997 if texturesSpec != "": 998 # Level 1 is no specular 999 tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) 1000 1001 else: 1002 # Level 2 is translated spec 1003 tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) 1004 1005 else: 1006 mappingDif = imgMapTransforms(t_dif) 1007 1008 if texturesAlpha != "": 1009 mappingAlpha = imgMapTransforms(t_alpha) 1010 1011 tabWrite("pigment {\n") 1012 tabWrite("pigment_pattern {\n") 1013 if texturesAlpha and texturesAlpha.startswith("PAT_"): 1014 tabWrite("function{f%s(x,y,z).transmit}%s\n" %(texturesAlpha, mappingAlpha)) 1015 else: 1016 tabWrite("uv_mapping image_map{%s \"%s\" %s}%s}\n" % \ 1017 (imageFormat(texturesAlpha), texturesAlpha, 1018 imgMap(t_alpha), mappingAlpha)) 1019 tabWrite("pigment_map {\n") 1020 tabWrite("[0 color rgbft<0,0,0,1,1>]\n") 1021 #if texturesAlpha and texturesAlpha.startswith("PAT_"): 1022 #tabWrite("[1 pigment{%s}]\n" %texturesDif) 1023 if texturesDif and not texturesDif.startswith("PAT_"): 1024 tabWrite("[1 uv_mapping image_map {%s \"%s\" %s} %s]\n" % \ 1025 (imageFormat(texturesDif), texturesDif, 1026 (imgGamma + imgMap(t_dif)), mappingDif)) 1027 elif texturesDif and texturesDif.startswith("PAT_"): 1028 tabWrite("[1 %s]\n" %texturesDif) 1029 tabWrite("}\n") 1030 tabWrite("}\n") 1031 if texturesAlpha and texturesAlpha.startswith("PAT_"): 1032 tabWrite("}\n") 1033 1034 else: 1035 if texturesDif and texturesDif.startswith("PAT_"): 1036 tabWrite("pigment{%s}\n" %texturesDif) 1037 else: 1038 tabWrite("pigment {uv_mapping image_map {%s \"%s\" %s}%s}\n" % \ 1039 (imageFormat(texturesDif), texturesDif, 1040 (imgGamma + imgMap(t_dif)), mappingDif)) 1041 1042 if texturesSpec != "": 1043 # Level 1 is no specular 1044 tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) 1045 1046 else: 1047 # Level 2 is translated specular 1048 tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) 1049 1050 ## scale 1 rotate y*0 1051 #imageMap = ("{image_map {%s \"%s\" %s }\n" % \ 1052 # (imageFormat(textures),textures,imgMap(t_dif))) 1053 #tabWrite("uv_mapping pigment %s} %s finish {%s}\n" % \ 1054 # (imageMap,mapping,safety(material_finish))) 1055 #tabWrite("pigment {uv_mapping image_map {%s \"%s\" %s}%s} " \ 1056 # "finish {%s}\n" % \ 1057 # (imageFormat(texturesDif), texturesDif, imgMap(t_dif), 1058 # mappingDif, safety(material_finish))) 1059 if texturesNorm != "": 1060 ## scale 1 rotate y*0 1061 1062 mappingNor =imgMapTransforms(t_nor) 1063 1064 if texturesNorm and texturesNorm.startswith("PAT_"): 1065 tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, ( - t_nor.normal_factor * 9.5), mappingNor)) 1066 else: 1067 tabWrite("normal {\n") 1068 # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials 1069 if (mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov): 1070 tabWrite("average\n") 1071 tabWrite("normal_map{\n") 1072 # 0.5 for entries below means a 50 percent mix 1073 # between the micro normal and user bump map 1074 # order seems indifferent as commutative 1075 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 1076 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 1077 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 1078 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 1079 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 1080 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 1081 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 1082 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 1083 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 1084 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 1085 tabWrite("[1.0 ") # Proceed with user bump... 1086 tabWrite("uv_mapping bump_map " \ 1087 "{%s \"%s\" %s bump_size %.4g }%s" % \ 1088 (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor), 1089 ( - t_nor.normal_factor * 9.5), mappingNor)) 1090 # ...Then close its last entry and the the normal_map itself 1091 if (mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov): 1092 tabWrite("]}}\n") 1093 else: 1094 tabWrite("]}\n") 1095 if texturesSpec != "": 1096 tabWrite("]\n") 1097 ##################Second index for mapping specular max value############### 1098 tabWrite("[1 \n") 1099 1100 if texturesDif == "" and mater.pov.replacement_text == "": 1101 if texturesAlpha != "": 1102 mappingAlpha = imgMapTransforms(t_alpha) 1103 1104 if texturesAlpha and texturesAlpha.startswith("PAT_"): 1105 tabWrite("function{f%s(x,y,z).transmit %s}\n" %(texturesAlpha, mappingAlpha)) 1106 else: 1107 tabWrite("pigment {pigment_pattern {uv_mapping image_map" \ 1108 "{%s \"%s\" %s}%s}\n" % \ 1109 (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), 1110 mappingAlpha)) 1111 tabWrite("pigment_map {\n") 1112 tabWrite("[0 color rgbft<0,0,0,1,1>]\n") 1113 tabWrite("[1 color rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>]\n" % \ 1114 (col[0], col[1], col[2], povFilter, trans)) 1115 tabWrite("}\n") 1116 tabWrite("}\n") 1117 1118 else: 1119 tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n" % \ 1120 (col[0], col[1], col[2], povFilter, trans)) 1121 1122 1123 if texturesSpec != "": 1124 # Level 3 is full specular 1125 tabWrite("finish {%s}\n" % (safety(material_finish, Level=3))) 1126 1127 if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: 1128 tabWrite("normal {\n") 1129 tabWrite("average\n") 1130 tabWrite("normal_map{\n") 1131 # 0.5 for entries below means a 50 percent mix 1132 # between the micro normal and user bump map 1133 # order seems indifferent as commutative 1134 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 1135 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 1136 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 1137 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 1138 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 1139 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 1140 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 1141 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 1142 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 1143 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 1144 #XXX IF USER BUMP_MAP 1145 if texturesNorm != "": 1146 tabWrite("[1.0 ") # Blurry reflection or not Proceed with user bump in either case... 1147 tabWrite("uv_mapping bump_map " \ 1148 "{%s \"%s\" %s bump_size %.4g }%s]\n" % \ 1149 (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor), 1150 ( - t_nor.normal_factor * 9.5), mappingNor)) 1151 # ...Then close the normal_map itself if blurry reflection 1152 if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: 1153 tabWrite("}}\n") 1154 else: 1155 tabWrite("}\n") 1156 elif colored_specular_found: 1157 # Level 1 is no specular 1158 tabWrite("finish {%s}\n" % (safety(material_finish, Level=1))) 1159 1160 else: 1161 # Level 2 is translated specular 1162 tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) 1163 1164 elif mater.pov.replacement_text == "": 1165 mappingDif = imgMapTransforms(t_dif) 1166 1167 if texturesAlpha != "": 1168 1169 mappingAlpha = imgMapTransforms(t_alpha) 1170 1171 if texturesAlpha and texturesAlpha.startswith("PAT_"): 1172 tabWrite("pigment{pigment_pattern {function{f%s(x,y,z).transmit}%s}\n" %(texturesAlpha, mappingAlpha)) 1173 else: 1174 tabWrite("pigment {pigment_pattern {uv_mapping image_map" \ 1175 "{%s \"%s\" %s}%s}\n" % \ 1176 (imageFormat(texturesAlpha), texturesAlpha, imgMap(t_alpha), 1177 mappingAlpha)) 1178 tabWrite("pigment_map {\n") 1179 tabWrite("[0 color rgbft<0,0,0,1,1>]\n") 1180 if texturesAlpha and texturesAlpha.startswith("PAT_"): 1181 tabWrite("[1 function{f%s(x,y,z).transmit}%s]\n" %(texturesAlpha, mappingAlpha)) 1182 elif texturesDif and not texturesDif.startswith("PAT_"): 1183 tabWrite("[1 uv_mapping image_map {%s \"%s\" %s} %s]\n" % \ 1184 (imageFormat(texturesDif), texturesDif, 1185 (imgMap(t_dif) + imgGamma), mappingDif)) 1186 elif texturesDif and texturesDif.startswith("PAT_"): 1187 tabWrite("[1 %s %s]\n" %(texturesDif, mappingDif)) 1188 tabWrite("}\n") 1189 tabWrite("}\n") 1190 1191 else: 1192 if texturesDif and texturesDif.startswith("PAT_"): 1193 tabWrite("pigment{%s %s}\n" %(texturesDif, mappingDif)) 1194 else: 1195 tabWrite("pigment {\n") 1196 tabWrite("uv_mapping image_map {\n") 1197 #tabWrite("%s \"%s\" %s}%s\n" % \ 1198 # (imageFormat(texturesDif), texturesDif, 1199 # (imgGamma + imgMap(t_dif)),mappingDif)) 1200 tabWrite("%s \"%s\" \n" % (imageFormat(texturesDif), texturesDif)) 1201 tabWrite("%s\n" % (imgGamma + imgMap(t_dif))) 1202 tabWrite("}\n") 1203 tabWrite("%s\n" % mappingDif) 1204 tabWrite("}\n") 1205 1206 if texturesSpec != "": 1207 # Level 3 is full specular 1208 tabWrite("finish {%s}\n" % (safety(material_finish, Level=3))) 1209 else: 1210 # Level 2 is translated specular 1211 tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) 1212 1213 ## scale 1 rotate y*0 1214 #imageMap = ("{image_map {%s \"%s\" %s }" % \ 1215 # (imageFormat(textures), textures,imgMap(t_dif))) 1216 #tabWrite("\n\t\t\tuv_mapping pigment %s} %s finish {%s}" % \ 1217 # (imageMap, mapping, safety(material_finish))) 1218 #tabWrite("\n\t\t\tpigment {uv_mapping image_map " \ 1219 # "{%s \"%s\" %s}%s} finish {%s}" % \ 1220 # (imageFormat(texturesDif), texturesDif,imgMap(t_dif), 1221 # mappingDif, safety(material_finish))) 1222 if texturesNorm != "" and mater.pov.replacement_text == "": 1223 1224 1225 mappingNor =imgMapTransforms(t_nor) 1226 1227 if texturesNorm and texturesNorm.startswith("PAT_"): 1228 tabWrite("normal{function{f%s(x,y,z).grey} bump_size %.4g %s}\n" %(texturesNorm, ( - t_nor.normal_factor * 9.5), mappingNor)) 1229 else: 1230 tabWrite("normal {\n") 1231 # XXX TODO: fix and propagate the micro normals reflection blur below to non textured materials 1232 if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: 1233 tabWrite("average\n") 1234 tabWrite("normal_map{\n") 1235 # 0.5 for entries below means a 50 percent mix 1236 # between the micro normal and user bump map 1237 # order seems indifferent as commutative 1238 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 1239 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 1240 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 1241 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 1242 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 1243 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 1244 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 1245 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 1246 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 1247 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 1248 tabWrite("[1.0 ") # Blurry reflection or not Proceed with user bump in either case... 1249 tabWrite("uv_mapping bump_map " \ 1250 "{%s \"%s\" %s bump_size %.4g }%s]\n" % \ 1251 (imageFormat(texturesNorm), texturesNorm, imgMap(t_nor), 1252 ( - t_nor.normal_factor * 9.5), mappingNor)) 1253 # ...Then close the normal_map itself if blurry reflection 1254 if mater.pov_raytrace_mirror.use and mater.pov_raytrace_mirror.gloss_factor < 1.0 and not using_uberpov: 1255 tabWrite("}}\n") 1256 else: 1257 tabWrite("}\n") 1258 if texturesSpec != "" and mater.pov.replacement_text == "": 1259 tabWrite("]\n") 1260 1261 tabWrite("}\n") 1262 1263 #End of slope/ior texture_map 1264 if mater.pov.diffuse_shader == 'MINNAERT' and mater.pov.replacement_text == "": 1265 tabWrite("]\n") 1266 tabWrite("}\n") 1267 if mater.pov.diffuse_shader == 'FRESNEL' and mater.pov.replacement_text == "": 1268 c = 1 1269 while (c <= lampCount): 1270 tabWrite("]\n") 1271 tabWrite("}\n") 1272 c += 1 1273 1274 1275 1276 # Close first layer of POV "texture" (Blender material) 1277 tabWrite("}\n") 1278 1279 if ((mater.pov.specular_color.s > 0.0) and (mater.pov.diffuse_shader != 'MINNAERT')): 1280 1281 colored_specular_found = True 1282 else: 1283 colored_specular_found = False 1284 1285 # Write another layered texture using invisible diffuse and metallic trick 1286 # to emulate colored specular highlights 1287 special_texture_found = False 1288 tmpidx = -1 1289 for t in mater.pov_texture_slots: 1290 tmpidx += 1 1291 # index = mater.pov.active_texture_index 1292 slot = mater.pov_texture_slots[tmpidx] # [index] 1293 povtex = slot.texture # slot.name 1294 tex = bpy.data.textures[povtex] 1295 if(t and t.use and ((tex.type == 'IMAGE' and tex.image) or tex.type != 'IMAGE') and 1296 (t.use_map_specular or t.use_map_raymir)): 1297 # Specular mapped textures would conflict with colored specular 1298 # because POV can't layer over or under pigment patterned textures 1299 special_texture_found = True 1300 1301 if colored_specular_found and not special_texture_found: 1302 if comments: 1303 tabWrite(" // colored highlights with a stransparent metallic layer\n") 1304 else: 1305 tabWrite("\n") 1306 1307 tabWrite("texture {\n") 1308 tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, 0, 1>}\n" % \ 1309 (mater.pov.specular_color[0], mater.pov.specular_color[1], mater.pov.specular_color[2])) 1310 tabWrite("finish {%s}\n" % (safety(material_finish, Level=2))) # Level 2 is translated spec 1311 1312 texturesNorm = "" 1313 for t in mater.pov_texture_slots: 1314 1315 if t and tex.pov.tex_pattern_type != 'emulator': 1316 proceduralFlag=True 1317 image_filename = string_strip_hyphen(bpy.path.clean_name(tex.name)) 1318 if (t and tex.type == 'IMAGE' and 1319 t.use and tex.image and 1320 tex.pov.tex_pattern_type == 'emulator'): 1321 proceduralFlag=False 1322 image_filename = path_image(tex.image) 1323 imgGamma = "" 1324 if image_filename: 1325 if t.use_map_normal: 1326 texturesNorm = image_filename 1327 # colvalue = t.normal_factor/10 # UNUSED XXX *-9.5 ! 1328 #textNormName=tex.image.name + ".normal" 1329 #was the above used? --MR 1330 t_nor = t 1331 if proceduralFlag: 1332 tabWrite("normal{function" \ 1333 "{f%s(x,y,z).grey} bump_size %.4g}\n" % \ 1334 (texturesNorm, 1335 ( - t_nor.normal_factor * 9.5))) 1336 else: 1337 tabWrite("normal {uv_mapping bump_map " \ 1338 "{%s \"%s\" %s bump_size %.4g }%s}\n" % \ 1339 (imageFormat(texturesNorm), 1340 texturesNorm, imgMap(t_nor), 1341 ( - t_nor.normal_factor * 9.5), 1342 mappingNor)) 1343 1344 tabWrite("}\n") # THEN IT CAN CLOSE LAST LAYER OF TEXTURE 1345 1346def string_strip_hyphen(name): 1347 return name.replace("-", "") 1348# WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1349def write_nodes(scene,povMatName,ntree,file): 1350 """translate Blender node trees to pov and write them to file""" 1351 declareNodes=[] 1352 scene=bpy.context.scene 1353 for node in ntree.nodes: 1354 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1355 if node.bl_idname == "PovrayFinishNode" and node.outputs["Finish"].is_linked: 1356 file.write('#declare %s = finish {\n'%povNodeName) 1357 emission=node.inputs["Emission"].default_value 1358 if node.inputs["Emission"].is_linked: 1359 pass 1360 file.write(' emission %.4g\n'%emission) 1361 for link in ntree.links: 1362 if link.to_node == node: 1363 1364 if link.from_node.bl_idname == 'PovrayDiffuseNode': 1365 intensity=0 1366 albedo="" 1367 brilliance=0 1368 crand=0 1369 if link.from_node.inputs["Intensity"].is_linked: 1370 pass 1371 else: 1372 intensity=link.from_node.inputs["Intensity"].default_value 1373 if link.from_node.inputs["Albedo"].is_linked: 1374 pass 1375 else: 1376 if link.from_node.inputs["Albedo"].default_value == True: 1377 albedo = "albedo" 1378 file.write(' diffuse %s %.4g\n'%(albedo,intensity)) 1379 if link.from_node.inputs["Brilliance"].is_linked: 1380 pass 1381 else: 1382 brilliance=link.from_node.inputs["Brilliance"].default_value 1383 file.write(' brilliance %.4g\n'%brilliance) 1384 if link.from_node.inputs["Crand"].is_linked: 1385 pass 1386 else: 1387 crand=link.from_node.inputs["Crand"].default_value 1388 if crand > 0: 1389 file.write(' crand %.4g\n'%crand) 1390 1391 1392 if link.from_node.bl_idname == 'PovraySubsurfaceNode': 1393 if scene.povray.sslt_enable: 1394 energy = 0 1395 r = g = b = 0 1396 if link.from_node.inputs["Translucency"].is_linked: 1397 pass 1398 else: 1399 r,g,b,a=link.from_node.inputs["Translucency"].default_value[:] 1400 if link.from_node.inputs["Energy"].is_linked: 1401 pass 1402 else: 1403 energy=link.from_node.inputs["Energy"].default_value 1404 file.write(' subsurface { translucency <%.4g,%.4g,%.4g>*%s }\n'%(r,g,b,energy)) 1405 1406 1407 1408 if link.from_node.bl_idname in {'PovraySpecularNode','PovrayPhongNode'}: 1409 intensity=0 1410 albedo="" 1411 roughness=0 1412 metallic=0 1413 phong_size=0 1414 highlight="specular" 1415 if link.from_node.inputs["Intensity"].is_linked: 1416 pass 1417 else: 1418 intensity=link.from_node.inputs["Intensity"].default_value 1419 1420 if link.from_node.inputs["Albedo"].is_linked: 1421 pass 1422 else: 1423 if link.from_node.inputs["Albedo"].default_value == True: 1424 albedo = "albedo" 1425 if link.from_node.bl_idname in {'PovrayPhongNode'}: 1426 highlight="phong" 1427 file.write(' %s %s %.4g\n'%(highlight,albedo,intensity)) 1428 1429 if link.from_node.bl_idname in {'PovraySpecularNode'}: 1430 if link.from_node.inputs["Roughness"].is_linked: 1431 pass 1432 else: 1433 roughness=link.from_node.inputs["Roughness"].default_value 1434 file.write(' roughness %.6g\n'%roughness) 1435 1436 if link.from_node.bl_idname in {'PovrayPhongNode'}: 1437 if link.from_node.inputs["Size"].is_linked: 1438 pass 1439 else: 1440 phong_size=link.from_node.inputs["Size"].default_value 1441 file.write(' phong_size %s\n'%phong_size) 1442 1443 if link.from_node.inputs["Metallic"].is_linked: 1444 pass 1445 else: 1446 metallic=link.from_node.inputs["Metallic"].default_value 1447 file.write(' metallic %.4g\n'%metallic) 1448 1449 if link.from_node.bl_idname in {'PovrayMirrorNode'}: 1450 file.write(' reflection {\n') 1451 color=None 1452 exponent=0 1453 metallic=0 1454 falloff=0 1455 fresnel="" 1456 conserve="" 1457 if link.from_node.inputs["Color"].is_linked: 1458 pass 1459 else: 1460 color=link.from_node.inputs["Color"].default_value[:] 1461 file.write(' <%.4g,%.4g,%.4g>\n'%color) 1462 1463 if link.from_node.inputs["Exponent"].is_linked: 1464 pass 1465 else: 1466 exponent=link.from_node.inputs["Exponent"].default_value 1467 file.write(' exponent %.4g\n'%exponent) 1468 1469 if link.from_node.inputs["Falloff"].is_linked: 1470 pass 1471 else: 1472 falloff=link.from_node.inputs["Falloff"].default_value 1473 file.write(' falloff %.4g\n'%falloff) 1474 1475 if link.from_node.inputs["Metallic"].is_linked: 1476 pass 1477 else: 1478 metallic=link.from_node.inputs["Metallic"].default_value 1479 file.write(' metallic %.4g'%metallic) 1480 1481 if link.from_node.inputs["Fresnel"].is_linked: 1482 pass 1483 else: 1484 if link.from_node.inputs["Fresnel"].default_value==True: 1485 fresnel="fresnel" 1486 1487 if link.from_node.inputs["Conserve energy"].is_linked: 1488 pass 1489 else: 1490 if link.from_node.inputs["Conserve energy"].default_value==True: 1491 conserve="conserve_energy" 1492 1493 file.write(' %s}\n %s\n'%(fresnel,conserve)) 1494 1495 if link.from_node.bl_idname == 'PovrayAmbientNode': 1496 ambient=(0,0,0) 1497 if link.from_node.inputs["Ambient"].is_linked: 1498 pass 1499 else: 1500 ambient=link.from_node.inputs["Ambient"].default_value[:] 1501 file.write(' ambient <%.4g,%.4g,%.4g>\n'%ambient) 1502 1503 if link.from_node.bl_idname in {'PovrayIridescenceNode'}: 1504 file.write(' irid {\n') 1505 amount=0 1506 thickness=0 1507 turbulence=0 1508 if link.from_node.inputs["Amount"].is_linked: 1509 pass 1510 else: 1511 amount=link.from_node.inputs["Amount"].default_value 1512 file.write(' %.4g\n'%amount) 1513 1514 if link.from_node.inputs["Thickness"].is_linked: 1515 pass 1516 else: 1517 exponent=link.from_node.inputs["Thickness"].default_value 1518 file.write(' thickness %.4g\n'%thickness) 1519 1520 if link.from_node.inputs["Turbulence"].is_linked: 1521 pass 1522 else: 1523 falloff=link.from_node.inputs["Turbulence"].default_value 1524 file.write(' turbulence %.4g}\n'%turbulence) 1525 1526 file.write('}\n') 1527 1528 for node in ntree.nodes: 1529 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1530 if node.bl_idname == "PovrayTransformNode" and node.outputs["Transform"].is_linked: 1531 tx=node.inputs["Translate x"].default_value 1532 ty=node.inputs["Translate y"].default_value 1533 tz=node.inputs["Translate z"].default_value 1534 rx=node.inputs["Rotate x"].default_value 1535 ry=node.inputs["Rotate y"].default_value 1536 rz=node.inputs["Rotate z"].default_value 1537 sx=node.inputs["Scale x"].default_value 1538 sy=node.inputs["Scale y"].default_value 1539 sz=node.inputs["Scale z"].default_value 1540 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)) 1541 1542 for node in ntree.nodes: 1543 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1544 if node.bl_idname == "PovrayColorImageNode" and node.outputs["Pigment"].is_linked: 1545 declareNodes.append(node.name) 1546 if node.image == "": 1547 file.write('#declare %s = pigment { color rgb 0.8}\n'%(povNodeName)) 1548 else: 1549 im=bpy.data.images[node.image] 1550 if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)): 1551 transform = "" 1552 for link in ntree.links: 1553 if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node: 1554 povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1555 transform="transform {%s}"%povTransName 1556 uv="" 1557 if node.map_type=="uv_mapping": 1558 uv="uv_mapping" 1559 filepath=bpy.path.abspath(im.filepath) 1560 file.write('#declare %s = pigment {%s image_map {\n'%(povNodeName,uv)) 1561 premul="off" 1562 if node.premultiplied: 1563 premul="on" 1564 once="" 1565 if node.once: 1566 once="once" 1567 file.write(' "%s"\n gamma %.6g\n premultiplied %s\n'%(filepath,node.inputs["Gamma"].default_value,premul)) 1568 file.write(' %s\n'%once) 1569 if node.map_type!="uv_mapping": 1570 file.write(' map_type %s\n'%(node.map_type)) 1571 file.write(' interpolate %s\n filter all %.4g\n transmit all %.4g\n'% 1572 (node.interpolate,node.inputs["Filter"].default_value,node.inputs["Transmit"].default_value)) 1573 file.write(' }\n') 1574 file.write(' %s\n'%transform) 1575 file.write(' }\n') 1576 1577 for node in ntree.nodes: 1578 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1579 if node.bl_idname == "PovrayImagePatternNode" and node.outputs["Pattern"].is_linked: 1580 declareNodes.append(node.name) 1581 if node.image != "": 1582 im=bpy.data.images[node.image] 1583 if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)): 1584 transform = "" 1585 for link in ntree.links: 1586 if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node: 1587 povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1588 transform="transform {%s}"%povTransName 1589 uv="" 1590 if node.map_type=="uv_mapping": 1591 uv="uv_mapping" 1592 filepath=bpy.path.abspath(im.filepath) 1593 file.write('#macro %s() %s image_pattern {\n'%(povNodeName,uv)) 1594 premul="off" 1595 if node.premultiplied: 1596 premul="on" 1597 once="" 1598 if node.once: 1599 once="once" 1600 file.write(' "%s"\n gamma %.6g\n premultiplied %s\n'%(filepath,node.inputs["Gamma"].default_value,premul)) 1601 file.write(' %s\n'%once) 1602 if node.map_type!="uv_mapping": 1603 file.write(' map_type %s\n'%(node.map_type)) 1604 file.write(' interpolate %s\n'%node.interpolate) 1605 file.write(' }\n') 1606 file.write(' %s\n'%transform) 1607 file.write('#end\n') 1608 1609 for node in ntree.nodes: 1610 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1611 if node.bl_idname == "PovrayBumpMapNode" and node.outputs["Normal"].is_linked: 1612 if node.image != "": 1613 im=bpy.data.images[node.image] 1614 if im.filepath and os.path.exists(bpy.path.abspath(im.filepath)): 1615 transform = "" 1616 for link in ntree.links: 1617 if link.from_node.bl_idname=='PovrayTransformNode' and link.to_node==node: 1618 povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1619 transform="transform {%s}"%povTransName 1620 uv="" 1621 if node.map_type=="uv_mapping": 1622 uv="uv_mapping" 1623 filepath=bpy.path.abspath(im.filepath) 1624 file.write('#declare %s = normal {%s bump_map {\n'%(povNodeName,uv)) 1625 once="" 1626 if node.once: 1627 once="once" 1628 file.write(' "%s"\n'%filepath) 1629 file.write(' %s\n'%once) 1630 if node.map_type!="uv_mapping": 1631 file.write(' map_type %s\n'%(node.map_type)) 1632 bump_size=node.inputs["Normal"].default_value 1633 if node.inputs["Normal"].is_linked: 1634 pass 1635 file.write(' interpolate %s\n bump_size %.4g\n'%(node.interpolate,bump_size)) 1636 file.write(' }\n') 1637 file.write(' %s\n'%transform) 1638 file.write(' }\n') 1639 declareNodes.append(node.name) 1640 1641 1642 1643 for node in ntree.nodes: 1644 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1645 if node.bl_idname == "PovrayPigmentNode" and node.outputs["Pigment"].is_linked: 1646 declareNodes.append(node.name) 1647 r,g,b=node.inputs["Color"].default_value[:] 1648 f=node.inputs["Filter"].default_value 1649 t=node.inputs["Transmit"].default_value 1650 if node.inputs["Color"].is_linked: 1651 pass 1652 file.write('#declare %s = pigment{color srgbft <%.4g,%.4g,%.4g,%.4g,%.4g>}\n'%(povNodeName,r,g,b,f,t)) 1653 1654 1655 for node in ntree.nodes: 1656 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1657 if node.bl_idname == "PovrayTextureNode" and node.outputs["Texture"].is_linked: 1658 declareNodes.append(node.name) 1659 r,g,b=node.inputs["Pigment"].default_value[:] 1660 povColName="color rgb <%.4g,%.4g,%.4g>"%(r,g,b) 1661 if node.inputs["Pigment"].is_linked: 1662 for link in ntree.links: 1663 if link.to_node==node and link.to_socket.name=="Pigment": 1664 povColName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1665 file.write('#declare %s = texture{\n pigment{%s}\n'%(povNodeName,povColName)) 1666 if node.inputs["Normal"].is_linked: 1667 for link in ntree.links: 1668 if link.to_node==node and link.to_socket.name=="Normal" and link.from_node.name in declareNodes: 1669 povNorName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1670 file.write(' normal{%s}\n'%povNorName) 1671 if node.inputs["Finish"].is_linked: 1672 for link in ntree.links: 1673 if link.to_node==node and link.to_socket.name=="Finish": 1674 povFinName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1675 file.write(' finish{%s}\n'%povFinName) 1676 file.write('}\n') 1677 declareNodes.append(node.name) 1678 1679 for i in range(0,len(ntree.nodes)): 1680 for node in ntree.nodes: 1681 if node.bl_idname in {"ShaderNodeGroup","ShaderTextureMapNode"}: 1682 for output in node.outputs: 1683 if output.name=="Texture" and output.is_linked and (node.name not in declareNodes): 1684 declare=True 1685 for link in ntree.links: 1686 if link.to_node==node and link.to_socket.name not in {"","Color ramp","Mapping","Transform","Modifier"}: 1687 if link.from_node.name not in declareNodes: 1688 declare=False 1689 if declare: 1690 povNodeName=string_strip_hyphen(bpy.path.clean_name(node.name))+"_%s"%povMatName 1691 uv="" 1692 warp="" 1693 for link in ntree.links: 1694 if link.to_node==node and link.from_node.bl_idname=='PovrayMappingNode' and link.from_node.warp_type!="NONE": 1695 w_type = link.from_node.warp_type 1696 if w_type=="uv_mapping": 1697 uv="uv_mapping" 1698 else: 1699 tor="" 1700 if w_type=="toroidal": 1701 tor="major_radius %.4g"%link.from_node.warp_tor_major_radius 1702 orient=link.from_node.warp_orientation 1703 exp=link.from_node.warp_dist_exp 1704 warp="warp{%s orientation %s dist_exp %.4g %s}"%(w_type,orient,exp,tor) 1705 if link.from_node.warp_type=="planar": 1706 warp="warp{%s %s %.4g}"%(w_type,orient,exp) 1707 if link.from_node.warp_type=="cubic": 1708 warp="warp{%s}"%w_type 1709 file.write('#declare %s = texture {%s\n'%(povNodeName,uv)) 1710 pattern=node.inputs[0].default_value 1711 advanced="" 1712 if node.inputs[0].is_linked: 1713 for link in ntree.links: 1714 if link.to_node==node and link.from_node.bl_idname=='ShaderPatternNode': 1715 ########### advanced ############################################### 1716 lfn=link.from_node 1717 pattern=lfn.pattern 1718 if pattern == 'agate': 1719 advanced = 'agate_turb %.4g'%lfn.agate_turb 1720 if pattern == 'crackle': 1721 advanced="form <%.4g,%.4g,%.4g>"%(lfn.crackle_form_x,lfn.crackle_form_y,lfn.crackle_form_z) 1722 advanced+=" metric %.4g"%lfn.crackle_metric 1723 if lfn.crackle_solid: 1724 advanced+=" solid" 1725 if pattern in {'spiral1', 'spiral2'}: 1726 advanced='%.4g'%lfn.spiral_arms 1727 if pattern in {'tiling'}: 1728 advanced='%.4g'%lfn.tiling_number 1729 if pattern in {'gradient'}: 1730 advanced='%s'%lfn.gradient_orient 1731 if link.to_node==node and link.from_node.bl_idname=='PovrayImagePatternNode': 1732 povMacroName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1733 pattern = "%s()"%povMacroName 1734 file.write(' %s %s %s\n'%(pattern,advanced,warp)) 1735 1736 repeat="" 1737 for link in ntree.links: 1738 if link.to_node==node and link.from_node.bl_idname=='PovrayMultiplyNode': 1739 if link.from_node.amount_x > 1: 1740 repeat+="warp{repeat %.4g * x}"%link.from_node.amount_x 1741 if link.from_node.amount_y > 1: 1742 repeat+=" warp{repeat %.4g * y}"%link.from_node.amount_y 1743 if link.from_node.amount_z > 1: 1744 repeat+=" warp{repeat %.4g * z}"%link.from_node.amount_z 1745 1746 transform="" 1747 for link in ntree.links: 1748 if link.to_node==node and link.from_node.bl_idname=='PovrayTransformNode': 1749 povTransName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1750 transform="transform {%s}"%povTransName 1751 x=0 1752 y=0 1753 z=0 1754 d=0 1755 e=0 1756 f=0 1757 g=0 1758 h=0 1759 modifier=False 1760 for link in ntree.links: 1761 if link.to_node==node and link.from_node.bl_idname=='PovrayModifierNode': 1762 modifier=True 1763 if link.from_node.inputs["Turb X"].is_linked: 1764 pass 1765 else: 1766 x = link.from_node.inputs["Turb X"].default_value 1767 1768 if link.from_node.inputs["Turb Y"].is_linked: 1769 pass 1770 else: 1771 y = link.from_node.inputs["Turb Y"].default_value 1772 1773 if link.from_node.inputs["Turb Z"].is_linked: 1774 pass 1775 else: 1776 z = link.from_node.inputs["Turb Z"].default_value 1777 1778 if link.from_node.inputs["Octaves"].is_linked: 1779 pass 1780 else: 1781 d = link.from_node.inputs["Octaves"].default_value 1782 1783 if link.from_node.inputs["Lambda"].is_linked: 1784 pass 1785 else: 1786 e = link.from_node.inputs["Lambda"].default_value 1787 1788 if link.from_node.inputs["Omega"].is_linked: 1789 pass 1790 else: 1791 f = link.from_node.inputs["Omega"].default_value 1792 1793 if link.from_node.inputs["Frequency"].is_linked: 1794 pass 1795 else: 1796 g = link.from_node.inputs["Frequency"].default_value 1797 1798 if link.from_node.inputs["Phase"].is_linked: 1799 pass 1800 else: 1801 h = link.from_node.inputs["Phase"].default_value 1802 1803 turb = "turbulence <%.4g,%.4g,%.4g>"%(x,y,z) 1804 octv = "octaves %s"%d 1805 lmbd = "lambda %.4g"%e 1806 omg = "omega %.4g"%f 1807 freq = "frequency %.4g"%g 1808 pha = "phase %.4g"%h 1809 1810 1811 file.write('\n') 1812 if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: 1813 file.write(' texture_map {\n') 1814 if node.inputs["Color ramp"].is_linked: 1815 for link in ntree.links: 1816 if link.to_node==node and link.from_node.bl_idname=="ShaderNodeValToRGB": 1817 els = link.from_node.color_ramp.elements 1818 n=-1 1819 for el in els: 1820 n+=1 1821 povInMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s_%s"%(n,povMatName) 1822 default=True 1823 for ilink in ntree.links: 1824 if ilink.to_node==node and ilink.to_socket.name == str(n): 1825 default=False 1826 povInMatName=string_strip_hyphen(bpy.path.clean_name(ilink.from_node.name))+"_%s"%povMatName 1827 if default: 1828 r,g,b,a=el.color[:] 1829 file.write(' #declare %s = texture{pigment{color srgbt <%.4g,%.4g,%.4g,%.4g>}};\n'%(povInMatName,r,g,b,1-a)) 1830 file.write(' [%s %s]\n'%(el.position,povInMatName)) 1831 else: 1832 els=[[0,0,0,0],[1,1,1,1]] 1833 for i in range(0,2): 1834 povInMatName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s_%s"%(i,povMatName) 1835 default=True 1836 for ilink in ntree.links: 1837 if ilink.to_node==node and ilink.to_socket.name == str(i): 1838 default=False 1839 povInMatName=string_strip_hyphen(bpy.path.clean_name(ilink.from_node.name))+"_%s"%povMatName 1840 if default: 1841 r,g,b=els[i][1],els[i][2],els[i][3] 1842 if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: 1843 file.write(' #declare %s = texture{pigment{color rgb <%.4g,%.4g,%.4g>}};\n'%(povInMatName,r,g,b)) 1844 else: 1845 file.write(' texture{pigment{color rgb <%.4g,%.4g,%.4g>}}\n'%(r,g,b)) 1846 if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: 1847 file.write(' [%s %s]\n'%(els[i][0],povInMatName)) 1848 else: 1849 if default==False: 1850 file.write(' texture{%s}\n'%povInMatName) 1851 if pattern not in {'checker', 'hexagon', 'square', 'triangular', 'brick'}: 1852 file.write('}\n') 1853 if pattern == 'brick': 1854 file.write("brick_size <%.4g, %.4g, %.4g> mortar %.4g \n"%(node.brick_size_x, 1855 node.brick_size_y, node.brick_size_z, node.brick_mortar)) 1856 file.write(' %s %s'%(repeat,transform)) 1857 if modifier: 1858 file.write(' %s %s %s %s %s %s'%(turb,octv,lmbd,omg,freq,pha)) 1859 file.write('}\n') 1860 declareNodes.append(node.name) 1861 1862 for link in ntree.links: 1863 if link.to_node.bl_idname == "PovrayOutputNode" and link.from_node.name in declareNodes: 1864 povMatNodeName=string_strip_hyphen(bpy.path.clean_name(link.from_node.name))+"_%s"%povMatName 1865 file.write('#declare %s = %s\n'%(povMatName,povMatNodeName)) 1866