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