Newer
Older
# 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)
tabWrite("#declare camLocation = <%.6f, %.6f, %.6f>;\n" %
matrix.translation[:])
tabWrite("#declare camLookAt = <%.6f, %.6f, %.6f>;\n" %
Bastien Montagne
committed
tuple([degrees(e) for e in matrix.to_3x3().to_euler()]))
tabWrite("camera {\n")
Bastien Montagne
committed
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
tabWrite("mesh{%s}\n" % active_object.name)
tabWrite("}\n")
tabWrite("location <0,0,.01>")
tabWrite("direction <0,0,-1>")
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))
Bastien Montagne
committed
tabWrite("rotate <%.6f, %.6f, %.6f>\n" % \
tuple([degrees(e) for e in matrix.to_3x3().to_euler()]))
tabWrite("translate <%.6f, %.6f, %.6f>\n" % matrix.translation[:])
Bastien Montagne
committed
if camera.data.pov.dof_enable and focal_point != 0:
tabWrite("aperture %.3g\n" % camera.data.pov.dof_aperture)
tabWrite("blur_samples %d %d\n" % \
(camera.data.pov.dof_samples_min, camera.data.pov.dof_samples_max))
tabWrite("variance 1/%d\n" % camera.data.pov.dof_variance)
tabWrite("confidence %.3g\n" % camera.data.pov.dof_confidence)
tabWrite("focal_point <0, 0, %f>\n" % focal_point)
tabWrite("}\n")
# Incremented after each lamp export to declare its target
# currently used for Fresnel diffuse shader as their slope vector:
global lampCount
lampCount = 0
# Get all lamps
for ob in lamps:
lamp = ob.data
matrix = global_matrix * ob.matrix_world
# Color is modified by energy #muiltiplie by 2 for a better match --Maurice
Bastien Montagne
committed
color = tuple([c * lamp.energy * 2.0 for c in lamp.color])
tabWrite("light_source {\n")
tabWrite("< 0,0,0 >\n")
tabWrite("color rgb<%.3g, %.3g, %.3g>\n" % color)
tabWrite("spotlight\n")
tabWrite("falloff %.2f\n" % (degrees(lamp.spot_size) / 2.0)) # 1 TO 179 FOR BOTH
Bastien Montagne
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
tabWrite("point_at <0, 0, -1>\n")
tabWrite("parallel\n")
tabWrite("point_at <0, 0, -1>\n") # *must* be after 'parallel'
tabWrite("area_illumination\n")
tabWrite("fade_distance %.6f\n" % (lamp.distance / 2.0))
Bastien Montagne
committed
# Area lights have no falloff type, so always use blenders lamp quad equivalent
# for those?
tabWrite("fade_power %d\n" % 2)
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
Maurice Raybaud
committed
tabWrite("area_light <%.6f,0,0>,<0,%.6f,0> %d, %d\n" % \
(size_x, size_y, samples_x, samples_y))
Maurice Raybaud
committed
if lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
if lamp.use_jitter:
tabWrite("jitter\n")
tabWrite("adaptive 1\n")
tabWrite("jitter\n")
Bastien Montagne
committed
# HEMI never has any shadow_method attribute
if(not scene.render.use_shadows or lamp.type == 'HEMI' or
(lamp.type != 'HEMI' and lamp.shadow_method == 'NOSHADOW')):
tabWrite("shadowless\n")
Bastien Montagne
committed
# 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.
if lamp.type not in {'SUN', 'AREA', 'HEMI'}:
tabWrite("fade_distance %.6f\n" % (lamp.distance / 2.0))
tabWrite("fade_power %d\n" % 2) # Use blenders lamp quad equivalent
tabWrite("fade_power %d\n" % 1) # Use blenders lamp linear
Maurice Raybaud
committed
# supposing using no fade power keyword would default to constant, no attenuation.
Bastien Montagne
committed
elif lamp.falloff_type == 'CONSTANT':
Bastien Montagne
committed
# Using Custom curve for fade power 3 for now.
elif lamp.falloff_type == 'CUSTOM_CURVE':
tabWrite("fade_power %d\n" % 4)
tabWrite("}\n")
lampCount += 1
# v(A,B) rotates vector A about origin by vector B.
Bastien Montagne
committed
file.write("#declare lampTarget%s= vrotate(<%.4g,%.4g,%.4g>,<%.4g,%.4g,%.4g>);\n" % \
(lampCount, -(ob.location.x), -(ob.location.y), -(ob.location.z),
ob.rotation_euler.x, ob.rotation_euler.y, ob.rotation_euler.z))
Bastien Montagne
committed
####################################################################################################
def exportMeta(metas):
# TODO - blenders 'motherball' naming is not supported.
if comments 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'}]
tabWrite("blob {\n")
tabWrite("threshold %.4g\n" % meta.threshold)
Bastien Montagne
committed
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
if elem.type == 'BALL':
Bastien Montagne
committed
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
Bastien Montagne
committed
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
trans = 1.0 - material.alpha
if material.use_transparency and material.transparency_method == 'RAYTRACE':
povFilter = material.raytrace_transparency.filter * (1.0 - material.alpha)
trans = (1.0 - material.alpha) - povFilter
material_finish = materialNames[material.name]
Bastien Montagne
committed
tabWrite("pigment {rgbft<%.3g, %.3g, %.3g, %.3g, %.3g>} \n" % \
(diffuse_color[0], diffuse_color[1], diffuse_color[2],
povFilter, trans))
tabWrite("finish {%s}\n" % safety(material_finish, Level=2))
tabWrite("pigment {rgb<1 1 1>} \n")
Bastien Montagne
committed
# Write the finish last.
tabWrite("finish {%s}\n" % (safety(DEF_MAT_NAME, Level=2)))
writeObjectMaterial(material, ob)
writeMatrix(global_matrix * ob.matrix_world)
Maurice Raybaud
committed
# Importance for radiosity sampling added here
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
tabWrite("}\n") # End of Metaball block
if comments and len(metas) >= 1:
file.write("\n")
Bastien Montagne
committed
# objectNames = {}
DEF_OBJ_NAME = "Default"
Bastien Montagne
committed
def exportMeshes(scene, sel):
# obmatslist = []
# def hasUniqueMaterial():
# # Grab materials attached to object instances ...
# if hasattr(ob, 'material_slots'):
# for ms in ob.material_slots:
# if ms.material is not None and ms.link == 'OBJECT':
Bastien Montagne
committed
# if ms.material in obmatslist:
# return False
# else:
# obmatslist.append(ms.material)
# return True
# def hasObjectMaterial(ob):
# # Grab materials attached to object instances ...
# if hasattr(ob, 'material_slots'):
# for ms in ob.material_slots:
# if ms.material is not None and ms.link == 'OBJECT':
Bastien Montagne
committed
# # If there is at least one material slot linked to the object
Bastien Montagne
committed
# # and not the data (mesh), always create a new, "private" data instance.
Bastien Montagne
committed
# return True
# return False
# For objects using local material(s) only!
# This is a mapping between a tuple (dataname, materialnames, ...), and the POV dataname.
Bastien Montagne
committed
# As only objects using:
# * The same data.
# * EXACTLY the same materials, in EXACTLY the same sockets.
# ... can share a same instance in POV export.
Bastien Montagne
committed
obmats2data = {}
Bastien Montagne
committed
def checkObjectMaterials(ob, name, dataname):
if hasattr(ob, 'material_slots'):
has_local_mats = False
key = [dataname]
for ms in ob.material_slots:
Bastien Montagne
committed
key.append(ms.material.name)
if ms.link == 'OBJECT' and not has_local_mats:
has_local_mats = True
else:
# Even if the slot is empty, it is important to grab it...
Bastien Montagne
committed
key.append("")
if has_local_mats:
# If this object uses local material(s), lets find if another object
# using the same data and exactly the same list of materials
# (in the same slots) has already been processed...
Bastien Montagne
committed
# Note that here also, we use object name as new, unique dataname for Pov.
key = tuple(key) # Lists are not hashable...
Bastien Montagne
committed
if key not in obmats2data:
obmats2data[key] = name
return obmats2data[key]
return None
data_ref = {}
Bastien Montagne
committed
def store(scene, ob, name, dataname, matrix):
# The Object needs to be written at least once but if its data is
# already in data_ref this has already been done.
Bastien Montagne
committed
# This func returns the "povray" name of the data, or None
Bastien Montagne
committed
# if no writing is needed.
if ob.is_modified(scene, 'RENDER'):
# Data modified.
# Create unique entry in data_ref by using object name
# (always unique in Blender) as data name.
data_ref[name] = [(name, MatrixAsPovString(matrix))]
return name
# Here, we replace dataname by the value returned by checkObjectMaterials, only if
# it is not evaluated to False (i.e. only if the object uses some local material(s)).
dataname = checkObjectMaterials(ob, name, dataname) or dataname
if dataname in data_ref:
# Data already known, just add the object instance.
data_ref[dataname].append((name, MatrixAsPovString(matrix)))
# No need to write data
return None
else:
# Data not yet processed, create a new entry in data_ref.
data_ref[dataname] = [(name, MatrixAsPovString(matrix))]
return dataname
Bastien Montagne
committed
ob_num = 0
Bastien Montagne
committed
# XXX I moved all those checks here, as there is no need to compute names
Bastien Montagne
committed
# for object we won't export here!
if ob.type in {'LAMP', 'CAMERA', 'EMPTY', 'META', 'ARMATURE', 'LATTICE'}:
for pSys in ob.particle_systems:
if pSys.settings.use_render_emitter:
renderEmitter = True
for mod in [m for m in ob.modifiers if (m is not None) and (m.type == 'PARTICLE_SYSTEM')]:
if (pSys.settings.render_type == 'PATH') and mod.show_render and (pSys.name == mod.particle_system.name):
tstart = time.time()
if ob.active_material is not None:
pmaterial = ob.active_material
if pmaterial.strand.use_blender_units:
strandStart = pmaterial.strand.root_size
strandEnd = pmaterial.strand.tip_size
strandStart = pmaterial.strand.root_size / 200.0
strandEnd = pmaterial.strand.tip_size / 200.0
strandShape = pmaterial.strand.shape
else:
pmaterial = "default" # No material assigned in blender, use default one
strandStart = 0.01
strandEnd = 0.01
strandShape = 0.0
# Set the number of particles to render count rather than 3d view display
pSys.set_resolution(scene, ob, 'RENDER')
steps = pSys.settings.draw_step
steps = 3 ** steps # or (power of 2 rather than 3) + 1 # Formerly : len(particle.hair_keys)
totalNumberOfHairs = ( len(pSys.particles) + len(pSys.child_particles) )
#hairCounter = 0
file.write('#declare HairArray = array[%i] {\n' % totalNumberOfHairs)
for pindex in range(0, totalNumberOfHairs):
#if particle.is_exist and particle.is_visible:
#hairCounter += 1
#controlPointCounter = 0
# Each hair is represented as a separate sphere_sweep in POV-Ray.
file.write('sphere_sweep{')
if pSys.settings.use_hair_bspline:
file.write('b_spline ')
file.write('%i,\n' % (steps + 2)) # +2 because the first point needs tripling to be more than a handle in POV
else:
file.write('linear_spline ')
file.write('%i,\n' % (steps))
for step in range(0, steps):
if pSys.settings.clump_factor != 0:
hDiameter = pSys.settings.clump_factor / 200.0 * random.uniform(0.5, 1)
hDiameter = strandStart
else:
hDiameter += (strandEnd-strandStart)/(pSys.settings.draw_step+1) #XXX +1 or not?
if step == 0 and pSys.settings.use_hair_bspline:
# Write three times the first point to compensate pov Bezier handling
file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter)))
file.write('<%.6g,%.6g,%.6g>,%.7g,\n' % (co[0], co[1], co[2], abs(hDiameter)))
Campbell Barton
committed
#file.write('<%.6g,%.6g,%.6g>,%.7g' % (particle.location[0], particle.location[1], particle.location[2], abs(hDiameter))) # Useless because particle location is the tip, not the root.
#totalNumberOfHairs += len(pSys.particles)# len(particle.hair_keys)
# Each control point is written out, along with the radius of the
# hair at that point.
file.write('<%.6g,%.6g,%.6g>,%.7g' % (co[0], co[1], co[2], abs(hDiameter)))
# All coordinates except the last need a following comma.
file.write(',\n')
else:
# End the sphere_sweep declaration for this hair
file.write('}\n')
# All but the final sphere_sweep (each array element) needs a terminating comma.
file.write(',\n')
else:
file.write('\n')
# End the array declaration.
file.write('}\n')
file.write('\n')
# Pick up the hair color and create a default POV-Ray hair texture.
file.write('#ifndef (HairTexture)\n')
file.write(' #declare HairTexture = texture {\n')
file.write(' pigment {rgbt <%s,%s,%s,%s>}\n' % (pmaterial.diffuse_color[0], pmaterial.diffuse_color[1], pmaterial.diffuse_color[2], (pmaterial.strand.width_fade + 0.05)))
file.write(' }\n')
file.write('#end\n')
file.write('\n')
# Dynamically create a union of the hairstrands (or a subset of them).
# By default use every hairstrand, commented line is for hand tweaking test renders.
file.write('//Increasing HairStep divides the amount of hair for test renders.\n')
file.write('#ifndef(HairStep) #declare HairStep = 1; #end\n')
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
file.write('union{\n')
file.write(' #local I = 0;\n')
file.write(' #while (I < %i)\n' % totalNumberOfHairs)
file.write(' object {HairArray[I] texture{HairTexture}\n')
# Translucency of the hair:
file.write(' hollow\n')
file.write(' double_illuminate\n')
file.write(' interior {\n')
file.write(' ior 1.45\n')
file.write(' media {\n')
file.write(' scattering { 1, 10*<0.73, 0.35, 0.15> /*extinction 0*/ }\n')
file.write(' absorption 10/<0.83, 0.75, 0.15>\n')
file.write(' samples 1\n')
file.write(' method 2\n')
file.write(' density {\n')
file.write(' color_map {\n')
file.write(' [0.0 rgb <0.83, 0.45, 0.35>]\n')
file.write(' [0.5 rgb <0.8, 0.8, 0.4>]\n')
file.write(' [1.0 rgb <1,1,1>]\n')
file.write(' }\n')
file.write(' }\n')
file.write(' }\n')
file.write(' }\n')
file.write(' }\n')
file.write(' #local I = I + HairStep;\n')
file.write(' #end\n')
writeMatrix(global_matrix * ob.matrix_world)
file.write('}')
print('Totals hairstrands written: %i' % totalNumberOfHairs)
print('Number of tufts (particle systems)', len(ob.particle_systems))
# Set back the displayed number of particles to preview count
pSys.set_resolution(scene, ob, 'PREVIEW')
if renderEmitter == False:
continue #don't render mesh, skip to next object.
except:
# happens when curves cant be made into meshes because of no-data
continue
Bastien Montagne
committed
importance = ob.pov.importance_value
me_faces = me.tessfaces[:]
Bastien Montagne
committed
#############################################
# Generating a name for object just like materials to be able to use it
# (baking for now or anything else).
Bastien Montagne
committed
# XXX I don't understand that: if we are here, sel if a non-empty iterable,
Bastien Montagne
committed
# so this condition is always True, IMO -- mont29
if sel:
name_orig = "OB" + ob.name
dataname_orig = "DATA" + ob.data.name
else:
name_orig = DEF_OBJ_NAME
dataname_orig = DEF_OBJ_NAME
name = string_strip_hyphen(bpy.path.clean_name(name_orig))
dataname = string_strip_hyphen(bpy.path.clean_name(dataname_orig))
Bastien Montagne
committed
## for slot in ob.material_slots:
## if slot.material is not None and slot.link == 'OBJECT':
Bastien Montagne
committed
## obmaterial = slot.material
#############################################
info_callback("Object %2.d of %2.d (%s)" % (ob_num, len(sel), ob.name))
#if ob.type != 'MESH':
# continue
matrix = global_matrix * ob.matrix_world
Bastien Montagne
committed
povdataname = store(scene, ob, name, dataname, matrix)
if povdataname is None:
print("This is an instance")
continue
print("Writing Down First Occurence")
uv_textures = me.tessface_uv_textures
if len(uv_textures) > 0:
if me.uv_textures.active and uv_textures.active.data:
uv_layer = uv_textures.active.data
else:
#vcol_layer = me.vertex_colors.active.data
vcol_layer = me.tessface_vertex_colors.active.data
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
file.write("\n")
Bastien Montagne
committed
tabWrite("#declare %s =\n" % povdataname)
tabWrite("mesh2 {\n")
tabWrite("vertex_vectors {\n")
tabWrite("%d" % len(me.vertices)) # vert count
Constantin Rahn
committed
tabStr = tab * tabLevel
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
else:
file.write(", ")
file.write("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
Constantin Rahn
committed
#tabWrite("<%.6f, %.6f, %.6f>" % v.co[:]) # vert count
file.write("\n")
tabWrite("}\n")
for fi, f in enumerate(me_faces):
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]
key = faces_normals[fi]
uniqueNormals[key] = [-1]
tabWrite("normal_vectors {\n")
tabWrite("%d" % len(uniqueNormals)) # vert count
Constantin Rahn
committed
tabStr = tab * tabLevel
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f, %.6f>" % no) # vert count
else:
file.write(", ")
file.write("<%.6f, %.6f, %.6f>" % no) # vert count
file.write("\n")
tabWrite("}\n")
# Vertex colors
vertCols = {} # Use for material colors also.
if uv_layer:
# Generate unique UV's
uniqueUVs = {}
#n = 0
for fi, uv in enumerate(uv_layer):
if len(faces_verts[fi]) == 4:
uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2], uv_layer[fi].uv[3]
uvs = uv_layer[fi].uv[0], uv_layer[fi].uv[1], uv_layer[fi].uv[2]
tabWrite("uv_vectors {\n")
tabWrite("%d" % len(uniqueUVs)) # vert count
Constantin Rahn
committed
tabStr = tab * tabLevel
file.write(",\n")
file.write(tabStr + "<%.6f, %.6f>" % uv)
else:
file.write(", ")
file.write("<%.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
file.write("\n")
tabWrite("}\n")
#Write down vertex colors as a texture for each vertex
tabWrite("texture_list {\n")
tabWrite("%d\n" % (((len(me_faces)-quadCount) * 3 )+ quadCount * 4)) # works only with tris and quad mesh for now
VcolIdx=0
if comments:
file.write("\n //Vertex colors: one simple pigment texture per vertex\n")
for fi, f in enumerate(me_faces):
# annoying, index may be invalid
try:
material = me_materials[material_index]
except:
material = None
if material: #and material.use_vertex_color_paint: #Always use vertex color when there is some for now
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!
VcolIdx+=1
vertCols[key] = [VcolIdx]
if linebreaksinlists:
tabWrite("texture {pigment{ color rgb <%6f,%6f,%6f> }}\n" % (col[0], col[1], col[2]))
else:
tabWrite("texture {pigment{ color rgb <%6f,%6f,%6f> }}" % (col[0], col[1], col[2]))
tabStr = tab * tabLevel
Maurice Raybaud
committed
# Multiply diffuse with SSS Color
if material.subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
Maurice Raybaud
committed
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \
material_index
vertCols[key] = [-1]
else:
diffuse_color = material.diffuse_color[:]
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], \
material_index
vertCols[key] = [-1]
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
tabWrite("\n}\n")
# Face indices
tabWrite("\nface_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, f in enumerate(me_faces):
fv = faces_verts[fi]
material_index = f.material_index
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
if vcol_layer:
col = vcol_layer[fi]
if len(fv) == 4:
cols = col.color1, col.color2, col.color3, col.color4
else:
cols = col.color1, col.color2, col.color3
if not me_materials or me_materials[material_index] is None: # No materials
for i1, i2, i3 in indices:
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
file.write(",\n")
# vert count
file.write(tabStr + "<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3]))
else:
file.write(", ")
file.write("<%d,%d,%d>" % (fv[i1], fv[i2], fv[i3])) # vert count
else:
material = me_materials[material_index]
for i1, i2, i3 in indices:
if me.vertex_colors: #and material.use_vertex_color_paint:
# Color per vertex - vertex color
col1 = cols[i1]
col2 = cols[i2]
col3 = cols[i3]
ci1 = vertCols[col1[0], col1[1], col1[2], material_index][0]
ci2 = vertCols[col2[0], col2[1], col2[2], material_index][0]
ci3 = vertCols[col3[0], col3[1], col3[2], material_index][0]
else:
# Color per material - flat material color
if material.subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
else:
diffuse_color = material.diffuse_color[:]
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], \
diffuse_color[2], f.material_index][0]
# ci are zero based index so we'll subtract 1 from them
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>, %d,%d,%d" % \
(fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>, %d,%d,%d" % \
(fv[i1], fv[i2], fv[i3], ci1-1, ci2-1, ci3-1)) # vert count
file.write("\n")
tabWrite("}\n")
# normal_indices indices
tabWrite("normal_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
for i1, i2, i3 in indices:
if me_faces[fi].use_smooth:
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[i1]]][0],\
uniqueNormals[verts_normals[fv[i2]]][0],\
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>" %\
(uniqueNormals[verts_normals[fv[i1]]][0],\
uniqueNormals[verts_normals[fv[i2]]][0],\
uniqueNormals[verts_normals[fv[i3]]][0])) # vert count
else:
idx = uniqueNormals[faces_normals[fi]][0]
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (idx, idx, idx)) # vert count
else:
file.write(", ")
file.write("<%d,%d,%d>" % (idx, idx, idx)) # vert count
file.write("\n")
tabWrite("}\n")
if uv_layer:
tabWrite("uv_indices {\n")
tabWrite("%d" % (len(me_faces) + quadCount)) # faces count
tabStr = tab * tabLevel
for fi, fv in enumerate(faces_verts):
if len(fv) == 4:
indices = (0, 1, 2), (0, 2, 3)
else:
indices = ((0, 1, 2),)
uv = uv_layer[fi]
if len(faces_verts[fi]) == 4:
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:], uv.uv[3][:]
else:
uvs = uv.uv[0][:], uv.uv[1][:], uv.uv[2][:]
for i1, i2, i3 in indices:
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
file.write(",\n")
file.write(tabStr + "<%d,%d,%d>" % (
uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
uniqueUVs[uvs[i3]][0]))
else:
file.write(", ")
file.write("<%d,%d,%d>" % (
uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
uniqueUVs[uvs[i3]][0]))
file.write("\n")
tabWrite("}\n")
if me.materials:
try:
material = me.materials[0] # dodgy
writeObjectMaterial(material, ob)
except IndexError:
print(me)
#Importance for radiosity sampling added here:
tabWrite("radiosity { \n")
tabWrite("importance %3g \n" % importance)
tabWrite("}\n")
tabWrite("}\n") # End of mesh block
# No vertex colors, so write material colors as vertex colors
for i, material in enumerate(me_materials):
if material:
Maurice Raybaud
committed
# Multiply diffuse with SSS Color
if material.subsurface_scattering.use:
diffuse_color = [i * j for i, j in zip(material.subsurface_scattering.color[:], material.diffuse_color[:])]
Maurice Raybaud
committed
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat
vertCols[key] = [-1]
else:
diffuse_color = material.diffuse_color[:]
key = diffuse_color[0], diffuse_color[1], diffuse_color[2], i # i == f.mat
vertCols[key] = [-1]
Maurice Raybaud
committed
idx = 0
LocalMaterialNames = []
Maurice Raybaud
committed
for col, index in vertCols.items():
#if me_materials:
mater = me_materials[col[3]]
Maurice Raybaud
committed
material_finish = DEF_MAT_NAME # not working properly,
trans = 0.0
Maurice Raybaud
committed
else:
material_finish = materialNames[mater.name]
if mater.use_transparency:
trans = 1.0 - mater.alpha
Maurice Raybaud
committed
else:
trans = 0.0
if (mater.specular_color.s == 0.0):
Maurice Raybaud
committed
colored_specular_found = False
else:
colored_specular_found = True
if mater.use_transparency and mater.transparency_method == 'RAYTRACE':
povFilter = mater.raytrace_transparency.filter * (1.0 - mater.alpha)
trans = (1.0 - mater.alpha) - povFilter
Maurice Raybaud
committed
else:
povFilter = 0.0
##############SF
texturesDif = ""
texturesSpec = ""
texturesNorm = ""
texturesAlpha = ""
#proceduralFlag=False
for t in mater.texture_slots:
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
if t and t.use and t.texture.type != 'IMAGE' and t.texture.type != 'NONE':
proceduralFlag=True
image_filename = "PAT_%s"%string_strip_hyphen(bpy.path.clean_name(t.texture.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.0 # UNUSED
#textNormName=t.texture.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=t.texture.image.name + ".displ"
#was the above used? --MR
t_alpha = t
if t and t.texture.type == 'IMAGE' and t.use and t.texture.image and t.texture.pov.tex_pattern_type == 'emulator':
proceduralFlag=False
if t.texture.image.packed_file:
orig_image_filename=t.texture.image.filepath_raw
workDir=os.path.dirname(__file__)
previewDir=os.path.join(workDir, "preview")
unpackedfilename= os.path.join(previewDir,("unpacked_img_"+(string_strip_hyphen(bpy.path.clean_name(t.texture.name)))))
if not os.path.exists(unpackedfilename):
# record which images that were newly copied and can be safely
# cleaned up
unpacked_images.append(unpackedfilename)
t.texture.image.filepath_raw=unpackedfilename
t.texture.image.save()
image_filename = unpackedfilename
t.texture.image.filepath_raw=orig_image_filename
else:
image_filename = path_image(t.texture.image)
Maurice Raybaud
committed
# IMAGE SEQUENCE BEGINS
if image_filename:
if bpy.data.images[t.texture.image.name].source == 'SEQUENCE':
korvaa = "." + str(bpy.data.textures[t.texture.name].image_user.frame_offset + 1).zfill(3) + "."
image_filename = image_filename.replace(".001.", korvaa)
print(" seq debug ")
print(image_filename)
# IMAGE SEQUENCE ENDS
Maurice Raybaud
committed
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
imgGamma = ""
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.0 # UNUSED
#textNormName=t.texture.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=t.texture.image.name + ".displ"
#was the above used? --MR
t_alpha = t
####################################################################################
file.write("\n")
# THIS AREA NEEDS TO LEAVE THE TEXTURE OPEN UNTIL ALL MAPS ARE WRITTEN DOWN.
# --MR
currentMatName = string_strip_hyphen(materialNames[mater.name])
Maurice Raybaud
committed
LocalMaterialNames.append(currentMatName)
file.write("\n #declare MAT_%s = \ntexture{\n" % currentMatName)
################################################################################
if mater.pov.replacement_text != "":
file.write("%s\n" % mater.pov.replacement_text)
#################################################################################
if mater.diffuse_shader == 'MINNAERT':
Maurice Raybaud
committed
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)))
Maurice Raybaud
committed
if mater.diffuse_shader == 'FRESNEL':
Maurice Raybaud
committed
# 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)))
Maurice Raybaud
committed
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")
if texturesSpec and texturesSpec.startswith("PAT_"):
tabWrite("function{f%s(x,y,z).grey}" %texturesSpec)
else:
# 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)
Maurice Raybaud
committed
tabWrite("}\n")
tabWrite("texture_map {\n")
tabWrite("[0 \n")
if texturesDif == "":
if texturesAlpha != "":
tabWrite("\n")
if texturesAlpha and texturesAlpha.startswith("PAT_"):