def set_export_path(self, scene): # replace /tmp/ with the real %temp% folder on Windows # OSX also has a special temp location that we should use fp = scene.render.filepath output_path_split = list(os.path.split(fp)) if sys.platform in ('win32', 'darwin') and output_path_split[0] == '/tmp': output_path_split[0] = efutil.temp_directory() fp = '/'.join(output_path_split) scene_path = efutil.filesystem_path(fp) if os.path.isdir(scene_path): self.output_dir = scene_path else: self.output_dir = os.path.dirname(scene_path) if self.output_dir[-1] not in ('/', '\\'): self.output_dir += '/' if scene.luxrender_engine.export_type == 'INT': write_files = scene.luxrender_engine.write_files if write_files: api_type = 'FILE' else: api_type = 'API' if sys.platform == 'darwin': self.output_dir = efutil.filesystem_path(bpy.app.tempdir) else: self.output_dir = efutil.temp_directory() else: api_type = 'FILE' write_files = True efutil.export_path = self.output_dir return api_type, write_files
def set_export_path(self, scene): # replace /tmp/ with the real %temp% folder on Windows # OSX also has a special temp location that we should use fp = scene.render.filepath output_path_split = list(os.path.split(fp)) if sys.platform in ('win32', 'darwin') and output_path_split[0] == '/tmp': output_path_split[0] = efutil.temp_directory() fp = '/'.join(output_path_split) scene_path = efutil.filesystem_path( fp ) if os.path.isdir(scene_path): self.output_dir = scene_path else: self.output_dir = os.path.dirname( scene_path ) if self.output_dir[-1] not in ('/', '\\'): self.output_dir += '/' if scene.luxrender_engine.export_type == 'INT': write_files = scene.luxrender_engine.write_files if write_files: api_type = 'FILE' else: api_type = 'API' if sys.platform == 'darwin': self.output_dir = efutil.filesystem_path( bpy.app.tempdir ) else: self.output_dir = efutil.temp_directory() else: api_type = 'FILE' write_files = True efutil.export_path = self.output_dir return api_type, write_files
def render_preview(self, scene): if sys.platform == 'darwin': self.output_dir = efutil.filesystem_path( bpy.app.tempdir ) else: self.output_dir = efutil.temp_directory() if self.output_dir[-1] != '/': self.output_dir += '/' efutil.export_path = self.output_dir from ..outputs.pure_api import PYLUX_AVAILABLE if not PYLUX_AVAILABLE: self.bl_use_preview = False LuxLog('ERROR: Material previews require pylux') return from ..export import materials as export_materials # Iterate through the preview scene, finding objects with materials attached objects_mats = {} for obj in [ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render]: for mat in export_materials.get_instance_materials(obj): if mat is not None: if not obj.name in objects_mats.keys(): objects_mats[obj] = [] objects_mats[obj].append(mat) PREVIEW_TYPE = None # 'MATERIAL' or 'TEXTURE' # find objects that are likely to be the preview objects preview_objects = [o for o in objects_mats.keys() if o.name.startswith('preview')] if len(preview_objects) > 0: PREVIEW_TYPE = 'MATERIAL' else: preview_objects = [o for o in objects_mats.keys() if o.name.startswith('texture')] if len(preview_objects) > 0: PREVIEW_TYPE = 'TEXTURE' if PREVIEW_TYPE == None: return # TODO: scene setup based on PREVIEW_TYPE # find the materials attached to the likely preview object likely_materials = objects_mats[preview_objects[0]] if len(likely_materials) < 1: print('no preview materials') return pm = likely_materials[0] pt = None LuxLog('Rendering material preview: %s' % pm.name) if PREVIEW_TYPE == 'TEXTURE': pt = pm.active_texture LM = LuxManager( scene.name, api_type = 'API', ) LuxManager.SetCurrentScene(scene) LuxManager.SetActive(LM) file_based_preview = False if file_based_preview: # Dump to file in temp dir for debugging from ..outputs.file_api import Custom_Context as lxs_writer preview_context = lxs_writer(scene.name) preview_context.set_filename(scene, 'luxblend25-preview', LXV=False) LM.lux_context = preview_context else: preview_context = LM.lux_context preview_context.logVerbosity('quiet') try: export_materials.ExportedMaterials.clear() export_materials.ExportedTextures.clear() from ..export import preview_scene xres, yres = scene.camera.data.luxrender_camera.luxrender_film.resolution(scene) # Don't render the tiny images if xres <= 96: raise Exception('Skipping material thumbnail update, image too small (%ix%i)' % (xres,yres)) preview_scene.preview_scene(scene, preview_context, obj=preview_objects[0], mat=pm, tex=pt) # render ! preview_context.worldEnd() if file_based_preview: preview_context = preview_context.parse('luxblend25-preview.lxs', True) LM.lux_context = preview_context while not preview_context.statistics('sceneIsReady'): time.sleep(0.05) def is_finished(ctx): return ctx.getAttribute('film', 'enoughSamples') def interruptible_sleep(sec, increment=0.05): sec_elapsed = 0.0 while not self.test_break() and sec_elapsed<=sec: sec_elapsed += increment time.sleep(increment) for i in range(multiprocessing.cpu_count()-2): # -2 since 1 thread already created and leave 1 spare if is_finished(preview_context): break preview_context.addThread() while not is_finished(preview_context): if self.test_break() or bpy.context.scene.render.engine != 'LUXRENDER_RENDER': raise Exception('Render interrupted') # progressively update the preview time.sleep(0.2) # safety-sleep if preview_context.getAttribute('renderer_statistics', 'samplesPerPixel') > 6: if PREVIEW_TYPE == 'TEXTURE': interruptible_sleep(0.8) # reduce update to every 1.0 sec until haltthreshold kills the render else: interruptible_sleep(1.8) # reduce update to every 2.0 sec until haltthreshold kills the render preview_context.updateStatisticsWindow() LuxLog('Updating preview (%ix%i - %s)' % (xres, yres, preview_context.getAttribute('renderer_statistics_formatted_short', '_recommended_string'))) result = self.begin_result(0, 0, xres, yres) if hasattr(preview_context, 'blenderCombinedDepthBuffers'): # use fast buffers pb, zb = preview_context.blenderCombinedDepthBuffers() result.layers.foreach_set("rect", pb) else: lay = result.layers[0] lay.rect = preview_context.blenderCombinedDepthRects()[0] self.end_result(result, 0) if bpy.app.version > (2, 63, 17 ) else self.end_result(result) # cycles tiles adaption except Exception as exc: LuxLog('Preview aborted: %s' % exc) preview_context.exit() preview_context.wait() # cleanup() destroys the pylux Context preview_context.cleanup() LM.reset()
def render(self, scene): ''' scene: bpy.types.Scene Export the given scene to LuxRender. Choose from one of several methods depending on what needs to be rendered. Returns None ''' with RENDERENGINE_luxrender.render_lock: # just render one thing at a time prev_cwd = os.getcwd() try: self.LuxManager = None self.render_update_timer = None self.output_dir = efutil.temp_directory() self.output_file = 'default.png' if scene is None: LuxLog('ERROR: Scene to render is not valid') return if scene.name == 'preview': self.render_preview(scene) return if scene.display_settings.display_device != "sRGB": LuxLog('WARNING: Colour Management not set to sRGB, render results may look too dark.') api_type, write_files = self.set_export_path(scene) os.chdir(efutil.export_path) is_animation = hasattr(self, 'is_animation') and self.is_animation make_queue = scene.luxrender_engine.export_type == 'EXT' and scene.luxrender_engine.binary_name == 'luxrender' and write_files if is_animation and make_queue: queue_file = efutil.export_path + '%s.%s.lxq' % (efutil.scene_filename(), bpy.path.clean_name(scene.name)) # Open/reset a queue file if scene.frame_current == scene.frame_start: open(queue_file, 'w').close() if hasattr(self, 'update_progress'): fr = scene.frame_end - scene.frame_start fo = scene.frame_current - scene.frame_start self.update_progress(fo/fr) exported_file = self.export_scene(scene) if exported_file == False: return # Export frame failed, abort rendering if is_animation and make_queue: self.LuxManager = LuxManager.GetActive() self.LuxManager.lux_context.worldEnd() with open(queue_file, 'a') as qf: qf.write("%s\n" % exported_file) if scene.frame_current == scene.frame_end: # run the queue self.render_queue(scene, queue_file) else: self.render_start(scene) except Exception as err: LuxLog('%s'%err) self.report({'ERROR'}, '%s'%err) os.chdir(prev_cwd)
def render_preview(self, scene): (width, height) = resolution(scene) if (width < 96 or height < 96): return objects_materials = {} for object_ in [ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render]: for mat in get_instance_materials(object_): if mat is not None: if not object_.name in objects_materials.keys(): objects_materials[object_] = [] objects_materials[object_].append(mat) # find objects that are likely to be the preview objects preview_objects = [o for o in objects_materials.keys() if o.name.startswith('preview')] if len(preview_objects) < 1: return # find the materials attached to the likely preview object likely_materials = objects_materials[preview_objects[0]] if len(likely_materials) < 1: return tempdir = efutil.temp_directory() scenefile = os.path.abspath(os.path.join(tempdir, "Scene.sc")) outfile = os.path.abspath(os.path.join(tempdir, "matpreview.png")) matfile = os.path.abspath(os.path.join(tempdir, "ObjectMaterial.mat.sc")) pm = likely_materials[0] mat_dic = create_shader_block(pm) linenum = 0 found = False if (('Shader' in mat_dic.keys()) and (len(mat_dic['Shader']) > 0)): for eachline in mat_dic['Shader']: if eachline.find(' name "') >= 0 : found = True break linenum += 1 if not found: return matgot = mat_dic['Shader'][:] matgot[1] = ' name "ObjectMaterial"' out_write = [] out_write.append('image {') out_write.append('resolution %s %s' % (width, height)) out_write.append('aa 0 1 samples 4 filter mitchell jitter False } ') out_write.extend(matgot) fi = open(matfile , 'w') [ fi.write("\n%s " % line) for line in out_write] fi.close() src = os.path.join(plugin_path() , "preview", 'SceneFloorUVgrid.png') shutil.copy(src, tempdir) src = os.path.join(plugin_path() , "preview", 'Scene.sc') shutil.copy(src, tempdir) jarpath = efutil.find_config_value('sunflow', 'defaults', 'jar_path', '') javapath = efutil.find_config_value('sunflow', 'defaults', 'java_path', '') memory = "-Xmx%sm" % efutil.find_config_value('sunflow', 'defaults', 'memoryalloc', '') cmd_line = [ javapath , memory , '-server' , '-jar' , jarpath , '-nogui', '-v', '0', '-o', outfile , scenefile ] sunflow_process = subprocess.Popen(cmd_line) framebuffer_thread = sunflowFilmDisplay() framebuffer_thread.set_kick_period(2) framebuffer_thread.begin(self, outfile, resolution(scene)) render_update_timer = None while sunflow_process.poll() == None and not self.test_break(): render_update_timer = threading.Timer(1, self.process_wait_timer) render_update_timer.start() if render_update_timer.isAlive(): render_update_timer.join() # If we exit the wait loop (user cancelled) and sunflow is still running, then send SIGINT if sunflow_process.poll() == None: # Use SIGTERM because that's the only one supported on Windows sunflow_process.send_signal(subprocess.signal.SIGTERM) # Stop updating the render result and load the final image framebuffer_thread.stop() framebuffer_thread.join() if sunflow_process.poll() != None and sunflow_process.returncode != 0: sunflowLog("Sunflow: Rendering failed -- check the console") else: framebuffer_thread.kick(render_end=True) framebuffer_thread.shutdown()
def render_preview(self, scene): # Iterate through the preview scene, finding objects with materials attached objects_materials = {} (width, height) = resolution(scene) if (width, height) == (96, 96): return MtsLog('Preview Render Res: {0}'.format(width, height)) for object in [ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render]: for mat in get_instance_materials(object): if mat is not None: if not object.name in objects_materials.keys(): objects_materials[object] = [] objects_materials[object].append(mat) # find objects that are likely to be the preview objects preview_objects = [o for o in objects_materials.keys() if o.name.startswith('preview')] if len(preview_objects) < 1: return # find the materials attached to the likely preview object likely_materials = objects_materials[preview_objects[0]] if len(likely_materials) < 1: return tempdir = efutil.temp_directory() matfile = "matpreview_materials.xml" output_file = os.path.join(tempdir, "matpreview.png") scene_file = os.path.join(os.path.join(plugin_path(), "matpreview"), "matpreview.xml") MtsLog('Scene path: %s'%scene_file) pm = likely_materials[0] exporter = SceneExporter(tempdir, matfile, bpy.data.materials, bpy.data.textures) exporter.adj_filename = os.path.join(tempdir, matfile) if not exporter.writeHeader(): MtsLog('Error while exporting -- check the console for details.') return; exporter.exportMaterial(pm) exporter.exportPreviewMesh(scene, pm) exporter.writeFooter() refresh_interval = 2 preview_spp = int(efutil.find_config_value('mitsuba', 'defaults', 'preview_spp', '16')) preview_depth = int(efutil.find_config_value('mitsuba', 'defaults', 'preview_depth', '2')) mitsuba_process = MtsLaunch(scene.mitsuba_engine.binary_path, tempdir, ['mitsuba', '-q', '-r%i' % refresh_interval, '-b16', '-Dmatfile=%s' % os.path.join(tempdir, matfile), '-Dwidth=%i' % width, '-Dheight=%i' % height, '-Dspp=%i' % preview_spp, '-Ddepth=%i' % preview_depth, '-o', output_file, scene_file], ) framebuffer_thread = MtsFilmDisplay() framebuffer_thread.set_kick_period(refresh_interval) framebuffer_thread.begin(self, output_file, resolution(scene), preview=True) render_update_timer = None while mitsuba_process.poll() == None and not self.test_break(): render_update_timer = threading.Timer(1, self.process_wait_timer) render_update_timer.start() if render_update_timer.isAlive(): render_update_timer.join() cancelled = False # If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT if mitsuba_process.poll() == None: MtsLog("MtsBlend: Terminating process..") # Use SIGTERM because that's the only one supported on Windows mitsuba_process.send_signal(subprocess.signal.SIGTERM) cancelled = True # Stop updating the render result and load the final image framebuffer_thread.stop() framebuffer_thread.join() if not cancelled: if mitsuba_process.poll() != None and mitsuba_process.returncode != 0: MtsLog("MtsBlend: Rendering failed -- check the console"); mitsuba_process.send_signal(subprocess.signal.SIGTERM) #fixes mitsuba preview not refresing after bad eg. reference else: framebuffer_thread.kick(render_end=True) framebuffer_thread.shutdown()
def render_preview(self, scene): # Iterate through the preview scene, finding objects with materials attached objects_materials = {} (width, height) = resolution(scene) if (width, height) == (96, 96): return MtsLog('Preview Render Res: {0}'.format(width, height)) for object in [ ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render ]: for mat in get_instance_materials(object): if mat is not None: if not object.name in objects_materials.keys(): objects_materials[object] = [] objects_materials[object].append(mat) # find objects that are likely to be the preview objects preview_objects = [ o for o in objects_materials.keys() if o.name.startswith('preview') ] if len(preview_objects) < 1: return # find the materials attached to the likely preview object likely_materials = objects_materials[preview_objects[0]] if len(likely_materials) < 1: return tempdir = efutil.temp_directory() matfile = "matpreview_materials.xml" output_file = os.path.join(tempdir, "matpreview.png") scene_file = os.path.join(os.path.join(plugin_path(), "matpreview"), "matpreview.xml") MtsLog('Scene path: %s' % scene_file) pm = likely_materials[0] exporter = SceneExporter(tempdir, matfile, bpy.data.materials, bpy.data.textures) exporter.adj_filename = os.path.join(tempdir, matfile) if not exporter.writeHeader(): MtsLog('Error while exporting -- check the console for details.') return exporter.exportMaterial(pm) exporter.exportPreviewMesh(scene, pm) exporter.writeFooter() refresh_interval = 2 preview_spp = int( efutil.find_config_value('mitsuba', 'defaults', 'preview_spp', '16')) preview_depth = int( efutil.find_config_value('mitsuba', 'defaults', 'preview_depth', '2')) mitsuba_process = MtsLaunch( scene.mitsuba_engine.binary_path, tempdir, [ 'mitsuba', '-q', '-r%i' % refresh_interval, '-b16', '-Dmatfile=%s' % os.path.join(tempdir, matfile), '-Dwidth=%i' % width, '-Dheight=%i' % height, '-Dspp=%i' % preview_spp, '-Ddepth=%i' % preview_depth, '-o', output_file, scene_file ], ) framebuffer_thread = MtsFilmDisplay() framebuffer_thread.set_kick_period(refresh_interval) framebuffer_thread.begin(self, output_file, resolution(scene), preview=True) render_update_timer = None while mitsuba_process.poll() == None and not self.test_break(): render_update_timer = threading.Timer(1, self.process_wait_timer) render_update_timer.start() if render_update_timer.isAlive(): render_update_timer.join() cancelled = False # If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT if mitsuba_process.poll() == None: MtsLog("MtsBlend: Terminating process..") # Use SIGTERM because that's the only one supported on Windows mitsuba_process.send_signal(subprocess.signal.SIGTERM) cancelled = True # Stop updating the render result and load the final image framebuffer_thread.stop() framebuffer_thread.join() if not cancelled: if mitsuba_process.poll( ) != None and mitsuba_process.returncode != 0: MtsLog("MtsBlend: Rendering failed -- check the console") mitsuba_process.send_signal( subprocess.signal.SIGTERM ) #fixes mitsuba preview not refresing after bad eg. reference else: framebuffer_thread.kick(render_end=True) framebuffer_thread.shutdown()
def render_preview(self, scene): if sys.platform == 'darwin': self.output_dir = efutil.filesystem_path(bpy.app.tempdir) else: self.output_dir = efutil.temp_directory() if self.output_dir[-1] != '/': self.output_dir += '/' efutil.export_path = self.output_dir from ..outputs.pure_api import PYLUX_AVAILABLE if not PYLUX_AVAILABLE: self.bl_use_preview = False LuxLog('ERROR: Material previews require pylux') return from ..export import materials as export_materials # Iterate through the preview scene, finding objects with materials attached objects_mats = {} for obj in [ ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render ]: for mat in export_materials.get_instance_materials(obj): if mat is not None: if not obj.name in objects_mats.keys(): objects_mats[obj] = [] objects_mats[obj].append(mat) PREVIEW_TYPE = None # 'MATERIAL' or 'TEXTURE' # find objects that are likely to be the preview objects preview_objects = [ o for o in objects_mats.keys() if o.name.startswith('preview') ] if len(preview_objects) > 0: PREVIEW_TYPE = 'MATERIAL' else: preview_objects = [ o for o in objects_mats.keys() if o.name.startswith('texture') ] if len(preview_objects) > 0: PREVIEW_TYPE = 'TEXTURE' if PREVIEW_TYPE == None: return # TODO: scene setup based on PREVIEW_TYPE # find the materials attached to the likely preview object likely_materials = objects_mats[preview_objects[0]] if len(likely_materials) < 1: print('no preview materials') return pm = likely_materials[0] pt = None LuxLog('Rendering material preview: %s' % pm.name) if PREVIEW_TYPE == 'TEXTURE': pt = pm.active_texture LM = LuxManager( scene.name, api_type='API', ) LuxManager.SetCurrentScene(scene) LuxManager.SetActive(LM) file_based_preview = False if file_based_preview: # Dump to file in temp dir for debugging from ..outputs.file_api import Custom_Context as lxs_writer preview_context = lxs_writer(scene.name) preview_context.set_filename(scene, 'luxblend25-preview', LXV=False) LM.lux_context = preview_context else: preview_context = LM.lux_context preview_context.logVerbosity('quiet') try: export_materials.ExportedMaterials.clear() export_materials.ExportedTextures.clear() from ..export import preview_scene xres, yres = scene.camera.data.luxrender_camera.luxrender_film.resolution( scene) # Don't render the tiny images if xres <= 96: raise Exception( 'Skipping material thumbnail update, image too small (%ix%i)' % (xres, yres)) preview_scene.preview_scene(scene, preview_context, obj=preview_objects[0], mat=pm, tex=pt) # render ! preview_context.worldEnd() if file_based_preview: preview_context = preview_context.parse( 'luxblend25-preview.lxs', True) LM.lux_context = preview_context while not preview_context.statistics('sceneIsReady'): time.sleep(0.05) def is_finished(ctx): return ctx.getAttribute('film', 'enoughSamples') def interruptible_sleep(sec, increment=0.05): sec_elapsed = 0.0 while not self.test_break() and sec_elapsed <= sec: sec_elapsed += increment time.sleep(increment) for i in range(multiprocessing.cpu_count() - 2): # -2 since 1 thread already created and leave 1 spare if is_finished(preview_context): break preview_context.addThread() while not is_finished(preview_context): if self.test_break( ) or bpy.context.scene.render.engine != 'LUXRENDER_RENDER': raise Exception('Render interrupted') # progressively update the preview time.sleep(0.2) # safety-sleep if preview_context.getAttribute('renderer_statistics', 'samplesPerPixel') > 6: if PREVIEW_TYPE == 'TEXTURE': interruptible_sleep( 0.8 ) # reduce update to every 1.0 sec until haltthreshold kills the render else: interruptible_sleep( 1.8 ) # reduce update to every 2.0 sec until haltthreshold kills the render preview_context.updateStatisticsWindow() LuxLog('Updating preview (%ix%i - %s)' % (xres, yres, preview_context.getAttribute( 'renderer_statistics_formatted_short', '_recommended_string'))) result = self.begin_result(0, 0, xres, yres) if hasattr(preview_context, 'blenderCombinedDepthBuffers'): # use fast buffers pb, zb = preview_context.blenderCombinedDepthBuffers() result.layers.foreach_set("rect", pb) else: lay = result.layers[0] lay.rect = preview_context.blenderCombinedDepthRects()[0] self.end_result( result, 0) if bpy.app.version > (2, 63, 17) else self.end_result( result) # cycles tiles adaption except Exception as exc: LuxLog('Preview aborted: %s' % exc) preview_context.exit() preview_context.wait() # cleanup() destroys the pylux Context preview_context.cleanup() LM.reset()
def render(self, scene): ''' scene: bpy.types.Scene Export the given scene to LuxRender. Choose from one of several methods depending on what needs to be rendered. Returns None ''' with RENDERENGINE_luxrender.render_lock: # just render one thing at a time prev_cwd = os.getcwd() try: self.LuxManager = None self.render_update_timer = None self.output_dir = efutil.temp_directory() self.output_file = 'default.png' if scene is None: LuxLog('ERROR: Scene to render is not valid') return if scene.name == 'preview': self.render_preview(scene) return if scene.display_settings.display_device != "sRGB": LuxLog( 'WARNING: Colour Management not set to sRGB, render results may look too dark.' ) api_type, write_files = self.set_export_path(scene) os.chdir(efutil.export_path) is_animation = hasattr(self, 'is_animation') and self.is_animation make_queue = scene.luxrender_engine.export_type == 'EXT' and scene.luxrender_engine.binary_name == 'luxrender' and write_files if is_animation and make_queue: queue_file = efutil.export_path + '%s.%s.lxq' % ( efutil.scene_filename(), bpy.path.clean_name( scene.name)) # Open/reset a queue file if scene.frame_current == scene.frame_start: open(queue_file, 'w').close() if hasattr(self, 'update_progress'): fr = scene.frame_end - scene.frame_start fo = scene.frame_current - scene.frame_start self.update_progress(fo / fr) exported_file = self.export_scene(scene) if exported_file == False: return # Export frame failed, abort rendering if is_animation and make_queue: self.LuxManager = LuxManager.GetActive() self.LuxManager.lux_context.worldEnd() with open(queue_file, 'a') as qf: qf.write("%s\n" % exported_file) if scene.frame_current == scene.frame_end: # run the queue self.render_queue(scene, queue_file) else: self.render_start(scene) except Exception as err: LuxLog('%s' % err) self.report({'ERROR'}, '%s' % err) os.chdir(prev_cwd)
def __render_material_preview(self, scene): """ Export and render the material preview scene. """ # Don't render material thumbnails. (width, height) = util.get_render_resolution(scene) if width <= 96: return # Collect objects and their materials in a object -> [materials] dictionary. objects_materials = {} for obj in (obj for obj in scene.objects if obj.is_visible(scene) and not obj.hide_render): for mat in util.get_instance_materials(obj): if mat is not None: if obj.name not in objects_materials.keys(): objects_materials[obj] = [] objects_materials[obj].append(mat) # Find objects that are likely to be the preview objects. preview_objects = [ o for o in objects_materials.keys() if o.name.startswith('preview') ] if not preview_objects: return # Find the materials attached to the likely preview object. likely_materials = objects_materials[preview_objects[0]] if not likely_materials: return # Build the path to the template preview project in the add-on directory. preview_template_dir = os.path.join( os.sep.join(util.realpath(__file__).split(os.sep)[:-1]), "mat_preview") # Build the path to the output preview project. preview_output_dir = os.path.join(efutil.temp_directory(), "mat_preview") preview_project_filepath = os.path.join(preview_output_dir, "mat_preview.appleseed") # Copy preview scene assets. if not os.path.isdir(preview_output_dir): os.mkdir(preview_output_dir) existing_files = os.listdir(preview_output_dir) for item in os.listdir(preview_template_dir): if item not in existing_files: copyfile(os.path.join(preview_template_dir, item), os.path.join(preview_output_dir, item)) prev_mat = likely_materials[0] prev_type = prev_mat.preview_render_type.lower() # Export the project. exporter = project_file_writer.Exporter() file_written = exporter.export_preview(scene, preview_project_filepath, preview_template_dir, prev_mat, prev_type, width, height) if not file_written: print('Error while exporting -- check the console for details.') return # Render the project. self.__render_project_file(scene, preview_project_filepath)
def __render_material_preview(self, scene): """ Export and render the material preview scene. """ # Don't render material thumbnails. (width, height) = util.get_render_resolution(scene) if width <= 96: return # Collect objects and their materials in a object -> [materials] dictionary. objects_materials = {} for obj in (obj for obj in scene.objects if obj.is_visible(scene) and not obj.hide_render): for mat in util.get_instance_materials(obj): if mat is not None: if obj.name not in objects_materials.keys(): objects_materials[obj] = [] objects_materials[obj].append(mat) # Find objects that are likely to be the preview objects. preview_objects = [o for o in objects_materials.keys() if o.name.startswith('preview')] if not preview_objects: return # Find the materials attached to the likely preview object. likely_materials = objects_materials[preview_objects[0]] if not likely_materials: return # Build the path to the template preview project in the add-on directory. preview_template_dir = os.path.join(os.sep.join(util.realpath(__file__).split(os.sep)[:-1]), "mat_preview") # Build the path to the output preview project. preview_output_dir = os.path.join(efutil.temp_directory(), "mat_preview") preview_project_filepath = os.path.join(preview_output_dir, "mat_preview.appleseed") # Copy preview scene assets. if not os.path.isdir(preview_output_dir): os.mkdir(preview_output_dir) existing_files = os.listdir(preview_output_dir) for item in os.listdir(preview_template_dir): if item not in existing_files: copyfile(os.path.join(preview_template_dir, item), os.path.join(preview_output_dir, item)) prev_mat = likely_materials[0] prev_type = prev_mat.preview_render_type.lower() # Export the project. exporter = project_file_writer.Exporter() file_written = exporter.export_preview(scene, preview_project_filepath, prev_mat, prev_type, width, height) if not file_written: print('Error while exporting. Check the console for details.') return # Render the project. self.__render_project_file(scene, preview_project_filepath)
def render_preview(self, scene): (width, height) = resolution(scene) if (width < 96 or height < 96): return objects_materials = {} for object_ in [ ob for ob in scene.objects if ob.is_visible(scene) and not ob.hide_render ]: for mat in get_instance_materials(object_): if mat is not None: if not object_.name in objects_materials.keys(): objects_materials[object_] = [] objects_materials[object_].append(mat) # find objects that are likely to be the preview objects preview_objects = [ o for o in objects_materials.keys() if o.name.startswith('preview') ] if len(preview_objects) < 1: return # find the materials attached to the likely preview object likely_materials = objects_materials[preview_objects[0]] if len(likely_materials) < 1: return tempdir = efutil.temp_directory() scenefile = os.path.abspath(os.path.join(tempdir, "Scene.sc")) outfile = os.path.abspath(os.path.join(tempdir, "matpreview.png")) matfile = os.path.abspath( os.path.join(tempdir, "ObjectMaterial.mat.sc")) pm = likely_materials[0] mat_dic = create_shader_block(pm) linenum = 0 found = False if (('Shader' in mat_dic.keys()) and (len(mat_dic['Shader']) > 0)): for eachline in mat_dic['Shader']: if eachline.find(' name "') >= 0: found = True break linenum += 1 if not found: return matgot = mat_dic['Shader'][:] matgot[1] = ' name "ObjectMaterial"' out_write = [] out_write.append('image {') out_write.append('resolution %s %s' % (width, height)) out_write.append( 'aa 0 1 samples 4 filter mitchell jitter False } ' ) out_write.extend(matgot) fi = open(matfile, 'w') [fi.write("\n%s " % line) for line in out_write] fi.close() src = os.path.join(plugin_path(), "preview", 'SceneFloorUVgrid.png') shutil.copy(src, tempdir) src = os.path.join(plugin_path(), "preview", 'Scene.sc') shutil.copy(src, tempdir) jarpath = efutil.find_config_value('sunflow', 'defaults', 'jar_path', '') javapath = efutil.find_config_value('sunflow', 'defaults', 'java_path', '') memory = "-Xmx%sm" % efutil.find_config_value('sunflow', 'defaults', 'memoryalloc', '') cmd_line = [ javapath, memory, '-server', '-jar', jarpath, '-nogui', '-v', '0', '-o', outfile, scenefile ] sunflow_process = subprocess.Popen(cmd_line) framebuffer_thread = sunflowFilmDisplay() framebuffer_thread.set_kick_period(2) framebuffer_thread.begin(self, outfile, resolution(scene)) render_update_timer = None while sunflow_process.poll() == None and not self.test_break(): render_update_timer = threading.Timer(1, self.process_wait_timer) render_update_timer.start() if render_update_timer.isAlive(): render_update_timer.join() # If we exit the wait loop (user cancelled) and sunflow is still running, then send SIGINT if sunflow_process.poll() == None: # Use SIGTERM because that's the only one supported on Windows sunflow_process.send_signal(subprocess.signal.SIGTERM) # Stop updating the render result and load the final image framebuffer_thread.stop() framebuffer_thread.join() if sunflow_process.poll() != None and sunflow_process.returncode != 0: sunflowLog("Sunflow: Rendering failed -- check the console") else: framebuffer_thread.kick(render_end=True) framebuffer_thread.shutdown()