Newer
Older
# ##### 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 #####
import bpy
import subprocess
import os
import sys
import time
import math
import platform as pltfrm
if pltfrm.architecture()[0] == '64bit':
bitness = 64
else:
bitness = 32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
##############################SF###########################
##############find image texture
def splitExt(path):
dotidx = path.rfind('.')
if dotidx == -1:
return path, ''
else:
return (path[dotidx:]).upper().replace('.','')
def imageFormat(imgF):
ext = ""
ext_orig = splitExt(imgF)
if ext_orig == 'JPG' or ext_orig == 'JPEG': ext='jpeg'
if ext_orig == 'GIF': ext = 'gif'
if ext_orig == 'TGA': ext = 'tga'
if ext_orig == 'IFF': ext = 'iff'
if ext_orig == 'PPM': ext = 'ppm'
if ext_orig == 'PNG': ext = 'png'
if ext_orig == 'SYS': ext = 'sys'
if ext_orig in ('TIFF', 'TIF'): ext = 'tiff'
if ext_orig == 'EXR': ext = 'exr'#POV3.7 Only!
if ext_orig == 'HDR': ext = 'hdr'#POV3.7 Only! --MR
print(imgF)
if not ext: print(' WARNING: texture image format not supported ') # % (imgF , '')) #(ext_orig)))
return ext
def imgMap(ts):
image_map=''
if ts.mapping=='FLAT':image_map= ' map_type 0 '
if ts.mapping=='SPHERE':image_map= ' map_type 1 '# map_type 7 in megapov
if ts.mapping=='TUBE':image_map= ' map_type 2 '
#if ts.mapping=='?':image_map= ' map_type 3 '# map_type 3 and 4 in development (?) for Povray, currently they just seem to default back to Flat (type 0)
#if ts.mapping=='?':image_map= ' map_type 4 '# map_type 3 and 4 in development (?) for Povray, currently they just seem to default back to Flat (type 0)
if ts.texture.use_interpolation: image_map+= " interpolate 2 "
if ts.texture.extension == 'CLIP': image_map+=' once '
#image_map+='}'
#if ts.mapping=='CUBE':image_map+= 'warp { cubic } rotate <-90,0,180>' #no direct cube type mapping. Though this should work in POV 3.7 it doesn't give that good results(best suited to environment maps?)
#if image_map=='': print(' No texture image found ')
return image_map
def imgMapBG(wts):
image_mapBG=''
if wts.texture_coords== 'VIEW':image_mapBG= ' map_type 0 ' #texture_coords refers to the mapping of world textures
if wts.texture_coords=='ANGMAP':image_mapBG= ' map_type 1 '
if wts.texture_coords=='TUBE':image_mapBG= ' map_type 2 '
if wts.texture.use_interpolation: image_mapBG+= " interpolate 2 "
if wts.texture.extension == 'CLIP': image_mapBG+=' once '
#image_mapBG+='}'
#if wts.mapping=='CUBE':image_mapBG+= 'warp { cubic } rotate <-90,0,180>' #no direct cube type mapping. Though this should work in POV 3.7 it doesn't give that good results(best suited to environment maps?)
#if image_mapBG=='': print(' No background texture image found ')
return image_mapBG
def splitFile(path):
idx = path.rfind('/')
if idx == -1:
idx = path.rfind('\\')
return path[idx:].replace("/", "").replace("\\", "")
def splitPath(path):
idx = path.rfind('/')
if idx == -1:
return path, ''
else:
return path[:idx]
def findInSubDir(filename, subdirectory=''):
pahFile=''
if subdirectory:
path = subdirectory
else:
path = os.getcwd()
try:
for root, dirs, names in os.walk(path):
if filename in names:
pahFile = os.path.join(root, filename)
return pahFile
def path_image(image):
import os
fn = bpy.path.abspath(image)
fn_strip = os.path.basename(fn)
if not os.path.isfile(fn):
fn=(findInSubDir(splitFile(fn),splitPath(bpy.data.filepath)))
()
return fn
##############end find image texture
##############safety string name material
def safety(name, Level):
# Level=1 is for texture with No specular nor Mirror reflection
# Level=2 is for texture with translation of spec and mir levels for when no map influences them
# Level=3 is for texture with Maximum Spec and Mirror
if int(name) > 0:
prefix='shader'
except:
prefix = ''
if Level == 2:
return prefix+name
elif Level == 1:
return prefix+name+'0'#used for 0 of specular map
elif Level == 3:
return prefix+name+'1'#used for 1 of specular map
##############end safety string name material
##############################EndSF###########################
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def write_pov(filename, scene=None, info_callback=None):
file = open(filename, 'w')
# Only for testing
if not scene:
scene = bpy.data.scenes[0]
render = scene.render
world = scene.world
def uniqueName(name, nameSeq):
if name not in nameSeq:
return name
name_orig = name
i = 1
while name in nameSeq:
name = '%s_%.3d' % (name_orig, i)
i += 1
return name
def writeMatrix(matrix):
file.write('\tmatrix <%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f>\n' %\
(matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0], matrix[1][1], matrix[1][2], matrix[2][0], matrix[2][1], matrix[2][2], matrix[3][0], matrix[3][1], matrix[3][2]))
def writeObjectMaterial(material):
Doug Hammond
committed
# DH - modified some variables to be function local, avoiding RNA write
# this should be checked to see if it is functionally correct
if material: #and material.transparency_method == 'RAYTRACE':#Commented out: always write IOR to be able to use it for SSS, Fresnel reflections...
#But there can be only one!
if material.subsurface_scattering.use:#SSS IOR get highest priority
file.write('\tinterior { ior %.6f\n' % material.subsurface_scattering.ior)
elif material.pov_mirror_use_IOR:#Then the raytrace IOR taken from raytrace transparency properties and used for reflections if IOR Mirror option is checked
file.write('\tinterior { ior %.6f\n' % material.raytrace_transparency.ior)
else:
file.write('\tinterior { ior %.6f\n' % material.raytrace_transparency.ior)
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = False
pov_photons_reflection = False
Maurice Raybaud
committed
if material.pov_refraction_type=="0":
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = False
pov_photons_reflection = True
Maurice Raybaud
committed
elif material.pov_refraction_type=="1":
Doug Hammond
committed
pov_fake_caustics = True
pov_photons_refraction = False
Maurice Raybaud
committed
elif material.pov_refraction_type=="2":
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = True
#If only Raytrace transparency is set, its IOR will be used for refraction, but user can set up "un-physical" fresnel reflections in raytrace mirror parameters.
#Last, if none of the above is specified, user can set up "un-physical" fresnel reflections in raytrace mirror parameters. And pov IOR defaults to 1.
if material.pov_caustics_enable:
Doug Hammond
committed
if pov_fake_caustics:
file.write('\tcaustics %.3g\n' % material.pov_fake_caustics_power)
if material.pov_photons_refraction:
file.write('\tdispersion %.3g\n' % material.pov_photons_dispersion) #Default of 1 means no dispersion
Maurice Raybaud
committed
#TODO
Maurice Raybaud
committed
# if material.use_transparency and material.transparency_method == 'RAYTRACE':
# fade_distance 2
# fade_power [Value]
# fade_color
# (variable) dispersion_samples (constant count for now)
file.write('\t}\n')
Doug Hammond
committed
if pov_photons_refraction or pov_photons_reflection:
file.write('\tphotons{\n')
file.write('\t\ttarget\n')
Doug Hammond
committed
if pov_photons_refraction:
Doug Hammond
committed
if pov_photons_reflection:
file.write('\t\treflection on\n')
file.write('\t}\n')
materialNames = {}
DEF_MAT_NAME = 'Default'
def writeMaterial(material):
# Assumes only called once on each material
if material:
name_orig = material.name
else:
name_orig = DEF_MAT_NAME
name = materialNames[name_orig] = uniqueName(bpy.path.clean_name(name_orig), materialNames)
##################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):
file.write('#declare %s = finish {\n' % safety(name, Level = 2))
file.write('#declare %s = finish {\n' % safety(name, Level = 1))
file.write('#declare %s = finish {\n' % safety(name, Level = 3))
if material:
#Povray 3.7 now uses two diffuse values respectively for front and back shading (the back diffuse is like blender translucency)
frontDiffuse=material.diffuse_intensity
backDiffuse=material.translucency
if material.pov_conserve_energy:
#Total should not go above one
if (frontDiffuse + backDiffuse) <= 1.0:
pass
elif frontDiffuse==backDiffuse:
frontDiffuse = backDiffuse = 0.5 # Try to respect the user's "intention" by comparing the two values but bringing the total back to one
elif frontDiffuse>backDiffuse: # Let the highest value stay the highest value
backDiffuse = 1-(1-frontDiffuse)
else:
frontDiffuse = 1-(1-backDiffuse)
# map hardness between 0.0 and 1.0
roughness = ((1.0 - ((material.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 / 511.0)
#####################################Diffuse Shader######################################
Maurice Raybaud
committed
# Not used for Full spec (Level=3) of the shader
if material.diffuse_shader == 'OREN_NAYAR' and Level != 3:
file.write('\tbrilliance %.3g\n' % (0.9+material.roughness))#blender roughness is what is generally called oren nayar Sigma, and brilliance in povray
if material.diffuse_shader == 'TOON' and Level != 3:
file.write('\tbrilliance %.3g\n' % (0.01+material.diffuse_toon_smooth*0.25))
frontDiffuse*=0.5 #Lower diffuse and increase specular for toon effect seems to look better in povray
if material.diffuse_shader == 'MINNAERT' and Level != 3:
#file.write('\taoi %.3g\n' % material.darkness)
pass #let's keep things simple for now
if material.diffuse_shader == 'FRESNEL' and Level != 3:
#file.write('\taoi %.3g\n' % material.diffuse_fresnel_factor)
pass #let's keep things simple for now
if material.diffuse_shader == 'LAMBERT' and Level != 3:
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
file.write('\tbrilliance 1.8\n') #trying to best match lambert attenuation by that constant brilliance value
if Level == 2:
####################################Specular Shader######################################
if material.specular_shader == 'COOKTORR' or material.specular_shader == 'PHONG':#No difference between phong and cook torrence in blender HaHa!
file.write('\tphong %.3g\n' % (material.specular_intensity))
file.write('\tphong_size %.3g\n'% (material.specular_hardness / 2 + 0.25))
if material.specular_shader == 'BLINN':#Povray "specular" keyword corresponds to a Blinn model, without the ior.
file.write('\tspecular %.3g\n' % (material.specular_intensity * (material.specular_ior/4))) #Use blender Blinn's IOR just as some factor for spec intensity
file.write('\troughness %.3g\n' % roughness)
#Could use brilliance 2(or varying around 2 depending on ior or factor) too.
if material.specular_shader == 'TOON':
file.write('\tphong %.3g\n' % (material.specular_intensity * 2))
file.write('\tphong_size %.3g\n' % (0.1+material.specular_toon_smooth / 2)) #use extreme phong_size
if material.specular_shader == 'WARDISO':
file.write('\tspecular %.3g\n' % (material.specular_intensity / (material.specular_slope+0.0005))) #find best suited default constant for brilliance Use both phong and specular for some values.
file.write('\troughness %.4g\n' % (0.0005+material.specular_slope/10)) #find best suited default constant for brilliance Use both phong and specular for some values.
file.write('\tbrilliance %.4g\n' % (1.8-material.specular_slope*1.8)) #find best suited default constant for brilliance Use both phong and specular for some values.
#########################################################################################
elif Level == 1:
file.write('\tspecular 0\n')
elif Level == 3:
file.write('\tspecular 1\n')
file.write('\tdiffuse %.3g %.3g\n' % (frontDiffuse, backDiffuse))
file.write('\tambient %.3g\n' % material.ambient)
#file.write('\tambient rgb <%.3g, %.3g, %.3g>\n' % tuple([c*material.ambient for c in world.ambient_color])) # povray blends the global value
file.write('\temission %.3g\n' % material.emit) #New in povray 3.7
#file.write('\troughness %.3g\n' % roughness) #povray just ignores roughness if there's no specular keyword
if material.pov_conserve_energy:
file.write('\tconserve_energy\n')#added for more realistic shading. Needs some checking to see if it really works. --Maurice.
# 'phong 70.0 '
if Level != 1:
if material.raytrace_mirror.use:
raytrace_mirror = material.raytrace_mirror
if raytrace_mirror.reflect_factor:
file.write('\treflection {\n')
file.write('\t\trgb <%.3g, %.3g, %.3g>' % tuple(material.mirror_color))
if material.pov_mirror_metallic:
file.write('\t\tmetallic %.3g' % (raytrace_mirror.reflect_factor))
if material.pov_mirror_use_IOR: #WORKING ?
file.write('\t\tfresnel 1 ')#Removed from the line below: gives a more physically correct material but needs proper IOR. --Maurice
file.write('\t\tfalloff %.3g exponent %.3g} ' % (raytrace_mirror.fresnel, raytrace_mirror.fresnel_factor))
if material.subsurface_scattering.use:
subsurface_scattering = material.subsurface_scattering
file.write('\tsubsurface { <%.3g, %.3g, %.3g>, <%.3g, %.3g, %.3g> }\n' % (sqrt(subsurface_scattering.radius[0])*1.5, sqrt(subsurface_scattering.radius[1])*1.5, sqrt(subsurface_scattering.radius[2])*1.5, 1-subsurface_scattering.color[0], 1-subsurface_scattering.color[1], 1-subsurface_scattering.color[2]))
if material.pov_irid_enable:
file.write('\tirid { %.4g thickness %.4g turbulence %.4g }' % (material.pov_irid_amount, material.pov_irid_thickness, material.pov_irid_turbulence))
else:
file.write('\tdiffuse 0.8\n')
file.write('\tphong 70.0\n')
#file.write('\tspecular 0.2\n')
# This is written into the object
'''
if material and material.transparency_method=='RAYTRACE':
'interior { ior %.3g} ' % material.raytrace_transparency.ior
'''
#file.write('\t\t\tcrand 1.0\n') # Sand granyness
#file.write('\t\t\tmetallic %.6f\n' % material.spec)
#file.write('\t\t\tphong %.6f\n' % material.spec)
#file.write('\t\t\tphong_size %.6f\n' % material.spec)
#file.write('\t\t\tbrilliance %.6f ' % (material.specular_hardness/256.0) # Like hardness
# Level=1 Means No specular nor Mirror reflection
povHasnoSpecularMaps(Level=1)
# Level=2 Means translation of spec and mir levels for when no map influences them
povHasnoSpecularMaps(Level=2)
# Level=3 Means Maximum Spec and Mirror
povHasnoSpecularMaps(Level=3)
Doug Hammond
committed
# DH disabled for now, this isn't the correct context
active_object = None #bpy.context.active_object # MR
focal_point = camera.data.dof_distance
# compute resolution
Qsize = float(render.resolution_x) / float(render.resolution_y)
file.write('#declare camLocation = <%.6f, %.6f, %.6f>;\n' % (matrix[3][0], matrix[3][1], matrix[3][2]))
file.write('#declare camLookAt = <%.6f, %.6f, %.6f>;\n' % tuple([degrees(e) for e in matrix.rotation_part().to_euler()]))
Doug Hammond
committed
if scene.pov_baking_enable and active_object and active_object.type=='MESH':
Loading
Loading full blame...