blender-addons/render_povray/shading.py
Maurice Raybaud e44e5845ee fix: Texture slots for world and materials
fix: Orthographic and perspective camera view angle thanks to Iari Marino
add: some numpy functions to export mesh possibly faster in next version
fix: parametric surfaces much accelerated and now actually usable (max gradient defaults were wrong from the time of their implementation in most pov literature. Thanks to William F. Pokorny for finding this out!
add: very basic "blurry reflection" hack for when using plain official POV
add: push of (as of yet badly formatted) feedback to interactive console
add: POV centric workspace, default when addon is left activated from previous session.
add: Sound signal support on finished render (set from addon preferences)
add: support for pov 3.8 and decremented in a few areas, waiting for the release
add: freestyle interface with convoluted workflow currently but preparing for next release.
fix: commented out Charset feature because POV 3.8 auto detects encoding
fix: a few dot notation look ups aliased and removed
fix: restored some more removed properties from 2.79 ( a few remain to do)
fix: texture mapped specular max value increased
fix: faster defaults for radiosity
fix: many default texture influences switched to 1 because boolean enabling is required anyway so 0 was a bad default
fix: some icons were missing since 2.8
fix: some formatting improvement was started
2020-08-02 00:07:39 +02:00

1866 lines
98 KiB
Python

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