Newer
Older
#print("ini file closed %s" % file.closed)
#print("ini file closed %s" % file.closed)
bl_label = "POV-Ray 3.7"
def _export(self, scene, povPath, renderImagePath):
Bastien Montagne
committed
if scene.pov.tempfiles_enable:
self._temp_file_in = tempfile.NamedTemporaryFile(suffix=".pov", delete=False).name
Bastien Montagne
committed
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
# POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".png", delete=False).name
#self._temp_file_out = tempfile.NamedTemporaryFile(suffix=".tga", delete=False).name
self._temp_file_ini = tempfile.NamedTemporaryFile(suffix=".ini", delete=False).name
else:
self._temp_file_in = povPath + ".pov"
Bastien Montagne
committed
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
# POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
self._temp_file_out = renderImagePath + ".png"
#self._temp_file_out = renderImagePath + ".tga"
self._temp_file_ini = povPath + ".ini"
'''
self._temp_file_in = "/test.pov"
Bastien Montagne
committed
# PNG with POV 3.7, can show the background color with alpha. In the long run using the
# POV-Ray interactive preview like bishop 3D could solve the preview for all formats.
self._temp_file_out = "/test.png"
#self._temp_file_out = "/test.tga"
self._temp_file_ini = "/test.ini"
'''
self.update_stats("", "POV-Ray 3.7: " + txt)
write_pov(self._temp_file_in, scene, info_callback)
Constantin Rahn
committed
def _render(self, scene):
os.remove(self._temp_file_out) # so as not to load the old file
write_pov_ini(scene, self._temp_file_ini, self._temp_file_in, self._temp_file_out)
print ("***-STARTING-***")
pov_binary = "povray"
Doug Hammond
committed
extra_args = []
Bastien Montagne
committed
if scene.pov.command_line_switches != "":
for newArg in scene.pov.command_line_switches.split(" "):
Constantin Rahn
committed
extra_args.append(newArg)
self._is_windows = False
self._is_windows = True
#extra_args.append("/EXIT")
import platform as pltfrm
if pltfrm.architecture()[0] == "64bit":
bitness = 64
else:
bitness = 32
regKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\POV-Ray\\v3.7\\Windows")
Maurice Raybaud
committed
# TODO, report api
# 64 bits blender
pov_binary = winreg.QueryValueEx(regKey, "Home")[0] + "\\bin\\pvengine64"
Bastien Montagne
committed
self._process = subprocess.Popen(
[pov_binary, self._temp_file_ini] + extra_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Maurice Raybaud
committed
# This would work too but means we have to wait until its done:
# os.system("%s %s" % (pov_binary, self._temp_file_ini))
except OSError:
# someone might run povray 32 bits on a 64 bits blender machine
try:
pov_binary = winreg.QueryValueEx(regKey, "Home")[0] + "\\bin\\pvengine"
Bastien Montagne
committed
self._process = subprocess.Popen(
[pov_binary, self._temp_file_ini] + extra_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
Maurice Raybaud
committed
# TODO, report api
Bastien Montagne
committed
print("POV-Ray 3.7: could not execute '%s', possibly POV-Ray isn't " \
"installed" % pov_binary)
Maurice Raybaud
committed
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
else:
print("POV-Ray 3.7 64 bits could not execute, running 32 bits instead")
Maurice Raybaud
committed
print("Command line arguments passed: " + str(extra_args))
return True
else:
print("POV-Ray 3.7 64 bits found")
Maurice Raybaud
committed
print("Command line arguments passed: " + str(extra_args))
return True
pov_binary = winreg.QueryValueEx(regKey, "Home")[0] + "\\bin\\pvengine"
Bastien Montagne
committed
self._process = subprocess.Popen(
[pov_binary, self._temp_file_ini] + extra_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# someone might also run povray 64 bits with a 32 bits build of blender.
except OSError:
try:
pov_binary = winreg.QueryValueEx(regKey, "Home")[0] + "\\bin\\pvengine64"
Bastien Montagne
committed
self._process = subprocess.Popen(
[pov_binary, self._temp_file_ini] + extra_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
Maurice Raybaud
committed
# TODO, report api
Bastien Montagne
committed
print("POV-Ray 3.7: could not execute '%s', possibly POV-Ray isn't " \
"installed" % pov_binary)
Maurice Raybaud
committed
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
Bastien Montagne
committed
print("Running POV-Ray 3.7 64 bits build with 32 bits Blender,\n" \
"You might want to run Blender 64 bits as well.")
Maurice Raybaud
committed
print("Command line arguments passed: " + str(extra_args))
return True
else:
print("POV-Ray 3.7 32 bits found")
Maurice Raybaud
committed
print("Command line arguments passed: " + str(extra_args))
return True
Doug Hammond
committed
else:
# DH - added -d option to prevent render window popup which leads to segfault on linux
extra_args.append("-d")
isExists = False
sysPathList = os.getenv("PATH").split(':')
sysPathList.append("")
for dirName in sysPathList:
if (os.path.exists(os.path.join(dirName, pov_binary))):
isExists = True
break
if not isExists:
print("POV-Ray 3.7: could not found execute '%s' - not if PATH" % pov_binary)
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
self._process = subprocess.Popen([pov_binary, self._temp_file_ini] + extra_args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
# TODO, report api
print("POV-Ray 3.7: could not execute '%s'" % pov_binary)
import traceback
traceback.print_exc()
print ("***-DONE-***")
return False
else:
print("POV-Ray 3.7 found")
print("Command line arguments passed: " + str(extra_args))
return True
# Now that we have a valid process
def _cleanup(self):
for f in (self._temp_file_in, self._temp_file_ini, self._temp_file_out):
for i in range(5):
try:
os.unlink(f)
break
except OSError:
# Wait a bit before retrying file might be still in use by Blender,
# and Windows does not know how to delete a file in use!
time.sleep(self.DELAY)
## if r.image_settings.file_format == 'OPENEXR':
## render.image_settings.color_mode = 'RGBA'
## r.image_settings.file_format = 'TARGA'
## r.image_settings.color_mode = 'RGBA'
blendSceneName = bpy.data.filepath.split(os.path.sep)[-1].split(".")[0]
povSceneName = ""
povPath = ""
renderImagePath = ""
Bastien Montagne
committed
# has to be called to update the frame on exporting animations
scene.frame_set(scene.frame_current)
Bastien Montagne
committed
if not scene.pov.tempfiles_enable:
Bastien Montagne
committed
povPath = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/')
if bpy.data.is_saved:
povPath = bpy.path.abspath("//")
else:
povPath = tempfile.gettempdir()
elif povPath.endswith("/"):
if povPath == "/":
povPath = bpy.path.abspath("//")
else:
Bastien Montagne
committed
povPath = bpy.path.abspath(scene.pov.scene_path)
try:
os.makedirs(povPath)
except:
import traceback
traceback.print_exc()
print("POV-Ray 3.7: Cannot create scenes directory: %r" % povPath)
Bastien Montagne
committed
self.update_stats("", "POV-Ray 3.7: Cannot create scenes directory %r" % \
povPath)
time.sleep(2.0)
return
Bastien Montagne
committed
renderImagePath = bpy.path.abspath(scene.pov.renderimage_path).replace('\\','/')
if bpy.data.is_saved:
renderImagePath = bpy.path.abspath("//")
else:
renderImagePath = tempfile.gettempdir()
#print("Path: " + renderImagePath)
elif path.endswith("/"):
if renderImagePath == "/":
renderImagePath = bpy.path.abspath("//")
else:
Bastien Montagne
committed
renderImagePath = bpy.path.abspath(scene.pov.renderimage_path)
if not os.path.exists(path):
print("POV-Ray 3.7: Cannot find render image directory")
self.update_stats("", "POV-Ray 3.7: Cannot find render image directory")
time.sleep(2.0)
return
'''
# check name
Bastien Montagne
committed
if scene.pov.scene_name == "":
if blendSceneName != "":
povSceneName = blendSceneName
else:
povSceneName = "untitled"
else:
Bastien Montagne
committed
povSceneName = scene.pov.scene_name
if os.path.isfile(povSceneName):
povSceneName = os.path.basename(povSceneName)
povSceneName = povSceneName.split('/')[-1].split('\\')[-1]
if not povSceneName:
print("POV-Ray 3.7: Invalid scene name")
self.update_stats("", "POV-Ray 3.7: Invalid scene name")
time.sleep(2.0)
return
povSceneName = os.path.splitext(povSceneName)[0]
print("Scene name: " + povSceneName)
print("Export path: " + povPath)
povPath = os.path.join(povPath, povSceneName)
povPath = os.path.realpath(povPath)
Bastien Montagne
committed
# for now this has to be the same like the pov output. Bug in POV-Ray RC3.
# renderImagePath = renderImagePath + "\\" + povSceneName
renderImagePath = povPath # Bugfix for POV-Ray RC3 bug
# renderImagePath = os.path.realpath(renderImagePath) # Bugfix for POV-Ray RC3 bug
#print("Export path: %s" % povPath)
#print("Render Image path: %s" % renderImagePath)
# start export
self.update_stats("", "POV-Ray 3.7: Exporting data from Blender")
self._export(scene, povPath, renderImagePath)
self.update_stats("", "POV-Ray 3.7: Parsing File")
if not self._render(scene):
self.update_stats("", "POV-Ray 3.7: Not found")
return
r = scene.render
# compute resolution
x = int(r.resolution_x * r.resolution_percentage * 0.01)
y = int(r.resolution_y * r.resolution_percentage * 0.01)
# This makes some tests on the render, returning True if all goes good, and False if
# it was finished one way or the other.
# It also pauses the script (time.sleep())
def _test_wait():
time.sleep(self.DELAY)
# User interrupts the rendering
print("***POV INTERRUPTED***")
return False
Doug Hammond
committed
poll_result = self._process.poll()
# POV process is finisehd, one way or the other
if poll_result < 0:
print("***POV PROCESS FAILED : %s ***" % poll_result)
self.update_stats("", "POV-Ray 3.7: Failed")
return False
return True
# Wait for the file to be created
# XXX This is no more valid, as 3.7 always creates output file once render is finished!
parsing = re.compile(br"= \[Parsing\.\.\.\] =")
rendering = re.compile(br"= \[Rendering\.\.\.\] =")
percent = re.compile(r"\(([0-9]{1,3})%\)")
# print("***POV WAITING FOR FILE***")
data = b""
last_line = ""
while _test_wait():
# POV in Windows does not output its stdout/stderr, it displays them in its GUI
if self._is_windows:
self.update_stats("", "POV-Ray 3.7: Rendering File")
else:
Bastien Montagne
committed
t_data = self._process.stdout.read(10000)
data += t_data
Bastien Montagne
committed
# XXX This is working for UNIX, not sure whether it might need adjustments for
# other OSs
# First replace is for windows
t_data = str(t_data).replace('\\r\\n', '\\n').replace('\\r', '\r')
lines = t_data.split('\\n')
last_line += lines[0]
lines[0] = last_line
print('\n'.join(lines), end="")
last_line = lines[-1]
if rendering.search(data):
_pov_rendering = True
match = percent.findall(str(data))
if match:
self.update_stats("", "POV-Ray 3.7: Rendering File (%s%%)" % match[-1])
else:
self.update_stats("", "POV-Ray 3.7: Rendering File")
elif parsing.search(data):
self.update_stats("", "POV-Ray 3.7: Parsing File")
if os.path.exists(self._temp_file_out):
# print("***POV FILE OK***")
#self.update_stats("", "POV-Ray 3.7: Rendering")
# prev_size = -1
xmin = int(r.border_min_x * x)
ymin = int(r.border_min_y * y)
xmax = int(r.border_max_x * x)
ymax = int(r.border_max_y * y)
# print("***POV UPDATING IMAGE***")
result = self.begin_result(0, 0, x, y)
Bastien Montagne
committed
# XXX, tests for border render.
#result = self.begin_result(xmin, ymin, xmax - xmin, ymax - ymin)
#result = self.begin_result(0, 0, xmax - xmin, ymax - ymin)
lay = result.layers[0]
# This assumes the file has been fully written We wait a bit, just in case!
time.sleep(self.DELAY)
try:
lay.load_from_file(self._temp_file_out)
Bastien Montagne
committed
# XXX, tests for border render.
#lay.load_from_file(self._temp_file_out, xmin, ymin)
except RuntimeError:
print("***POV ERROR WHILE READING OUTPUT FILE***")
# Not needed right now, might only be useful if we find a way to use temp raw output of
# pov 3.7 (in which case it might go under _test_wait()).
# def update_image():
# # possible the image wont load early on.
# try:
# lay.load_from_file(self._temp_file_out)
Bastien Montagne
committed
# # XXX, tests for border render.
# #lay.load_from_file(self._temp_file_out, xmin, ymin)
# #lay.load_from_file(self._temp_file_out, xmin, ymin)
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
# except RuntimeError:
# pass
# # Update while POV-Ray renders
# while True:
# # print("***POV RENDER LOOP***")
# # test if POV-Ray exists
# if self._process.poll() is not None:
# print("***POV PROCESS FINISHED***")
# update_image()
# break
# # user exit
# if self.test_break():
# try:
# self._process.terminate()
# print("***POV PROCESS INTERRUPTED***")
# except OSError:
# 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)
self.end_result(result)
Doug Hammond
committed
else:
print("***POV FILE NOT FOUND***")
print("***POV FINISHED***")
self.update_stats("", "")
Bastien Montagne
committed
if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable: