Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
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:
# Colour per material - flat material colour
diffuse_color = material.diffuse_color
ci1 = ci2 = ci3 = vertCols[diffuse_color[0], diffuse_color[1], diffuse_color[2], f.material_index][0]
file.write(',\n\t\t<%d,%d,%d>, %d,%d,%d' % (fv[i1], fv[i2], fv[i3], ci1, ci2, ci3)) # vert count
file.write('\n }\n')
# normal_indices indicies
file.write('\tnormal_indices {\n')
file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
for fi, fv in enumerate(faces_verts):
if len(fv) == 4:
indicies = (0, 1, 2), (0, 2, 3)
else:
indicies = ((0, 1, 2),)
for i1, i2, i3 in indicies:
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
file.write(',\n\t\t<%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]
file.write(',\n\t\t<%d,%d,%d>' % (idx, idx, idx)) # vert count
file.write('\n }\n')
if uv_layer:
file.write('\tuv_indices {\n')
file.write('\t\t%d' % (len(me.faces) + quadCount)) # faces count
for fi, fv in enumerate(faces_verts):
if len(fv) == 4:
indicies = (0, 1, 2), (0, 2, 3)
else:
indicies = ((0, 1, 2),)
uv = uv_layer[fi]
if len(faces_verts[fi]) == 4:
uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3), tuple(uv.uv4)
else:
uvs = tuple(uv.uv1), tuple(uv.uv2), tuple(uv.uv3)
for i1, i2, i3 in indicies:
file.write(',\n\t\t<%d,%d,%d>' %\
(uniqueUVs[uvs[i1]][0],\
uniqueUVs[uvs[i2]][0],\
try:
material = me.materials[0] # dodgy
writeObjectMaterial(material)
except IndexError:
print(me)
Maurice Raybaud
committed
file.write('%s\n' % name) # Use named declaration to allow reference e.g. for baking. MR
bpy.data.meshes.remove(me)
def exportWorld(world):
render = scene.render
camera = scene.camera
matrix = camera.matrix_world
#############Maurice####################################
#These lines added to get sky gradient (visible with PNG output)
if world:
#For simple flat background:
if not world.use_sky_blend:
#Non fully transparent background could premultiply alpha and avoid anti-aliasing display issue:
if render.alpha_mode == 'PREMUL' or render.alpha_mode == 'PREMUL' :
file.write('background {rgbt<%.3g, %.3g, %.3g, 0.75>}\n' % (tuple(world.horizon_color)))
#Currently using no alpha with Sky option:
elif render.alpha_mode == 'SKY':
file.write('background {rgbt<%.3g, %.3g, %.3g, 0>}\n' % (tuple(world.horizon_color)))
#StraightAlpha:
else:
file.write('background {rgbt<%.3g, %.3g, %.3g, 1>}\n' % (tuple(world.horizon_color)))
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
#For Background image textures
for t in world.texture_slots: #risk to write several sky_spheres but maybe ok.
if t and t.texture.type == 'IMAGE': #and t.use: #No enable checkbox for world textures yet (report it?)
image_filename = path_image(t.texture.image.filepath)
if t.texture.image.filepath != image_filename: t.texture.image.filepath = image_filename
if image_filename != '' and t.use_map_blend:
texturesBlend = image_filename
#colvalue = t.default_value
t_blend = t
#commented below was an idea to make the Background image oriented as camera taken here: http://news.povray.org/povray.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.povray.org%3E/
#mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees(atan((camLocation - camLookAt).x/(camLocation - camLookAt).y)) rotate x*degrees(atan((camLocation - camLookAt).y/(camLocation - camLookAt).z)) rotate y*degrees(atan((camLocation - camLookAt).z/(camLocation - camLookAt).x)) scale <%.4g,%.4g,%.4g>b" % (t_blend.offset.x / 10 ,t_blend.offset.y / 10 ,t_blend.offset.z / 10, t_blend.scale.x ,t_blend.scale.y ,t_blend.scale.z))#replace 4/3 by the ratio of each image found by some custom or existing function
#using camera rotation valuesdirectly from blender seems much easier
mappingBlend = (" translate <%.4g-0.5,%.4g-0.5,%.4g-0.5> rotate<%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % (t_blend.offset.x / 10 ,t_blend.offset.y / 10 ,t_blend.offset.z / 10, degrees(camera.rotation_euler[0]), degrees(camera.rotation_euler[1]), degrees(camera.rotation_euler[2]), t_blend.scale.x*0.85 , t_blend.scale.y*0.85 , t_blend.scale.z*0.85 ))
#Putting the map on a plane would not introduce the skysphere distortion and allow for better image scale matching but also some waay to chose depth and size of the plane relative to camera.
file.write('sky_sphere {\n')
file.write('\tpigment {\n')
file.write("\t\timage_map{%s \"%s\" %s}\n\t}\n\t%s\n" % (imageFormat(texturesBlend),texturesBlend,imgMapBG(t_blend),mappingBlend))
file.write('}\n')
#file.write('\t\tscale 2\n')
#file.write('\t\ttranslate -1\n')
#For only Background gradient
if not t:
if world.use_sky_blend:
file.write('sky_sphere {\n')
file.write('\tpigment {\n')
file.write('\t\tgradient z\n')#maybe Should follow the advice of POV doc about replacing gradient for skysphere..5.5
file.write('\t\tcolor_map {\n')
if render.alpha_mode == 'STRAIGHT':
file.write('\t\t\t[0.0 rgbt<%.3g, %.3g, %.3g, 1>]\n' % (tuple(world.horizon_color)))
file.write('\t\t\t[1.0 rgbt<%.3g, %.3g, %.3g, 1>]\n' % (tuple(world.zenith_color)))
elif render.alpha_mode == 'PREMUL':
file.write('\t\t\t[0.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n' % (tuple(world.horizon_color)))
file.write('\t\t\t[1.0 rgbt<%.3g, %.3g, %.3g, 0.99>]\n' % (tuple(world.zenith_color))) #aa premult not solved with transmit 1
file.write('\t\t\t[0.0 rgbt<%.3g, %.3g, %.3g, 0>]\n' % (tuple(world.horizon_color)))
file.write('\t\t\t[1.0 rgbt<%.3g, %.3g, %.3g, 0>]\n' % (tuple(world.zenith_color)))
file.write('\t\t}\n')
file.write('\t}\n')
file.write('}\n')
#sky_sphere alpha (transmit) is not translating into image alpha the same way as "background"
scene.pov_radio_enable=1
#Maybe change the above to scene.pov_radio_enable = world.light_settings.use_indirect_light ?
###############################################################
if mist.use_mist:
file.write('fog {\n')
file.write('\tdistance %.6f\n' % mist.depth)
file.write('\tcolor rgbt<%.3g, %.3g, %.3g, %.3g>\n' % (tuple(world.horizon_color) + (1 - mist.intensity,)))
#file.write('\tfog_offset %.6f\n' % mist.start)
#file.write('\tfog_alt 5\n')
#file.write('\tturbulence 0.2\n')
#file.write('\tturb_depth 0.3\n')
file.write('\tfog_type 1\n')
file.write('}\n')
def exportGlobalSettings(scene):
file.write('global_settings {\n')
if scene.pov_radio_enable:
file.write('\tradiosity {\n')
file.write("\t\tadc_bailout %.4g\n" % scene.pov_radio_adc_bailout)
file.write("\t\talways_sample %d\n" % scene.pov_radio_always_sample)
file.write("\t\tbrightness %.4g\n" % scene.pov_radio_brightness)
file.write("\t\tcount %d\n" % scene.pov_radio_count)
file.write("\t\terror_bound %.4g\n" % scene.pov_radio_error_bound)
file.write("\t\tgray_threshold %.4g\n" % scene.pov_radio_gray_threshold)
file.write("\t\tlow_error_factor %.4g\n" % scene.pov_radio_low_error_factor)
file.write("\t\tmedia %d\n" % scene.pov_radio_media)
file.write("\t\tminimum_reuse %.4g\n" % scene.pov_radio_minimum_reuse)
file.write("\t\tnearest_count %d\n" % scene.pov_radio_nearest_count)
file.write("\t\tnormal %d\n" % scene.pov_radio_normal)
file.write("\t\trecursion_limit %d\n" % scene.pov_radio_recursion_limit)
file.write('\t}\n')
once=1
for material in bpy.data.materials:
if material.subsurface_scattering.use and once:
file.write("\tmm_per_unit %.6f\n" % (material.subsurface_scattering.scale * (-100) + 15))#In pov, the scale has reversed influence compared to blender. these number should correct that
once=0 #In povray, the scale factor for all subsurface shaders needs to be the same
file.write("\tambient_light rgb<%.3g, %.3g, %.3g>\n" % tuple(world.ambient_color))
if material.pov_photons_refraction or material.pov_photons_reflection:
file.write("\tphotons {\n")
file.write("\t\tspacing 0.003\n")
file.write("\t\tmax_trace_level 4\n")
file.write("\t\tadc_bailout 0.1\n")
file.write("\t\tgather 30, 150\n")
file.write("\t}\n")
file.write('}\n')
# Convert all materials to strings we can access directly per vertex.
writeMaterial(None) # default material
for material in bpy.data.materials:
writeMaterial(material)
exportLamps([l for l in sel if l.type == 'LAMP'])
exportMeta([l for l in sel if l.type == 'META'])
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
exportWorld(scene.world)
exportGlobalSettings(scene)
file.close()
def write_pov_ini(filename_ini, filename_pov, filename_image):
scene = bpy.data.scenes[0]
render = scene.render
x = int(render.resolution_x * render.resolution_percentage * 0.01)
y = int(render.resolution_y * render.resolution_percentage * 0.01)
file = open(filename_ini, 'w')
file.write('Input_File_Name="%s"\n' % filename_pov)
file.write('Output_File_Name="%s"\n' % filename_image)
file.write('Width=%d\n' % x)
file.write('Height=%d\n' % y)
# Needed for border render.
'''
file.write('Start_Column=%d\n' % part.x)
file.write('End_Column=%d\n' % (part.x+part.w))
file.write('Start_Row=%d\n' % (part.y))
file.write('End_Row=%d\n' % (part.y+part.h))
'''
file.write('Bounding_Method=2\n')#The new automatic BSP is faster in most scenes
file.write('Display=1\n')#Activated (turn this back off when better live exchange is done between the two programs (see next comment)
file.write('Output_File_Type=N\n') # PNG, with POV 3.7, can show background color with alpha. In the long run using the Povray interactive preview like bishop 3D could solve the preview for all formats.
#file.write('Output_File_Type=T\n') # TGA, best progressive loading
aa_mapping = {'5': 2, '8': 3, '11': 4, '16': 5} # method 2 (recursive) with higher max subdiv forced because no mipmapping in povray needs higher sampling.
file.write('Sampling_Method=2\n')
file.write('Antialias_Depth=%d\n' % aa_mapping[render.antialiasing_samples])
file.write('Antialias_Threshold=0.1\n')#rather high settings but necessary.
file.write('Jitter=off\n')#prevent animation flicker
Maurice Raybaud
committed
file.write('Version=3.7')
file.close()
class PovrayRender(bpy.types.RenderEngine):
Doug Hammond
committed
DELAY = 0.05
def _export(self, scene):
import tempfile
self._temp_file_in = tempfile.mktemp(suffix='.pov')
self._temp_file_out = tempfile.mktemp(suffix='.png')#PNG with POV 3.7, can show the background color with alpha. In the long run using the Povray interactive preview like bishop 3D could solve the preview for all formats.
#self._temp_file_out = tempfile.mktemp(suffix='.tga')
self._temp_file_ini = tempfile.mktemp(suffix='.ini')
'''
self._temp_file_in = '/test.pov'
self._temp_file_out = '/test.png'#PNG with POV 3.7, can show the background color with alpha. In the long run using the Povray interactive preview like bishop 3D could solve the preview for all formats.
#self._temp_file_out = '/test.tga'
self._temp_file_ini = '/test.ini'
'''
def info_callback(txt):
write_pov(self._temp_file_in, scene, info_callback)
def _render(self):
try:
os.remove(self._temp_file_out) # so as not to load the old file
pass
write_pov_ini(self._temp_file_ini, self._temp_file_in, self._temp_file_out)
print ("***-STARTING-***")
pov_binary = "povray"
Doug Hammond
committed
extra_args = []
regKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Software\\POV-Ray\\v3.7\\Windows')
if bitness == 64:
pov_binary = winreg.QueryValueEx(regKey, 'Home')[0] + '\\bin\\pvengine64'
else:
pov_binary = winreg.QueryValueEx(regKey, 'Home')[0] + '\\bin\\pvengine'
Doug Hammond
committed
else:
# DH - added -d option to prevent render window popup which leads to segfault on linux
extra_args.append("-d")
if 1:
# TODO, when povray isnt found this gives a cryptic error, would be nice to be able to detect if it exists
try:
Doug Hammond
committed
self._process = subprocess.Popen([pov_binary, self._temp_file_ini] + extra_args) # stdout=subprocess.PIPE, stderr=subprocess.PIPE
print("POVRAY 3.7: could not execute '%s', possibly povray isn't installed" % pov_binary)
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
else:
# This works too but means we have to wait until its done
os.system('%s %s' % (pov_binary, self._temp_file_ini))
Doug Hammond
committed
# print ("***-DONE-***")
return True
def _cleanup(self):
for f in (self._temp_file_in, self._temp_file_ini, self._temp_file_out):
try:
os.remove(f)
except OSError: #was that the proper error type?
self.update_stats("", "POVRAY 3.7: Exporting data from Blender")
##WIP output format
## if r.file_format == 'OPENEXR':
## fformat = 'EXR'
## render.color_mode = 'RGBA'
## else:
## fformat = 'TGA'
## r.file_format = 'TARGA'
## r.color_mode = 'RGBA'
# compute resolution
x = int(r.resolution_x * r.resolution_percentage * 0.01)
y = int(r.resolution_y * r.resolution_percentage * 0.01)
# Wait for the file to be created
while not os.path.exists(self._temp_file_out):
Doug Hammond
committed
# print("***POV WAITING FOR FILE***")
Doug Hammond
committed
print("***POV INTERRUPTED***")
Doug Hammond
committed
poll_result = self._process.poll()
Doug Hammond
committed
print("***POV PROCESS FAILED : %s ***" % poll_result)
break
time.sleep(self.DELAY)
if os.path.exists(self._temp_file_out):
Doug Hammond
committed
# print("***POV FILE OK***")
Doug Hammond
committed
# print("***POV UPDATING IMAGE***")
result = self.begin_result(0, 0, x, y)
lay = result.layers[0]
# possible the image wont load early on.
try:
lay.load_from_file(self._temp_file_out)
pass
self.end_result(result)
# Update while povray renders
while True:
Doug Hammond
committed
# print("***POV RENDER LOOP***")
Doug Hammond
committed
print("***POV PROCESS FINISHED***")
update_image()
break
# user exit
if self.test_break():
try:
Doug Hammond
committed
print("***POV PROCESS INTERRUPTED***")
pass
break
# Would be nice to redirect the output
# stdout_value, stderr_value = self._process.communicate() # locks
# check if the file updated
new_size = os.path.getsize(self._temp_file_out)
if new_size != prev_size:
update_image()
prev_size = new_size
time.sleep(self.DELAY)
Doug Hammond
committed
else:
print("***POV FILE NOT FOUND***")
print("***POV FINISHED***")