161 lines
4.6 KiB
Python
161 lines
4.6 KiB
Python
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or
|
||
|
# modify it under the terms of the GNU General Public License
|
||
|
# as published by the Free Software Foundation; either version 2
|
||
|
# of the License, or (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program; if not, write to the Free Software Foundation,
|
||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
#
|
||
|
# ##### END GPL LICENSE BLOCK #####
|
||
|
|
||
|
import bpy
|
||
|
import subprocess
|
||
|
import os
|
||
|
import sys
|
||
|
import math
|
||
|
import copy
|
||
|
import shutil
|
||
|
import time
|
||
|
|
||
|
# Basic Mitsuba integration based on the POV-Ray add-on
|
||
|
# Piggybacks on the COLLADA exporter to get most things done
|
||
|
class MitsubaRender(bpy.types.RenderEngine):
|
||
|
bl_idname = 'MITSUBA_RENDER'
|
||
|
bl_label = "Mitsuba"
|
||
|
|
||
|
def _export(self, scene):
|
||
|
import tempfile
|
||
|
self._temp_dir = tempfile.mkdtemp(prefix='mitsuba_');
|
||
|
self._temp_dae = os.path.join(self._temp_dir, 'scene.dae')
|
||
|
self._temp_xml = os.path.join(self._temp_dir, 'scene.xml')
|
||
|
self._temp_adj = os.path.join(self._temp_dir, 'scene_adjustments.xml')
|
||
|
self._temp_out = os.path.join(self._temp_dir, 'scene.png')
|
||
|
print("MtsBlend: Writing COLLADA file")
|
||
|
while True:
|
||
|
try:
|
||
|
bpy.ops.wm.collada_export(filepath=self._temp_dae, check_existing=False)
|
||
|
break
|
||
|
except SystemError:
|
||
|
# Weird SystemError (Operator bpy.ops.wm.collada_export.poll()
|
||
|
# failed, context is incorrect) -> try again
|
||
|
print("MtsBlend: Retrying")
|
||
|
time.sleep(0.1)
|
||
|
print("MtsBlend: Writing adjustments file")
|
||
|
adjfile = open(self._temp_adj, 'w')
|
||
|
adjfile.write('<adjustments>\n');
|
||
|
adjfile.write('</adjustments>\n');
|
||
|
adjfile.close()
|
||
|
|
||
|
def _render(self):
|
||
|
mts_path = '/home/wenzel/mitsuba'
|
||
|
mtsimport_binary = os.path.join(mts_path, "mtsimport")
|
||
|
mitsuba_binary = os.path.join(mts_path, "mitsuba")
|
||
|
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||
|
mts_core_libpath = os.path.join(mts_path, "src/libcore")
|
||
|
mts_hw_libpath = os.path.join(mts_path, "src/libhw")
|
||
|
env = copy.copy(os.environ)
|
||
|
env['LD_LIBRARY_PATH'] = mts_core_libpath + ":" + mts_render_libpath + ":" + mts_hw_libpath
|
||
|
scene = bpy.data.scenes[0]
|
||
|
render = scene.render
|
||
|
width = int(render.resolution_x * render.resolution_percentage * 0.01)
|
||
|
height = int(render.resolution_y * render.resolution_percentage * 0.01)
|
||
|
|
||
|
try:
|
||
|
print("MtsBlend: Launching mtsimport")
|
||
|
process = subprocess.Popen(
|
||
|
[mtsimport_binary, '-s', '-r', '%dx%d' % (width, height),
|
||
|
'-l', 'pngfilm',
|
||
|
self._temp_dae, self._temp_xml,
|
||
|
self._temp_adj],
|
||
|
env = env,
|
||
|
cwd = self._temp_dir
|
||
|
)
|
||
|
if process.wait() != 0:
|
||
|
print("MtsBlend: mtsimport returned with a nonzero status")
|
||
|
return False
|
||
|
|
||
|
self._process = subprocess.Popen(
|
||
|
[mitsuba_binary, self._temp_xml, '-o', self._temp_out],
|
||
|
env = env,
|
||
|
cwd = self._temp_dir
|
||
|
)
|
||
|
except OSError:
|
||
|
print("MtsBlend: Could not execute '%s', possibly Mitsuba isn't installed" % mtsimport_binary)
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
def _cleanup(self):
|
||
|
#shutil.rmtree(self._temp_dir)
|
||
|
print("Not cleaning up")
|
||
|
|
||
|
def render(self, scene):
|
||
|
self._export(scene)
|
||
|
if not self._render():
|
||
|
self.update_stats("", "MtsBlend: Unable to render (please check the console)")
|
||
|
return
|
||
|
|
||
|
r = scene.render
|
||
|
x = int(r.resolution_x * r.resolution_percentage * 0.01)
|
||
|
y = int(r.resolution_y * r.resolution_percentage * 0.01)
|
||
|
DELAY = 0.02
|
||
|
|
||
|
# Wait for the file to be created
|
||
|
while not os.path.exists(self._temp_out):
|
||
|
if self.test_break():
|
||
|
try:
|
||
|
self._process.terminate()
|
||
|
except:
|
||
|
pass
|
||
|
break
|
||
|
|
||
|
if self._process.poll() != None:
|
||
|
self.update_stats("", "MtsBlend: Failed to render (check console)")
|
||
|
break
|
||
|
|
||
|
time.sleep(DELAY)
|
||
|
|
||
|
if os.path.exists(self._temp_out):
|
||
|
self.update_stats("", "MtsBlend: Rendering")
|
||
|
prev_size = -1
|
||
|
|
||
|
def update_image():
|
||
|
result = self.begin_result(0, 0, x, y)
|
||
|
layer = result.layers[0]
|
||
|
try:
|
||
|
print("Loading %s" % self._temp_out)
|
||
|
layer.load_from_file(self._temp_out)
|
||
|
except:
|
||
|
pass
|
||
|
self.end_result(result)
|
||
|
|
||
|
while True:
|
||
|
if self._process.poll() is not None:
|
||
|
update_image()
|
||
|
break
|
||
|
|
||
|
if self.test_break():
|
||
|
try:
|
||
|
self._process.terminate()
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
break
|
||
|
|
||
|
new_size = os.path.getsize(self._temp_out)
|
||
|
if new_size != prev_size:
|
||
|
update_image()
|
||
|
prev_size = new_size
|
||
|
|
||
|
time.sleep(DELAY)
|
||
|
|
||
|
self._cleanup()
|