PsychoBlend: fixed some bugs and made exporting even faster.

This commit is contained in:
Nathan Vegdahl 2017-06-10 01:38:33 -07:00
parent 9025715335
commit 7236d2e666
4 changed files with 72 additions and 31 deletions

View File

@ -1,6 +1,6 @@
import bpy
from .util import escape_name, mat2str, needs_def_mb, needs_xform_mb
from .util import escape_name, mat2str, needs_def_mb, needs_xform_mb, ExportCancelled
class Assembly:
def __init__(self, render_engine, objects, visible_layers, group_prefix="", translation_offset=(0,0,0)):
@ -80,10 +80,21 @@ class Assembly:
def take_sample(self, render_engine, scene, time):
for mat in self.materials:
# Check if render is cancelled
if render_engine.test_break():
raise ExportCancelled()
mat.take_sample(render_engine, scene, time)
for ob in self.objects:
# Check if render is cancelled
if render_engine.test_break():
raise ExportCancelled()
ob.take_sample(render_engine, scene, time)
for inst in self.instances:
# Check if render is cancelled
if render_engine.test_break():
raise ExportCancelled()
inst.take_sample(render_engine, time, self.translation_offset)
def cleanup(self):
@ -131,11 +142,13 @@ class Mesh:
def __init__(self, render_engine, ob, name):
self.ob = ob
self.name = name
self.needs_mb = needs_def_mb(self.ob)
self.time_meshes = []
def take_sample(self, render_engine, scene, time):
render_engine.update_stats("", "Psychopath: Collecting '%s' at time %f" % (self.ob.name, time))
self.time_meshes += [self.ob.to_mesh(scene, True, 'RENDER')]
if len(self.time_meshes) == 0 or self.needs_mb:
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(self.ob.name, time))
self.time_meshes += [self.ob.to_mesh(scene, True, 'RENDER')]
def cleanup(self):
for mesh in self.time_meshes:
@ -184,7 +197,7 @@ class SphereLamp:
self.time_rad = []
def take_sample(self, render_engine, scene, time):
render_engine.update_stats("", "Psychopath: Collecting '%s' at time %f" % (self.ob.name, time))
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(self.ob.name, time))
self.time_col += [self.ob.data.color * self.ob.data.energy]
self.time_rad += [self.ob.data.shadow_soft_size]
@ -215,7 +228,7 @@ class RectLamp:
self.time_dim = []
def take_sample(self, render_engine, scene, time):
render_engine.update_stats("", "Psychopath: Collecting '%s' at time %f" % (self.ob.name, time))
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(self.ob.name, time))
self.time_col += [self.ob.data.color * self.ob.data.energy]
if ob.data.shape == 'RECTANGLE':
self.time_dim += [(self.ob.data.size, self.ob.data.size_y)]
@ -243,15 +256,17 @@ class Instance:
def __init__(self, render_engine, ob, data_name):
self.ob = ob
self.data_name = data_name
self.needs_mb = needs_xform_mb(self.ob)
self.time_xforms = []
def take_sample(self, render_engine, time, translation_offset):
render_engine.update_stats("", "Psychopath: Collecting '%s' at time %f" % (self.ob.name, time))
mat = self.ob.matrix_world.copy()
mat[0][3] += translation_offset[0]
mat[1][3] += translation_offset[1]
mat[2][3] += translation_offset[2]
self.time_xforms += [mat]
if len(self.time_xforms) == 0 or self.needs_mb:
render_engine.update_stats("", "Psychopath: Collecting '{}' xforms at time {}".format(self.ob.name, time))
mat = self.ob.matrix_world.copy()
mat[0][3] += translation_offset[0]
mat[1][3] += translation_offset[1]
mat[2][3] += translation_offset[2]
self.time_xforms += [mat]
def export(self, render_engine, w):
render_engine.update_stats("", "Psychopath: Exporting %s" % self.ob.name)

View File

@ -4,13 +4,7 @@ from math import degrees, pi, log
from mathutils import Vector, Matrix
from .assembly import Assembly
from .util import escape_name, mat2str
class ExportCancelled(Exception):
""" Indicates that the render was cancelled in the middle of exporting
the scene file.
"""
pass
from .util import escape_name, mat2str, ExportCancelled
class IndentedWriter:
@ -181,7 +175,7 @@ class PsychoExporter:
root_assembly.export(self.render_engine, self.w)
except ExportCancelled:
root_assembly.cleanup()
raise ExportCancelled()
raise
else:
root_assembly.cleanup()

View File

@ -34,7 +34,7 @@ class PsychopathRender(bpy.types.RenderEngine):
return psy_binary
return ""
def _render(self, scene, psy_filepath, use_stdin, crop):
def _start_psychopath(self, scene, psy_filepath, use_stdin, crop):
psy_binary = PsychopathRender._locate_binary()
if not psy_binary:
print("Psychopath: could not execute psychopath, possibly Psychopath isn't installed")
@ -86,6 +86,15 @@ class PsychopathRender(bpy.types.RenderEngine):
self.end_result(result)
def render(self, scene):
self._process = None
try:
self._render(scene)
except:
if self.process != None:
self._process.terminate()
raise
def _render(self, scene):
# has to be called to update the frame on exporting animations
scene.frame_set(scene.frame_current)
@ -116,22 +125,19 @@ class PsychopathRender(bpy.types.RenderEngine):
if use_stdin:
# Start rendering
if not self._render(scene, export_path, use_stdin, crop):
if not self._start_psychopath(scene, export_path, use_stdin, crop):
self.update_stats("", "Psychopath: Not found")
return
self.update_stats("", "Psychopath: Collecting...")
# Export to Psychopath's stdin
try:
if not psy_export.PsychoExporter(self._process.stdin, self, scene).export_psy():
# Render cancelled in the middle of exporting,
# so just return.
return
self._process.stdin.write(bytes("__PSY_EOF__", "utf-8"))
self._process.stdin.flush()
except:
if not psy_export.PsychoExporter(self._process.stdin, self, scene).export_psy():
# Render cancelled in the middle of exporting,
# so just return.
self._process.terminate()
raise
return
self._process.stdin.write(bytes("__PSY_EOF__", "utf-8"))
self._process.stdin.flush()
self.update_stats("", "Psychopath: Building")
else:
@ -145,7 +151,7 @@ class PsychopathRender(bpy.types.RenderEngine):
# Start rendering
self.update_stats("", "Psychopath: Rendering from %s" % export_path)
if not self._render(scene, export_path, use_stdin, crop):
if not self._start_psychopath(scene, export_path, use_stdin, crop):
self.update_stats("", "Psychopath: Not found")
return

View File

@ -1,3 +1,10 @@
class ExportCancelled(Exception):
""" Indicates that the render was cancelled in the middle of exporting
the scene file.
"""
pass
def mat2str(m):
""" Converts a matrix into a single-line string of values.
"""
@ -12,14 +19,33 @@ def needs_def_mb(ob):
""" Determines if the given object needs to be exported with
deformation motion blur or not.
"""
anim = ob.animation_data
no_anim_data = anim == None or (anim.action == None and len(anim.nla_tracks) == 0 and len(anim.drivers) == 0)
for mod in ob.modifiers:
if mod.type == 'SUBSURF':
pass
elif mod.type == 'MULTIRES':
pass
elif mod.type == 'MIRROR':
if mod.mirror_object == None:
pass
else:
return True
elif mod.type == 'BEVEL' and no_anim_data:
pass
elif mod.type == 'EDGE_SPLIT' and no_anim_data:
pass
elif mod.type == 'SOLIDIFY' and no_anim_data:
pass
elif mod.type == 'MASK' and no_anim_data:
pass
elif mod.type == 'REMESH' and no_anim_data:
pass
elif mod.type == 'TRIANGULATE' and no_anim_data:
pass
elif mod.type == 'WIREFRAME' and no_anim_data:
pass
else:
return True