PsychoBlend: fixed some bugs and made exporting even faster.
This commit is contained in:
parent
9025715335
commit
7236d2e666
|
@ -1,6 +1,6 @@
|
||||||
import bpy
|
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:
|
class Assembly:
|
||||||
def __init__(self, render_engine, objects, visible_layers, group_prefix="", translation_offset=(0,0,0)):
|
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):
|
def take_sample(self, render_engine, scene, time):
|
||||||
for mat in self.materials:
|
for mat in self.materials:
|
||||||
|
# Check if render is cancelled
|
||||||
|
if render_engine.test_break():
|
||||||
|
raise ExportCancelled()
|
||||||
mat.take_sample(render_engine, scene, time)
|
mat.take_sample(render_engine, scene, time)
|
||||||
|
|
||||||
for ob in self.objects:
|
for ob in self.objects:
|
||||||
|
# Check if render is cancelled
|
||||||
|
if render_engine.test_break():
|
||||||
|
raise ExportCancelled()
|
||||||
ob.take_sample(render_engine, scene, time)
|
ob.take_sample(render_engine, scene, time)
|
||||||
|
|
||||||
for inst in self.instances:
|
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)
|
inst.take_sample(render_engine, time, self.translation_offset)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
|
@ -131,11 +142,13 @@ class Mesh:
|
||||||
def __init__(self, render_engine, ob, name):
|
def __init__(self, render_engine, ob, name):
|
||||||
self.ob = ob
|
self.ob = ob
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.needs_mb = needs_def_mb(self.ob)
|
||||||
self.time_meshes = []
|
self.time_meshes = []
|
||||||
|
|
||||||
def take_sample(self, render_engine, scene, time):
|
def take_sample(self, render_engine, scene, time):
|
||||||
render_engine.update_stats("", "Psychopath: Collecting '%s' at time %f" % (self.ob.name, time))
|
if len(self.time_meshes) == 0 or self.needs_mb:
|
||||||
self.time_meshes += [self.ob.to_mesh(scene, True, 'RENDER')]
|
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):
|
def cleanup(self):
|
||||||
for mesh in self.time_meshes:
|
for mesh in self.time_meshes:
|
||||||
|
@ -184,7 +197,7 @@ class SphereLamp:
|
||||||
self.time_rad = []
|
self.time_rad = []
|
||||||
|
|
||||||
def take_sample(self, render_engine, scene, time):
|
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_col += [self.ob.data.color * self.ob.data.energy]
|
||||||
self.time_rad += [self.ob.data.shadow_soft_size]
|
self.time_rad += [self.ob.data.shadow_soft_size]
|
||||||
|
|
||||||
|
@ -215,7 +228,7 @@ class RectLamp:
|
||||||
self.time_dim = []
|
self.time_dim = []
|
||||||
|
|
||||||
def take_sample(self, render_engine, scene, time):
|
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_col += [self.ob.data.color * self.ob.data.energy]
|
||||||
if ob.data.shape == 'RECTANGLE':
|
if ob.data.shape == 'RECTANGLE':
|
||||||
self.time_dim += [(self.ob.data.size, self.ob.data.size_y)]
|
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):
|
def __init__(self, render_engine, ob, data_name):
|
||||||
self.ob = ob
|
self.ob = ob
|
||||||
self.data_name = data_name
|
self.data_name = data_name
|
||||||
|
self.needs_mb = needs_xform_mb(self.ob)
|
||||||
self.time_xforms = []
|
self.time_xforms = []
|
||||||
|
|
||||||
def take_sample(self, render_engine, time, translation_offset):
|
def take_sample(self, render_engine, time, translation_offset):
|
||||||
render_engine.update_stats("", "Psychopath: Collecting '%s' at time %f" % (self.ob.name, time))
|
if len(self.time_xforms) == 0 or self.needs_mb:
|
||||||
mat = self.ob.matrix_world.copy()
|
render_engine.update_stats("", "Psychopath: Collecting '{}' xforms at time {}".format(self.ob.name, time))
|
||||||
mat[0][3] += translation_offset[0]
|
mat = self.ob.matrix_world.copy()
|
||||||
mat[1][3] += translation_offset[1]
|
mat[0][3] += translation_offset[0]
|
||||||
mat[2][3] += translation_offset[2]
|
mat[1][3] += translation_offset[1]
|
||||||
self.time_xforms += [mat]
|
mat[2][3] += translation_offset[2]
|
||||||
|
self.time_xforms += [mat]
|
||||||
|
|
||||||
def export(self, render_engine, w):
|
def export(self, render_engine, w):
|
||||||
render_engine.update_stats("", "Psychopath: Exporting %s" % self.ob.name)
|
render_engine.update_stats("", "Psychopath: Exporting %s" % self.ob.name)
|
||||||
|
|
|
@ -4,13 +4,7 @@ from math import degrees, pi, log
|
||||||
from mathutils import Vector, Matrix
|
from mathutils import Vector, Matrix
|
||||||
|
|
||||||
from .assembly import Assembly
|
from .assembly import Assembly
|
||||||
from .util import escape_name, mat2str
|
from .util import escape_name, mat2str, ExportCancelled
|
||||||
|
|
||||||
class ExportCancelled(Exception):
|
|
||||||
""" Indicates that the render was cancelled in the middle of exporting
|
|
||||||
the scene file.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class IndentedWriter:
|
class IndentedWriter:
|
||||||
|
@ -181,7 +175,7 @@ class PsychoExporter:
|
||||||
root_assembly.export(self.render_engine, self.w)
|
root_assembly.export(self.render_engine, self.w)
|
||||||
except ExportCancelled:
|
except ExportCancelled:
|
||||||
root_assembly.cleanup()
|
root_assembly.cleanup()
|
||||||
raise ExportCancelled()
|
raise
|
||||||
else:
|
else:
|
||||||
root_assembly.cleanup()
|
root_assembly.cleanup()
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ class PsychopathRender(bpy.types.RenderEngine):
|
||||||
return psy_binary
|
return psy_binary
|
||||||
return ""
|
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()
|
psy_binary = PsychopathRender._locate_binary()
|
||||||
if not psy_binary:
|
if not psy_binary:
|
||||||
print("Psychopath: could not execute psychopath, possibly Psychopath isn't installed")
|
print("Psychopath: could not execute psychopath, possibly Psychopath isn't installed")
|
||||||
|
@ -86,6 +86,15 @@ class PsychopathRender(bpy.types.RenderEngine):
|
||||||
self.end_result(result)
|
self.end_result(result)
|
||||||
|
|
||||||
def render(self, scene):
|
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
|
# has to be called to update the frame on exporting animations
|
||||||
scene.frame_set(scene.frame_current)
|
scene.frame_set(scene.frame_current)
|
||||||
|
|
||||||
|
@ -116,22 +125,19 @@ class PsychopathRender(bpy.types.RenderEngine):
|
||||||
|
|
||||||
if use_stdin:
|
if use_stdin:
|
||||||
# Start rendering
|
# 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")
|
self.update_stats("", "Psychopath: Not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.update_stats("", "Psychopath: Collecting...")
|
self.update_stats("", "Psychopath: Collecting...")
|
||||||
# Export to Psychopath's stdin
|
# Export to Psychopath's stdin
|
||||||
try:
|
if not psy_export.PsychoExporter(self._process.stdin, self, scene).export_psy():
|
||||||
if not psy_export.PsychoExporter(self._process.stdin, self, scene).export_psy():
|
# Render cancelled in the middle of exporting,
|
||||||
# Render cancelled in the middle of exporting,
|
# so just return.
|
||||||
# so just return.
|
|
||||||
return
|
|
||||||
self._process.stdin.write(bytes("__PSY_EOF__", "utf-8"))
|
|
||||||
self._process.stdin.flush()
|
|
||||||
except:
|
|
||||||
self._process.terminate()
|
self._process.terminate()
|
||||||
raise
|
return
|
||||||
|
self._process.stdin.write(bytes("__PSY_EOF__", "utf-8"))
|
||||||
|
self._process.stdin.flush()
|
||||||
|
|
||||||
self.update_stats("", "Psychopath: Building")
|
self.update_stats("", "Psychopath: Building")
|
||||||
else:
|
else:
|
||||||
|
@ -145,7 +151,7 @@ class PsychopathRender(bpy.types.RenderEngine):
|
||||||
|
|
||||||
# Start rendering
|
# Start rendering
|
||||||
self.update_stats("", "Psychopath: Rendering from %s" % export_path)
|
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")
|
self.update_stats("", "Psychopath: Not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -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):
|
def mat2str(m):
|
||||||
""" Converts a matrix into a single-line string of values.
|
""" 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
|
""" Determines if the given object needs to be exported with
|
||||||
deformation motion blur or not.
|
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:
|
for mod in ob.modifiers:
|
||||||
if mod.type == 'SUBSURF':
|
if mod.type == 'SUBSURF':
|
||||||
pass
|
pass
|
||||||
|
elif mod.type == 'MULTIRES':
|
||||||
|
pass
|
||||||
elif mod.type == 'MIRROR':
|
elif mod.type == 'MIRROR':
|
||||||
if mod.mirror_object == None:
|
if mod.mirror_object == None:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return True
|
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:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user