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 subprocess
import os
import sys
import time
import math
import platform as pltfrm
if pltfrm.architecture()[0] == '64bit':
bitness = 64
else:
bitness = 32
Constantin Rahn
committed
##############################SF###########################
##############find image texture
def splitExt(path):
dotidx = path.rfind('.')
if dotidx == -1:
return path, ''
else:
return path[dotidx:].upper().replace(".", "")
Maurice Raybaud
committed
if ext_orig == 'JPG' or ext_orig == 'JPEG':
ext = 'jpeg'
elif ext_orig == 'GIF':
ext = 'gif'
elif ext_orig == 'TGA':
ext = 'tga'
elif ext_orig == 'IFF':
ext = 'iff'
elif ext_orig == 'PPM':
ext = 'ppm'
elif ext_orig == 'PNG':
ext = 'png'
elif ext_orig == 'SYS':
ext = 'sys'
elif ext_orig in ('TIFF', 'TIF'):
ext = 'tiff'
elif ext_orig == 'EXR':
ext = 'exr' # POV3.7 Only!
elif ext_orig == 'HDR':
ext = 'hdr' # POV3.7 Only! --MR
if not ext:
print(" WARNING: texture image format not supported ") # % (imgF , '')) #(ext_orig)))
image_map = ""
if ts.mapping == 'FLAT':
image_map = "map_type 0 "
elif ts.mapping == 'SPHERE':
image_map = "map_type 1 " # map_type 7 in megapov
elif ts.mapping == 'TUBE':
image_map = "map_type 2 "
#if ts.mapping=='?':image_map= ' map_type 3 '# map_type 3 and 4 in development (?) for POV-Ray, 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 POV-Ray, 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 ')
image_mapBG = ""
if wts.texture_coords == 'VIEW':
image_mapBG = " map_type 0 " # texture_coords refers to the mapping of world textures
elif wts.texture_coords == 'ANGMAP':
image_mapBG = " map_type 1 "
elif 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 ')
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))
##############end find image texture
Maurice Raybaud
committed
def splitHyphen(name):
hyphidx = name.find('-')
if hyphidx == -1:
return name
else:
return name[hyphidx:].replace("-", "")
def safety(name, Level):
# safety string name material
#
# 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
Maurice Raybaud
committed
Maurice Raybaud
committed
name = splitHyphen(name)
return prefix + name + "0" # used for 0 of specular map
return prefix + name + "1" # used for 1 of specular map
Maurice Raybaud
committed
##############end safety string name material
##############################EndSF###########################
Constantin Rahn
committed
TabLevel = 0
import mathutils
#file = filename
file = open(filename.name, 'w')
# Only for testing
if not scene:
scene = bpy.data.scenes[0]
render = scene.render
world = scene.world
global_matrix = mathutils.Matrix.Rotation(-pi / 2.0, 4, 'X')
Constantin Rahn
committed
def setTab(tabtype, spaces):
TabStr = ''
if tabtype == '0':
TabStr = ''
Constantin Rahn
committed
TabStr = '\t'
elif tabtype == '2':
TabStr = spaces * ' '
return TabStr
Tab = setTab(scene.pov_indentation_character, scene.pov_indentation_spaces)
Constantin Rahn
committed
def tabWrite(str_o):
global TabLevel
brackets = str_o.count('{') - str_o.count('}') + str_o.count('[') - str_o.count(']')
Constantin Rahn
committed
if brackets < 0:
TabLevel = TabLevel + brackets
Constantin Rahn
committed
if TabLevel < 0:
print('Indentation Warning: TabLevel = %s' % TabLevel)
TabLevel = 0
Constantin Rahn
committed
file.write('%s' % Tab * TabLevel)
file.write(str_o)
if brackets > 0:
TabLevel = TabLevel + brackets
Constantin Rahn
committed
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
Maurice Raybaud
committed
name = splitHyphen(name)
Constantin Rahn
committed
tabWrite('matrix <%.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
Constantin Rahn
committed
tabWrite('interior {\n')
tabWrite('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
Constantin Rahn
committed
tabWrite('interior {\n')
tabWrite('ior %.6f\n' % material.raytrace_transparency.ior)
Constantin Rahn
committed
tabWrite('interior {\n')
tabWrite('ior %.6f\n' % material.raytrace_transparency.ior)
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = False
pov_photons_reflection = False
if material.pov_refraction_type == "0":
Doug Hammond
committed
pov_fake_caustics = False
pov_photons_refraction = False
pov_photons_reflection = True # should respond only to proper checkerbox
elif material.pov_refraction_type == "1":
Doug Hammond
committed
pov_fake_caustics = True
pov_photons_refraction = False
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.
Doug Hammond
committed
if pov_fake_caustics:
Constantin Rahn
committed
tabWrite('caustics %.3g\n' % material.pov_fake_caustics_power)
Maurice Raybaud
committed
if pov_photons_refraction:
tabWrite('dispersion %.3g\n' % material.pov_photons_dispersion) # Default of 1 means no dispersion
#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)
Constantin Rahn
committed
tabWrite('}\n')
Doug Hammond
committed
if pov_photons_refraction or pov_photons_reflection:
Constantin Rahn
committed
tabWrite('photons{\n')
tabWrite('target\n')
Doug Hammond
committed
if pov_photons_refraction:
Constantin Rahn
committed
tabWrite('refraction on\n')
Doug Hammond
committed
if pov_photons_reflection:
Constantin Rahn
committed
tabWrite('reflection on\n')
tabWrite('}\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):
tabWrite('#declare %s = finish {' % safety(name, Level=1))
if comments:
file.write(' //No specular nor Mirror reflection\n')
else:
tabWrite('\n')
tabWrite('#declare %s = finish {' % safety(name, Level=2))
if comments:
file.write(' //translation of spec and mir levels for when no map influences them\n')
else:
tabWrite('\n')
tabWrite('#declare %s = finish {' % safety(name, Level=3))
if comments:
file.write(' //Maximum Spec and Mirror\n')
else:
tabWrite('\n')
#POV-Ray 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) # XXX FIXME!
frontDiffuse = 1 - (1 - backDiffuse) # XXX FIXME!
# 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
# add a small value because 0.0 is invalid
#####################################Diffuse Shader######################################
Maurice Raybaud
committed
# Not used for Full spec (Level=3) of the shader
if material.diffuse_shader == 'OREN_NAYAR' and Level != 3:
tabWrite('brilliance %.3g\n' % (0.9 + material.roughness)) # blender roughness is what is generally called oren nayar Sigma, and brilliance in POV-Ray
if material.diffuse_shader == 'TOON' and Level != 3:
tabWrite('brilliance %.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 POV-Ray
if material.diffuse_shader == 'MINNAERT' and Level != 3:
Constantin Rahn
committed
#tabWrite('aoi %.3g\n' % material.darkness)
pass # let's keep things simple for now
if material.diffuse_shader == 'FRESNEL' and Level != 3:
Constantin Rahn
committed
#tabWrite('aoi %.3g\n' % material.diffuse_fresnel_factor)
pass # let's keep things simple for now
if material.diffuse_shader == 'LAMBERT' and Level != 3:
tabWrite('brilliance 1.8\n') # trying to best match lambert attenuation by that constant brilliance value
####################################Specular Shader######################################
if material.specular_shader == 'COOKTORR' or material.specular_shader == 'PHONG': # No difference between phong and cook torrence in blender HaHa!
Constantin Rahn
committed
tabWrite('phong %.3g\n' % (material.specular_intensity))
tabWrite('phong_size %.3g\n' % (material.specular_hardness / 2 + 0.25))
elif material.specular_shader == 'BLINN': # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior.
tabWrite('specular %.3g\n' % (material.specular_intensity * (material.specular_ior / 4.0))) # Use blender Blinn's IOR just as some factor for spec intensity
tabWrite('roughness %.3g\n' % roughness)
#Could use brilliance 2(or varying around 2 depending on ior or factor) too.
elif material.specular_shader == 'TOON':
Constantin Rahn
committed
tabWrite('phong %.3g\n' % (material.specular_intensity * 2))
tabWrite('phong_size %.3g\n' % (0.1 + material.specular_toon_smooth / 2)) # use extreme phong_size
elif material.specular_shader == 'WARDISO':
tabWrite("specular %.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.
tabWrite("roughness %.4g\n" % (0.0005 + material.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.specular_slope * 1.8)) # find best suited default constant for brilliance Use both phong and specular for some values.
#########################################################################################
Constantin Rahn
committed
tabWrite('specular 0\n')
Constantin Rahn
committed
tabWrite('specular 1\n')
tabWrite('diffuse %.3g %.3g\n' % (frontDiffuse, backDiffuse))
Constantin Rahn
committed
tabWrite('ambient %.3g\n' % material.ambient)
#tabWrite('ambient rgb <%.3g, %.3g, %.3g>\n' % tuple([c*material.ambient for c in world.ambient_color])) # POV-Ray blends the global value
tabWrite('emission %.3g\n' % material.emit) # New in POV-Ray 3.7
#tabWrite('roughness %.3g\n' % roughness) #POV-Ray just ignores roughness if there's no specular keyword
if material.pov_conserve_energy:
tabWrite('conserve_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:
Constantin Rahn
committed
tabWrite('reflection {\n')
tabWrite('rgb <%.3g, %.3g, %.3g>' % material.mirror_color[:])
if material.pov_mirror_metallic:
Constantin Rahn
committed
tabWrite('metallic %.3g' % (raytrace_mirror.reflect_factor))
if material.pov_mirror_use_IOR: # WORKING ?
tabWrite('fresnel 1 ') # Removed from the line below: gives a more physically correct material but needs proper IOR. --Maurice
Constantin Rahn
committed
tabWrite('falloff %.3g exponent %.3g} ' % (raytrace_mirror.fresnel, raytrace_mirror.fresnel_factor))
if material.subsurface_scattering.use:
subsurface_scattering = material.subsurface_scattering
tabWrite('subsurface { <%.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.0 - subsurface_scattering.color[0],
1.0 - subsurface_scattering.color[1],
1.0 - subsurface_scattering.color[2],
)
)
if material.pov_irid_enable:
Constantin Rahn
committed
tabWrite('irid { %.4g thickness %.4g turbulence %.4g }' % (material.pov_irid_amount, material.pov_irid_thickness, material.pov_irid_turbulence))
Constantin Rahn
committed
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.transparency_method=='RAYTRACE':
'interior { ior %.3g} ' % material.raytrace_transparency.ior
'''
Constantin Rahn
committed
#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.specular_hardness/256.0) # Like hardness
Constantin Rahn
committed
tabWrite('}\n\n')
# Level=2 Means translation of spec and mir levels for when no map influences them
povHasnoSpecularMaps(Level=2)
special_texture_found = False
for t in material.texture_slots:
if t and t.texture.type == 'IMAGE' and t.use and t.texture.image and (t.use_map_specular or t.use_map_raymir or t.use_map_normal or t.use_map_alpha):
continue # Some texture found
if special_texture_found:
# Level=1 Means No specular nor Mirror reflection
povHasnoSpecularMaps(Level=1)
# 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 # does not always work MR
matrix = global_matrix * camera.matrix_world
focal_point = camera.data.dof_distance
# compute resolution
Qsize = float(render.resolution_x) / float(render.resolution_y)
Constantin Rahn
committed
tabWrite('#declare camLocation = <%.6f, %.6f, %.6f>;\n' % (matrix[3][0], matrix[3][1], matrix[3][2]))
tabWrite('#declare camLookAt = <%.6f, %.6f, %.6f>;\n' % tuple([degrees(e) for e in matrix.rotation_part().to_euler()]))
Constantin Rahn
committed
tabWrite('camera {\n')
if scene.pov_baking_enable and active_object and active_object.type == 'MESH':
tabWrite('mesh_camera{ 1 3\n') # distribution 3 is what we want here
Constantin Rahn
committed
tabWrite('mesh{%s}\n' % active_object.name)
tabWrite('}\n')
tabWrite('location <0,0,.01>')
tabWrite('direction <0,0,-1>')
Constantin Rahn
committed
tabWrite('location <0, 0, 0>\n')
tabWrite('look_at <0, 0, -1>\n')
tabWrite('right <%s, 0, 0>\n' % - Qsize)
tabWrite('up <0, 1, 0>\n')
tabWrite('angle %f \n' % (360.0 * atan(16.0 / camera.data.lens) / pi))
tabWrite('rotate <%.6f, %.6f, %.6f>\n' % tuple([degrees(e) for e in matrix.rotation_part().to_euler()]))
tabWrite('translate <%.6f, %.6f, %.6f>\n' % (matrix[3][0], matrix[3][1], matrix[3][2]))
tabWrite('aperture 0.25\n') # fixed blur amount for now to do, add slider a button?
Constantin Rahn
committed
tabWrite('blur_samples 96 128\n')
tabWrite('variance 1/10000\n')
tabWrite('focal_point <0, 0, %f>\n' % focal_point)
tabWrite('}\n')
def exportLamps(lamps):
# Get all lamps
for ob in lamps:
lamp = ob.data
matrix = global_matrix * ob.matrix_world
color = tuple([c * lamp.energy * 2.0 for c in lamp.color]) # Colour is modified by energy #muiltiplie by 2 for a better match --Maurice
Constantin Rahn
committed
tabWrite('light_source {\n')
tabWrite('< 0,0,0 >\n')
tabWrite('color rgb<%.3g, %.3g, %.3g>\n' % color)
Constantin Rahn
committed
tabWrite('spotlight\n')
tabWrite('falloff %.2f\n' % (degrees(lamp.spot_size) / 2.0)) # 1 TO 179 FOR BOTH
Constantin Rahn
committed
tabWrite('radius %.6f\n' % ((degrees(lamp.spot_size) / 2.0) * (1.0 - lamp.spot_blend)))
# Blender does not have a tightness equivilent, 0 is most like blender default.
tabWrite('tightness 0\n') # 0:10f
Constantin Rahn
committed
tabWrite('point_at <0, 0, -1>\n')
Constantin Rahn
committed
tabWrite('parallel\n')
tabWrite('point_at <0, 0, -1>\n') # *must* be after 'parallel'
tabWrite('fade_distance %.6f\n' % (lamp.distance / 5.0))
tabWrite('fade_power %d\n' % 2) # Area lights have no falloff type, so always use blenders lamp quad equivalent for those?
size_x = lamp.size
samples_x = lamp.shadow_ray_samples_x
if lamp.shape == 'SQUARE':
size_y = size_x
samples_y = samples_x
else:
size_y = lamp.size_y
samples_y = lamp.shadow_ray_samples_y
Constantin Rahn
committed
tabWrite('area_light <%d,0,0>,<0,0,%d> %d, %d\n' % (size_x, size_y, samples_x, samples_y))
Maurice Raybaud
committed
if lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
Constantin Rahn
committed
tabWrite('jitter\n')
Constantin Rahn
committed
tabWrite('adaptive 1\n')
tabWrite('jitter\n')
if lamp.type == 'HEMI': # HEMI never has any shadow attribute
Constantin Rahn
committed
tabWrite('shadowless\n')
Maurice Raybaud
committed
elif lamp.shadow_method == 'NOSHADOW':
Constantin Rahn
committed
tabWrite('shadowless\n')
if lamp.type not in ('SUN', 'AREA', 'HEMI'): # Sun shouldn't be attenuated. Hemi and area lights have no falloff attribute so they are put to type 2 attenuation a little higher above.
tabWrite("fade_distance %.6f\n" % (lamp.distance / 5.0))
tabWrite('fade_power %d\n' % 2) # Use blenders lamp quad equivalent
tabWrite('fade_power %d\n' % 1) # Use blenders lamp linear
elif lamp.falloff_type == 'CONSTANT': # upposing using no fade power keyword would default to constant, no attenuation.
elif lamp.falloff_type == 'CUSTOM_CURVE': # Using Custom curve for fade power 3 for now.
Constantin Rahn
committed
tabWrite('fade_power %d\n' % 4)
Constantin Rahn
committed
tabWrite('}\n')
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
##################################################################################################################################
#Wip to be Used for fresnel, but not tested yet.
##################################################################################################################################
## lampLocation=[0,0,0]
## lampRotation=[0,0,0]
## lampDistance=0.00
## averageLampLocation=[0,0,0]
## averageLampRotation=[0,0,0]
## averageLampDistance=0.00
## lamps=[]
## for l in scene.objects:
## if l.type == 'LAMP':#get all lamps
## lamps += [l]
## for ob in lamps:
## lamp = ob.data
## lampLocation[0]+=ob.location[0]
## lampLocation[1]+=ob.location[1]
## lampLocation[2]+=ob.location[2]
## lampRotation[0]+=ob.rotation_euler[0]
## lampRotation[1]+=ob.rotation_euler[1]
## lampRotation[2]+=ob.rotation_euler[2]
## lampDistance+=ob.data.distance
## averageLampRotation[0]=lampRotation[0] / len(lamps)#create an average direction for all lamps.
## averageLampRotation[1]=lampRotation[1] / len(lamps)#create an average direction for all lamps.
## averageLampRotation[2]=lampRotation[2] / len(lamps)#create an average direction for all lamps.
##
## averageLampLocation[0]=lampLocation[0] / len(lamps)#create an average position for all lamps.
## averageLampLocation[1]=lampLocation[1] / len(lamps)#create an average position for all lamps.
## averageLampLocation[2]=lampLocation[2] / len(lamps)#create an average position for all lamps.
## averageLampDistance=lampDistance / len(lamps)#create an average distance for all lamps.
## file.write('\n#declare lampTarget= vrotate(<%.4g,%.4g,%.4g>,<%.4g,%.4g,%.4g>);' % (-(averageLampLocation[0]-averageLampDistance), -(averageLampLocation[1]-averageLampDistance), -(averageLampLocation[2]-averageLampDistance), averageLampRotation[0], averageLampRotation[1], averageLampRotation[2]))
## #v(A,B) rotates vector A about origin by vector B.
##
####################################################################################################################################
def exportMeta(metas):
# TODO - blenders 'motherball' naming is not supported.
if scene.pov_comments_enable and len(metas) >= 1:
file.write('//--Blob objects--\n\n')
# important because no elements will break parsing.
elements = [elem for elem in meta.elements if elem.type in ('BALL', 'ELLIPSOID')]
if elements:
tabWrite('blob {\n')
tabWrite('threshold %.4g\n' % meta.threshold)
importance = ob.pov_importance_value
material = meta.materials[0] # lame! - blender cant do enything else.
except:
material = None
for elem in elements:
loc = elem.co
stiffness = elem.stiffness
if elem.use_negative:
stiffness = - stiffness
tabWrite('sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n' % (loc.x, loc.y, loc.z, elem.radius, stiffness))
# After this wecould do something simple like...
# 'pigment {Blue} }'
# except we'll write the color
elif elem.type == 'ELLIPSOID':
# location is modified by scale
tabWrite('sphere { <%.6g, %.6g, %.6g>, %.4g, %.4g }\n' % (loc.x / elem.size_x, loc.y / elem.size_y, loc.z / elem.size_z, elem.radius, stiffness))
tabWrite('scale <%.6g, %.6g, %.6g> \n' % (elem.size_x, elem.size_y, elem.size_z))
if material:
diffuse_color = material.diffuse_color
if material.use_transparency and material.transparency_method == 'RAYTRACE':
trans = 1.0 - material.raytrace_transparency.filter
else:
trans = 0.0
material_finish = materialNames[material.name]
tabWrite('pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n' % (diffuse_color[0], diffuse_color[1], diffuse_color[2], 1.0 - material.alpha, trans))
tabWrite('finish {%s}\n' % safety(material_finish, Level=2))
else:
tabWrite('pigment {rgb<1 1 1>} \n')
tabWrite('finish {%s}\n' % (safety(DEF_MAT_NAME, Level=1))) # Write the finish last.
writeObjectMaterial(material)
writeMatrix(global_matrix * ob.matrix_world)
#Importance for radiosity sampling added here:
tabWrite('radiosity { \n')
tabWrite('importance %3g \n' % importance)
tabWrite('}\n')
tabWrite('}\n') # End of Metaball block
if scene.pov_comments_enable and len(metas) >= 1:
file.write('\n')
Maurice Raybaud
committed
objectNames = {}
DEF_OBJ_NAME = 'Default'
def exportMeshs(scene, sel):
ob_num = 0
for ob in sel:
ob_num += 1
Maurice Raybaud
committed
#############################################
#Generating a name for object just like materials to be able to use it (baking for now or anything else).
if sel:
name_orig = ob.name
else:
name_orig = DEF_OBJ_NAME
name = objectNames[name_orig] = uniqueName(bpy.path.clean_name(name_orig), objectNames)
#############################################
if ob.type in ('LAMP', 'CAMERA', 'EMPTY', 'META', 'ARMATURE', 'LATTICE'):
try:
me = ob.create_mesh(scene, True, 'RENDER')
except:
# happens when curves cant be made into meshes because of no-data
continue
importance = ob.pov_importance_value
continue
if info_callback:
info_callback('Object %2.d of %2.d (%s)' % (ob_num, len(sel), ob.name))
#if ob.type!='MESH':
# continue
# me = ob.data
matrix = global_matrix * ob.matrix_world
faces_verts = [f.vertices[:] for f in me_faces]
faces_normals = [f.normal[:] for f in me_faces]
verts_normals = [v.normal[:] for v in me.vertices]
quadCount = sum(1 for f in faces_verts if len(f) == 4)
# Use named declaration to allow reference e.g. for baking. MR
tabWrite('#declare %s =\n' % name)
Constantin Rahn
committed
tabWrite('mesh2 {\n')
tabWrite('vertex_vectors {\n')
tabWrite('%s' % (len(me.vertices))) # vert count
Constantin Rahn
committed
file.write(',\n')
tabWrite('<%.6f, %.6f, %.6f>' % v.co[:]) # vert count
Constantin Rahn
committed
tabWrite('}\n')
fv = faces_verts[fi]
# [-1] is a dummy index, use a list so we can modify in place
if f.use_smooth: # Use vertex normals
for v in fv:
key = verts_normals[v]
uniqueNormals[key] = [-1]
Constantin Rahn
committed
tabWrite('normal_vectors {\n')
tabWrite('%d' % len(uniqueNormals)) # vert count
Constantin Rahn
committed
file.write(',\n')
tabWrite('<%.6f, %.6f, %.6f>' % no) # vert count
Constantin Rahn
committed
tabWrite('}\n')
vertCols = {} # Use for material colours also.
if uv_layer:
# Generate unique UV's
uniqueUVs = {}
for fi, uv in enumerate(uv_layer):
if len(faces_verts[fi]) == 4:
uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
else:
uvs = uv.uv1, uv.uv2, uv.uv3
for uv in uvs:
Constantin Rahn
committed
tabWrite('uv_vectors {\n')
tabWrite('%s' % (len(uniqueUVs))) # vert count
Constantin Rahn
committed
file.write(',\n')
tabWrite('<%.6f, %.6f>' % uv)
index[0] = idx
idx += 1
'''
else:
# Just add 1 dummy vector, no real UV's
Constantin Rahn
committed
tabWrite('1') # vert count
Constantin Rahn
committed
tabWrite('}\n')
material_index = f.material_index
material = me_materials[material_index]
if material and material.use_vertex_color_paint:
col = vcol_layer[fi]
if len(faces_verts[fi]) == 4:
cols = col.color1, col.color2, col.color3, col.color4
else:
cols = col.color1, col.color2, col.color3
for col in cols:
key = col[0], col[1], col[2], material_index # Material index!
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], material_index
vertCols[key] = [-1]
else:
# No vertex colours, so write material colours as vertex colours
for i, material in enumerate(me_materials):
if material:
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat
Constantin Rahn
committed
tabWrite('texture_list {\n')
tabWrite('%s' % (len(vertCols))) # vert count
for col, index in vertCols.items():
if me_materials:
material = me_materials[col[3]]
material_finish = materialNames[material.name]
Maurice Raybaud
committed
if material.use_transparency:
trans = 1.0 - material.alpha
material_finish = DEF_MAT_NAME # not working properly,
texturesDif = ""
texturesSpec = ""
texturesNorm = ""
texturesAlpha = ""
if t and t.texture.type == 'IMAGE' and t.use and t.texture.image:
image_filename = path_image(t.texture.image.filepath)
if t.use_map_color_diffuse:
texturesDif = image_filename
colvalue = t.default_value
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
t_spec = t
texturesNorm = image_filename
colvalue = t.normal_factor * 10.0
#textNormName=t.texture.image.name + '.normal'
#was the above used? --MR
t_nor = t
texturesAlpha = image_filename
colvalue = t.alpha_factor * 10.0
#textDispName=t.texture.image.name + '.displ'
#was the above used? --MR
t_alpha = t
##############################################################################################################
Constantin Rahn
committed
tabWrite('\n')
tabWrite('texture {\n') # THIS AREA NEEDS TO LEAVE THE TEXTURE OPEN UNTIL ALL MAPS ARE WRITTEN DOWN. --MR
##############################################################################################################
if material.diffuse_shader == 'MINNAERT':
Constantin Rahn
committed
tabWrite('\n')
tabWrite('aoi\n')
tabWrite('texture_map {\n')
tabWrite('[%.3g finish {diffuse %.3g}]\n' % (material.darkness / 2.0, 2.0 - material.darkness))
tabWrite("[%.3g" % (1.0 - (material.darkness / 2.0)))
######TO OPTIMIZE? or present a more elegant way? At least make it work!##################################################################
#If Fresnel gets removed from 2.5, why bother?
if material.diffuse_shader == 'FRESNEL':
######END of part TO OPTIMIZE? or present a more elegant way?##################################################################
## #lampLocation=lamp.position
## lampRotation=
## a=lamp.Rotation[0]
## b=lamp.Rotation[1]
## c=lamp.Rotation[2]
## lampLookAt=tuple (x,y,z)
## lampLookAt[3]= 0.0 #Put 'target' of the lamp on the floor plane to elimianate one unknown value
## degrees(atan((lampLocation - lampLookAt).y/(lampLocation - lampLookAt).z))=lamp.rotation[0]
## degrees(atan((lampLocation - lampLookAt).z/(lampLocation - lampLookAt).x))=lamp.rotation[1]
## degrees(atan((lampLocation - lampLookAt).x/(lampLocation - lampLookAt).y))=lamp.rotation[2]
## degrees(atan((lampLocation - lampLookAt).y/(lampLocation.z))=lamp.rotation[0]
## degrees(atan((lampLocation.z/(lampLocation - lampLookAt).x))=lamp.rotation[1]
## degrees(atan((lampLocation - lampLookAt).x/(lampLocation - lampLookAt).y))=lamp.rotation[2]
#color = tuple([c * lamp.energy for c in lamp.color]) # Colour is modified by energy
Constantin Rahn
committed
tabWrite('\n')
tabWrite('slope { lampTarget }\n')
tabWrite('texture_map {\n')
tabWrite('[%.3g finish {diffuse %.3g}]\n' % (material.diffuse_fresnel / 2, 2.0 - material.diffuse_fresnel_factor))
tabWrite("[%.3g\n" % (1 - (material.diffuse_fresnel / 2.0)))
#if material.diffuse_shader == 'FRESNEL': pigment pattern aoi pigment and texture map above, the rest below as one of its entry
##########################################################################################################################
#special_texture_found = False
#for t in material.texture_slots:
# if t and t.texture.type == 'IMAGE' and t.use and t.texture.image 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:
if texturesSpec != "" or texturesAlpha != "" or texturesNorm != "":
if texturesSpec != "":
# tabWrite('\n')
tabWrite('pigment_pattern {\n')
Maurice Raybaud
committed
# POV-Ray "scale" is not a number of repetitions factor, but its inverse, a standard scale factor.
# Offset seems needed relatively to scale so probably center of the scale is not the same in blender and POV
mappingSpec = "translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>\n" % (-t_spec.offset.x, t_spec.offset.y, t_spec.offset.z, 1.0 / t_spec.scale.x, 1.0 / t_spec.scale.y, 1.0 / t_spec.scale.z)
tabWrite("uv_mapping image_map{%s \"%s\" %s}\n" % (imageFormat(texturesSpec), texturesSpec, imgMap(t_spec)))
tabWrite('%s\n' % mappingSpec)
Constantin Rahn
committed
tabWrite('}\n')
tabWrite('texture_map {\n')
tabWrite('[0 \n')
if texturesDif == '':
tabWrite('\n')
# POV-Ray "scale" is not a number of repetitions factor, but its inverse, a standard scale factor.
# Offset seems needed relatively to scale so probably center of the scale is not the same in blender and POV
mappingAlpha = " translate <%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>\n" % (-t_alpha.offset.x, t_alpha.offset.y, t_alpha.offset.z, 1.0 / t_alpha.scale.x, 1.0 / t_alpha.scale.y, 1.0 / t_alpha.scale.z)
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], 1.0 - material.alpha, trans))
tabWrite('}\n')
tabWrite('}\n')
tabWrite('pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>}\n' % (col[0], col[1], col[2], 1.0 - material.alpha, trans))
if texturesSpec != "":
tabWrite('finish {%s}\n' % (safety(material_finish, Level=1))) # Level 1 is no specular